Skip to content

Instantly share code, notes, and snippets.

@justinm
Created July 18, 2019 23:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save justinm/a8efe68bc8cd07462d9b93b9c05e25c6 to your computer and use it in GitHub Desktop.
Save justinm/a8efe68bc8cd07462d9b93b9c05e25c6 to your computer and use it in GitHub Desktop.
Deploy AWS EKS via Lambda
/**
* The KubeConfig must be passed in via the ENV variable KUBECONFIG.
*/
const AWS = require('aws-sdk')
const tmp = require('tmp')
const unzip = require('unzip')
const fs = require('fs')
const child_process = require('child_process')
exports.handler = async (event, context) => {
const codepipeline = new AWS.CodePipeline()
const job = event["CodePipeline.job"]
const jobId = job.id
return new Promise((resolve, reject) => {
console.log(JSON.stringify(event))
/* Helper methods */
const putJobSuccess = (message) => {
console.log('JobSuccess:', message)
codepipeline.putJobSuccessResult({
jobId: jobId
}, (err, data) => {
if (err) {
console.error('JobSuccess: failed to update', err);
context.fail(err);
reject(err)
} else {
console.log("JobSuccess: updated");
context.succeed(message)
resolve(data)
}
})
};
const putJobFailure = (message) => {
console.log('JobFailure:', message)
codepipeline.putJobFailureResult({
jobId: jobId,
failureDetails: {
message: JSON.stringify(message),
type: 'JobFailed',
externalExecutionId: context.invokeid
}
}, (err, data) => {
if (err) {
console.error('JobFailure: failed to updatee', err);
context.fail(err);
reject(err)
} else {
console.log("JobFailure: updated");
resolve(data)
}
})
};
try {
const artifact = job.data.inputArtifacts.filter((j) => j.name === "dashboard_images")[0]
const s3 = new AWS.S3(job.data.artifactCredentials)
const extractTo = tmp.dirSync()
let params;
try {
params = JSON.parse(job.data.actionConfiguration.configuration.UserParameters)
} catch (e) {
params = {};
}
console.log(`Downloading artifact from s3://${artifact.location.s3Location.bucketName}/${artifact.location.s3Location.objectKey}`)
const stream = s3.getObject({
Bucket: artifact.location.s3Location.bucketName,
Key: artifact.location.s3Location.objectKey,
}).createReadStream().pipe(unzip.Extract({path: extractTo.name}))
stream.on('error', function(err) {
putJobFailure(err.message)
})
stream.on('close', () => {
const kubePath = `${extractTo.name}/.kubeconfig`
console.log(`Writing KUBECONFIG to ${kubePath}`)
const cipherText = { CiphertextBlob: new Buffer(process.env.KUBECONFIG, 'base64') };
const kms = new AWS.KMS();
kms.decrypt(cipherText, (err, data) => {
if (err) {
console.log('Decrypt error:', err);
putJobFailure(err.message)
}
fs.writeFileSync(kubePath, data.Plaintext.toString())
console.log("PATH is", process.env.PATH, __dirname)
const configPath = `${extractTo.name}/build/${params.environment}`
console.log(`Applying Kubernetes configuration at ${configPath}`)
let output
try {
output = child_process.execFileSync('./kubectl', ['apply', `-f${configPath}`, `-n${params.environment}`], {
env: {
KUBECONFIG: `${kubePath}`,
PATH: `${process.env.PATH}:${__dirname}`,
}
})
console.log(output.toString())
putJobSuccess("success")
} catch (e) {
console.log(output)
putJobFailure(e.message)
}
})
})
} catch (e) {
putJobFailure(e.message)
}
});
}
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: ${EKS_CA}
server: ${EKS_CLUSTER_HOST}
name: ${EKS_CLUSTER_NAME}
contexts:
- context:
cluster: ${EKS_CLUSTER_NAME}
namespace: default
user: ${EKS_CLUSTER_USER_NAME}
name: ${EKS_CLUSTER_USER_NAME}
current-context: ${EKS_CLUSTER_USER_NAME}
kind: Config
preferences: {}
users:
- name: ${EKS_CLUSTER_USER_NAME}
user:
token: ${TOKEN}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment