diff --git a/docker-compose-host-macos.yml b/docker-compose-host-macos.yml index 6ad445784..32fa8109c 100644 --- a/docker-compose-host-macos.yml +++ b/docker-compose-host-macos.yml @@ -55,7 +55,7 @@ services: - "8080:8080" auth: - image: quay.io/oauth2-proxy/oauth2-proxy:v7.2.1 + image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 container_name: radix-auth_container environment: # See the `radixconfig.yaml` file for a description of these settings @@ -67,6 +67,7 @@ services: - OAUTH2_PROXY_EMAIL_DOMAINS=* - OAUTH2_PROXY_HTTP_ADDRESS=http://:8000 - OAUTH2_PROXY_OIDC_ISSUER_URL=https://login.microsoftonline.com/3aa4a235-b6e2-48d5-9195-7fcf05b459b0/v2.0 + - OAUTH2_PROXY_SKIP_CLAIMS_FROM_PROFILE_URL=true - OAUTH2_PROXY_PASS_ACCESS_TOKEN=true - OAUTH2_PROXY_PASS_BASIC_AUTH=false - OAUTH2_PROXY_PASS_USER_HEADERS=false diff --git a/docker-compose-host.yml b/docker-compose-host.yml index c0507636c..3ef1e4396 100644 --- a/docker-compose-host.yml +++ b/docker-compose-host.yml @@ -37,7 +37,7 @@ services: - "8080:8080" auth: - image: quay.io/oauth2-proxy/oauth2-proxy:v7.2.1 + image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 container_name: radix-auth_container environment: # See the `radixconfig.yaml` file for a description of these settings @@ -49,6 +49,7 @@ services: - OAUTH2_PROXY_EMAIL_DOMAINS=* - OAUTH2_PROXY_HTTP_ADDRESS=http://:8000 - OAUTH2_PROXY_OIDC_ISSUER_URL=https://login.microsoftonline.com/3aa4a235-b6e2-48d5-9195-7fcf05b459b0/v2.0 + - OAUTH2_PROXY_SKIP_CLAIMS_FROM_PROFILE_URL=true - OAUTH2_PROXY_PASS_ACCESS_TOKEN=true - OAUTH2_PROXY_PASS_BASIC_AUTH=false - OAUTH2_PROXY_PASS_USER_HEADERS=false diff --git a/docker-compose.yml b/docker-compose.yml index a0b97bf3c..3499e26a0 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -41,7 +41,7 @@ services: - "8080:8080" auth: - image: quay.io/oauth2-proxy/oauth2-proxy:v7.2.1 + image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 container_name: radix-auth_container environment: # See the `radixconfig.yaml` file for a description of these settings @@ -53,6 +53,7 @@ services: - OAUTH2_PROXY_EMAIL_DOMAINS=* - OAUTH2_PROXY_HTTP_ADDRESS=http://:8000 - OAUTH2_PROXY_OIDC_ISSUER_URL=https://login.microsoftonline.com/3aa4a235-b6e2-48d5-9195-7fcf05b459b0/v2.0 + - OAUTH2_PROXY_SKIP_CLAIMS_FROM_PROFILE_URL=true - OAUTH2_PROXY_PASS_ACCESS_TOKEN=true - OAUTH2_PROXY_PASS_BASIC_AUTH=false - OAUTH2_PROXY_PASS_USER_HEADERS=false diff --git a/radixconfig.yaml b/radixconfig.yaml index 60aabdb6c..7d7d1e7e0 100644 --- a/radixconfig.yaml +++ b/radixconfig.yaml @@ -38,7 +38,7 @@ spec: - DYNATRACE_API_TOKEN # Token to use for display of availability metrics - OAUTH2_CLIENT_ID # Azure Application ID - name: auth - image: quay.io/oauth2-proxy/oauth2-proxy:v7.2.1 # see https://github.com/oauth2-proxy/oauth2-proxy/blob/master/docs/docs/configuration/overview.md + image: quay.io/oauth2-proxy/oauth2-proxy:v7.6.0 # see https://github.com/oauth2-proxy/oauth2-proxy/blob/master/docs/docs/configuration/overview.md ports: - name: http port: 8000 @@ -63,6 +63,7 @@ spec: OAUTH2_PROXY_EMAIL_DOMAINS: "*" # Any email address registered in AD should be accepted OAUTH2_PROXY_HTTP_ADDRESS: "http://:8000" # The port oauth2_proxy listens on OAUTH2_PROXY_OIDC_ISSUER_URL: "https://login.microsoftonline.com/3aa4a235-b6e2-48d5-9195-7fcf05b459b0/v2.0" # That's the Equinor tenant ID + OAUTH2_PROXY_SKIP_CLAIMS_FROM_PROFILE_URL: "true" OAUTH2_PROXY_PASS_ACCESS_TOKEN: "true" # Pass the access token upstream (to the proxy component) OAUTH2_PROXY_PASS_BASIC_AUTH: "false" # Disable unused default OAUTH2_PROXY_PASS_USER_HEADERS: "false" # Disable unused default diff --git a/src/components/app-config-ci/index.tsx b/src/components/app-config-ci/index.tsx index c71675331..bb5f44a15 100644 --- a/src/components/app-config-ci/index.tsx +++ b/src/components/app-config-ci/index.tsx @@ -1,8 +1,8 @@ import { Typography } from '@equinor/eds-core-react'; import { debounce } from 'lodash'; import * as PropTypes from 'prop-types'; -import { useRef, useState } from 'react'; -import { MultiValue, SingleValue, StylesConfig } from 'react-select'; +import { useEffect, useRef, useState } from 'react'; +import { MultiValue, SingleValue } from 'react-select'; import { ConfigurationItemPopover } from './ci-popover'; import { ConfigurationItemSelect } from './ci-select'; @@ -16,7 +16,7 @@ import { GetApplicationsApiResponse, Application, } from '../../store/service-now-api'; -import { getFetchErrorCode, getFetchErrorMessage } from '../../store/utils'; +import { getFetchErrorMessage } from '../../store/utils'; export type OnConfigurationItemChangeCallback = (ci?: Application) => void; type GetApplicationsFunction = ReturnType< @@ -49,34 +49,30 @@ export function AppConfigConfigurationItem({ configurationItemChangeCallback, disabled, }: Props) { - const [currentCI, setCurrentCI] = useState(null); + const [selectedCI, setSelectedCI] = useState(null); const [popoverCI, setPopoverCI] = useState(); const [popoverOpen, setPopoverOpen] = useState(false); const [getApplications] = serviceNowApi.endpoints.getApplications.useLazyQuery(); - const { data, ...state } = useGetApplicationQuery({ - appId: configurationItem, - }); + const { data: currentCI, ...currentCIState } = useGetApplicationQuery( + { + appId: configurationItem, + }, + { skip: !configurationItem } + ); + useEffect(() => { + setSelectedCI(currentCI); + }, [currentCI]); const containerRef = useRef(null); function onChange(newValue?: Application): void { configurationItemChangeCallback(newValue); - setCurrentCI(newValue); + setSelectedCI(newValue); setPopoverOpen(false); } - const selectStyle: StylesConfig = { - singleValue: (styles) => { - if (state.error && getFetchErrorCode(state.error) === 404) { - styles.backgroundColor = 'var(--eds_interactive_danger__highlight)'; - styles.color = 'var(--eds_interactive_danger__text)'; - } - return styles; - }, - }; - return (
@@ -93,7 +89,6 @@ export function AppConfigConfigurationItem({ setPopoverOpen(!popoverOpen); }} containerRef={containerRef} - styles={selectStyle} name="ConfigurationItem" menuPosition="fixed" closeMenuOnScroll={({ target }: Event) => @@ -110,18 +105,18 @@ export function AppConfigConfigurationItem({ getOptionValue={({ id }) => id} isClearable closeMenuOnSelect={false} - value={currentCI || data} + value={selectedCI} isDisabled={disabled} /> Application from IT Software Inventory (type 3 characters to search) - {state.isError && ( + {currentCIState.isError && (
- Failed to load. {getFetchErrorMessage(state.error)} + Failed to load. {getFetchErrorMessage(currentCIState.error)}
diff --git a/src/components/app-list/index.tsx b/src/components/app-list/index.tsx index 8cb2c3a68..32d36e221 100644 --- a/src/components/app-list/index.tsx +++ b/src/components/app-list/index.tsx @@ -35,11 +35,10 @@ export default function AppList() { [] ); - const { - data: appsData, - refetch, - ...appsState - } = useShowApplicationsQuery({}, { pollingInterval }); + const { data: appsData, ...appsState } = useShowApplicationsQuery( + {}, + { pollingInterval } + ); const { data: favsData, ...favsState } = useGetSearchApplicationsQuery( { apps: favourites?.join(','), @@ -78,7 +77,7 @@ export default function AppList() {
Favourites
- +
diff --git a/src/components/component/toolbar.tsx b/src/components/component/toolbar.tsx index fde5c9ff4..e87c9e62f 100644 --- a/src/components/component/toolbar.tsx +++ b/src/components/component/toolbar.tsx @@ -16,7 +16,7 @@ type Props = { component?: Component; startEnabled?: boolean; stopEnabled?: boolean; - refetch: Function; + refetch?: Function; }; export function Toolbar({ appName, @@ -55,7 +55,7 @@ export function Toolbar({ envName, componentName: component.name, }).unwrap(); - await refetch(); + await refetch?.(); } catch (error) { errorToast(`Failed to start component. ${getFetchErrorMessage(error)}`); } @@ -67,7 +67,7 @@ export function Toolbar({ envName, componentName: component.name, }).unwrap(); - await refetch(); + await refetch?.(); } catch (error) { errorToast(`Failed to stop component. ${getFetchErrorMessage(error)}`); } @@ -79,7 +79,7 @@ export function Toolbar({ envName, componentName: component.name, }).unwrap(); - await refetch(); + await refetch?.(); } catch (error) { errorToast(`Failed to restart component. ${getFetchErrorMessage(error)}`); } diff --git a/src/components/configure-application-github/index.tsx b/src/components/configure-application-github/index.tsx index 37e99aa62..2d2ec0a8c 100644 --- a/src/components/configure-application-github/index.tsx +++ b/src/components/configure-application-github/index.tsx @@ -28,12 +28,13 @@ import { import { pollingInterval } from '../../store/defaults'; import { handlePromiseWithToast } from '../global-top-nav/styled-toaster'; import { getFetchErrorMessage } from '../../store/utils'; +import { ScrimPopup } from '../scrim-popup'; const radixZoneDNS = configVariables.RADIX_CLUSTER_BASE; interface Props { app: ApplicationRegistration; - refetch: Function; + refetch?: Function; onDeployKeyChange: (appName: string) => void; startVisible?: boolean; useOtherCiToolOptionVisible?: boolean; @@ -53,7 +54,8 @@ export const ConfigureApplicationGithub = ({ const isExpanded = !!startVisible; const webhookURL = `https://webhook.${radixZoneDNS}/events/github?appName=${app.name}`; const [useOtherCiTool, setUseOtherCiTool] = useState(false); - + const [visibleRegenerateScrim, setVisibleRegenerateScrim] = + useState(false); const [regenerateSecrets, { isLoading, error }] = useRegenerateDeployKeyMutation(); const { data: secrets, refetch: refetchSecrets } = @@ -63,13 +65,14 @@ export const ConfigureApplicationGithub = ({ ); const onRegenerate = handlePromiseWithToast(async () => { + setVisibleRegenerateScrim(false); await regenerateSecrets({ appName: app.name, regenerateDeployKeyAndSecretData: { sharedSecret: nanoid() }, }).unwrap(); await refetchSecrets(); - await refetch(); - }); + await refetch?.(); + }, 'Successfully re-generated deploy key and webhook secret'); return (
@@ -130,9 +133,40 @@ export const ConfigureApplicationGithub = ({ Regenerating… ) : ( - + <> + setVisibleRegenerateScrim(false)} + isDismissable + > +
+
+ + Do you want to re-generate{' '} + deploy key and webhook secret? + + + New deploy key and webhook secret need to be put + to the GitHub repository settings + +
+ + + + + +
+
+ + )}
diff --git a/src/components/configure-application-github/style.css b/src/components/configure-application-github/style.css index 6b78d972b..1fed62dfd 100644 --- a/src/components/configure-application-github/style.css +++ b/src/components/configure-application-github/style.css @@ -34,3 +34,19 @@ filter: invert(0); } } + +.regenerate-content { + padding: var(--eds_spacing_medium); + padding-top: 0; + overflow: auto; +} +@media (min-width: 150rem) { + .regenerate-content { + margin: auto; + } +} + +.regenerate-options { + margin-top: auto; + margin-bottom: auto; +} diff --git a/src/components/create-application-form/index.tsx b/src/components/create-application-form/index.tsx index ced45a34d..cf6dc0694 100644 --- a/src/components/create-application-form/index.tsx +++ b/src/components/create-application-form/index.tsx @@ -36,7 +36,7 @@ function sanitizeName(name: string): string { } type Props = { - onCreated: (application: ApplicationRegistration) => Promise; + onCreated: (application: ApplicationRegistration) => void; }; export default function CreateApplicationForm({ onCreated }: Props) { const [acknowledgeWarnings, setAcknowledgeWarnings] = useState(false); @@ -92,8 +92,8 @@ export default function CreateApplicationForm({ onCreated }: Props) { }).unwrap(); //Only call onCreated when created without warnings, or created with ack warnings - if (response.warnings?.length === 0 || acknowledgeWarnings) { - await onCreated(response.applicationRegistration); + if (!response.warnings?.length || acknowledgeWarnings) { + onCreated(response.applicationRegistration); successToast('Saved'); } else { warningToast('Registration had warnings'); diff --git a/src/components/data-chart/index.tsx b/src/components/data-chart/index.tsx index dfe7447b0..3ece37eaa 100644 --- a/src/components/data-chart/index.tsx +++ b/src/components/data-chart/index.tsx @@ -27,6 +27,7 @@ import { useGetAvailabilityItemsQuery, useLazyGetStatusItemsQuery, } from '../../store/dynatrace-api'; +import { isNull } from 'lodash'; type GetStatusItemsFunction = ReturnType[0]; @@ -78,7 +79,7 @@ function timelineTooltip(start: Date, end: Date, status?: string): string { return ( '
' + ' Status code: ' + - ` ` + + ` ` + (status?.substring(3) ?? 'N/A') + ' ' + ' ' + @@ -174,17 +175,18 @@ function reduceAvailabilityData(data: GenericResponse) { const { timestamps, values } = data?.result?.[0]?.data[0] ?? {}; const reduced = - timestamps?.reduce>( - (carry, x, i) => [ + timestamps?.reduce>((carry, x, i) => { + if (isNull(values[i])) return carry; + + return [ ...carry, { date: new Date(x), value: values[i], description: availabilityTooltip(x, values[i]), }, - ], - [] - ) ?? []; + ]; + }, []) ?? []; return reduced; } @@ -199,7 +201,10 @@ export const AvailabilityCharts: FunctionComponent = () => { { monitorName }, { selectFromResult: ({ data, ...stats }) => { - return { data: reduceAvailabilityData(data), ...stats }; + return { + data: data ? reduceAvailabilityData(data) : undefined, + ...stats, + }; }, } ); @@ -227,13 +232,20 @@ export const AvailabilityCharts: FunctionComponent = () => { if (error) { return Failed to load chart; - } else if (isAvailabilityLoading || statusLoading) { + } + + if (isAvailabilityLoading || statusLoading) { return ( Loading ); - } else if (availabilityData.length === 0 && statusCodes.length === 0) { + } + + if ( + !availabilityData || + (availabilityData.length === 0 && statusCodes.length === 0) + ) { return ( Not enough data to display charts diff --git a/src/components/page-active-component/external-dns.tsx b/src/components/page-active-component/external-dns.tsx index 48e3f1f67..3f1d07a50 100644 --- a/src/components/page-active-component/external-dns.tsx +++ b/src/components/page-active-component/external-dns.tsx @@ -143,6 +143,9 @@ export const ExternalDNSAccordion: FunctionComponent<{ { + if (v.tls.useAutomation) { + return; + } setSelectedExternalDns(v); setVisibleScrim(true); }} diff --git a/src/components/page-configuration/change-admin-form.tsx b/src/components/page-configuration/change-admin-form.tsx index f77bc8595..ebdf3584c 100644 --- a/src/components/page-configuration/change-admin-form.tsx +++ b/src/components/page-configuration/change-admin-form.tsx @@ -13,13 +13,14 @@ import { useModifyRegistrationDetailsMutation, } from '../../store/radix-api'; import { handlePromiseWithToast } from '../global-top-nav/styled-toaster'; +import { difference } from 'lodash'; const isEqual = (a: Array, b: Array) => - JSON.stringify(a.sort()) === JSON.stringify(b.sort()); + a.length == b.length && difference(a, b).length === 0; interface Props { registration: ApplicationRegistration; - refetch: Function; + refetch?: Function; } export default function ChangeAdminForm({ registration, refetch }: Props) { const [adminAdGroup, setAdminAdGroup] = useState>(); @@ -40,7 +41,7 @@ export default function ChangeAdminForm({ registration, refetch }: Props) { }, }, }).unwrap(); - await refetch(); + await refetch?.(); setAdminAdGroup(undefined); setReaderAdGroup(undefined); } @@ -101,5 +102,5 @@ export default function ChangeAdminForm({ registration, refetch }: Props) { ChangeAdminForm.proptypes = { registration: PropTypes.object.isRequired, - refetch: PropTypes.func.isRequired, + refetch: PropTypes.func, }; diff --git a/src/components/page-configuration/change-ci-form.tsx b/src/components/page-configuration/change-ci-form.tsx index 27e41065d..56f0a80bb 100644 --- a/src/components/page-configuration/change-ci-form.tsx +++ b/src/components/page-configuration/change-ci-form.tsx @@ -17,7 +17,7 @@ import { Application } from '../../store/service-now-api'; interface Props { appName: string; configurationItem?: string; - refetch: Function; + refetch?: Function; } export const ChangeConfigurationItemForm = ({ @@ -40,7 +40,7 @@ export const ChangeConfigurationItemForm = ({ }, }).unwrap(); - await refetch(); + await refetch?.(); }); return ( @@ -93,5 +93,5 @@ export const ChangeConfigurationItemForm = ({ ChangeConfigurationItemForm.propTypes = { appName: PropTypes.string.isRequired, configurationItem: PropTypes.string, - refetch: PropTypes.func.isRequired, + refetch: PropTypes.func, }; diff --git a/src/components/page-configuration/change-config-branch-form.tsx b/src/components/page-configuration/change-config-branch-form.tsx index e50a93455..8c4950c40 100644 --- a/src/components/page-configuration/change-config-branch-form.tsx +++ b/src/components/page-configuration/change-config-branch-form.tsx @@ -20,7 +20,7 @@ import { getFetchErrorMessage } from '../../store/utils'; export interface ChangeConfigBranchFormProps { appName: string; configBranch: string; - refetch: Function; + refetch?: Function; } export const ChangeConfigBranchForm: FunctionComponent< @@ -41,7 +41,7 @@ export const ChangeConfigBranchForm: FunctionComponent< }, }).unwrap(); - await refetch(); + await refetch?.(); }); return ( diff --git a/src/components/page-configuration/change-config-file-form.tsx b/src/components/page-configuration/change-config-file-form.tsx index 85c678dfb..e7d9d5556 100644 --- a/src/components/page-configuration/change-config-file-form.tsx +++ b/src/components/page-configuration/change-config-file-form.tsx @@ -16,7 +16,7 @@ import { getFetchErrorMessage } from '../../store/utils'; export interface ChangeConfigFileFormProps { appName: string; radixConfigFullName?: string; - refetch: Function; + refetch?: Function; } const defaultConfigName = 'radixconfig.yaml'; @@ -39,7 +39,7 @@ export const ChangeConfigFileForm: FunctionComponent< }, }).unwrap(); - await refetch(); + await refetch?.(); }); return ( @@ -104,5 +104,5 @@ export const ChangeConfigFileForm: FunctionComponent< ChangeConfigFileForm.propTypes = { appName: PropTypes.string.isRequired, radixConfigFullName: PropTypes.string, - refetch: PropTypes.func.isRequired, + refetch: PropTypes.func, }; diff --git a/src/components/page-configuration/change-repository-form.tsx b/src/components/page-configuration/change-repository-form.tsx index ef347267a..dee490b6e 100644 --- a/src/components/page-configuration/change-repository-form.tsx +++ b/src/components/page-configuration/change-repository-form.tsx @@ -42,7 +42,7 @@ const DeployKey = ({ appName }: { appName: string }) => { interface Props { appName: string; repository: string; - refetch: Function; + refetch?: Function; sharedSecret: string; } export function ChangeRepositoryForm({ @@ -71,7 +71,7 @@ export function ChangeRepositoryForm({ }, }).unwrap(); - await refetch(); + await refetch?.(); }); return ( @@ -254,6 +254,6 @@ export function ChangeRepositoryForm({ ChangeRepositoryForm.propTypes = { appName: PropTypes.string.isRequired, repository: PropTypes.string.isRequired, - refetch: PropTypes.func.isRequired, + refetch: PropTypes.func, sharedSecret: PropTypes.string.isRequired, }; diff --git a/src/components/page-create-application/dev.tsx b/src/components/page-create-application/dev.tsx index 367a1baa1..9a4263d29 100644 --- a/src/components/page-create-application/dev.tsx +++ b/src/components/page-create-application/dev.tsx @@ -9,6 +9,6 @@ export default ( padding: '16px', }} > - {}} /> +
); diff --git a/src/components/page-create-application/index.tsx b/src/components/page-create-application/index.tsx index 7399fd379..f47f3658a 100644 --- a/src/components/page-create-application/index.tsx +++ b/src/components/page-create-application/index.tsx @@ -16,8 +16,7 @@ function scrollToPosition(elementRef: Element, x: number, y: number): void { elementRef.scrollTo?.(x, y); } -type Props = { refetch: Function }; -export default function PageCreateApplication({ refetch }: Props) { +export default function PageCreateApplication() { const [visibleScrim, setVisibleScrim] = useState(false); const containerRef = useRef(null); const [registration, setRegistration] = @@ -25,12 +24,12 @@ export default function PageCreateApplication({ refetch }: Props) { const onCloseScrim = () => { setVisibleScrim(false); + setRegistration(null); }; - const onCreated = async (newRegistration: ApplicationRegistration) => { - setRegistration(newRegistration); - await refetch(); + const onCreated = (newRegistration: ApplicationRegistration) => { scrollToPosition(containerRef.current, 0, 0); + setRegistration(newRegistration); }; return ( @@ -59,7 +58,6 @@ export default function PageCreateApplication({ refetch }: Props) { set up
void 0}