mirror of
https://github.com/grafana/grafana.git
synced 2025-07-31 06:22:56 +08:00

* Update the generator to include version * Add versioned APIs * Update imports * Prettier
69 lines
2.5 KiB
TypeScript
69 lines
2.5 KiB
TypeScript
import { useCallback } from 'react';
|
|
|
|
import {
|
|
RepositorySpec,
|
|
useCreateRepositoryMutation,
|
|
useCreateRepositoryTestMutation,
|
|
useReplaceRepositoryMutation,
|
|
} from 'app/api/clients/provisioning/v0alpha1';
|
|
|
|
export function useCreateOrUpdateRepository(name?: string) {
|
|
const [create, createRequest] = useCreateRepositoryMutation();
|
|
const [update, updateRequest] = useReplaceRepositoryMutation();
|
|
const [testConfig, testRequest] = useCreateRepositoryTestMutation();
|
|
|
|
const updateOrCreate = useCallback(
|
|
async (data: RepositorySpec) => {
|
|
// First test the config and wait for the result
|
|
// unwrap will throw an error if the test fails
|
|
await testConfig({
|
|
// HACK: we need to provide a name to the test configuration
|
|
name: name || 'new',
|
|
body: {
|
|
spec: data,
|
|
},
|
|
}).unwrap();
|
|
|
|
// If test passes, proceed with create/update
|
|
if (name) {
|
|
return update({
|
|
name,
|
|
repository: {
|
|
metadata: {
|
|
name,
|
|
// TODO? -- replace with patch spec, so the rest of the metadata is not replaced?
|
|
// Can that support optimistic locking? (eg, make sure the RV is the same?)
|
|
finalizers: ['cleanup', 'remove-orphan-resources'],
|
|
},
|
|
spec: data,
|
|
},
|
|
});
|
|
}
|
|
return create({ repository: { metadata: generateRepositoryMetadata(data), spec: data } });
|
|
},
|
|
[create, name, update, testConfig]
|
|
);
|
|
|
|
return [updateOrCreate, name ? updateRequest : createRequest, testRequest] as const;
|
|
}
|
|
|
|
const generateRepositoryMetadata = (data: RepositorySpec) => {
|
|
// We don't know for sure that we can use a normalised name. If we can't, we'll ask the server to generate one for us.
|
|
const normalisedName = data.title.toLowerCase().replaceAll(/[^a-z0-9\-_]+/g, '');
|
|
|
|
if (
|
|
crypto.randomUUID && // we might not be in a secure context
|
|
normalisedName && // we need a non-empty string before we check the first character
|
|
normalisedName.charAt(0) >= 'a' && // required to start with a letter to be a valid k8s name
|
|
normalisedName.charAt(0) <= 'z' &&
|
|
normalisedName.replaceAll(/[^a-z]/g, '').length >= 3 // must look sensible to a human
|
|
) {
|
|
// We still want a suffix, to avoid name collisions.
|
|
const randomBit = crypto.randomUUID().substring(0, 7);
|
|
const shortenedName = normalisedName.substring(0, 63 - 1 - randomBit.length);
|
|
return { name: `${shortenedName}-${randomBit}` };
|
|
} else {
|
|
return { generateName: 'r' };
|
|
}
|
|
};
|