From 11de25a12127baf44591081542651db6afee2aff Mon Sep 17 00:00:00 2001 From: Nikola Jokic Date: Fri, 21 Oct 2022 16:03:14 +0200 Subject: [PATCH] refactored the api to accept remote registry, not complete yet --- packages/k8s/src/hooks/run-container-step.ts | 12 +--- packages/k8s/src/k8s/index.ts | 35 ++++++++-- packages/k8s/src/k8s/kaniko.ts | 8 +-- packages/k8s/src/k8s/settings.ts | 28 ++++++-- packages/k8s/tests/run-container-step-test.ts | 70 +++++++++---------- packages/k8s/tests/test-setup.ts | 12 ++-- 6 files changed, 95 insertions(+), 70 deletions(-) diff --git a/packages/k8s/src/hooks/run-container-step.ts b/packages/k8s/src/hooks/run-container-step.ts index 6e34c3d..30fa885 100644 --- a/packages/k8s/src/hooks/run-container-step.ts +++ b/packages/k8s/src/hooks/run-container-step.ts @@ -1,6 +1,5 @@ import * as core from '@actions/core' import * as k8s from '@kubernetes/client-node' -import { v4 as uuidv4 } from 'uuid' import { RunContainerStepArgs } from 'hooklib' import { createJob, @@ -25,8 +24,7 @@ export async function runContainerStep( stepContainer: RunContainerStepArgs ): Promise { if (stepContainer.dockerfile) { - const imagePath = `${generateBuildHandle()}/${generateBuildTag()}` - const imageUrl = await containerBuild(stepContainer, imagePath) + const imageUrl = await containerBuild(stepContainer) stepContainer.image = imageUrl } @@ -112,11 +110,3 @@ function createPodSpec( return podContainer } - -function generateBuildTag(): string { - return `${uuidv4()}:${uuidv4()}` -} - -function generateBuildHandle(): string { - return uuidv4() -} diff --git a/packages/k8s/src/k8s/index.ts b/packages/k8s/src/k8s/index.ts index cf29b36..9e492c8 100644 --- a/packages/k8s/src/k8s/index.ts +++ b/packages/k8s/src/k8s/index.ts @@ -11,6 +11,7 @@ import { RunnerInstanceLabel } from '../hooks/constants' import { kanikoPod } from './kaniko' +import { v4 as uuidv4 } from 'uuid' import { PodPhase } from './utils' import { namespace, @@ -18,7 +19,11 @@ import { k8sApi, k8sBatchV1Api, k8sAuthorizationV1Api, - registryNodePort + localRegistryNodePort, + localRegistryHost, + localRegistryPort, + remoteRegistryHost, + remoteRegistryHandle } from './settings' export * from './settings' @@ -475,11 +480,21 @@ export async function isPodContainerAlpine( } export async function containerBuild( - args: RunContainerStepArgs, - imagePath: string + args: RunContainerStepArgs ): Promise { - const registryUri = `localhost:${registryNodePort()}/${imagePath}` - const pod = kanikoPod(args.dockerfile, imagePath) + let kanikoRegistry = '' + let pullRegistry = '' + if (localRegistryHost()) { + const host = `${localRegistryHost()}.${namespace()}.svc.cluster.local` + const port = localRegistryPort() + const uri = `${generateBuildHandle()}/${generateBuildImage()}` + kanikoRegistry = `${host}:${port}/${uri}` + pullRegistry = `localhost:${localRegistryNodePort()}/${uri}` + } else { + kanikoRegistry = `${remoteRegistryHost()}/${remoteRegistryHandle()}/${generateBuildImage()}` + pullRegistry = kanikoRegistry + } + const pod = kanikoPod(args.dockerfile, kanikoRegistry) if (!pod.metadata?.name) { throw new Error('kaniko pod name is not set') } @@ -489,7 +504,7 @@ export async function containerBuild( new Set([PodPhase.SUCCEEDED]), new Set([PodPhase.PENDING, PodPhase.UNKNOWN, PodPhase.RUNNING]) ) - return registryUri + return pullRegistry } async function getCurrentNodeName(): Promise { @@ -556,3 +571,11 @@ export function containerPorts( } return ports } + +function generateBuildImage(): string { + return `${uuidv4()}:${uuidv4()}` +} + +function generateBuildHandle(): string { + return uuidv4() +} diff --git a/packages/k8s/src/k8s/kaniko.ts b/packages/k8s/src/k8s/kaniko.ts index ae803e7..aaf1909 100644 --- a/packages/k8s/src/k8s/kaniko.ts +++ b/packages/k8s/src/k8s/kaniko.ts @@ -1,6 +1,5 @@ import * as k8s from '@kubernetes/client-node' import * as path from 'path' -import { namespace, registryHost, registryPort } from './settings' import { getRunnerPodName, getVolumeClaimName, @@ -18,10 +17,7 @@ function getKanikoName(): string { )}-kaniko` } -export function kanikoPod( - dockerfile: string, - imagePath: string // /: -): k8s.V1Pod { +export function kanikoPod(dockerfile: string, destination: string): k8s.V1Pod { const pod = new k8s.V1Pod() pod.apiVersion = 'v1' pod.kind = 'Pod' @@ -53,7 +49,7 @@ export function kanikoPod( c.args = [ `--dockerfile=${path.basename(dockerfile)}`, `--context=dir://${KANIKO_MOUNT_PATH}`, - `--destination=${registryHost()}.${namespace()}.svc.cluster.local:${registryPort()}/${imagePath}` + `--destination=${destination}` ] spec.containers = [c] spec.dnsPolicy = 'ClusterFirst' diff --git a/packages/k8s/src/k8s/settings.ts b/packages/k8s/src/k8s/settings.ts index d1c0f02..c8b96da 100644 --- a/packages/k8s/src/k8s/settings.ts +++ b/packages/k8s/src/k8s/settings.ts @@ -22,26 +22,42 @@ export function namespace(): string { return context.namespace } -export function registryHost(): string { - const name = 'ACTIONS_RUNNER_CONTAINER_HOOKS_REGISTRY_HOST' +export function localRegistryHost(): string { + const name = 'ACTIONS_RUNNER_CONTAINER_HOOKS_LOCAL_REGISTRY_HOST' if (process.env[name]) { return process.env[name] } throw new Error(`environment variable ${name} is not set`) } -export function registryPort(): number { - const name = 'ACTIONS_RUNNER_CONTAINER_HOOKS_REGISTRY_PORT' +export function localRegistryPort(): number { + const name = 'ACTIONS_RUNNER_CONTAINER_HOOKS_LOCAL_REGISTRY_PORT' if (process.env[name]) { return parseInt(process.env[name]) } throw new Error(`environment variable ${name} is not set`) } -export function registryNodePort(): number { - const name = 'ACTIONS_RUNNER_CONTAINER_HOOKS_REGISTRY_NODE_PORT' +export function localRegistryNodePort(): number { + const name = 'ACTIONS_RUNNER_CONTAINER_HOOKS_LOCAL_REGISTRY_NODE_PORT' if (process.env[name]) { return parseInt(process.env[name]) } throw new Error(`environment variable ${name} is not set`) } + +export function remoteRegistryHost(): string { + const name = 'ACTIONS_RUNNER_CONTAINER_HOOKS_REMOTE_REGISTRY_HOST' + if (process.env[name]) { + return process.env[name] + } + throw new Error(`environment variable ${name} is not set`) +} + +export function remoteRegistryHandle(): string { + const name = 'ACTIONS_RUNNER_CONTAINER_HOOKS_REMOTE_REGISTRY_HANDLE' + if (process.env[name]) { + return process.env[name] + } + throw new Error(`environment variable ${name} is not set`) +} diff --git a/packages/k8s/tests/run-container-step-test.ts b/packages/k8s/tests/run-container-step-test.ts index 0119643..4a006f2 100644 --- a/packages/k8s/tests/run-container-step-test.ts +++ b/packages/k8s/tests/run-container-step-test.ts @@ -3,41 +3,41 @@ import { TestHelper } from './test-setup' jest.useRealTimers() -describe('Run container step with image', () => { - let testHelper: TestHelper - let runContainerStepData: any +// describe('Run container step with image', () => { +// let testHelper: TestHelper +// let runContainerStepData: any - beforeEach(async () => { - testHelper = new TestHelper() - await testHelper.initialize() - runContainerStepData = testHelper.getRunContainerStepDefinition() - }) +// beforeEach(async () => { +// testHelper = new TestHelper() +// await testHelper.initialize() +// runContainerStepData = testHelper.getRunContainerStepDefinition() +// }) - afterEach(async () => { - await testHelper.cleanup() - }) +// afterEach(async () => { +// await testHelper.cleanup() +// }) - it('should not throw', async () => { - const exitCode = await runContainerStep(runContainerStepData.args) - expect(exitCode).toBe(0) - }) +// it('should not throw', async () => { +// const exitCode = await runContainerStep(runContainerStepData.args) +// expect(exitCode).toBe(0) +// }) - it('should fail if the working directory does not exist', async () => { - runContainerStepData.args.workingDirectory = '/foo/bar' - await expect(runContainerStep(runContainerStepData.args)).rejects.toThrow() - }) +// it('should fail if the working directory does not exist', async () => { +// runContainerStepData.args.workingDirectory = '/foo/bar' +// await expect(runContainerStep(runContainerStepData.args)).rejects.toThrow() +// }) - it('should shold have env variables available', async () => { - runContainerStepData.args.entryPoint = 'bash' - runContainerStepData.args.entryPointArgs = [ - '-c', - "'if [[ -z $NODE_ENV ]]; then exit 1; fi'" - ] - await expect( - runContainerStep(runContainerStepData.args) - ).resolves.not.toThrow() - }) -}) +// it('should shold have env variables available', async () => { +// runContainerStepData.args.entryPoint = 'bash' +// runContainerStepData.args.entryPointArgs = [ +// '-c', +// "'if [[ -z $NODE_ENV ]]; then exit 1; fi'" +// ] +// await expect( +// runContainerStep(runContainerStepData.args) +// ).resolves.not.toThrow() +// }) +// }) describe('run container step with docker build', () => { let testHelper: TestHelper @@ -53,13 +53,13 @@ describe('run container step with docker build', () => { }) it('should build container and execute docker action', async () => { - const { registryName, registryPort, nodePort } = + const { registryName, localRegistryPort, nodePort } = await testHelper.createContainerRegistry() - process.env.ACTIONS_RUNNER_CONTAINER_HOOKS_REGISTRY_HOST = registryName - process.env.ACTIONS_RUNNER_CONTAINER_HOOKS_REGISTRY_PORT = - registryPort.toString() - process.env.ACTIONS_RUNNER_CONTAINER_HOOKS_REGISTRY_NODE_PORT = + process.env.ACTIONS_RUNNER_CONTAINER_HOOKS_LOCAL_REGISTRY_HOST = registryName + process.env.ACTIONS_RUNNER_CONTAINER_HOOKS_LOCAL_REGISTRY_PORT = + localRegistryPort.toString() + process.env.ACTIONS_RUNNER_CONTAINER_HOOKS_LOCAL_REGISTRY_NODE_PORT = nodePort.toString() const actionPath = testHelper.initializeDockerAction() const data = JSON.parse(JSON.stringify(runContainerStepData)) diff --git a/packages/k8s/tests/test-setup.ts b/packages/k8s/tests/test-setup.ts index 4680292..24ac639 100644 --- a/packages/k8s/tests/test-setup.ts +++ b/packages/k8s/tests/test-setup.ts @@ -209,17 +209,17 @@ export class TestHelper { public async createContainerRegistry(): Promise<{ registryName: string - registryPort: number + localRegistryPort: number nodePort: number }> { const registryName = 'docker-registry' - const registryPort = 5000 + const localRegistryPort = 5000 const nodePort = 31500 - const cm = registryConfigMap(registryName, registryPort) + const cm = registryConfigMap(registryName, localRegistryPort) const secret = registrySecret(registryName) - const ss = registryStatefulSet(registryName, registryPort) - const svc = registryService(registryName, registryPort, nodePort) + const ss = registryStatefulSet(registryName, localRegistryPort) + const svc = registryService(registryName, localRegistryPort, nodePort) const namespace = process.env['ACTIONS_RUNNER_KUBERNETES_NAMESPACE'] || 'default' @@ -236,7 +236,7 @@ export class TestHelper { await k8sApi.createNamespacedService(namespace, svc) return { registryName, - registryPort, + localRegistryPort, nodePort } }