Skip to content

Instantly share code, notes, and snippets.

@yyano
Created February 6, 2018 12:37
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 yyano/8fe6662b491b414c99d2ebafe286ea17 to your computer and use it in GitHub Desktop.
Save yyano/8fe6662b491b414c99d2ebafe286ea17 to your computer and use it in GitHub Desktop.
"use strict";
const AWS = require('aws-sdk');
const cwevents = new AWS.CloudWatchEvents({ apiVersion: '2015-10-07', region: process.env.aws_region });
const lambda = new AWS.Lambda({ apiVersion: '2015-03-31', region: process.env.aws_region });
/**
* Lambda Function に CloudWatch Events を追加する
*
*/
function lambdaAddPermission(jobid, ruleArn, functionName) {
var paramsPermission = {
Action: "lambda:InvokeFunction",
FunctionName: functionName,
Principal: "events.amazonaws.com",
StatementId: jobid,
SourceArn: ruleArn
};
return new Promise(function(resolve, reject) {
lambda.addPermission(paramsPermission, (err, data) => {
if (err) {
reject(err);
}
else {
resolve(data);
}
});
});
}
/**
* Lambda Function から CloudWatch Events を削除する
*
*/
function lambdaRemovePermission(jobid, functionName) {
var params = {
FunctionName: functionName,
StatementId: jobid,
};
return new Promise(function(resolve, reject) {
lambda.removePermission(params, function(err, data) {
if (err) {
reject(err);
}
else {
resolve(data);
}
});
});
}
/**
* CloudWatch Events に Target を追加
*
*/
function putTarget(jobid, functionName, passEvent) {
var paramsTarget = {
Rule: jobid,
Targets: [{
Arn: functionName,
Id: jobid,
Input: JSON.stringify(passEvent)
}]
};
return new Promise(function(resolve, reject) {
cwevents.putTargets(paramsTarget, (err, data) => {
if (err) {
reject(err);
}
else {
resolve(data);
}
});
});
}
/**
* CloudWatch Eventに通知する
*
*/
function putEvents(functionName, passEvent, detailType) {
var paramsEvents = {
Entries: [{
Detail: JSON.stringify(passEvent),
DetailType: detailType,
Resources: [
functionName,
],
Source: 'com.koemoni.schedule'
}]
};
console.log("putEvents", paramsEvents);
return new Promise(function(resolve, reject) {
cwevents.putEvents(paramsEvents, (err, data) => {
if (err) {
reject(err);
}
else {
resolve(data);
}
});
});
}
/**
* /eventsの処理
*
*/
function processingEvents(lambdaEvent, jobid) {
switch (lambdaEvent.context['http-method']) {
case 'GET': // get event lists
return cwevents.listRules({ 'NamePrefix': process.env.jobid_prefix }).promise();
break;
case 'POST': // cretate events, rule
var paramsRule = {
Name: jobid,
Description: lambdaEvent['body-json'].schedule_description,
ScheduleExpression: lambdaEvent['body-json'].schedule_expression,
State: 'ENABLED'
};
var functionName = lambdaEvent['body-json'].function_name;
console.log("functionName:", functionName);
return cwevents.putRule(paramsRule).promise()
.then((r) => {
console.log("putRule result:", r);
return lambdaAddPermission(jobid, r.RuleArn, functionName);
})
.then((r) => {
console.log("lambdaAddPermission result:", r);
return putTarget(jobid, functionName, lambdaEvent['body-json'].pass_event);
})
.then((r) => {
console.log("putTarget result:", r);
return putEvents(functionName, lambdaEvent['body-json'].pass_event, 'Scheduled Event');
})
.then((r) => {
console.log("putEvents result:", r);
return cwevents.listRules({ 'NamePrefix': jobid }).promise();
})
.then((r) => {
console.log("processingEvents result:", r);
return new Promise((resolve, reject) => {
resolve(r);
});
})
.catch((e) => {
console.log("processingEvents error:", e);
return new Promise((resolve, reject) => {
reject(e);
});
});
break;
default:
return new Promise((resolve, reject) => {
reject("error:method type.");
});
}
}
/**
* /events/{ruleid} の処理
*
*/
function processingRuleId(lambdaEvent, jobid) {
return cwevents.describeRule({ 'Name': jobid }).promise()
.then((r) => {
console.log("describeRule result:", r);
switch (lambdaEvent.context['http-method']) {
case 'GET':
return new Promise((resolve, reject) => {
resolve(r);
});
break;
case 'DELETE':
var targetFunctionArn;
var targetInput;
return cwevents.listTargetsByRule({ 'Rule': r.Name }).promise()
.then((rD) => {
console.log("listTargetsByRule result:", rD);
targetFunctionArn = rD.Targets[0].Arn;
console.log("targetFunctionArn:", targetFunctionArn);
targetInput = rD.Targets[0].Input;
console.log("targetInput:", targetInput);
return lambdaRemovePermission(jobid, targetFunctionArn);
})
.then((rD) => {
console.log("lambdaRemovePermission result:", rD);
return cwevents.removeTargets({ Rule: r.Name, Ids: [r.Name] }).promise();
})
.then((rD) => {
console.log("removeTargets result:", rD);
return cwevents.deleteRule({ Name: r.Name }).promise();
})
.then((r) => {
console.log("deleteRule result:", r);
return putEvents(targetFunctionArn, targetInput, 'Deleted Event');
})
.then((rD) => {
console.log("putEvents result:", rD);
return "Deleted rule:" + r.Name;
})
.catch((eD) => {
console.log("processingEvents error:", eD);
return eD;
});
break;
case 'PATCH':
console.log("PATCH ruleState:", lambdaEvent.params.querystring.state);
var ruleState = lambdaEvent.params.querystring.state.toUpperCase();
switch (ruleState) {
case 'DISABLED':
return cwevents.disableRule({ Name: r.Name }).promise();
break;
case 'ENABLED':
return cwevents.enableRule({ Name: r.Name }).promise();
break;
default:
return new Promise((resolve, reject) => {
reject("error: ENABLED or DISABLED");
});
}
break;
default:
return new Promise((resolve, reject) => {
reject("error:method type");
});
}
})
.catch((e) => {
return e;
});
}
/**
* メイン
*
*/
exports.handler = (event, context, callback) => {
console.log("event:", event);
console.log("context:", context);
switch (event.context['resource-path']) {
case '/events':
var jobid = process.env.jobid_prefix + context.awsRequestId;
console.log('jobid:', jobid);
processingEvents(event, jobid)
.then((r) => {
console.log("/events result:", r);
callback(null, r);
})
.catch((e) => {
console.log("/events error:", e);
callback(e, null);
});
break;
case '/events/{ruleid}':
var jobid = event.params.path.ruleid;
console.log('jobid:', jobid);
processingRuleId(event, jobid)
.then((r) => {
console.log("/events/{ruleid} result:", r);
callback(null, r);
})
.catch((e) => {
console.log("/events/{ruleid} error:", e);
callback(e, null);
});
break;
default:
var message = "error resource path:" + event.context['resource-path'];
console.log(message);
callback("error", message);
}
};
---
swagger: "2.0"
info:
version: "2018-02-06T12:33:53Z"
title: "schedule-gateway"
host: "xxxxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com"
basePath: "/prod"
schemes:
- "https"
paths:
/events:
get:
consumes:
- "application/json"
produces:
- "application/json"
responses:
200:
description: "200 response"
schema:
$ref: "#/definitions/Empty"
post:
consumes:
- "application/json"
produces:
- "application/json"
responses:
200:
description: "200 response"
schema:
$ref: "#/definitions/Empty"
/events/{ruleid}:
get:
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- name: "ruleid"
in: "path"
required: true
type: "string"
responses:
200:
description: "200 response"
schema:
$ref: "#/definitions/Empty"
delete:
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- name: "ruleid"
in: "path"
required: true
type: "string"
responses:
200:
description: "200 response"
schema:
$ref: "#/definitions/Empty"
patch:
consumes:
- "application/json"
produces:
- "application/json"
parameters:
- name: "state"
in: "query"
required: true
type: "string"
- name: "ruleid"
in: "path"
required: true
type: "string"
responses:
200:
description: "200 response"
schema:
$ref: "#/definitions/Empty"
definitions:
Empty:
type: "object"
title: "Empty Schema"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment