@rlyle1179/serverless-aws-batch 1.1.19 → 1.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/settings.json +5 -0
- package/LICENSE +21 -21
- package/README.md +362 -362
- package/index.js +66 -66
- package/lib/awscli.js +107 -107
- package/lib/batchenvironment.js +418 -418
- package/lib/batchtask.js +390 -390
- package/lib/docker.js +139 -139
- package/lib/ecr.js +29 -29
- package/lib/generateCoreTemplate.js +120 -120
- package/lib/schedule.js +90 -90
- package/package.json +35 -35
package/lib/docker.js
CHANGED
|
@@ -1,139 +1,139 @@
|
|
|
1
|
-
const BbPromise = require('bluebird');
|
|
2
|
-
const { spawnSync } = require('child_process');
|
|
3
|
-
const _ = require('lodash');
|
|
4
|
-
const fse = require('fs-extra');
|
|
5
|
-
const path = require('path');
|
|
6
|
-
const util = require('util');
|
|
7
|
-
const { getDockerLoginToECRCommand } = require('./awscli');
|
|
8
|
-
|
|
9
|
-
const DOCKER_TAG = `${Date.now()}`;
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @returns {string} "<ECR Repo Name>:latest"
|
|
13
|
-
*/
|
|
14
|
-
function getDockerImageName() {
|
|
15
|
-
return `${this.provider.naming.getECRRepositoryURL()}:${DOCKER_TAG}`;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Helper function to run a docker command
|
|
20
|
-
* @param {string[]} options
|
|
21
|
-
* @param {string} cwd Current working directory
|
|
22
|
-
* @return {Object}
|
|
23
|
-
*/
|
|
24
|
-
function dockerCommand(options, cwd = null, stdio = null) {
|
|
25
|
-
const cmd = 'docker';
|
|
26
|
-
var spawnOptions = {
|
|
27
|
-
encoding: 'utf-8'
|
|
28
|
-
}
|
|
29
|
-
if (cwd != null) {
|
|
30
|
-
spawnOptions.cwd = cwd;
|
|
31
|
-
}
|
|
32
|
-
if (stdio != null) {
|
|
33
|
-
spawnOptions.stdio = stdio;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
//console.error("dockerCommand:", options, spawnOptions);
|
|
37
|
-
const ps = spawnSync(cmd, options, spawnOptions);
|
|
38
|
-
if (ps.error) {
|
|
39
|
-
if (ps.error.code === 'ENOENT') {
|
|
40
|
-
throw new Error('docker not found! Please install it.');
|
|
41
|
-
}
|
|
42
|
-
throw new Error(ps.error);
|
|
43
|
-
} else if (ps.status !== 0) {
|
|
44
|
-
//console.error("docker output:", ps.output);
|
|
45
|
-
//console.error("docker stdout:", ps.stdout);
|
|
46
|
-
//console.error("docker stderr:", ps.stderr)
|
|
47
|
-
throw new Error(ps.stderr);
|
|
48
|
-
}
|
|
49
|
-
return ps;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Build the custom Docker image by copying our package to the /var/task directory
|
|
54
|
-
* in the docker image.
|
|
55
|
-
*
|
|
56
|
-
* Our base image uses the Lambda Docker Image for the platform:
|
|
57
|
-
* https://hub.docker.com/r/lambci/lambda/
|
|
58
|
-
*/
|
|
59
|
-
function buildDockerImage() {
|
|
60
|
-
let image = this.provider.naming.getDockerImageName();
|
|
61
|
-
this.serverless.cli.log(`Building docker image: "${image}"...`);
|
|
62
|
-
|
|
63
|
-
// Get any additional run commands we'd like to include in the docker image
|
|
64
|
-
let addtionalBuildCommands = "";
|
|
65
|
-
if (this.serverless.service.custom
|
|
66
|
-
&& this.serverless.service.custom.awsBatch
|
|
67
|
-
&& this.serverless.service.custom.awsBatch.addtionalBuildCommands) {
|
|
68
|
-
|
|
69
|
-
_.forEach(
|
|
70
|
-
this.serverless.service.custom.awsBatch.addtionalBuildCommands,
|
|
71
|
-
runCommand => {
|
|
72
|
-
addtionalBuildCommands += `${runCommand}\n`;
|
|
73
|
-
}
|
|
74
|
-
)
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
let additionalCommands = "";
|
|
78
|
-
if (this.serverless.service.custom
|
|
79
|
-
&& this.serverless.service.custom.awsBatch
|
|
80
|
-
&& this.serverless.service.custom.awsBatch.additionalCommands) {
|
|
81
|
-
|
|
82
|
-
_.forEach(
|
|
83
|
-
this.serverless.service.custom.awsBatch.additionalCommands,
|
|
84
|
-
runCommand => {
|
|
85
|
-
additionalCommands += `${runCommand}\n`;
|
|
86
|
-
}
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
let buildImage = _.get(this.serverless.service,"custom.awsBatch.buildImage", "368461407828.dkr.ecr.us-east-1.amazonaws.com/build-batch-image-base:latest" );
|
|
91
|
-
let batchImage = _.get(this.serverless.service,"custom.awsBatch.batchImage", "368461407828.dkr.ecr.us-east-1.amazonaws.com/batch-image-base:latest" );
|
|
92
|
-
|
|
93
|
-
// Override some of the default lambci environmental variables.
|
|
94
|
-
// - Function Timeout and Function Memory are set by Env Variables on the Job Definition
|
|
95
|
-
// - Access Key and Secret are unset to that we use the role on the container that AWS provides
|
|
96
|
-
const dockerFileContents = `
|
|
97
|
-
FROM ${buildImage} AS builder
|
|
98
|
-
USER root
|
|
99
|
-
RUN mkdir -p /tmp/task/
|
|
100
|
-
COPY ${this.serverless.service.service}.zip /tmp/task
|
|
101
|
-
RUN cd /tmp/task && unzip -q ${this.serverless.service.service}.zip && rm ${this.serverless.service.service}.zip
|
|
102
|
-
${addtionalBuildCommands}
|
|
103
|
-
|
|
104
|
-
FROM ${batchImage}
|
|
105
|
-
USER root
|
|
106
|
-
COPY --from=builder /tmp/task /var/task/
|
|
107
|
-
${additionalCommands}
|
|
108
|
-
RUN rm -rf /tmp/*
|
|
109
|
-
USER sbx_user1051
|
|
110
|
-
`;
|
|
111
|
-
|
|
112
|
-
const servicePath = this.serverless.config.servicePath || '';
|
|
113
|
-
const packagePath = path.join(servicePath || '.', '.serverless');
|
|
114
|
-
const dockerFile = path.join(packagePath, 'Dockerfile');
|
|
115
|
-
fse.writeFileSync(dockerFile, dockerFileContents);
|
|
116
|
-
|
|
117
|
-
const dockerOptions = ['build', '-f', dockerFile, '-t', image, '.'];
|
|
118
|
-
dockerCommand(dockerOptions, packagePath, 'inherit');
|
|
119
|
-
|
|
120
|
-
return BbPromise.resolve();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Uses docker to upload the image to ECR
|
|
125
|
-
*/
|
|
126
|
-
function pushDockerImageToECR() {
|
|
127
|
-
// Log docker into our AWS ECR repo so that we can push images to it
|
|
128
|
-
this.serverless.cli.log("Logging into ECR...");
|
|
129
|
-
const loginCommand = getDockerLoginToECRCommand.bind(this)();
|
|
130
|
-
dockerCommand(loginCommand.split(" "));
|
|
131
|
-
|
|
132
|
-
// Then perform the upload
|
|
133
|
-
this.serverless.cli.log("Uploading to ECR...");
|
|
134
|
-
dockerCommand(['push', '--all-tags', this.provider.naming.getECRRepositoryURL()], null, 'inherit');
|
|
135
|
-
|
|
136
|
-
return BbPromise.resolve();
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
module.exports = { getDockerImageName, buildDockerImage, pushDockerImageToECR };
|
|
1
|
+
const BbPromise = require('bluebird');
|
|
2
|
+
const { spawnSync } = require('child_process');
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
const fse = require('fs-extra');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const util = require('util');
|
|
7
|
+
const { getDockerLoginToECRCommand } = require('./awscli');
|
|
8
|
+
|
|
9
|
+
const DOCKER_TAG = `${Date.now()}`;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* @returns {string} "<ECR Repo Name>:latest"
|
|
13
|
+
*/
|
|
14
|
+
function getDockerImageName() {
|
|
15
|
+
return `${this.provider.naming.getECRRepositoryURL()}:${DOCKER_TAG}`;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Helper function to run a docker command
|
|
20
|
+
* @param {string[]} options
|
|
21
|
+
* @param {string} cwd Current working directory
|
|
22
|
+
* @return {Object}
|
|
23
|
+
*/
|
|
24
|
+
function dockerCommand(options, cwd = null, stdio = null) {
|
|
25
|
+
const cmd = 'docker';
|
|
26
|
+
var spawnOptions = {
|
|
27
|
+
encoding: 'utf-8'
|
|
28
|
+
}
|
|
29
|
+
if (cwd != null) {
|
|
30
|
+
spawnOptions.cwd = cwd;
|
|
31
|
+
}
|
|
32
|
+
if (stdio != null) {
|
|
33
|
+
spawnOptions.stdio = stdio;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
//console.error("dockerCommand:", options, spawnOptions);
|
|
37
|
+
const ps = spawnSync(cmd, options, spawnOptions);
|
|
38
|
+
if (ps.error) {
|
|
39
|
+
if (ps.error.code === 'ENOENT') {
|
|
40
|
+
throw new Error('docker not found! Please install it.');
|
|
41
|
+
}
|
|
42
|
+
throw new Error(ps.error);
|
|
43
|
+
} else if (ps.status !== 0) {
|
|
44
|
+
//console.error("docker output:", ps.output);
|
|
45
|
+
//console.error("docker stdout:", ps.stdout);
|
|
46
|
+
//console.error("docker stderr:", ps.stderr)
|
|
47
|
+
throw new Error(ps.stderr);
|
|
48
|
+
}
|
|
49
|
+
return ps;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Build the custom Docker image by copying our package to the /var/task directory
|
|
54
|
+
* in the docker image.
|
|
55
|
+
*
|
|
56
|
+
* Our base image uses the Lambda Docker Image for the platform:
|
|
57
|
+
* https://hub.docker.com/r/lambci/lambda/
|
|
58
|
+
*/
|
|
59
|
+
function buildDockerImage() {
|
|
60
|
+
let image = this.provider.naming.getDockerImageName();
|
|
61
|
+
this.serverless.cli.log(`Building docker image: "${image}"...`);
|
|
62
|
+
|
|
63
|
+
// Get any additional run commands we'd like to include in the docker image
|
|
64
|
+
let addtionalBuildCommands = "";
|
|
65
|
+
if (this.serverless.service.custom
|
|
66
|
+
&& this.serverless.service.custom.awsBatch
|
|
67
|
+
&& this.serverless.service.custom.awsBatch.addtionalBuildCommands) {
|
|
68
|
+
|
|
69
|
+
_.forEach(
|
|
70
|
+
this.serverless.service.custom.awsBatch.addtionalBuildCommands,
|
|
71
|
+
runCommand => {
|
|
72
|
+
addtionalBuildCommands += `${runCommand}\n`;
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let additionalCommands = "";
|
|
78
|
+
if (this.serverless.service.custom
|
|
79
|
+
&& this.serverless.service.custom.awsBatch
|
|
80
|
+
&& this.serverless.service.custom.awsBatch.additionalCommands) {
|
|
81
|
+
|
|
82
|
+
_.forEach(
|
|
83
|
+
this.serverless.service.custom.awsBatch.additionalCommands,
|
|
84
|
+
runCommand => {
|
|
85
|
+
additionalCommands += `${runCommand}\n`;
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
let buildImage = _.get(this.serverless.service,"custom.awsBatch.buildImage", "368461407828.dkr.ecr.us-east-1.amazonaws.com/build-batch-image-base:latest" );
|
|
91
|
+
let batchImage = _.get(this.serverless.service,"custom.awsBatch.batchImage", "368461407828.dkr.ecr.us-east-1.amazonaws.com/batch-image-base:latest" );
|
|
92
|
+
|
|
93
|
+
// Override some of the default lambci environmental variables.
|
|
94
|
+
// - Function Timeout and Function Memory are set by Env Variables on the Job Definition
|
|
95
|
+
// - Access Key and Secret are unset to that we use the role on the container that AWS provides
|
|
96
|
+
const dockerFileContents = `
|
|
97
|
+
FROM ${buildImage} AS builder
|
|
98
|
+
USER root
|
|
99
|
+
RUN mkdir -p /tmp/task/
|
|
100
|
+
COPY ${this.serverless.service.service}.zip /tmp/task
|
|
101
|
+
RUN cd /tmp/task && unzip -q ${this.serverless.service.service}.zip && rm ${this.serverless.service.service}.zip
|
|
102
|
+
${addtionalBuildCommands}
|
|
103
|
+
|
|
104
|
+
FROM ${batchImage}
|
|
105
|
+
USER root
|
|
106
|
+
COPY --from=builder /tmp/task /var/task/
|
|
107
|
+
${additionalCommands}
|
|
108
|
+
RUN rm -rf /tmp/*
|
|
109
|
+
USER sbx_user1051
|
|
110
|
+
`;
|
|
111
|
+
|
|
112
|
+
const servicePath = this.serverless.config.servicePath || '';
|
|
113
|
+
const packagePath = path.join(servicePath || '.', '.serverless');
|
|
114
|
+
const dockerFile = path.join(packagePath, 'Dockerfile');
|
|
115
|
+
fse.writeFileSync(dockerFile, dockerFileContents);
|
|
116
|
+
|
|
117
|
+
const dockerOptions = ['build', '-f', dockerFile, '-t', image, '.'];
|
|
118
|
+
dockerCommand(dockerOptions, packagePath, 'inherit');
|
|
119
|
+
|
|
120
|
+
return BbPromise.resolve();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Uses docker to upload the image to ECR
|
|
125
|
+
*/
|
|
126
|
+
function pushDockerImageToECR() {
|
|
127
|
+
// Log docker into our AWS ECR repo so that we can push images to it
|
|
128
|
+
this.serverless.cli.log("Logging into ECR...");
|
|
129
|
+
const loginCommand = getDockerLoginToECRCommand.bind(this)();
|
|
130
|
+
dockerCommand(loginCommand.split(" "));
|
|
131
|
+
|
|
132
|
+
// Then perform the upload
|
|
133
|
+
this.serverless.cli.log("Uploading to ECR...");
|
|
134
|
+
dockerCommand(['push', '--all-tags', this.provider.naming.getECRRepositoryURL()], null, 'inherit');
|
|
135
|
+
|
|
136
|
+
return BbPromise.resolve();
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
module.exports = { getDockerImageName, buildDockerImage, pushDockerImageToECR };
|
package/lib/ecr.js
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
const { getAWSAccountID } = require('./awscli');
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @returns {string} "ECRRepository"
|
|
5
|
-
*/
|
|
6
|
-
function getECRLogicalId() {
|
|
7
|
-
return "ECRRepository";
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* @returns {string} "<serviceName>-<stage>"
|
|
12
|
-
*/
|
|
13
|
-
function getECRRepositoryName() {
|
|
14
|
-
return `${this.provider.serverless.service.service}-${this.provider.getStage()}`;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @type {string} "<awsAccountID>.dkr.ecr.us-east-1.amazonaws.com/<serviceName>-<stage>:<tag>"
|
|
20
|
-
*/
|
|
21
|
-
|
|
22
|
-
function getECRRepositoryURL() {
|
|
23
|
-
return `${getAWSAccountID()}.dkr.ecr.${this.provider.getRegion()}.amazonaws.com/${this.provider.naming.getECRRepositoryName()}`
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
module.exports = {
|
|
27
|
-
getECRLogicalId,
|
|
28
|
-
getECRRepositoryName,
|
|
29
|
-
getECRRepositoryURL
|
|
1
|
+
const { getAWSAccountID } = require('./awscli');
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @returns {string} "ECRRepository"
|
|
5
|
+
*/
|
|
6
|
+
function getECRLogicalId() {
|
|
7
|
+
return "ECRRepository";
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @returns {string} "<serviceName>-<stage>"
|
|
12
|
+
*/
|
|
13
|
+
function getECRRepositoryName() {
|
|
14
|
+
return `${this.provider.serverless.service.service}-${this.provider.getStage()}`;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @type {string} "<awsAccountID>.dkr.ecr.us-east-1.amazonaws.com/<serviceName>-<stage>:<tag>"
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
function getECRRepositoryURL() {
|
|
23
|
+
return `${getAWSAccountID()}.dkr.ecr.${this.provider.getRegion()}.amazonaws.com/${this.provider.naming.getECRRepositoryName()}`
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = {
|
|
27
|
+
getECRLogicalId,
|
|
28
|
+
getECRRepositoryName,
|
|
29
|
+
getECRRepositoryURL
|
|
30
30
|
}
|
|
@@ -1,121 +1,121 @@
|
|
|
1
|
-
// Handles setting up our ECR repository so that we can push our docker image to it
|
|
2
|
-
|
|
3
|
-
'use strict';
|
|
4
|
-
|
|
5
|
-
const BbPromise = require('bluebird');
|
|
6
|
-
const path = require('path');
|
|
7
|
-
const _ = require('lodash');
|
|
8
|
-
var util = require('util');
|
|
9
|
-
|
|
10
|
-
const lifeCyclePolicies = {
|
|
11
|
-
"rules": [
|
|
12
|
-
{
|
|
13
|
-
"rulePriority": 1,
|
|
14
|
-
"description": "Remove images over 90 days old",
|
|
15
|
-
"selection": {
|
|
16
|
-
"tagStatus": "any",
|
|
17
|
-
"countType": "sinceImagePushed",
|
|
18
|
-
"countUnit": "days",
|
|
19
|
-
"countNumber": 90
|
|
20
|
-
},
|
|
21
|
-
"action": {
|
|
22
|
-
"type": "expire"
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
]
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Adds the ECR repository to the "create" template so that we have a repository we can upload our docker image to
|
|
30
|
-
* during deployment.
|
|
31
|
-
*/
|
|
32
|
-
function generateCoreTemplate() {
|
|
33
|
-
// Setup our ECR Repository to delete untagged images after 1 day
|
|
34
|
-
// const ecrTemplate = `
|
|
35
|
-
// {
|
|
36
|
-
// "Type" : "AWS::ECR::Repository",
|
|
37
|
-
// "Properties" : {
|
|
38
|
-
// "LifecyclePolicy" : {
|
|
39
|
-
// "LifecyclePolicyText" : ${JSON.stringify(JSON.stringify(lifeCyclePolicies))}
|
|
40
|
-
// },
|
|
41
|
-
// "RepositoryName" : "${this.provider.naming.getECRRepositoryName()}"
|
|
42
|
-
// }
|
|
43
|
-
// }
|
|
44
|
-
// `;
|
|
45
|
-
const ecrTemplate = `
|
|
46
|
-
{
|
|
47
|
-
"Type" : "AWS::ECR::Repository",
|
|
48
|
-
"Properties" : {
|
|
49
|
-
"RepositoryName" : "${this.provider.naming.getECRRepositoryName()}"
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
`;
|
|
53
|
-
|
|
54
|
-
const newECRObject = {
|
|
55
|
-
[this.provider.naming.getECRLogicalId()]: JSON.parse(ecrTemplate)
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
// Add it to our initial compiled cloud formation templates
|
|
59
|
-
_.merge(
|
|
60
|
-
this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
|
|
61
|
-
newECRObject
|
|
62
|
-
);
|
|
63
|
-
|
|
64
|
-
// Look for the serverless-log-forwarding custom parameters, if found, then forward the logs
|
|
65
|
-
// from our batch jobs to the same ARN...
|
|
66
|
-
const logGroupName = _.get(this.serverless.service,"custom.awsBatch.logGroupName");
|
|
67
|
-
const logDestinationArn = _.get(this.serverless.service,"custom.logForwarding.destinationARN" );
|
|
68
|
-
if ( logDestinationArn && logGroupName ) {
|
|
69
|
-
const batchLogGroupTemplate = {
|
|
70
|
-
"BatchLogGroupLambdaPermission": {
|
|
71
|
-
"Type": "AWS::Lambda::Permission",
|
|
72
|
-
"Properties": {
|
|
73
|
-
"FunctionName": logDestinationArn,
|
|
74
|
-
"Action": "lambda:InvokeFunction",
|
|
75
|
-
"Principal": "logs.us-east-1.amazonaws.com"
|
|
76
|
-
}
|
|
77
|
-
},
|
|
78
|
-
"BatchLogGroup": {
|
|
79
|
-
"Type": "AWS::Logs::LogGroup",
|
|
80
|
-
"Properties": {
|
|
81
|
-
"LogGroupName": logGroupName,
|
|
82
|
-
"RetentionInDays": 7
|
|
83
|
-
}
|
|
84
|
-
},
|
|
85
|
-
"BatchLogGroupSubscriptionFilter": {
|
|
86
|
-
"Type": "AWS::Logs::SubscriptionFilter",
|
|
87
|
-
"Properties": {
|
|
88
|
-
"DestinationArn": logDestinationArn,
|
|
89
|
-
"FilterPattern": "",
|
|
90
|
-
"LogGroupName": logGroupName
|
|
91
|
-
},
|
|
92
|
-
"DependsOn": [
|
|
93
|
-
"BatchLogGroupLambdaPermission",
|
|
94
|
-
"BatchLogGroup"
|
|
95
|
-
]
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
_.merge(
|
|
100
|
-
this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
|
|
101
|
-
batchLogGroupTemplate
|
|
102
|
-
);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
// Then write it back out to the file
|
|
106
|
-
const coreTemplateFileName = this.provider.naming.getCoreTemplateFileName();
|
|
107
|
-
|
|
108
|
-
const coreTemplateFilePath = path.join(this.serverless.config.servicePath,
|
|
109
|
-
'.serverless',
|
|
110
|
-
coreTemplateFileName);
|
|
111
|
-
|
|
112
|
-
this.serverless.utils.writeFileSync(coreTemplateFilePath,
|
|
113
|
-
this.serverless.service.provider.compiledCloudFormationTemplate);
|
|
114
|
-
|
|
115
|
-
this.serverless.service.provider.coreCloudFormationTemplate =
|
|
116
|
-
_.cloneDeep(this.serverless.service.provider.compiledCloudFormationTemplate);
|
|
117
|
-
|
|
118
|
-
return BbPromise.resolve();
|
|
119
|
-
}
|
|
120
|
-
|
|
1
|
+
// Handles setting up our ECR repository so that we can push our docker image to it
|
|
2
|
+
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
const BbPromise = require('bluebird');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const _ = require('lodash');
|
|
8
|
+
var util = require('util');
|
|
9
|
+
|
|
10
|
+
const lifeCyclePolicies = {
|
|
11
|
+
"rules": [
|
|
12
|
+
{
|
|
13
|
+
"rulePriority": 1,
|
|
14
|
+
"description": "Remove images over 90 days old",
|
|
15
|
+
"selection": {
|
|
16
|
+
"tagStatus": "any",
|
|
17
|
+
"countType": "sinceImagePushed",
|
|
18
|
+
"countUnit": "days",
|
|
19
|
+
"countNumber": 90
|
|
20
|
+
},
|
|
21
|
+
"action": {
|
|
22
|
+
"type": "expire"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
]
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Adds the ECR repository to the "create" template so that we have a repository we can upload our docker image to
|
|
30
|
+
* during deployment.
|
|
31
|
+
*/
|
|
32
|
+
function generateCoreTemplate() {
|
|
33
|
+
// Setup our ECR Repository to delete untagged images after 1 day
|
|
34
|
+
// const ecrTemplate = `
|
|
35
|
+
// {
|
|
36
|
+
// "Type" : "AWS::ECR::Repository",
|
|
37
|
+
// "Properties" : {
|
|
38
|
+
// "LifecyclePolicy" : {
|
|
39
|
+
// "LifecyclePolicyText" : ${JSON.stringify(JSON.stringify(lifeCyclePolicies))}
|
|
40
|
+
// },
|
|
41
|
+
// "RepositoryName" : "${this.provider.naming.getECRRepositoryName()}"
|
|
42
|
+
// }
|
|
43
|
+
// }
|
|
44
|
+
// `;
|
|
45
|
+
const ecrTemplate = `
|
|
46
|
+
{
|
|
47
|
+
"Type" : "AWS::ECR::Repository",
|
|
48
|
+
"Properties" : {
|
|
49
|
+
"RepositoryName" : "${this.provider.naming.getECRRepositoryName()}"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
|
|
54
|
+
const newECRObject = {
|
|
55
|
+
[this.provider.naming.getECRLogicalId()]: JSON.parse(ecrTemplate)
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Add it to our initial compiled cloud formation templates
|
|
59
|
+
_.merge(
|
|
60
|
+
this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
|
|
61
|
+
newECRObject
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// Look for the serverless-log-forwarding custom parameters, if found, then forward the logs
|
|
65
|
+
// from our batch jobs to the same ARN...
|
|
66
|
+
const logGroupName = _.get(this.serverless.service,"custom.awsBatch.logGroupName");
|
|
67
|
+
const logDestinationArn = _.get(this.serverless.service,"custom.logForwarding.destinationARN" );
|
|
68
|
+
if ( logDestinationArn && logGroupName ) {
|
|
69
|
+
const batchLogGroupTemplate = {
|
|
70
|
+
"BatchLogGroupLambdaPermission": {
|
|
71
|
+
"Type": "AWS::Lambda::Permission",
|
|
72
|
+
"Properties": {
|
|
73
|
+
"FunctionName": logDestinationArn,
|
|
74
|
+
"Action": "lambda:InvokeFunction",
|
|
75
|
+
"Principal": "logs.us-east-1.amazonaws.com"
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"BatchLogGroup": {
|
|
79
|
+
"Type": "AWS::Logs::LogGroup",
|
|
80
|
+
"Properties": {
|
|
81
|
+
"LogGroupName": logGroupName,
|
|
82
|
+
"RetentionInDays": 7
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"BatchLogGroupSubscriptionFilter": {
|
|
86
|
+
"Type": "AWS::Logs::SubscriptionFilter",
|
|
87
|
+
"Properties": {
|
|
88
|
+
"DestinationArn": logDestinationArn,
|
|
89
|
+
"FilterPattern": "",
|
|
90
|
+
"LogGroupName": logGroupName
|
|
91
|
+
},
|
|
92
|
+
"DependsOn": [
|
|
93
|
+
"BatchLogGroupLambdaPermission",
|
|
94
|
+
"BatchLogGroup"
|
|
95
|
+
]
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
_.merge(
|
|
100
|
+
this.serverless.service.provider.compiledCloudFormationTemplate.Resources,
|
|
101
|
+
batchLogGroupTemplate
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Then write it back out to the file
|
|
106
|
+
const coreTemplateFileName = this.provider.naming.getCoreTemplateFileName();
|
|
107
|
+
|
|
108
|
+
const coreTemplateFilePath = path.join(this.serverless.config.servicePath,
|
|
109
|
+
'.serverless',
|
|
110
|
+
coreTemplateFileName);
|
|
111
|
+
|
|
112
|
+
this.serverless.utils.writeFileSync(coreTemplateFilePath,
|
|
113
|
+
this.serverless.service.provider.compiledCloudFormationTemplate);
|
|
114
|
+
|
|
115
|
+
this.serverless.service.provider.coreCloudFormationTemplate =
|
|
116
|
+
_.cloneDeep(this.serverless.service.provider.compiledCloudFormationTemplate);
|
|
117
|
+
|
|
118
|
+
return BbPromise.resolve();
|
|
119
|
+
}
|
|
120
|
+
|
|
121
121
|
module.exports = { generateCoreTemplate };
|