diff --git a/packages/backend-common/src/util/KubernetesContainerRunner.test.ts b/packages/backend-common/src/util/KubernetesContainerRunner.test.ts index 52af488d66..b978855567 100644 --- a/packages/backend-common/src/util/KubernetesContainerRunner.test.ts +++ b/packages/backend-common/src/util/KubernetesContainerRunner.test.ts @@ -32,20 +32,6 @@ describe('KubernetesContainerRunner', () => { const kubeConfig = new KubeConfig(); kubeConfig.loadFromDefault(); const name = 'kube-runner'; - const api = kubeConfig.makeApiClient(CoreV1Api); - const authApi = kubeConfig.makeApiClient(RbacAuthorizationV1Api); - - beforeAll(async () => { - await api.createNamespace({ - metadata: { - name: 'test', - }, - }); - }); - - afterAll(async () => { - await api.deleteNamespace('test'); - }); it('should throw error when no namespace is configured', () => { const testConfig = new KubeConfig(); @@ -196,13 +182,58 @@ describe('KubernetesContainerRunner', () => { ); }); - it('should fail when watch fails', async () => { - await api.createNamespacedServiceAccount('test', { + describe('with namespace test', () => { + const api = kubeConfig.makeApiClient(CoreV1Api); + const authApi = kubeConfig.makeApiClient(RbacAuthorizationV1Api); + + beforeAll(async () => { + await api.createNamespace({ + metadata: { + name: 'test', + }, + }); + }); + afterAll(async () => { + await api.deleteNamespace('test'); + }); + + it('should fail when watch fails', async () => { + const testConfig = await givenAServiceAccountThatCannotWatchPods( + api, + authApi, + kubeConfig, + ); + const options: KubernetesContainerRunnerOptions = { + kubeConfig: testConfig, + name, + namespace: 'test', + }; + const containerRunner = new KubernetesContainerRunner(options); + const runOptions: RunContainerOptions = { + imageName: 'golang:1.17', + args: ['echo', 'hello world'], + }; + await expect( + containerRunner.runContainer(runOptions), + ).rejects.toThrowError( + 'Kubernetes watch request failed with the following error message: Error: Forbidden', + ); + }); + }); +}); + +async function givenAServiceAccountThatCannotWatchPods( + api: CoreV1Api, + authApi: RbacAuthorizationV1Api, + kubeConfig: KubeConfig, +) { + await Promise.all([ + api.createNamespacedServiceAccount('test', { metadata: { name: 'test', }, - }); - await authApi.createNamespacedRole('test', { + }), + authApi.createNamespacedRole('test', { metadata: { name: 'test', }, @@ -213,8 +244,8 @@ describe('KubernetesContainerRunner', () => { resources: ['jobs'], }, ], - }); - await authApi.createNamespacedRoleBinding('test', { + }), + authApi.createNamespacedRoleBinding('test', { metadata: { name: 'test', }, @@ -229,38 +260,26 @@ describe('KubernetesContainerRunner', () => { kind: 'Role', name: 'test', }, - }); - const token = ( - await api.createNamespacedServiceAccountToken('test', 'test', { - spec: { - audiences: [], - }, - }) - ).body.status?.token; - const testConfig = new KubeConfig(); - testConfig.loadFromDefault(); - testConfig.addUser({ - name: 'test', - token, - }); - testConfig.addContext({ - name: 'test', - cluster: kubeConfig.getCurrentCluster()!.name, - user: 'test', - }); - testConfig.setCurrentContext('test'); - const options: KubernetesContainerRunnerOptions = { - kubeConfig: testConfig, - name, - namespace: 'test', - }; - const containerRunner = new KubernetesContainerRunner(options); - const runOptions: RunContainerOptions = { - imageName: 'golang:1.17', - args: ['echo', 'hello world'], - }; - await expect(containerRunner.runContainer(runOptions)).rejects.toThrowError( - 'Kubernetes watch request failed with the following error message: Error: Forbidden', - ); + }), + ]); + const token = ( + await api.createNamespacedServiceAccountToken('test', 'test', { + spec: { + audiences: [], + }, + }) + ).body.status?.token; + const testConfig = new KubeConfig(); + testConfig.loadFromDefault(); + testConfig.addUser({ + name: 'test', + token, }); -}); + testConfig.addContext({ + name: 'test', + cluster: kubeConfig.getCurrentCluster()!.name, + user: 'test', + }); + testConfig.setCurrentContext('test'); + return testConfig; +} diff --git a/packages/backend-common/src/util/KubernetesContainerRunner.ts b/packages/backend-common/src/util/KubernetesContainerRunner.ts index e4393c1bd9..3cdc44144a 100644 --- a/packages/backend-common/src/util/KubernetesContainerRunner.ts +++ b/packages/backend-common/src/util/KubernetesContainerRunner.ts @@ -150,6 +150,7 @@ export class KubernetesContainerRunner implements ContainerRunner { const taskId = uuid(); + // TODO find a way to merge recursively const mergedPodTemplate: V1PodTemplateSpec = { metadata: { ...{ diff --git a/yarn.lock b/yarn.lock index 6309737e43..ecde048ee8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7365,7 +7365,7 @@ resolved "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz#7ee330ba7caafb98090bece86a5ee44115904c2c" integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== -"@types/react-dom@*", "@types/react-dom@<18.0.0": +"@types/react-dom@*", "@types/react-dom@<18.0.0", "@types/react-dom@^17": version "17.0.17" resolved "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.17.tgz#2e3743277a793a96a99f1bf87614598289da68a1" integrity sha512-VjnqEmqGnasQKV0CWLevqMTXBYG9GbwuE6x3VetERLh0cq2LTptFE73MrQi2S7GkKXCf2GgwItB/melLnxfnsg== @@ -26588,7 +26588,7 @@ ws@^7.3.1, ws@^7.4.6: resolved "https://registry.npmjs.org/ws/-/ws-7.5.7.tgz#9e0ac77ee50af70d58326ecff7e85eb3fa375e67" integrity sha512-KMvVuFzpKBuiIXW3E4u3mySRO2/mCHSyZDJQM5NQ9Q9KHWHWh0NHgfbRMLLrceUK5qAL4ytALJbpRMjixFZh8A== -ws@^8.3.0: +ws@^8.0.0, ws@^8.3.0: version "8.8.1" resolved "https://registry.npmjs.org/ws/-/ws-8.8.1.tgz#5dbad0feb7ade8ecc99b830c1d77c913d4955ff0" integrity sha512-bGy2JzvzkPowEJV++hF07hAD6niYSr0JzBNo/J29WsB57A2r7Wlc1UFcTR9IzrPvuNVO4B8LGqF8qcpsVOhJCA==