cockpitApi: get worker config
Add a query to load the `/etc/osbuild-worker/osbuild-worker.toml` config and use this to set the state of the `cloudConfig` store slice.
This commit is contained in:
parent
d7945a458a
commit
ecc1c2c8cd
4 changed files with 113 additions and 5 deletions
|
|
@ -1,17 +1,62 @@
|
||||||
import React from 'react';
|
import React, { useCallback, useEffect } from 'react';
|
||||||
|
|
||||||
import { PageSection, Wizard, WizardStep } from '@patternfly/react-core';
|
import { PageSection, Wizard, WizardStep } from '@patternfly/react-core';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
|
|
||||||
import { AWSConfig } from './AWSConfig';
|
import { AWSConfig } from './AWSConfig';
|
||||||
|
import { isAwsStepValid } from './validators';
|
||||||
|
|
||||||
|
import {
|
||||||
|
changeAWSBucketName,
|
||||||
|
changeAWSCredsPath,
|
||||||
|
reinitializeAWSConfig,
|
||||||
|
} from '../../store/cloudProviderConfigSlice';
|
||||||
|
import { useGetWorkerConfigQuery } from '../../store/cockpit/cockpitApi';
|
||||||
|
import { AWSWorkerConfig } from '../../store/cockpit/types';
|
||||||
|
import { useAppDispatch } from '../../store/hooks';
|
||||||
import { resolveRelPath } from '../../Utilities/path';
|
import { resolveRelPath } from '../../Utilities/path';
|
||||||
import { ImageBuilderHeader } from '../sharedComponents/ImageBuilderHeader';
|
import { ImageBuilderHeader } from '../sharedComponents/ImageBuilderHeader';
|
||||||
|
|
||||||
export const CloudProviderConfig = () => {
|
export const CloudProviderConfig = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
const handleClose = () => navigate(resolveRelPath(''));
|
const handleClose = () => navigate(resolveRelPath(''));
|
||||||
|
|
||||||
|
const { data, error } = useGetWorkerConfigQuery({});
|
||||||
|
|
||||||
|
const initAWSConfig = useCallback(
|
||||||
|
(config: AWSWorkerConfig | undefined) => {
|
||||||
|
if (!config) {
|
||||||
|
dispatch(reinitializeAWSConfig());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { bucket, credentials } = config;
|
||||||
|
if (bucket && bucket !== '') {
|
||||||
|
dispatch(changeAWSBucketName(bucket));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (credentials && credentials !== '') {
|
||||||
|
dispatch(changeAWSCredsPath(credentials));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[dispatch]
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
initAWSConfig(data?.aws);
|
||||||
|
}, [data, initAWSConfig]);
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
// TODO: improve error alert
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
There was an error reading the `/etc/osbuild-worker/osbuild-worker.toml`
|
||||||
|
config file
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<ImageBuilderHeader inWizard={true} />
|
<ImageBuilderHeader inWizard={true} />
|
||||||
|
|
@ -22,6 +67,7 @@ export const CloudProviderConfig = () => {
|
||||||
id="aws-config"
|
id="aws-config"
|
||||||
footer={{
|
footer={{
|
||||||
nextButtonText: 'Submit',
|
nextButtonText: 'Submit',
|
||||||
|
isNextDisabled: !isAwsStepValid(config),
|
||||||
isBackDisabled: true,
|
isBackDisabled: true,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,37 @@
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
|
||||||
export const isAwsBucketValid = (bucket: string): boolean => {
|
import { AWSWorkerConfig } from '../../../store/cockpit/types';
|
||||||
|
|
||||||
|
export const isAwsBucketValid = (bucket?: string): boolean => {
|
||||||
|
if (!bucket || bucket === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const regex = /^[a-z0-9](?:[a-z0-9]|[-.](?=[a-z0-9])){1,61}[a-z0-9]$/;
|
const regex = /^[a-z0-9](?:[a-z0-9]|[-.](?=[a-z0-9])){1,61}[a-z0-9]$/;
|
||||||
return regex.test(bucket);
|
return regex.test(bucket);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isAwsCredsPathValid = (credsPath: string): boolean => {
|
export const isAwsCredsPathValid = (credsPath?: string): boolean => {
|
||||||
|
if (!credsPath || credsPath === '') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const validPathPattern = /^(\/[^/\0]*)+\/?$/;
|
const validPathPattern = /^(\/[^/\0]*)+\/?$/;
|
||||||
return path.isAbsolute(credsPath) && validPathPattern.test(credsPath);
|
return path.isAbsolute(credsPath) && validPathPattern.test(credsPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const isAwsStepValid = (
|
||||||
|
config: AWSWorkerConfig | undefined
|
||||||
|
): boolean => {
|
||||||
|
if (!config) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.bucket && !config.credentials) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
isAwsBucketValid(config.bucket) && isAwsCredsPathValid(config.credentials)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,16 @@ export const initialState: CloudProviderConfigState = {
|
||||||
aws: {},
|
aws: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const selectAWSConfig = (state: RootState) => {
|
||||||
|
if (Object.keys(state.cloudConfig.aws).length === 0) {
|
||||||
|
// just return undefined since the config is empty
|
||||||
|
// and we don't want to save `[aws]` header to the
|
||||||
|
// worker config file with no body
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return state.cloudConfig.aws;
|
||||||
|
};
|
||||||
|
|
||||||
export const selectAWSBucketName = (state: RootState) => {
|
export const selectAWSBucketName = (state: RootState) => {
|
||||||
return state.cloudConfig.aws.bucket;
|
return state.cloudConfig.aws.bucket;
|
||||||
};
|
};
|
||||||
|
|
@ -20,6 +30,9 @@ export const cloudProviderConfigSlice = createSlice({
|
||||||
name: 'cloudConfig',
|
name: 'cloudConfig',
|
||||||
initialState,
|
initialState,
|
||||||
reducers: {
|
reducers: {
|
||||||
|
reinitializeAWSConfig: (state) => {
|
||||||
|
state.aws = {};
|
||||||
|
},
|
||||||
changeAWSBucketName: (state, action: PayloadAction<string>) => {
|
changeAWSBucketName: (state, action: PayloadAction<string>) => {
|
||||||
state.aws.bucket = action.payload;
|
state.aws.bucket = action.payload;
|
||||||
},
|
},
|
||||||
|
|
@ -29,5 +42,8 @@ export const cloudProviderConfigSlice = createSlice({
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const { changeAWSBucketName, changeAWSCredsPath } =
|
export const {
|
||||||
cloudProviderConfigSlice.actions;
|
reinitializeAWSConfig,
|
||||||
|
changeAWSBucketName,
|
||||||
|
changeAWSCredsPath,
|
||||||
|
} = cloudProviderConfigSlice.actions;
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import { v4 as uuidv4 } from 'uuid';
|
||||||
// the same unix socket. This allows us to split out the code a little
|
// the same unix socket. This allows us to split out the code a little
|
||||||
// bit so that the `cockpitApi` doesn't become a monolith.
|
// bit so that the `cockpitApi` doesn't become a monolith.
|
||||||
import { contentSourcesApi } from './contentSourcesApi';
|
import { contentSourcesApi } from './contentSourcesApi';
|
||||||
|
import type { WorkerConfigResponse } from './types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
mapHostedToOnPrem,
|
mapHostedToOnPrem,
|
||||||
|
|
@ -584,6 +585,24 @@ export const cockpitApi = contentSourcesApi.injectEndpoints({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
getWorkerConfig: builder.query<WorkerConfigResponse, unknown>({
|
||||||
|
queryFn: async () => {
|
||||||
|
try {
|
||||||
|
const config = await cockpit
|
||||||
|
.file('/etc/osbuild-worker/osbuild-worker.toml')
|
||||||
|
.read();
|
||||||
|
|
||||||
|
return { data: TOML.parse(config) };
|
||||||
|
} catch (error) {
|
||||||
|
// no worker file error message
|
||||||
|
if (error.message === 'input is null') {
|
||||||
|
return { data: {} };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { error };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
// since we are inheriting some endpoints,
|
// since we are inheriting some endpoints,
|
||||||
|
|
@ -607,4 +626,5 @@ export const {
|
||||||
useGetComposesQuery,
|
useGetComposesQuery,
|
||||||
useGetBlueprintComposesQuery,
|
useGetBlueprintComposesQuery,
|
||||||
useGetComposeStatusQuery,
|
useGetComposeStatusQuery,
|
||||||
|
useGetWorkerConfigQuery,
|
||||||
} = cockpitApi;
|
} = cockpitApi;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue