@@ -39,6 +39,8 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes, enableECSMa
39
39
const assignPublicIP = core.getInput('run-task-assign-public-IP', { required: false }) || 'DISABLED';
40
40
const tags = JSON.parse(core.getInput('run-task-tags', { required: false }) || '[]');
41
41
const capacityProviderStrategy = JSON.parse(core.getInput('run-task-capacity-provider-strategy', { required: false }) || '[]');
42
+ const runTaskManagedEBSVolumeName = core.getInput('run-task-managed-ebs-volume', { required: false }) || '';
43
+ const runTaskManagedEBSVolume = core.getInput('run-task-managed-ebs-volume-name', { required: false }) || '{}';
42
44
43
45
let awsvpcConfiguration = {}
44
46
@@ -53,6 +55,21 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes, enableECSMa
53
55
if(assignPublicIP != "" && (subnetIds != "" || securityGroupIds != "")){
54
56
awsvpcConfiguration["assignPublicIp"] = assignPublicIP
55
57
}
58
+ let volumeConfigurations = []
59
+ let volumeConfigurationJSON = {}
60
+
61
+ if (runTaskManagedEBSVolumeName != '') {
62
+ if (runTaskManagedEBSVolume != '{}') {
63
+ taskManagedEBSVolumeObject = convertToManagedEbsVolumeObject(runTaskManagedEbsVolume);
64
+ volumeConfigurationJSON["name"] = runTaskManagedEbsVolumeName;
65
+ volumeConfigurationJSON["managedEBSVolume"] = taskManagedEbsVolumeObject;
66
+ volumeConfigurations.push(volumeConfigurationJSON);
67
+ } else {
68
+ core.warning(`run-task-managed-ebs-volume-name provided without run-task-managed-ebs-volume value. Ignoring run-task-managed-ebs-volume property`);
69
+ }
70
+ } else {
71
+ core.info(`No VolumeConfiguration Property provided for run-task-managed-ebs-volume`);
72
+ }
56
73
57
74
const runTaskResponse = await ecs.runTask({
58
75
startedBy: startedBy,
@@ -65,7 +82,8 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes, enableECSMa
65
82
launchType: capacityProviderStrategy.length === 0 ? launchType : null,
66
83
networkConfiguration: Object.keys(awsvpcConfiguration).length === 0 ? null : { awsvpcConfiguration: awsvpcConfiguration },
67
84
enableECSManagedTags: enableECSManagedTags,
68
- tags: tags
85
+ tags: tags,
86
+ volumeConfigurations: volumeConfigurations
69
87
});
70
88
71
89
core.debug(`Run task response ${JSON.stringify(runTaskResponse)}`)
@@ -92,6 +110,46 @@ async function runTask(ecs, clusterName, taskDefArn, waitForMinutes, enableECSMa
92
110
}
93
111
}
94
112
113
+ async function convertToManagedEbsVolumeObject(managedEbsVolume) {
114
+ managedEbsVolumeObject = {}
115
+ const ebsVolumeObject = JSON.parse(managedEbsVolume);
116
+ if ('roleArn' in ebsVolumeObject){ // required property
117
+ managedEbsVolumeObject['roleArn'] = ebsVolumeObject['roleArn'];
118
+ core.debug(`Found RoleArn ${ebsVolumeObject['roleArn']}`);
119
+ } else {
120
+ throw new Error('managed-ebs-volume must provide "role-arn" to associate with the EBS volume')
121
+ }
122
+
123
+ if ('encrypted' in ebsVolumeObject) {
124
+ managedEbsVolumeObject['encrypted'] = ebsVolumeObject.encrypted;
125
+ }
126
+ if ('filesystemType' in ebsVolumeObject) {
127
+ managedEbsVolumeObject['filesystemType'] = ebsVolumeObject.filesystemType;
128
+ }
129
+ if ('iops' in ebsVolumeObject) {
130
+ managedEbsVolumeObject['iops'] = ebsVolumeObject.iops;
131
+ }
132
+ if ('kmsKeyId' in ebsVolumeObject) {
133
+ managedEbsVolumeObject['kmsKeyId'] = ebsVolumeObject.kmsKeyId;
134
+ }
135
+ if ('sizeInGiB' in ebsVolumeObject) {
136
+ managedEbsVolumeObject['sizeInGiB'] = ebsVolumeObject.sizeInGiB;
137
+ }
138
+ if ('snapshotId' in ebsVolumeObject) {
139
+ managedEbsVolumeObject['snapshotId'] = ebsVolumeObject.snapshotId;
140
+ }
141
+ if ('tagSpecifications' in ebsVolumeObject) {
142
+ managedEbsVolumeObject['tagSpecifications'] = ebsVolumeObject.tagSpecifications;
143
+ }
144
+ if (('throughput' in ebsVolumeObject) && (('volumeType' in ebsVolumeObject) && (ebsVolumeObject.volumeType == 'gp3'))){
145
+ managedEbsVolumeObject["throughput"] = ebsVolumeObject.throughput;
146
+ }
147
+ if ('volumeType' in ebsVolumeObject) {
148
+ managedEbsVolumeObject['volumeType'] = ebsVolumeObject.volumeType;
149
+ }
150
+ return managedEbsVolumeObject;
151
+ }
152
+
95
153
// Poll tasks until they enter a stopped state
96
154
async function waitForTasksStopped(ecs, clusterName, taskArns, waitForMinutes) {
97
155
if (waitForMinutes > MAX_WAIT_MINUTES) {
@@ -140,15 +198,47 @@ async function tasksExitCode(ecs, clusterName, taskArns) {
140
198
141
199
// Deploy to a service that uses the 'ECS' deployment controller
142
200
async function updateEcsService(ecs, clusterName, service, taskDefArn, waitForService, waitForMinutes, forceNewDeployment, desiredCount, enableECSManagedTags, propagateTags) {
143
- core.debug('Updating the service');
201
+ core.debug('Updating the provided ECS service');
202
+
203
+ const serviceManagedEbsVolumeName = core.getInput('service-managed-ebs-volume-name', { required: false }) || '';
204
+ core.debug('serviceManagedEbsVolume Name: ${serviceManagedEbsVolumeName}');
205
+ core.debug('serviceManagedEbsVolume Name.');
206
+ const serviceManagedEbsVolume = core.getInput('service-managed-ebs-volume', { required: false }) || '{}';
207
+ core.debug('serviceManagedEbsVolume Value: ${serviceManagedEbsVolume}');
208
+ core.debug('serviceManagedEbsVolume Value.');
209
+
210
+ core.debug('Updating the service contd..');
211
+
212
+ let volumeConfigurations = []
213
+ let volumeConfigurationJSON = {}
214
+
215
+ if (serviceManagedEbsVolumeName != '') {
216
+ core.debug(`Assigning VolumeConfiguration Name: ${serviceManagedEbsVolumeName}`);
217
+ core.debug('Assigning VolumeConfiguration.');
218
+ if (serviceManagedEbsVolume != '{}') {
219
+ serviceManagedEbsVolumeObject = convertToManagedEbsVolumeObject(serviceManagedEbsVolume);
220
+ volumeConfigurationJSON["name"] = serviceManagedEbsVolumeName;
221
+ volumeConfigurationJSON["managedEBSVolume"] = serviceManagedEbsVolumeObject;
222
+ volumeConfigurations.push(volumeConfigurationJSON);
223
+ core.debug('Assigning VolumeConfiguration Object');
224
+ } else {
225
+ core.warning('service-managed-ebs-volume-name provided without service-managed-ebs-volume value. Ignoring service-managed-ebs-volume property');
226
+ }
227
+ } else {
228
+ core.debug('No VolumeConfiguration Property provided for service-managed-ebs-volume');
229
+ }
230
+ core.debug('VolumeConfiguration Value: ${volumeConfiguration}');
231
+ core.debug('VolumeConfiguration Value Set.');
232
+
144
233
145
234
let params = {
146
235
cluster: clusterName,
147
236
service: service,
148
237
taskDefinition: taskDefArn,
149
238
forceNewDeployment: forceNewDeployment,
150
239
enableECSManagedTags: enableECSManagedTags,
151
- propagateTags: propagateTags
240
+ propagateTags: propagateTags,
241
+ volumeConfigurations: volumeConfigurations
152
242
};
153
243
154
244
// Add the desiredCount property only if it is defined and a number.
@@ -249,9 +339,9 @@ function removeIgnoredAttributes(taskDef) {
249
339
for (var attribute of IGNORED_TASK_DEFINITION_ATTRIBUTES) {
250
340
if (taskDef[attribute]) {
251
341
core.warning(`Ignoring property '${attribute}' in the task definition file. ` +
252
- 'This property is returned by the Amazon ECS DescribeTaskDefinition API and may be shown in the ECS console, ' +
253
- 'but it is not a valid field when registering a new task definition. ' +
254
- 'This field can be safely removed from your task definition file.');
342
+ 'This property is returned by the Amazon ECS DescribeTaskDefinition API and may be shown in the ECS console, ' +
343
+ 'but it is not a valid field when registering a new task definition. ' +
344
+ 'This field can be safely removed from your task definition file.');
255
345
delete taskDef[attribute];
256
346
}
257
347
}
@@ -260,29 +350,29 @@ function removeIgnoredAttributes(taskDef) {
260
350
}
261
351
262
352
function maintainValidObjects(taskDef) {
263
- if (validateProxyConfigurations(taskDef)) {
264
- taskDef.proxyConfiguration.properties.forEach((property, index, arr) => {
265
- if (!('value' in property)) {
266
- arr[index].value = '';
267
- }
268
- if (!('name' in property)) {
269
- arr[index].name = '';
270
- }
271
- });
272
- }
353
+ if (validateProxyConfigurations(taskDef)) {
354
+ taskDef.proxyConfiguration.properties.forEach((property, index, arr) => {
355
+ if (!('value' in property)) {
356
+ arr[index].value = '';
357
+ }
358
+ if (!('name' in property)) {
359
+ arr[index].name = '';
360
+ }
361
+ });
362
+ }
273
363
274
- if(taskDef && taskDef.containerDefinitions){
275
- taskDef.containerDefinitions.forEach((container) => {
276
- if(container.environment){
277
- container.environment.forEach((property, index, arr) => {
278
- if (!('value' in property)) {
279
- arr[index].value = '';
280
- }
281
- });
282
- }
283
- });
284
- }
285
- return taskDef;
364
+ if(taskDef && taskDef.containerDefinitions){
365
+ taskDef.containerDefinitions.forEach((container) => {
366
+ if(container.environment){
367
+ container.environment.forEach((property, index, arr) => {
368
+ if (!('value' in property)) {
369
+ arr[index].value = '';
370
+ }
371
+ });
372
+ }
373
+ });
374
+ }
375
+ return taskDef;
286
376
}
287
377
288
378
function validateProxyConfigurations(taskDef){
@@ -314,8 +404,8 @@ async function createCodeDeployDeployment(codedeploy, clusterName, service, task
314
404
315
405
// Insert the task def ARN into the appspec file
316
406
const appSpecPath = path.isAbsolute(codeDeployAppSpecFile) ?
317
- codeDeployAppSpecFile :
318
- path.join(process.env.GITHUB_WORKSPACE, codeDeployAppSpecFile);
407
+ codeDeployAppSpecFile :
408
+ path.join(process.env.GITHUB_WORKSPACE, codeDeployAppSpecFile);
319
409
const fileContents = fs.readFileSync(appSpecPath, 'utf8');
320
410
const appSpecContents = yaml.parse(fileContents);
321
411
@@ -414,8 +504,8 @@ async function run() {
414
504
// Register the task definition
415
505
core.debug('Registering the task definition');
416
506
const taskDefPath = path.isAbsolute(taskDefinitionFile) ?
417
- taskDefinitionFile :
418
- path.join(process.env.GITHUB_WORKSPACE, taskDefinitionFile);
507
+ taskDefinitionFile :
508
+ path.join(process.env.GITHUB_WORKSPACE, taskDefinitionFile);
419
509
const fileContents = fs.readFileSync(taskDefPath, 'utf8');
420
510
const taskDefContents = maintainValidObjects(removeIgnoredAttributes(cleanNullKeys(yaml.parse(fileContents))));
421
511
let registerResponse;
@@ -484,7 +574,7 @@ module.exports = run;
484
574
485
575
/* istanbul ignore next */
486
576
if (require.main === require.cache[eval('__filename')]) {
487
- run();
577
+ run();
488
578
}
489
579
490
580
0 commit comments