From a5fad46f1b8fd40c7cc36631ea314bcf276a45ab Mon Sep 17 00:00:00 2001 From: YanJin Date: Tue, 14 Nov 2023 17:54:05 +0100 Subject: [PATCH] ZKUI-390: Prepare all the mutation needed for Veeam --- src/react/databrowser/objects/ObjectList.tsx | 3 +- .../objects/__tests__/ObjectList.test.tsx | 3 +- src/react/ui-elements/Veeam/VeeamConstants.ts | 41 ++ src/react/ui-elements/Veeam/mutations.test.ts | 581 ++++++++++++++++++ src/react/ui-elements/Veeam/mutations.ts | 170 +++++ 5 files changed, 795 insertions(+), 3 deletions(-) create mode 100644 src/react/ui-elements/Veeam/mutations.test.ts create mode 100644 src/react/ui-elements/Veeam/mutations.ts diff --git a/src/react/databrowser/objects/ObjectList.tsx b/src/react/databrowser/objects/ObjectList.tsx index 18bdbefa6..86b63b9a3 100644 --- a/src/react/databrowser/objects/ObjectList.tsx +++ b/src/react/databrowser/objects/ObjectList.tsx @@ -18,6 +18,7 @@ import { useQueryParams } from '../../utils/hooks'; import { useHistory, useLocation } from 'react-router-dom'; import { Box } from '@scality/core-ui/dist/next'; import { useBucketVersionning } from '../../next-architecture/domain/business/buckets'; +import { VEEAM_XML_PREFIX } from '../../ui-elements/Veeam/VeeamConstants'; type Props = { objects: List; bucketName: string; @@ -26,8 +27,6 @@ type Props = { listType: ListObjectsType; }; -export const VEEAM_XML_PREFIX = '.system-d26a9498-cb7c-4a87-a44a-8ae204f5ba6c'; - export default function ObjectList({ objects, bucketName, diff --git a/src/react/databrowser/objects/__tests__/ObjectList.test.tsx b/src/react/databrowser/objects/__tests__/ObjectList.test.tsx index 89cfec06b..2b3f450f0 100644 --- a/src/react/databrowser/objects/__tests__/ObjectList.test.tsx +++ b/src/react/databrowser/objects/__tests__/ObjectList.test.tsx @@ -5,7 +5,7 @@ import * as s3object from '../../../actions/s3object'; import * as hooks from '../../../next-architecture/domain/business/buckets'; import * as queryHooks from '../../../utils/hooks'; import { checkBox, reduxMount } from '../../../utils/testUtil'; -import ObjectList, { VEEAM_XML_PREFIX } from '../ObjectList'; +import ObjectList from '../ObjectList'; import { FIRST_FORMATTED_OBJECT, SECOND_FORMATTED_OBJECT, @@ -15,6 +15,7 @@ import { TEST_API_BASE_URL, reduxRender } from '../../../utils/testUtil'; import { screen, waitFor } from '@testing-library/react'; import { rest } from 'msw'; import { setupServer } from 'msw/node'; +import { VEEAM_XML_PREFIX } from '../../../ui-elements/Veeam/VeeamConstants'; const server = setupServer( rest.get(`${TEST_API_BASE_URL}/${BUCKET_NAME}`, (req, res, ctx) => { diff --git a/src/react/ui-elements/Veeam/VeeamConstants.ts b/src/react/ui-elements/Veeam/VeeamConstants.ts index 1e03ae607..b8afd1140 100644 --- a/src/react/ui-elements/Veeam/VeeamConstants.ts +++ b/src/react/ui-elements/Veeam/VeeamConstants.ts @@ -1,3 +1,44 @@ export const BUCKET_TAG_USECASE = 'X-Scality-Usecase'; export const VEEAMVERSION11 = 'Veeam 11'; export const VEEAMVERSION12 = 'Veeam 12'; +export type VeeamVersion = 'Veeam 12' | 'Veeam 11'; +export const VEEAM_IMMUTABLE_POLICY_NAME = 'Scality-Veeam-Immutable-Policy'; +export const GET_VEEAM_IMMUTABLE_POLICY = (bucketName: string) => + JSON.stringify({ + Version: '2012-10-17', + Statement: [ + { + Sid: 'VisualEditor0', + Effect: 'Allow', + Action: [ + 's3:GetBucketLocation', + 's3:GetObject', + 's3:PutObject', + 's3:DeleteObject', + 's3:GetBucketVersioning', + 's3:GetBucketObjectLockConfiguration', + 's3:ListBucketVersions', + 's3:GetObjectVersion', + 's3:GetObjectRetention', + 's3:GetObjectLegalHold', + 's3:PutObjectRetention', + 's3:PutObjectLegalHold', + 's3:DeleteObjectVersion', + ], + Resource: [ + `arn:aws:s3:::${bucketName}/*`, + `arn:aws:s3:::${bucketName}`, + ], + }, + { + Sid: 'VisualEditor1', + Effect: 'Allow', + Action: ['s3:ListAllMyBuckets', 's3:ListBucket'], + Resource: '*', + }, + ], + }); +export const VEEAM_XML_PREFIX = '.system-d26a9498-cb7c-4a87-a44a-8ae204f5ba6c'; +export const SYSTEM_XML_CONTENT = `"1.0""ARTESCA v1.7"truefalsefalse`; +export const GET_CAPACITY_XML_CONTENT = (capacity: number) => + `${capacity}00`; diff --git a/src/react/ui-elements/Veeam/mutations.test.ts b/src/react/ui-elements/Veeam/mutations.test.ts new file mode 100644 index 000000000..8d35bcdf9 --- /dev/null +++ b/src/react/ui-elements/Veeam/mutations.test.ts @@ -0,0 +1,581 @@ +import { rest } from 'msw'; +import { setupServer } from 'msw/node'; +import { NewWrapper, TEST_API_BASE_URL } from '../../utils/testUtil'; +import { renderHook } from '@testing-library/react-hooks'; +import { + useAttachVeeamPolicyToUserMutation, + useCreateIAMUserMutation, + useCreateS3EndpointMutation, + useCreateVeeamAccountMutation, + useCreateVeeamPolicyMutation, + useEnableSOSAPIMutation, + useSetSOSAPICapacityMutation, + useStoreVeeamUsecaseMutation, +} from './mutations'; +import { SYSTEM_XML_CONTENT, VEEAM_XML_PREFIX } from './VeeamConstants'; + +//Subject Under Testing +const SUT = jest.fn(); +const instanceId = 'a5c1ad24-27a2-4aaf-a609-26b708729363'; +const bucketName = 'Veeam-Bucket'; +const userName = 'Veeam-User'; +const locationName = 'us-east-1'; +const hostname = 's3.veeam.com'; + +const server = setupServer( + // create endpoint + rest.post( + `${TEST_API_BASE_URL}/api/v1/config/${instanceId}/endpoint`, + (req, res, ctx) => { + SUT(req.body); + if (req.body.hostname === 's3.veeam-error.com') { + return res(ctx.status(400)); + } + + return res( + ctx.status(201), + ctx.json({ + hostname, + locationName, + }), + ); + }, + ), + // createConfigurationOverlayUser + rest.post( + `${TEST_API_BASE_URL}/api/v1/config/${instanceId}/user`, + (req, res, ctx) => { + SUT(req.body); + if (req.body.Name === 'Veeam-Account-Already-Exists') { + return res(ctx.status(409)); + } + return res( + ctx.status(201), + ctx.json({ + arn: 'arn:aws:iam::749861052561:/Veeam-Account/', + canonicalId: + '9151880e827fdab2e7b3d7e686e4ea0546d207d012b877f31631affdffea47f2', + createDate: '2023-11-16T09:58:27.000Z', + email: 'veeam12@scality.com', + id: '749861052561', + userName: 'Veeam-Account', + }), + ); + }, + ), + rest.post(`${TEST_API_BASE_URL}/`, (req, res, ctx) => { + const params = new URLSearchParams(req.body); + SUT(params); + if (params.get('Action') === 'CreateUser') { + if (params.get('UserName') === 'User-Already-Exists') { + return res( + ctx.status(409), + ctx.xml( + `EntityAlreadyExistsThe request was rejected because it attempted to create a resource that already exists.b2ea3e6ea54a80d77dac`, + ), + ); + } + return res( + ctx.status(201), + ctx.xml( + `/new-userUW9BTCBLM9N473PUUIS696OHWPY6M3F0arn:aws:iam::771072028988:user/new-userb66a35b0ce42b10ceca6`, + ), + ); + } + if (params.get('Action') === 'CreatePolicy') { + if ( + params.get('PolicyName') === + 'Scality-Veeam-Immutable-Policy-Veeam-Bucket-Already-Exists' + ) { + return ( + ctx.status(400), + ctx.xml( + `ValidationErrorThe specified value is invalid.caeb1338404c9f821a2d`, + ) + ); + } + return res( + ctx.status(200), + ctx.xml( + `Scality-Veeam-Immutable-Policy-Veeam-Bucketv1WFICM40ZMHLDXLXIK2843MZODDN6VD96/arn:aws:iam::771072028988:policy/Scality-Veeam-Immutable-Policy-Veeam-Buckettrue02023-11-15T14:29:06Z2023-11-15T14:29:06Zac51e21fa045a30fbf5a`, + ), + ); + } + if (params.get('Action') === 'AttachUserPolicy') { + if (params.get('UserName') === 'Veeam-User-Error') { + return res( + ctx.status(400), + ctx.xml( + `ValidationErrorThe specified value is invalid.caeb1338404c9f821a2d`, + ), + ); + } + return res( + ctx.xml(` + + + 2e30c3c68e45ad7122f7 + + ; + `), + ); + } + }), + // putBucketTagging + rest.put(`${TEST_API_BASE_URL}/${bucketName}`, (req, res, ctx) => { + if (req.url.searchParams.get('tagging') === '') { + SUT(req.body); + return res( + ctx.xml(` + + + 2e30c3c68e45ad7122f7 + + ; + `), + ); + } + }), + rest.put(`${TEST_API_BASE_URL}/Veeam-Bucket-Error`, (req, res, ctx) => { + if (req.url.searchParams.get('tagging') === '') { + SUT(req.body); + return res( + ctx.status(400), + ctx.xml( + `f5dc66229d45a9aff4a4`, + ), + ); + } + }), + // putObject + rest.put( + `${TEST_API_BASE_URL}/${bucketName}/${VEEAM_XML_PREFIX}/system.xml`, + (req, res, ctx) => { + SUT(req.body); + return res(ctx.status(200)); + }, + ), + rest.put( + `${TEST_API_BASE_URL}/Veeam-Bucket-Error/${VEEAM_XML_PREFIX}/system.xml`, + (req, res, ctx) => { + SUT(req.body); + return res( + ctx.status(400), + ctx.xml( + `f5dc66229d45a9aff4a4`, + ), + ); + }, + ), + rest.put( + `${TEST_API_BASE_URL}/${bucketName}/${VEEAM_XML_PREFIX}/capacity.xml`, + (req, res, ctx) => { + SUT(req.body); + return res(ctx.status(200)); + }, + ), + rest.put( + `${TEST_API_BASE_URL}/Veeam-Bucket-Error/${VEEAM_XML_PREFIX}/capacity.xml`, + (req, res, ctx) => { + SUT(req.body); + return res( + ctx.status(400), + ctx.xml( + `f5dc66229d45a9aff4a4`, + ), + ); + }, + ), +); + +beforeAll(() => server.listen()); +afterEach(() => { + server.resetHandlers(); + SUT.mockClear(); +}); +afterAll(() => server.close()); + +describe('mutations', () => { + it('should handle the useCreateS3EndpointMutation', async () => { + //Setup + const { result, waitFor } = renderHook( + () => useCreateS3EndpointMutation(), + { wrapper: NewWrapper() }, + ); + //Exercise + result.current?.mutate({ + instanceId, + hostname, + locationName, + }); + //Verify + await waitFor(() => { + expect(result.current?.isSuccess).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith({ + hostname, + locationName, + isBuiltin: false, + }); + }); + it('should handle the error case of useCreateS3EndpointMutation', async () => { + //Setup + const { result, waitFor } = renderHook( + () => useCreateS3EndpointMutation(), + { wrapper: NewWrapper() }, + ); + //Exercise + const hostname = 's3.veeam-error.com'; + result.current?.mutate({ + instanceId, + hostname, + locationName, + }); + //Verify + await waitFor(() => { + expect(result.current?.isError).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith({ + hostname, + locationName, + isBuiltin: false, + }); + }); + it('should handle the useCreateVeeamAccountMutation', async () => { + //Setup + const { result, waitFor } = renderHook( + () => useCreateVeeamAccountMutation(), + { wrapper: NewWrapper() }, + ); + //Exercise + const user = { + Name: 'Veeam-Account', + email: 'veeam12@scality.com', + }; + result.current?.mutate({ user, instanceId }); + //Verify + await waitFor(() => { + expect(result.current?.isSuccess).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith({ + Name: 'Veeam-Account', + email: 'veeam12@scality.com', + userName: 'Veeam-Account', + }); + }); + it('should handle the error case of useCreateVeeamAccountMutation', async () => { + //Setup + const { result, waitFor } = renderHook( + () => useCreateVeeamAccountMutation(), + { wrapper: NewWrapper() }, + ); + //Exercise + const user = { + Name: 'Veeam-Account-Already-Exists', + email: 'veeam12@scality.com', + }; + result.current?.mutate({ user, instanceId }); + //Verify + await waitFor(() => { + expect(result.current?.isError).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith({ + Name: 'Veeam-Account-Already-Exists', + email: 'veeam12@scality.com', + userName: 'Veeam-Account-Already-Exists', + }); + }); + it('should handle the useCreateUserMutation', async () => { + //Setup + const { result, waitFor } = renderHook(() => useCreateIAMUserMutation(), { + wrapper: NewWrapper(), + }); + //Exercise + result.current.mutate({ userName }); + //Verify + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith( + new URLSearchParams({ + Action: 'CreateUser', + UserName: userName, + Version: '2010-05-08', + }), + ); + }); + it('should handle the useCreateUserMutation when user already exists', async () => { + //Setup + const { result, waitFor } = renderHook(() => useCreateIAMUserMutation(), { + wrapper: NewWrapper(), + }); + //Exercise + const userName = 'User-Already-Exists'; + result.current.mutate({ userName }); + //Verify + await waitFor(() => { + expect(result.current.isError).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith( + new URLSearchParams({ + Action: 'CreateUser', + UserName: userName, + Version: '2010-05-08', + }), + ); + }); + it('should handle the useCreateVeeamPolicyMutation', async () => { + //Setup + const { result, waitFor } = renderHook( + () => useCreateVeeamPolicyMutation(), + { wrapper: NewWrapper() }, + ); + //Exercise + result.current.mutate({ bucketName }); + //Verify + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith( + new URLSearchParams({ + Action: 'CreatePolicy', + PolicyDocument: JSON.stringify({ + Version: '2012-10-17', + Statement: [ + { + Sid: 'VisualEditor0', + Effect: 'Allow', + Action: [ + 's3:GetBucketLocation', + 's3:GetObject', + 's3:PutObject', + 's3:DeleteObject', + 's3:GetBucketVersioning', + 's3:GetBucketObjectLockConfiguration', + 's3:ListBucketVersions', + 's3:GetObjectVersion', + 's3:GetObjectRetention', + 's3:GetObjectLegalHold', + 's3:PutObjectRetention', + 's3:PutObjectLegalHold', + 's3:DeleteObjectVersion', + ], + Resource: [ + `arn:aws:s3:::${bucketName}/*`, + `arn:aws:s3:::${bucketName}`, + ], + }, + { + Sid: 'VisualEditor1', + Effect: 'Allow', + Action: ['s3:ListAllMyBuckets', 's3:ListBucket'], + Resource: '*', + }, + ], + }), + PolicyName: 'Scality-Veeam-Immutable-Policy-Veeam-Bucket', + Version: '2010-05-08', + }), + ); + }); + it('should handle the useCreateVeeamPolicyMutation when the bucket already exists', async () => { + //Setup + const { result, waitFor } = renderHook( + () => useCreateVeeamPolicyMutation(), + { wrapper: NewWrapper() }, + ); + //Exercise + const bucketName = 'Veeam-Bucket-Already-Exists'; + result.current.mutate({ bucketName }); + //Verify + await waitFor(() => { + expect(result.current.isError).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith( + new URLSearchParams({ + Action: 'CreatePolicy', + PolicyDocument: JSON.stringify({ + Version: '2012-10-17', + Statement: [ + { + Sid: 'VisualEditor0', + Effect: 'Allow', + Action: [ + 's3:GetBucketLocation', + 's3:GetObject', + 's3:PutObject', + 's3:DeleteObject', + 's3:GetBucketVersioning', + 's3:GetBucketObjectLockConfiguration', + 's3:ListBucketVersions', + 's3:GetObjectVersion', + 's3:GetObjectRetention', + 's3:GetObjectLegalHold', + 's3:PutObjectRetention', + 's3:PutObjectLegalHold', + 's3:DeleteObjectVersion', + ], + Resource: [ + `arn:aws:s3:::${bucketName}/*`, + `arn:aws:s3:::${bucketName}`, + ], + }, + { + Sid: 'VisualEditor1', + Effect: 'Allow', + Action: ['s3:ListAllMyBuckets', 's3:ListBucket'], + Resource: '*', + }, + ], + }), + PolicyName: + 'Scality-Veeam-Immutable-Policy-Veeam-Bucket-Already-Exists', + Version: '2010-05-08', + }), + ); + }); + it('should handle the useAttachVeeamPolicyToUserMutation', async () => { + //Setup + const { result, waitFor } = renderHook( + () => useAttachVeeamPolicyToUserMutation(), + { wrapper: NewWrapper() }, + ); + //Exercise + const policyArn = + 'arn:aws:iam::771072028988:policy/Scality-Veeam-Immutable-Policy-Veeam-Bucket'; + result.current.mutate({ userName, policyArn }); + //Verify + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith( + new URLSearchParams({ + Action: 'AttachUserPolicy', + PolicyArn: policyArn, + UserName: userName, + Version: '2010-05-08', + }), + ); + }); + it('should handle the useAttachVeeamPolicyToUserMutation in case of error', async () => { + //Setup + const { result, waitFor } = renderHook( + () => useAttachVeeamPolicyToUserMutation(), + { wrapper: NewWrapper() }, + ); + //Exercise + const userName = 'Veeam-User-Error'; + const policyArn = + 'arn:aws:iam::771072028988:policy/Scality-Veeam-Immutable-Policy-Veeam-Bucket'; + result.current.mutate({ userName, policyArn }); + //Verify + await waitFor(() => { + expect(result.current.isError).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith( + new URLSearchParams({ + Action: 'AttachUserPolicy', + PolicyArn: policyArn, + UserName: userName, + Version: '2010-05-08', + }), + ); + }); + it('should have the useStoreVeeamUsecaseMutation', async () => { + //Setup + const { result, waitFor } = renderHook( + () => useStoreVeeamUsecaseMutation(), + { wrapper: NewWrapper() }, + ); + //Exercise + const version = 'Veeam 12'; + result.current.mutate({ bucketName, version }); + //Verify + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + }); + const bucketTaggingXML = + 'X-Scality-UsecaseVeeam 12'; + expect(SUT).toHaveBeenCalledWith(bucketTaggingXML); + }); + it('should handle the error case of useStoreVeeamUsecaseMutation', async () => { + //Setup + const { result, waitFor } = renderHook( + () => useStoreVeeamUsecaseMutation(), + { wrapper: NewWrapper() }, + ); + //Exercise + const bucketName = 'Veeam-Bucket-Error'; + const version = 'Veeam 12'; + result.current.mutate({ bucketName, version }); + //Verify + await waitFor(() => { + expect(result.current.isError).toBe(true); + }); + const bucketTaggingXML = + 'X-Scality-UsecaseVeeam 12'; + expect(SUT).toHaveBeenCalledWith(bucketTaggingXML); + }); + it('should handle the useEnableSOSAPIMutation', async () => { + //Setup + const { result, waitFor } = renderHook(() => useEnableSOSAPIMutation(), { + wrapper: NewWrapper(), + }); + //Exercise + result.current.mutate(bucketName); + //Verify + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith(SYSTEM_XML_CONTENT); + }); + it('should handle the error case of useEnableSOSAPIMutation', async () => { + //Setup + const { result, waitFor } = renderHook(() => useEnableSOSAPIMutation(), { + wrapper: NewWrapper(), + }); + //Exercise + const bucketName = 'Veeam-Bucket-Error'; + result.current.mutate(bucketName); + //Verify + await waitFor(() => { + expect(result.current.isError).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith(SYSTEM_XML_CONTENT); + }); + it('should handle the useSetSOSAPICapacityMutation', async () => { + //Setup + const { result, waitFor } = renderHook( + () => useSetSOSAPICapacityMutation(), + { wrapper: NewWrapper() }, + ); + //Exercise + const capacity = 100; + result.current.mutate({ bucketName, capacity }); + //Verify + await waitFor(() => { + expect(result.current.isSuccess).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith( + `${capacity}00`, + ); + }); + it('should handle error case of useSetSOSAPICapacityMutation', async () => { + //Setup + const { result, waitFor } = renderHook( + () => useSetSOSAPICapacityMutation(), + { wrapper: NewWrapper() }, + ); + //Exercise + const bucketName = 'Veeam-Bucket-Error'; + const capacity = 100; + result.current.mutate({ bucketName, capacity }); + //Verify + await waitFor(() => { + expect(result.current.isError).toBe(true); + }); + expect(SUT).toHaveBeenCalledWith( + `${capacity}00`, + ); + }); +}); diff --git a/src/react/ui-elements/Veeam/mutations.ts b/src/react/ui-elements/Veeam/mutations.ts new file mode 100644 index 000000000..aa5a5951d --- /dev/null +++ b/src/react/ui-elements/Veeam/mutations.ts @@ -0,0 +1,170 @@ +import { CreateAccountRequest } from '../../../types/account'; +import { useIAMClient } from '../../IAMProvider'; +import { useManagementClient } from '../../ManagementProvider'; +import { useMutation } from 'react-query'; +import { + BUCKET_TAG_USECASE, + GET_CAPACITY_XML_CONTENT, + GET_VEEAM_IMMUTABLE_POLICY, + SYSTEM_XML_CONTENT, + VEEAM_IMMUTABLE_POLICY_NAME, + VEEAM_XML_PREFIX, + VeeamVersion, +} from './VeeamConstants'; +import { + useAssumeRoleQuery, + useS3Client, +} from '../../next-architecture/ui/S3ClientProvider'; +import { setRoleArnStored } from '../../utils/localStorage'; + +const useCreateS3EndpointMutation = () => { + const managementClient = useManagementClient(); + if (managementClient) { + return useMutation({ + mutationFn: ({ + hostname, + locationName, + instanceId, + }: { + hostname: string; + locationName: string; + instanceId: string; + }) => { + const params = { + uuid: instanceId, + endpoint: { + hostname, + locationName, + isBuiltin: false, + }, + }; + return managementClient.createConfigurationOverlayEndpoint( + params.endpoint, + params.uuid, + ); + }, + }); + } +}; + +const useCreateVeeamAccountMutation = () => { + const managementClient = useManagementClient(); + if (managementClient) { + return useMutation({ + mutationFn: ({ + user, + instanceId, + }: { + user: CreateAccountRequest; + instanceId: string; + }) => { + const params = { + uuid: instanceId, + user: { ...user, userName: user.Name }, + }; + return managementClient.createConfigurationOverlayUser( + params.user, + params.uuid, + ); + }, + }); + } +}; + +// const roleArn = `arn:aws:iam::${accountId}:role/storage-manager-role`; +const useAssumeRoleMutation = () => { + const { getQuery } = useAssumeRoleQuery(); + return useMutation({ + mutationFn: (roleArn: string) => getQuery(roleArn).queryFn(), + onSuccess(_, variables) { + setRoleArnStored(variables); + }, + }); +}; + +const useCreateIAMUserMutation = () => { + const IAMClient = useIAMClient(); + return useMutation({ + mutationFn: ({ userName }: { userName: string }) => + IAMClient.createUser(userName), + }); +}; + +const useCreateVeeamPolicyMutation = () => { + const IAMClient = useIAMClient(); + + return useMutation({ + mutationFn: ({ bucketName }: { bucketName: string }) => + IAMClient.createPolicy( + `${VEEAM_IMMUTABLE_POLICY_NAME}-${bucketName}`, + GET_VEEAM_IMMUTABLE_POLICY(bucketName), + ), + }); +}; + +const useAttachVeeamPolicyToUserMutation = () => { + const IAMClient = useIAMClient(); + return useMutation({ + mutationFn: ({ + userName, + policyArn, + }: { + userName: string; + policyArn: string; + }) => IAMClient.attachUserPolicy(userName, policyArn), + }); +}; + +const useStoreVeeamUsecaseMutation = () => { + const s3Client = useS3Client(); + return useMutation( + ({ bucketName, version }: { bucketName: string; version: VeeamVersion }) => + s3Client + .putBucketTagging({ + Bucket: bucketName, + Tagging: { TagSet: [{ Key: BUCKET_TAG_USECASE, Value: version }] }, + }) + .promise(), + ); +}; + +const useEnableSOSAPIMutation = () => { + const s3Client = useS3Client(); + + return useMutation((bucketName: string) => + s3Client + .putObject({ + Bucket: bucketName, + Key: `${VEEAM_XML_PREFIX}/system.xml`, + Body: SYSTEM_XML_CONTENT, + }) + .promise(), + ); +}; + +const useSetSOSAPICapacityMutation = () => { + const s3Client = useS3Client(); + + return useMutation( + ({ bucketName, capacity }: { bucketName: string; capacity: number }) => + s3Client + .putObject({ + Bucket: bucketName, + Key: `${VEEAM_XML_PREFIX}/capacity.xml`, + Body: GET_CAPACITY_XML_CONTENT(capacity), + }) + .promise(), + ); +}; + +export { + useCreateS3EndpointMutation, + useCreateIAMUserMutation, + useCreateVeeamAccountMutation, + useCreateVeeamPolicyMutation, + useAttachVeeamPolicyToUserMutation, + useStoreVeeamUsecaseMutation, + useEnableSOSAPIMutation, + useSetSOSAPICapacityMutation, + useAssumeRoleMutation, +};