diff --git a/src/types/privatekubectl.test.ts b/src/types/privatekubectl.test.ts index 2d4198a57..915e1231f 100644 --- a/src/types/privatekubectl.test.ts +++ b/src/types/privatekubectl.test.ts @@ -1,8 +1,8 @@ -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,15 +12,21 @@ 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` ) }) test('Should throw well defined Error on error from Azure', async () => { const errorMsg = 'An error message' jest.spyOn(exec, 'getExecOutput').mockImplementation(async () => { - return {exitCode: 1, stdout: '', stderr: errorMsg} + return { exitCode: 1, stdout: '', stderr: errorMsg } }) await expect(mockKube.executeCommand('az', 'test')).rejects.toThrow( diff --git a/src/types/privatekubectl.ts b/src/types/privatekubectl.ts index 19c80bb82..a562ade97 100644 --- a/src/types/privatekubectl.ts +++ b/src/types/privatekubectl.ts @@ -1,6 +1,6 @@ -import {Kubectl} from './kubectl' +import { Kubectl } from './kubectl' import * as minimist from 'minimist' -import {ExecOptions, ExecOutput, getExecOutput} from '@actions/exec' +import { ExecOptions, ExecOutput, getExecOutput } from '@actions/exec' import * as core from '@actions/core' import * as os from 'os' import * as fs from 'fs' @@ -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,19 @@ 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) } } @@ -80,7 +78,7 @@ export class PrivateKubectl extends Kubectl { ) } - const runObj: {logs: string; exitCode: number} = JSON.parse( + const runObj: { logs: string; exitCode: number } = JSON.parse( runOutput.stdout ) if (!silent) core.info(runObj.logs) @@ -95,48 +93,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 ') @@ -145,7 +101,7 @@ export class PrivateKubectl extends Kubectl { private createTempManifestsDirectory() { const manifestsDir = '/tmp/manifests' if (!fs.existsSync('/tmp/manifests')) { - fs.mkdirSync('/tmp/manifests', {recursive: true}) + fs.mkdirSync('/tmp/manifests', { recursive: true }) } } @@ -154,8 +110,8 @@ export class PrivateKubectl extends Kubectl { if (!fs.existsSync('/tmp/' + file)) { core.debug( '/tmp/' + - file + - ' does not exist, and therefore cannot be moved to the manifest directory' + file + + ' does not exist, and therefore cannot be moved to the manifest directory' ) } @@ -163,21 +119,63 @@ export class PrivateKubectl extends Kubectl { if (err) { core.debug( 'Could not rename ' + - '/tmp/' + - file + - ' to ' + - '/tmp/manifests/' + - file + - ' ERROR: ' + - err + '/tmp/' + + file + + ' to ' + + '/tmp/manifests/' + + file + + ' ERROR: ' + + err ) return } core.debug( "Successfully moved file '" + - file + - "' from /tmp to /tmp/manifest directory" + file + + "' from /tmp to /tmp/manifest directory" ) }) } } + +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 +}