Skip to content

Commit

Permalink
Feature opensearch (#240)
Browse files Browse the repository at this point in the history
Signed-off-by: Andrei Stepanov <astepano@redhat.com>
Co-authored-by: Chris Kelley <ckelley@redhat.com>
  • Loading branch information
Andrei-Stepanov and ckelleyRH committed Apr 24, 2024
1 parent fe273e3 commit 0a2d30c
Show file tree
Hide file tree
Showing 89 changed files with 13,827 additions and 27,040 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ fedmsg-listener[fedmsg listener] --> queue
Loader --> queue
end
Loader --> db[MongoDB]
Loader --> db[Opensearch]
server["ciboard-server<br>(backend)"] --> db
ciboard["ciboard<br>(frontend)"]:::focus --> server
Expand Down
24,260 changes: 7,452 additions & 16,808 deletions package-lock.json

Large diffs are not rendered by default.

32 changes: 17 additions & 15 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,18 @@
],
"dependencies": {
"@apollo/client": "^3.7.17",
"@patternfly/react-charts": "^6.67.1",
"@patternfly/react-core": "^4.276.6",
"@patternfly/react-icons": "^4.65.1",
"@patternfly/react-table": "^4.113.0",
"@reduxjs/toolkit": "^1.9.5",
"@testing-library/jest-dom": "^5.17.0",
"@testing-library/react": "^12.1.5",
"@patternfly/react-charts": "^7.1.1",
"@patternfly/react-core": "^5.1.1",
"@patternfly/react-icons": "^5.1.1",
"@patternfly/react-table": "^5.1.1",
"@reduxjs/toolkit": "^2.2.3",
"@testing-library/jest-dom": "^6.4.2",
"@testing-library/react": "^15.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/jest": "^29.5.3",
"@types/node": "^20.4.5",
"@types/react": "^17.0.45",
"@types/react-dom": "^17.0.17",
"@types/react": "^18.2.33",
"@types/react-dom": "^18.2.14",
"axios": "^1.4.0",
"buffer": "^6.0.3",
"classnames": "^2.3.1",
Expand All @@ -33,21 +33,22 @@
"moment-duration-format": "^2.3.2",
"moment-timezone": "^0.5.43",
"pako": "^2.0.4",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^8.1.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-redux": "^9.1.0",
"react-router-dom": "^6.11.2",
"react-scripts": "5.0.1",
"react-scripts": "^5.0.1",
"react-use-localstorage": "^3.5.3",
"redux": "^4.2.1",
"redux": "^5.0.1",
"typescript": "^5.1.3",
"uuid": "^9.0.0",
"validator": "^13.9.0",
"web-vitals": "^3.4.0",
"xml2js-parser": "^1.1.1"
},
"overrides": {
"typescript": "^5.1.3"
"typescript": "^5.1.3",
"@svgr/webpack": "$@svgr/webpack"
},
"scripts": {
"start": "react-scripts start",
Expand Down Expand Up @@ -75,6 +76,7 @@
]
},
"devDependencies": {
"@svgr/webpack": "^8.1.0",
"@types/linkifyjs": "^2.1.4",
"@types/lodash": "^4.14.196",
"@types/moment-duration-format": "^2.2.3",
Expand Down
23 changes: 23 additions & 0 deletions src/1.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<EntitiesDescriptor xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" Name="urn:keycloak">
<EntityDescriptor entityID="https://auth.redhat.com/auth/realms/EmployeeIDP">
<IDPSSODescriptor WantAuthnRequestsSigned="true" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="signing">
<dsig:KeyInfo>
<dsig:KeyName>APbMv27WYbGMYVaBNtILEQpnmprNUEuV76uCtODDZGs</dsig:KeyName>
<dsig:X509Data>
<dsig:X509Certificate>MIIE+jCCA+KgAwIBAgIED/4AJzANBgkqhkiG9w0BAQsFADBBMRAwDgYDVQQKDAdSZWQgSGF0MQ0wCwYDVQQLDARwcm9kMR4wHAYDVQQDDBVDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMTcwNjIwMTI1MTQwWhcNMjIwNjE5MTI1MTQwWjCBqTELMAkGA1UEBhMCVVMxFzAVBgNVBAgMDk5vcnRoIENhcm9saW5hMRAwDgYDVQQHDAdSYWxlaWdoMRYwFAYDVQQKDA1SZWQgSGF0LCBJbmMuMQwwCgYDVQQLDANJQU0xIjAgBgNVBAMMGVJlZCBIYXQgUHJvZCBFbXBsb3llZSBTU08xJTAjBgkqhkiG9w0BCQEWFnNlcnZpY2VkZXNrQHJlZGhhdC5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC089RqFDc8mGgKpKy9ZOdH+arhvDg94+kGCNCVFXNQFnBbmxwodtRnF0r2pGFfd+Yw7PRU3cfgD7WVq6cInPnpuVAU3H0+Fni+RrzeoKs2O2WvmVBmxFK4JQ7bzeAnfTd92pCGaua95VnfgqVRt6FzL+bvWc/3YCr+KcgI3lcOZdEPJ3/WMOXWhPpcKYRo7rsu/vI9R19NBHwN+/DjyWeq6kVLp1tjdA07RgcihqeZ5f3BqjcMuKhcEQVjwiwcqKbSUBW2VCJ5YKXmOv1R6asjHMJsiRPBWSPIzhAyhw0GGXvM6F8q3w0EExUDOet08Ffl1Sl73paoKcNQ7hR9ljobpsy7Hhq0j4Ink0XR+pSVUQT+yCeyO4aaSxOc+75CAzvqvMSLrUP+UST0sW+1mv0jCvWJabng63isNyHx0aLTC8p9MWOxskNBZ6ce3+n70kGk3cMbhveAB/RgMs232XhUKcJApsuGjPL83vhE9n23t15IXuv+2X68ECGuoGW4VNq7Diq3QoZSHAa2gwa9bcLYRoOgGtWdysQ++Kks+XXPgL4UHcKWULKJlzOh20Jypi9N2KBU5IGccRve1jCfIQ0w246aRfTthsUF62vMD6T28e5XHijBPlNPAA+Vx3uCECZYpAksmyqK+wuUscOAH3FW0yrbSftROjzNvd0/wpnwXQIDAQABo4GQMIGNMB8GA1UdIwQYMBaAFHvaCfVJXdnXXMk2+FXSG5eeES9+MDsGCCsGAQUFBwEBBC8wLTArBggrBgEFBQcwAYYfaHR0cDovL29jc3AucmVkaGF0LmNvbS9jYS9vY3NwLzAOBgNVHQ8BAf8EBAMCBPAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQDBPTR0hAB/LTUWzi5jOG8Ni54gl6GDu/klaoOXjXzOUJY4keiNKKytyec9nEhUrUfuSMXGrteGnUc+8xq1WNmY9qHeaKHU2u8wsA8ekvmhSx550qZ1nocOumbswNKzSknTU9l1TH/GONgZwW99xxpbAmj6g7CjrsfQ2mESNkEzTT373eRUJriz/AgfxxgSyvBoxbNPx6IoekNUL8d/kHy1Jd7rOXbqBmYjeI7tMtidzezWDFAJkoQ05I3pDYvJfL999pYj/ykbqHg8Hkv/P+zLWSUuoI8ReIUCQDIO57+PTUMM9q7LwMX/viyym6jv2dKzDTGrB3AEYkRbBKxKng+u</dsig:X509Certificate>
</dsig:X509Data>
</dsig:KeyInfo>
</KeyDescriptor>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://auth.redhat.com/auth/realms/EmployeeIDP/protocol/saml" />
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://auth.redhat.com/auth/realms/EmployeeIDP/protocol/saml" />
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://auth.redhat.com/auth/realms/EmployeeIDP/protocol/saml" />
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="https://auth.redhat.com/auth/realms/EmployeeIDP/protocol/saml" />
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="https://auth.redhat.com/auth/realms/EmployeeIDP/protocol/saml" />
</IDPSSODescriptor>
</EntityDescriptor>
</EntitiesDescriptor>
114 changes: 39 additions & 75 deletions src/actions/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* This file is part of ciboard
* Copyright (c) 2021, 2022, 2023 Andrei Stepanov <astepano@redhat.com>
* Copyright (c) 2021, 2022, 2023, 2024 Andrei Stepanov <astepano@redhat.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
Expand All @@ -19,20 +19,22 @@
*/

import _ from 'lodash';
import axios from 'axios';
import axios, { AxiosResponse } from 'axios';
import { ApolloClient } from '@apollo/client';

import { Artifact, getANvr, getAType } from '../types';
import { greenwave } from '../config';
import { GASetSearchOptionsPayload } from './types';
import { AppDispatch, GetState } from '../reduxStore';
import WaiverdbNewMutation from '../mutations/WaiverdbNew';
import * as alertsSlice from '../slices/alertsSlice';
import * as authSlice from '../slices/authSlice';
import * as filtersSlice from '../slices/filtersSlice';
import * as gatingTestsFormSlice from '../slices/gatingTestsFormSlice';
import * as waiveSlice from '../slices/waiveSlice';
import { Artifact, PayloadRPMBuildType } from '../artifact';
import { greenwave } from '../config';
import WaiverdbNewMutation from '../mutations/WaiverdbNew';
import { db_field_from_atype } from '../utils/artifactUtils';
import { AlertVariant } from '@patternfly/react-core';
import { CiTest } from '../components/PageDetails/types';
export * from '../slices/artifactsSlice';
export * from '../slices/artifactsQuerySlice';

export const cleanseGatingFormState = () => gatingTestsFormSlice.cleanse();

Expand All @@ -49,10 +51,10 @@ export const updateGatingSearchOptions = (
gatingOptions: GASetSearchOptionsPayload,
) => gatingTestsFormSlice.updateCriteria(gatingOptions);

type AlertVariantType = 'success' | 'danger' | 'warning' | 'info' | 'default';

export const popAlert = (key: number) => alertsSlice.popAlert({ key });

type AlertVariantKeys = keyof typeof AlertVariant;

/**
* Push a new alert to the alerts queue.
* @param variant Variant of the alert component, e.g. `success` or `warning`.
Expand All @@ -61,7 +63,7 @@ export const popAlert = (key: number) => alertsSlice.popAlert({ key });
* @returns Promise that resolves after a succesful event dispatch.
*/
export const pushAlert = (
variant: AlertVariantType,
variant: AlertVariantKeys,
title: React.ReactNode,
autoRm = true,
) => {
Expand All @@ -76,62 +78,22 @@ export const pushAlert = (
};
};

export const addFilter = (newval = '', type = '') => {
return async (dispatch: AppDispatch, getState: GetState) => {
const { filters } = getState();
const currentType = filters.type;
const activeFilters = filters.active;
const foreignRegex = /[^\u0000-\u007f]/;
if (foreignRegex.test(newval)) {
console.log('Ignoring filter with no-latin character: %s', newval);
return null;
}
console.log('%O', { newval, type });
if (!_.has(db_field_from_atype, type)) {
console.log('Ignoring filter with unsupported type: %s', type);
return null;
}
console.log('Add new filter', type, newval);
if (type !== currentType) {
/** new epoch */
} else if (_.includes(activeFilters, newval)) {
console.log('Do not add existing filter', newval);
return null;
}
dispatch(filtersSlice.addFilter({ newval, type }));
};
};

export const deleteFilter = (delval = '') =>
filtersSlice.deleteFilter({ delval });

export const setOptionsForFilters = (newOptions: any) => {
return async (dispatch: AppDispatch, getState: GetState) => {
const { filters } = getState();
const currentOptions = filters.options;
const optionsSame = _.isMatch(currentOptions, newOptions);
if (optionsSame) {
return null;
}
const type = filters.type;
const activeFilters = filters.active;
dispatch(filtersSlice.setOptions(newOptions));
for (const filter of activeFilters) {
dispatch(addFilter(filter, type));
}
};
};

export const fetchUser = () => {
return async (dispatch: AppDispatch) => {
const res = await axios.get('/current_user');
let res: AxiosResponse<any, any>;
try {
res = await axios.get('/current_user');
} catch (err) {
console.log('Cannot get current user', err);
return;
}
dispatch(authSlice.fetchUser(res.data));
};
};

export const createWaiver = (
artifact: Artifact | undefined,
testcase: string | undefined,
ciTest: CiTest | undefined,
) => {
return async (dispatch: AppDispatch, getState: GetState) => {
const { displayName, nameID } = getState().auth;
Expand All @@ -147,7 +109,7 @@ export const createWaiver = (
);
return;
}
dispatch(waiveSlice.createWaiver({ artifact, testcase }));
dispatch(waiveSlice.createWaiver({ artifact, ciTest }));
};
};

