diff --git a/.github/workflows/run-integration-tests-private.yml b/.github/workflows/run-integration-tests-private.yml index bb40438f5..5552afd65 100644 --- a/.github/workflows/run-integration-tests-private.yml +++ b/.github/workflows/run-integration-tests-private.yml @@ -43,7 +43,7 @@ jobs: run: | set +x # create cluster - az group create --location eastus --name ${{ env.NAMESPACE }} + az group create --location eastus2 --name ${{ env.NAMESPACE }} az aks create --name ${{ env.NAMESPACE }} --resource-group ${{ env.NAMESPACE }} --enable-private-cluster --generate-ssh-keys az aks get-credentials --resource-group ${{ env.NAMESPACE }} --name ${{ env.NAMESPACE }} @@ -63,6 +63,7 @@ jobs: images: nginx:1.14.2 manifests: | test/integration/manifests/test.yml + test/integration/manifests/test2.yml action: deploy private-cluster: true resource-group: ${{ env.NAMESPACE }} @@ -73,6 +74,9 @@ jobs: python test/integration/k8s-deploy-test.py private=${{ env.NAMESPACE }} namespace=${{ env.NAMESPACE }} kind=Deployment name=nginx-deployment containerName=nginx:1.14.2 labels=app:nginx,workflow:actions.github.com-k8s-deploy,workflowFriendlyName:Cluster_Integration_Tests_-_private_cluster selectorLabels=app:nginx python test/integration/k8s-deploy-test.py private=${{ env.NAMESPACE }} namespace=${{ env.NAMESPACE }} kind=Service name=nginx-service labels=workflow:actions.github.com-k8s-deploy,workflowFriendlyName:Cluster_Integration_Tests_-_private_cluster selectorLabels=app:nginx + python test/integration/k8s-deploy-test.py private=${{ env.NAMESPACE }} namespace=${{ env.NAMESPACE }} kind=Deployment name=nginx-deployment2 containerName=nginx:1.14.2 labels=app:nginx2,workflow:actions.github.com-k8s-deploy,workflowFriendlyName:Cluster_Integration_Tests_-_private_cluster selectorLabels=app:nginx2 + python test/integration/k8s-deploy-test.py private=${{ env.NAMESPACE }} namespace=${{ env.NAMESPACE }} kind=Service name=nginx-service2 labels=workflow:actions.github.com-k8s-deploy,workflowFriendlyName:Cluster_Integration_Tests_-_private_cluster selectorLabels=app:nginx2 + - name: Clean up AKS cluster if: ${{ always() }} run: | diff --git a/package-lock.json b/package-lock.json index 6d4c18d70..9d81a691c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "k8s-deploy-action", - "version": "0.0.0", + "version": "5.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "k8s-deploy-action", - "version": "0.0.0", + "version": "5.0.0", "license": "MIT", "dependencies": { "@actions/core": "^1.10.0", @@ -24,7 +24,7 @@ "@types/node": "^12.20.41", "@vercel/ncc": "^0.36.1", "jest": "^26.0.0", - "prettier": "^2.7.1", + "prettier": "^2.8.8", "ts-jest": "^26.0.0", "typescript": "3.9.5" } @@ -4648,10 +4648,11 @@ } }, "node_modules/prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin-prettier.js" }, @@ -10160,9 +10161,9 @@ "dev": true }, "prettier": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.7.1.tgz", - "integrity": "sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g==", + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true }, "pretty-format": { diff --git a/package.json b/package.json index c2e20ade3..5505351f1 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "@types/node": "^12.20.41", "@vercel/ncc": "^0.36.1", "jest": "^26.0.0", - "prettier": "^2.7.1", + "prettier": "^2.8.8", "ts-jest": "^26.0.0", "typescript": "3.9.5" } diff --git a/src/types/privatekubectl.test.ts b/src/types/privatekubectl.test.ts index 2d4198a57..3b735f25b 100644 --- a/src/types/privatekubectl.test.ts +++ b/src/types/privatekubectl.test.ts @@ -1,8 +1,12 @@ -import {PrivateKubectl} from './privatekubectl' +import { + PrivateKubectl, + extractFileNames, + replaceFileNamesWithBaseNames +} from './privatekubectl' import * as exec from '@actions/exec' describe('Private kubectl', () => { - const testString = `kubectl annotate -f test.yml,test2.yml,test3.yml -f test4.yml --filename test5.yml actions.github.com/k8s-deploy={"run":"3498366832","repository":"jaiveerk/k8s-deploy","workflow":"Minikube Integration Tests - private cluster","workflowFileName":"run-integration-tests-private.yml","jobName":"run-integration-test","createdBy":"jaiveerk","runUri":"https://github.com/jaiveerk/k8s-deploy/actions/runs/3498366832","commit":"c63b323186ea1320a31290de6dcc094c06385e75","lastSuccessRunCommit":"NA","branch":"refs/heads/main","deployTimestamp":1668787848577,"dockerfilePaths":{"nginx:1.14.2":""},"manifestsPaths":["https://github.com/jaiveerk/k8s-deploy/blob/c63b323186ea1320a31290de6dcc094c06385e75/test/integration/manifests/test.yml"],"helmChartPaths":[],"provider":"GitHub"} --overwrite --namespace test-3498366832` + const testString = `kubectl annotate -f testdir/test.yml,test2.yml,testdir/subdir/test3.yml -f test4.yml --filename test5.yml actions.github.com/k8s-deploy={"run":"3498366832","repository":"jaiveerk/k8s-deploy","workflow":"Minikube Integration Tests - private cluster","workflowFileName":"run-integration-tests-private.yml","jobName":"run-integration-test","createdBy":"jaiveerk","runUri":"https://github.com/jaiveerk/k8s-deploy/actions/runs/3498366832","commit":"c63b323186ea1320a31290de6dcc094c06385e75","lastSuccessRunCommit":"NA","branch":"refs/heads/main","deployTimestamp":1668787848577,"dockerfilePaths":{"nginx:1.14.2":""},"manifestsPaths":["https://github.com/jaiveerk/k8s-deploy/blob/c63b323186ea1320a31290de6dcc094c06385e75/test/integration/manifests/test.yml"],"helmChartPaths":[],"provider":"GitHub"} --overwrite --namespace test-3498366832` const mockKube = new PrivateKubectl( 'kubectlPath', 'namespace', @@ -12,8 +16,18 @@ describe('Private kubectl', () => { ) it('should extract filenames correctly', () => { - expect(mockKube.extractFilesnames(testString)).toEqual( - 'test.yml test2.yml test3.yml test4.yml test5.yml' + expect(extractFileNames(testString)).toEqual([ + 'testdir/test.yml', + 'test2.yml', + 'testdir/subdir/test3.yml', + 'test4.yml', + 'test5.yml' + ]) + }) + + it('should replace filenames with basenames correctly', () => { + expect(replaceFileNamesWithBaseNames(testString)).toEqual( + `kubectl annotate -f test.yml,test2.yml,test3.yml -f test4.yml --filename test5.yml actions.github.com/k8s-deploy={"run":"3498366832","repository":"jaiveerk/k8s-deploy","workflow":"Minikube Integration Tests - private cluster","workflowFileName":"run-integration-tests-private.yml","jobName":"run-integration-test","createdBy":"jaiveerk","runUri":"https://github.com/jaiveerk/k8s-deploy/actions/runs/3498366832","commit":"c63b323186ea1320a31290de6dcc094c06385e75","lastSuccessRunCommit":"NA","branch":"refs/heads/main","deployTimestamp":1668787848577,"dockerfilePaths":{"nginx:1.14.2":""},"manifestsPaths":["https://github.com/jaiveerk/k8s-deploy/blob/c63b323186ea1320a31290de6dcc094c06385e75/test/integration/manifests/test.yml"],"helmChartPaths":[],"provider":"GitHub"} --overwrite --namespace test-3498366832` ) }) diff --git a/src/types/privatekubectl.ts b/src/types/privatekubectl.ts index 19c80bb82..475a8b654 100644 --- a/src/types/privatekubectl.ts +++ b/src/types/privatekubectl.ts @@ -19,7 +19,7 @@ export class PrivateKubectl extends Kubectl { if (this.containsFilenames(kubectlCmd)) { // For private clusters, files will referenced solely by their basename - kubectlCmd = this.replaceFilnamesWithBasenames(kubectlCmd) + kubectlCmd = replaceFileNamesWithBaseNames(kubectlCmd) addFileFlag = true } @@ -43,21 +43,21 @@ export class PrivateKubectl extends Kubectl { ] if (addFileFlag) { - const filenames = this.extractFilesnames(kubectlCmd).split(' ') + const filenames = extractFileNames(kubectlCmd) const tempDirectory = process.env['runner.tempDirectory'] || os.tmpdir() + '/manifests' eo.cwd = tempDirectory privateClusterArgs.push(...['--file', '.']) - let filenamesArr = filenames[0].split(',') - for (let index = 0; index < filenamesArr.length; index++) { - const file = filenamesArr[index] - - if (!file) { - continue + for (const filename of filenames) { + try { + this.moveFileToTempManifestDir(filename) + } catch (e) { + core.debug( + `Error moving file ${filename} to temp directory: ${e}` + ) } - this.moveFileToTempManifestDir(file) } } @@ -95,49 +95,6 @@ export class PrivateKubectl extends Kubectl { } as ExecOutput } - private replaceFilnamesWithBasenames(kubectlCmd: string) { - let exFilenames = this.extractFilesnames(kubectlCmd) - let filenames = exFilenames.split(' ') - let filenamesArr = filenames[0].split(',') - - for (let index = 0; index < filenamesArr.length; index++) { - filenamesArr[index] = path.basename(filenamesArr[index]) - } - - let baseFilenames = filenamesArr.join() - - let result = kubectlCmd.replace(exFilenames, baseFilenames) - return result - } - - public extractFilesnames(strToParse: string) { - const fileNames: string[] = [] - const argv = minimist(strToParse.split(' ')) - const fArg = 'f' - const filenameArg = 'filename' - - fileNames.push(...this.extractFilesFromMinimist(argv, fArg)) - fileNames.push(...this.extractFilesFromMinimist(argv, filenameArg)) - - return fileNames.join(' ') - } - - private extractFilesFromMinimist(argv, arg: string): string[] { - if (!argv[arg]) { - return [] - } - const toReturn: string[] = [] - if (typeof argv[arg] === 'string') { - toReturn.push(...argv[arg].split(',')) - } else { - for (const value of argv[arg] as string[]) { - toReturn.push(...value.split(',')) - } - } - - return toReturn - } - private containsFilenames(str: string) { return str.includes('-f ') || str.includes('filename ') } @@ -181,3 +138,51 @@ export class PrivateKubectl extends Kubectl { }) } } + +export function replaceFileNamesWithBaseNames(kubectlCmd: string) { + let filenames = extractFileNames(kubectlCmd) + let basenames = filenames.map((filename) => path.basename(filename)) + + let result = kubectlCmd + if (filenames.length != basenames.length) { + throw Error( + 'replacing filenames with basenames, ' + + filenames.length + + ' filenames != ' + + basenames.length + + 'basenames' + ) + } + for (let index = 0; index < filenames.length; index++) { + result = result.replace(filenames[index], basenames[index]) + } + return result +} + +export function extractFileNames(strToParse: string) { + const fileNames: string[] = [] + const argv = minimist(strToParse.split(' ')) + const fArg = 'f' + const filenameArg = 'filename' + + fileNames.push(...extractFilesFromMinimist(argv, fArg)) + fileNames.push(...extractFilesFromMinimist(argv, filenameArg)) + + return fileNames +} + +export function extractFilesFromMinimist(argv, arg: string): string[] { + if (!argv[arg]) { + return [] + } + const toReturn: string[] = [] + if (typeof argv[arg] === 'string') { + toReturn.push(...argv[arg].split(',')) + } else { + for (const value of argv[arg] as string[]) { + toReturn.push(...value.split(',')) + } + } + + return toReturn +} diff --git a/test/integration/manifests/test2.yml b/test/integration/manifests/test2.yml new file mode 100644 index 000000000..29d75eb8b --- /dev/null +++ b/test/integration/manifests/test2.yml @@ -0,0 +1,33 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-deployment2 + labels: + app: nginx2 +spec: + replicas: 1 + selector: + matchLabels: + app: nginx2 + template: + metadata: + labels: + app: nginx2 + spec: + containers: + - name: nginx + image: nginx + ports: + - containerPort: 80 +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx-service2 +spec: + selector: + app: nginx2 + ports: + - protocol: TCP + port: 80 + targetPort: 80