diff --git a/src/otomi-stack.ts b/src/otomi-stack.ts index d6346828..a28a9bed 100644 --- a/src/otomi-stack.ts +++ b/src/otomi-stack.ts @@ -1,4 +1,4 @@ -import { CoreV1Api, KubeConfig, User as k8sUser, V1ObjectReference } from '@kubernetes/client-node' +import { CoreV1Api, User as k8sUser, KubeConfig, V1ObjectReference } from '@kubernetes/client-node' import Debug from 'debug' import { getRegions, ObjectStorageKeyRegions } from '@linode/api-v4' @@ -131,7 +131,7 @@ import { import { getAplObjectFromV1, getV1MergeObject, getV1ObjectFromApl } from './utils/manifests' import { getSealedSecretsPEM, sealedSecretManifest } from './utils/sealedSecretUtils' import { getKeycloakUsers, isValidUsername } from './utils/userUtils' -import { ObjectStorageClient } from './utils/wizardUtils' +import { defineClusterId, ObjectStorageClient } from './utils/wizardUtils' import { fetchChartYaml, fetchWorkloadCatalog, NewHelmChartValues, sparseCloneChart } from './utils/workloadUtils' interface ExcludedApp extends App { @@ -301,12 +301,11 @@ export default class OtomiStack { const createdBuckets = [] as Array if (data?.apiToken && data?.regionId) { const { cluster } = this.getSettings(['cluster']) - let lkeClusterId: null | number = null - if (cluster?.name?.includes('aplinstall')) { - lkeClusterId = Number(cluster?.name?.replace('aplinstall', '')) - } else if (lkeClusterId === null) { - return { status: 'error', errorMessage: 'Cluster ID is not found in the cluster name.' } + let lkeClusterId: undefined | string = defineClusterId(cluster?.name) + if (lkeClusterId === undefined) { + return { status: 'error', errorMessage: 'Cluster name is not found.' } } + const bucketNames = { cnpg: `lke${lkeClusterId}-cnpg`, harbor: `lke${lkeClusterId}-harbor`, diff --git a/src/utils/wizardUtils.test.ts b/src/utils/wizardUtils.test.ts index 9c8388d0..4c2eeaf4 100644 --- a/src/utils/wizardUtils.test.ts +++ b/src/utils/wizardUtils.test.ts @@ -15,11 +15,13 @@ jest.mock('@linode/api-v4', () => ({ import { createBucket, createObjectStorageKeys, ObjectStorageKey, setToken } from '@linode/api-v4' import { OtomiError } from 'src/error' -import { ObjectStorageClient } from './wizardUtils' +import { ObjWizard } from 'src/otomi-models' +import OtomiStack from 'src/otomi-stack' +import { defineClusterId, ObjectStorageClient } from './wizardUtils' describe('ObjectStorageClient', () => { let client: ObjectStorageClient - const clusterId = 12345 + let clusterId: string | undefined = '12345' beforeEach(() => { client = new ObjectStorageClient('test-token') @@ -35,7 +37,16 @@ describe('ObjectStorageClient', () => { describe('createObjectStorageBucket', () => { const label = 'test-bucket' const region = 'us-east' + let otomiStack: OtomiStack + const domainSuffix = 'dev.linode-apl.net' + beforeEach(async () => { + otomiStack = new OtomiStack() + await otomiStack.init() + }) + afterEach(() => { + jest.restoreAllMocks() + }) it('should successfully create bucket', async () => { const mockResponse = { label: 'test-bucket' } ;(createBucket as jest.Mock).mockResolvedValue(mockResponse) @@ -81,6 +92,38 @@ describe('ObjectStorageClient', () => { // @ts-ignore expect(result.code).toBe(500) }) + + test('should return lkeClusterId', () => { + const settings = { cluster: { name: 'cluster-123' } } + clusterId = defineClusterId(settings.cluster.name) + + expect(clusterId).toBe('cluster-123') + }) + + test('should return stripped down clusterId when name does not include prefix', () => { + const settings = { cluster: { name: 'aplinstall123' } } + clusterId = defineClusterId(settings.cluster.name) + + expect(clusterId).toBe('123') + }) + + test('should return undefined when cluster name is undefined', () => { + const settings: any = { cluster: {} } + clusterId = defineClusterId(settings.cluster?.name) + + expect(clusterId).toBe(undefined) + }) + + test('should return error when cluster name is undefined', async () => { + const data = { apiToken: 'some-token', regionId: 'us-east', label: 'my-cluster' } + jest.spyOn(otomiStack, 'getSettings').mockReturnValue({ + cluster: { domainSuffix, provider: 'linode' }, + } as any) + const result: ObjWizard = await otomiStack.createObjWizard(data) + + expect(result.status).toBe('error') + expect(result.errorMessage).toBe('Cluster name is not found.') + }) }) describe('createObjectStorageKey', () => { @@ -103,7 +146,7 @@ describe('ObjectStorageClient', () => { } ;(createObjectStorageKeys as jest.Mock).mockResolvedValue(mockResponse) - const result = await client.createObjectStorageKey(clusterId, region, bucketNames) + const result = await client.createObjectStorageKey(clusterId!, region, bucketNames) expect(createObjectStorageKeys).toHaveBeenCalledWith({ label: `lke${clusterId}-key-1704110400000`, @@ -125,7 +168,7 @@ describe('ObjectStorageClient', () => { } ;(createObjectStorageKeys as jest.Mock).mockRejectedValue(mockError) - const result = await client.createObjectStorageKey(clusterId, region, bucketNames) + const result = await client.createObjectStorageKey(clusterId!, region, bucketNames) expect(result).toBeInstanceOf(OtomiError) // @ts-ignore expect(result.publicMessage).toBe('Your OAuth token is not authorized to use this endpoint') diff --git a/src/utils/wizardUtils.ts b/src/utils/wizardUtils.ts index 66944426..57c448b8 100644 --- a/src/utils/wizardUtils.ts +++ b/src/utils/wizardUtils.ts @@ -28,7 +28,7 @@ export class ObjectStorageClient { } public async createObjectStorageKey( - lkeClusterId: number, + lkeClusterId: string, region: string, bucketNames: string[], ): Promise | OtomiError> { @@ -56,3 +56,8 @@ export class ObjectStorageClient { } } } +// define cluster id based on cluster name +export function defineClusterId(clusterName: string | undefined): string | undefined { + if (!clusterName) return undefined + return clusterName.replace('aplinstall', '') +}