import * as core from '@actions/core'; import { issueCommand } from '@actions/core/lib/command'; import * as path from 'path'; import * as fs from 'fs'; import * as io from '@actions/io'; import * as toolCache from '@actions/tool-cache'; import * as os from 'os'; import { ToolRunner } from "@actions/exec/lib/toolrunner"; import * as jsyaml from 'js-yaml'; import * as util from 'util'; function getKubeconfig(): string { const method = core.getInput('method', {required: true}); if (method == 'kubeconfig') { const kubeconfig = core.getInput('kubeconfig', {required : true}); core.debug("Setting context using kubeconfig"); return kubeconfig; } else if (method == 'service-account') { const clusterUrl = core.getInput('k8s-url', { required: true }); core.debug("Found clusterUrl, creating kubeconfig using certificate and token"); let k8sSecret = core.getInput('k8s-secret', {required : true}); var parsedk8sSecret = jsyaml.safeLoad(k8sSecret); let kubernetesServiceAccountSecretFieldNotPresent = 'The service acount secret yaml does not contain %s; field. Make sure that its present and try again.'; if (!parsedk8sSecret) { throw Error("The service account secret yaml specified is invalid. Make sure that its a valid yaml and try again."); } if (!parsedk8sSecret.data) { throw Error(util.format(kubernetesServiceAccountSecretFieldNotPresent, "data")); } if (!parsedk8sSecret.data.token) { throw Error(util.format(kubernetesServiceAccountSecretFieldNotPresent, "data.token")); } if (!parsedk8sSecret.data["ca.crt"]) { throw Error(util.format(kubernetesServiceAccountSecretFieldNotPresent, "data[ca.crt]")); } const certAuth = parsedk8sSecret.data["ca.crt"]; const token = Buffer.from(parsedk8sSecret.data.token, 'base64').toString(); const kubeconfigObject = { "apiVersion": "v1", "kind": "Config", "clusters": [ { "cluster": { "certificate-authority-data": certAuth, "server": clusterUrl } } ], "users": [ { "user": { "token": token } } ] }; return JSON.stringify(kubeconfigObject); } else { throw Error("Invalid method specified. Acceptable values are kubeconfig and service-account."); } } function getExecutableExtension(): string { if (os.type().match(/^Win/)) { return '.exe'; } return ''; } async function getKubectlPath() { let kubectlPath = await io.which('kubectl', false); if (!kubectlPath) { const allVersions = toolCache.findAllVersions('kubectl'); kubectlPath = allVersions.length > 0 ? toolCache.find('kubectl', allVersions[0]) : ''; if (!kubectlPath) { throw new Error('Kubectl is not installed'); } kubectlPath = path.join(kubectlPath, `kubectl${getExecutableExtension()}`); } return kubectlPath; } async function setContext(kubeconfigPath: string) { let context = core.getInput('context'); if (context) { //To use kubectl commands, the environment variable KUBECONFIG needs to be set for this step process.env['KUBECONFIG'] = kubeconfigPath; const kubectlPath = await getKubectlPath(); let toolRunner = new ToolRunner(kubectlPath, ['config', 'use-context', context]); await toolRunner.exec(); toolRunner = new ToolRunner(kubectlPath, ['config', 'current-context']); await toolRunner.exec(); } } async function run() { let kubeconfig = getKubeconfig(); const runnerTempDirectory = process.env['RUNNER_TEMP']; // Using process.env until the core libs are updated const kubeconfigPath = path.join(runnerTempDirectory, `kubeconfig_${Date.now()}`); core.debug(`Writing kubeconfig contents to ${kubeconfigPath}`); fs.writeFileSync(kubeconfigPath, kubeconfig); fs.chmodSync(kubeconfigPath, '600'); issueCommand('set-env', { name: 'KUBECONFIG' }, kubeconfigPath); console.log('KUBECONFIG environment variable is set'); await setContext(kubeconfigPath); } run().catch(core.setFailed);