Expand All @@ -168,14 +130,19 @@ export const submitWaiver = (reason: string, client: ApolloClient<object>) => {
* get NVR, for modules we need to convert it to 'brew' like form
*/
let waiveError: string;
const { artifact, testcase } = getState().waive;
if (_.isNil(_.get(artifact, 'payload.nvr')) || _.isNil(testcase)) {
return;
}
const { artifact, ciTest } = getState().waive;
const testcaseName = ciTest?.name;
// NOTE: We know that artifact.payload is not null thanks to the check at the
// top of the function. Moreover, we know that payload has the nvr property,
// so we assert the type of the payload here.
const nvr = (artifact!.payload! as PayloadRPMBuildType).nvr;
const nvr = getANvr(artifact!);
if (_.isNil(nvr) || _.isNil(testcaseName)) {
const waiveError = `Cannot submit waiver for: ${nvr}, ${testcaseName}`;
dispatch(
waiveSlice.submitWaiver({ waiveError, reason: 'bad call' }),
);
return;
}
if (!nvr) {
waiveError = 'Could not get NVR, please contact support.';
dispatch(waiveSlice.submitWaiver({ waiveError, reason: '' }));
Expand All @@ -187,26 +154,23 @@ export const submitWaiver = (reason: string, client: ApolloClient<object>) => {
* NOTE: We know that artifact is not null thanks to the check at the top
* of the function.
*/
let artifactType = artifact!.type;
if (artifactType === 'brew-build' && nvr.match(/.*-container-.*/)) {
artifactType = 'redhat-container-image';
let aType = getAType(artifact!);
if (aType === 'brew-build' && nvr.match(/.*-container-.*/)) {
aType = 'redhat-container-image';
}
const product_version = greenwave.decision.product_version(
nvr,
artifactType,
);
const product_version = greenwave.decision.product_version(nvr, aType);
try {
const response = await client.mutate({
mutation: WaiverdbNewMutation,
variables: {
// NOTE: We know that artifact is not null thanks to the check at
// the top of the function.
subject_type: artifact!.type,
subject_identifier: nvr,
testcase,
waived: true,
product_version,
comment: reason,
testcase: testcaseName,
subject_type: aType,
product_version,
subject_identifier: nvr,
},
});
console.log('Got response from WaiverDB', response);
Expand Down

0 comments on commit 0a2d30c

Please sign in to comment.