UNPKG

18.3 kBJavaScriptView Raw
1'use strict';
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 return new (P || (P = Promise))(function (resolve, reject) {
4 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7 step((generator = generator.apply(thisArg, _arguments || [])).next());
8 });
9};
10const getProfile = require('./profile').getProfile;
11const { getFcClient } = require('./client');
12const debug = require('debug')('fun:trigger');
13const _ = require('lodash');
14const ram = require('./ram');
15const util = require('util');
16const { red, yellow } = require('colors');
17const triggerTypeMapping = {
18 'Datahub': 'datahub',
19 'Timer': 'timer',
20 'HTTP': 'http',
21 'Log': 'log',
22 'OSS': 'oss',
23 'RDS': 'rds',
24 'MNSTopic': 'mns_topic',
25 'TableStore': 'tablestore',
26 'CDN': 'cdn_events'
27};
28function getSourceArn(triggerType, triggerProperties) {
29 return __awaiter(this, void 0, void 0, function* () {
30 const profile = yield getProfile();
31 if (triggerType === 'Log') {
32 return `acs:log:${profile.defaultRegion}:${profile.accountId}:project/${triggerProperties.LogConfig.Project}`;
33 }
34 else if (triggerType === 'RDS') {
35 return `acs:rds:${profile.defaultRegion}:${profile.accountId}:dbinstance/${triggerProperties.InstanceId}`;
36 }
37 else if (triggerType === 'MNSTopic') {
38 if (triggerProperties.Region !== undefined) {
39 return `acs:mns:${triggerProperties.Region}:${profile.accountId}:/topics/${triggerProperties.TopicName}`;
40 }
41 return `acs:mns:${profile.defaultRegion}:${profile.accountId}:/topics/${triggerProperties.TopicName}`;
42 }
43 else if (triggerType === 'TableStore') {
44 return `acs:ots:${profile.defaultRegion}:${profile.accountId}:instance/${triggerProperties.InstanceName}/table/${triggerProperties.TableName}`;
45 }
46 else if (triggerType === 'OSS') {
47 return `acs:oss:${profile.defaultRegion}:${profile.accountId}:${triggerProperties.BucketName || triggerProperties.bucketName}`;
48 }
49 else if (triggerType === 'CDN') {
50 return `acs:cdn:*:${profile.accountId}`;
51 }
52 return;
53 });
54}
55function getTriggerNameList({ serviceName, functionName }) {
56 return __awaiter(this, void 0, void 0, function* () {
57 const fc = yield getFcClient();
58 var listTriggerResponse = yield fc.listTriggers(serviceName, functionName);
59 var triggerNameArray = [];
60 if (listTriggerResponse && listTriggerResponse.data.triggers) {
61 triggerNameArray = listTriggerResponse.data.triggers.map(p => p.triggerName);
62 }
63 return triggerNameArray;
64 });
65}
66function getTriggerConfig(triggerType, triggerProperties) {
67 if (triggerType === 'Timer') {
68 return {
69 payload: triggerProperties.Payload,
70 cronExpression: triggerProperties.CronExpression,
71 enable: triggerProperties.Enable
72 };
73 }
74 else if (triggerType === 'HTTP') {
75 return {
76 authType: (triggerProperties.AuthType).toLowerCase(),
77 methods: triggerProperties.Methods
78 };
79 }
80 else if (triggerType === 'Log') {
81 const logConfig = triggerProperties.LogConfig;
82 const jobConfig = triggerProperties.JobConfig;
83 const sourceConfig = triggerProperties.SourceConfig;
84 return {
85 sourceConfig: {
86 logstore: sourceConfig.Logstore
87 },
88 jobConfig: {
89 maxRetryTime: jobConfig.MaxRetryTime,
90 triggerInterval: jobConfig.TriggerInterval
91 },
92 logConfig: {
93 project: logConfig.Project,
94 logstore: logConfig.Logstore
95 },
96 functionParameter: triggerProperties.FunctionParameter || {},
97 Enable: !(triggerProperties.Enable === false)
98 };
99 }
100 else if (triggerType === 'RDS') {
101 return {
102 subscriptionObjects: triggerProperties.SubscriptionObjects,
103 retry: triggerProperties.Retry,
104 concurrency: triggerProperties.Concurrency,
105 eventFormat: triggerProperties.EventFormat
106 };
107 }
108 else if (triggerType === 'MNSTopic') {
109 var notifyContentFormat = 'STREAM';
110 if (triggerProperties.NotifyContentFormat !== undefined) {
111 notifyContentFormat = triggerProperties.NotifyContentFormat;
112 }
113 var notifyStrategy = 'BACKOFF_RETRY';
114 if (triggerProperties.NotifyStrategy !== undefined) {
115 notifyStrategy = triggerProperties.NotifyStrategy;
116 }
117 var triggerCfg = {
118 NotifyContentFormat: notifyContentFormat,
119 NotifyStrategy: notifyStrategy
120 };
121 if (triggerProperties.FilterTag !== undefined) {
122 triggerCfg.FilterTag = triggerProperties.FilterTag;
123 }
124 return triggerCfg;
125 }
126 else if (triggerType === 'TableStore') {
127 return {};
128 }
129 else if (triggerType === 'OSS') {
130 return {
131 events: triggerProperties.Events || triggerProperties.events,
132 filter: triggerProperties.Filter || triggerProperties.filter
133 };
134 }
135 else if (triggerType === 'CDN') {
136 return {
137 eventName: triggerProperties.EventName,
138 eventVersion: triggerProperties.EventVersion,
139 notes: triggerProperties.Notes,
140 filter: _.mapKeys(triggerProperties.Filter, (value, key) => {
141 return _.lowerFirst(key);
142 })
143 };
144 }
145 console.error(`trigger type is ${triggerType} not supported.`);
146}
147function makeInvocationRole(serviceName, functionName, triggerType) {
148 return __awaiter(this, void 0, void 0, function* () {
149 if (triggerType === 'Log') {
150 const invocationRoleName = ram.normalizeRoleOrPoliceName(`AliyunFcGeneratedInvocationRole-${serviceName}-${functionName}`);
151 const invocationRole = yield ram.makeRole(invocationRoleName, true, 'Used for fc invocation', {
152 'Statement': [{
153 'Action': 'sts:AssumeRole',
154 'Effect': 'Allow',
155 'Principal': {
156 'Service': [
157 'log.aliyuncs.com'
158 ]
159 }
160 }],
161 'Version': '1'
162 });
163 const policyName = ram.normalizeRoleOrPoliceName(`AliyunFcGeneratedInvocationPolicy-${serviceName}-${functionName}`);
164 yield ram.makePolicy(policyName, {
165 'Version': '1',
166 'Statement': [{
167 'Action': [
168 'fc:InvokeFunction'
169 ],
170 'Resource': `acs:fc:*:*:services/${serviceName}/functions/*`,
171 'Effect': 'Allow'
172 },
173 {
174 'Action': [
175 'log:Get*',
176 'log:List*',
177 'log:PostLogStoreLogs',
178 'log:CreateConsumerGroup',
179 'log:UpdateConsumerGroup',
180 'log:DeleteConsumerGroup',
181 'log:ListConsumerGroup',
182 'log:ConsumerGroupUpdateCheckPoint',
183 'log:ConsumerGroupHeartBeat',
184 'log:GetConsumerGroupCheckPoint'
185 ],
186 'Resource': '*',
187 'Effect': 'Allow'
188 }
189 ]
190 });
191 yield ram.attachPolicyToRole(policyName, invocationRoleName, 'Custom');
192 return invocationRole.Role;
193 }
194 else if (triggerType === 'RDS' || triggerType === 'MNSTopic') {
195 const invocationRoleName = ram.normalizeRoleOrPoliceName(`FunCreateRole-${serviceName}-${functionName}`);
196 var tMap = {
197 'RDS': 'rds',
198 'MNSTopic': 'mns'
199 };
200 var principalService = util.format('%s.aliyuncs.com', tMap[triggerType]);
201 const invocationRole = yield ram.makeRole(invocationRoleName, true, 'Used for fc invocation', {
202 'Statement': [{
203 'Action': 'sts:AssumeRole',
204 'Effect': 'Allow',
205 'Principal': {
206 'Service': [
207 principalService
208 ]
209 }
210 }],
211 'Version': '1'
212 });
213 const policyName = ram.normalizeRoleOrPoliceName(`FunCreatePolicy-${serviceName}-${functionName}`);
214 yield ram.makePolicy(policyName, {
215 'Version': '1',
216 'Statement': [{
217 'Action': [
218 'fc:InvokeFunction'
219 ],
220 'Resource': `acs:fc:*:*:services/${serviceName}/functions/*`,
221 'Effect': 'Allow'
222 }]
223 });
224 yield ram.attachPolicyToRole(policyName, invocationRoleName, 'Custom');
225 return invocationRole.Role;
226 }
227 else if (triggerType === 'TableStore') {
228 const invocationRoleName = ram.normalizeRoleOrPoliceName(`FunCreateRole-${serviceName}-${functionName}`);
229 const invocationRole = yield ram.makeRole(invocationRoleName, true, 'Used for fc invocation', {
230 'Statement': [{
231 'Action': 'sts:AssumeRole',
232 'Effect': 'Allow',
233 'Principal': {
234 'RAM': [
235 'acs:ram::1604337383174619:root'
236 ]
237 }
238 }],
239 'Version': '1'
240 });
241 const invkPolicyName = ram.normalizeRoleOrPoliceName(`FunCreateInvkPolicy-${serviceName}-${functionName}`);
242 yield ram.makePolicy(invkPolicyName, {
243 'Version': '1',
244 'Statement': [{
245 'Action': [
246 'fc:InvokeFunction'
247 ],
248 'Resource': '*',
249 'Effect': 'Allow'
250 }]
251 });
252 yield ram.attachPolicyToRole(invkPolicyName, invocationRoleName, 'Custom');
253 const otsReadPolicyName = ram.normalizeRoleOrPoliceName(`FunCreateOtsReadPolicy-${serviceName}-${functionName}`);
254 yield ram.makePolicy(otsReadPolicyName, {
255 'Version': '1',
256 'Statement': [{
257 'Action': [
258 'ots:BatchGet*',
259 'ots:Describe*',
260 'ots:Get*',
261 'ots:List*'
262 ],
263 'Resource': '*',
264 'Effect': 'Allow'
265 }]
266 });
267 yield ram.attachPolicyToRole(otsReadPolicyName, invocationRoleName, 'Custom');
268 return invocationRole.Role;
269 }
270 else if (triggerType === 'OSS') {
271 const invocationRoleName = ram.normalizeRoleOrPoliceName(`FunCreateRole-${serviceName}-${functionName}`);
272 const invocationRole = yield ram.makeRole(invocationRoleName, true, 'Used for fc invocation', {
273 'Statement': [
274 {
275 'Action': 'sts:AssumeRole',
276 'Effect': 'Allow',
277 'Principal': {
278 'Service': [
279 'oss.aliyuncs.com'
280 ]
281 }
282 }
283 ],
284 'Version': '1'
285 });
286 const policyName = ram.normalizeRoleOrPoliceName(`FunCreateOSSPolicy-${serviceName}-${functionName}`);
287 yield ram.makePolicy(policyName, {
288 'Version': '1',
289 'Statement': [{
290 'Action': [
291 'fc:InvokeFunction'
292 ],
293 'Resource': `acs:fc:*:*:services/${serviceName}/functions/*`,
294 'Effect': 'Allow'
295 }]
296 });
297 yield ram.attachPolicyToRole(policyName, invocationRoleName, 'Custom');
298 return invocationRole.Role;
299 }
300 else if (triggerType === 'CDN') {
301 const invocationRoleName = ram.normalizeRoleOrPoliceName(`FunCreateRole-${serviceName}-${functionName}`);
302 const invocationRole = yield ram.makeRole(invocationRoleName, true, 'Used for fc invocation', {
303 'Statement': [
304 {
305 'Action': 'sts:AssumeRole',
306 'Effect': 'Allow',
307 'Principal': {
308 'Service': [
309 'cdn.aliyuncs.com'
310 ]
311 }
312 }
313 ],
314 'Version': '1'
315 });
316 const policyName = ram.normalizeRoleOrPoliceName(`FunCreateCDNPolicy-${serviceName}-${functionName}`);
317 yield ram.makePolicy(policyName, {
318 'Version': '1',
319 'Statement': [{
320 'Action': [
321 'fc:InvokeFunction'
322 ],
323 'Resource': `acs:fc:*:*:services/${serviceName}/functions/*`,
324 'Effect': 'Allow'
325 }]
326 });
327 yield ram.attachPolicyToRole(policyName, invocationRoleName, 'Custom');
328 return invocationRole.Role;
329 }
330 return;
331 });
332}
333function deleteTrigger(serviceName, functionName, triggerName) {
334 return __awaiter(this, void 0, void 0, function* () {
335 const fc = yield getFcClient();
336 yield fc.deleteTrigger(serviceName, functionName, triggerName);
337 });
338}
339function makeTrigger({ serviceName, functionName, triggerName, triggerType, triggerProperties }) {
340 return __awaiter(this, void 0, void 0, function* () {
341 const fc = yield getFcClient();
342 var trigger;
343 try {
344 trigger = yield fc.getTrigger(serviceName, functionName, triggerName);
345 }
346 catch (ex) {
347 if (ex.code !== 'TriggerNotFound') {
348 throw ex;
349 }
350 }
351 const params = {
352 triggerType: triggerTypeMapping[triggerType],
353 triggerConfig: getTriggerConfig(triggerType, triggerProperties)
354 };
355 debug('serviceName is %s, functionName is %s, trigger params is %j', serviceName, functionName, params);
356 let invocationRoleArn = triggerProperties.InvocationRole;
357 if (!invocationRoleArn) {
358 const invocationRole = yield makeInvocationRole(serviceName, functionName, triggerType);
359 if (invocationRole) {
360 invocationRoleArn = invocationRole.Arn;
361 }
362 }
363 if (invocationRoleArn) {
364 Object.assign(params, {
365 'invocationRole': invocationRoleArn
366 });
367 }
368 const sourceArn = yield getSourceArn(triggerType, triggerProperties);
369 if (sourceArn) {
370 Object.assign(params, {
371 'sourceArn': sourceArn
372 });
373 }
374 if (triggerProperties.Qualifier) {
375 Object.assign(params, {
376 'qualifier': triggerProperties.Qualifier
377 });
378 }
379 if (!trigger) {
380 params.triggerName = triggerName;
381 trigger = yield fc.createTrigger(serviceName, functionName, params);
382 }
383 else {
384 if (triggerType === 'TableStore' || triggerType === 'MNSTopic') {
385 // no triggerConfig, so no updateTrigger, first delete, then create
386 // await fc.deleteTrigger(serviceName, functionName, triggerName);
387 // params.triggerName = triggerName;
388 // trigger = await fc.createTrigger(serviceName, functionName, params);
389 console.log(red(`\t\tWarning: TableStore and MNSTopic Trigger cann't update`));
390 return;
391 }
392 trigger = yield fc.updateTrigger(serviceName, functionName, triggerName, params);
393 }
394 return trigger;
395 });
396}
397function displayTriggerInfo(serviceName, functionName, triggerName, triggerType, triggerProperties, wrap) {
398 return __awaiter(this, void 0, void 0, function* () {
399 if (triggerType === 'HTTP' || triggerType === 'http') {
400 const profile = yield getProfile();
401 const accountId = profile.accountId;
402 const region = profile.defaultRegion;
403 const resolveWrap = wrap || '';
404 if (triggerName) {
405 console.log(`${resolveWrap}triggerName: ${yellow(triggerName)}`);
406 }
407 console.log(`${resolveWrap}methods: ${yellow(triggerProperties.Methods || triggerProperties.methods)}`);
408 console.log(`${resolveWrap}url: ` + yellow(`https://${accountId}.${region}.fc.aliyuncs.com/2016-08-15/proxy/${serviceName}/${functionName}/`));
409 console.log(red(`${resolveWrap}Http Trigger will forcefully add a 'Content-Disposition: attachment' field to the response header, which cannot be overwritten \n${resolveWrap}and will cause the response to be downloaded as an attachment in the browser. This issue can be avoided by using CustomDomain.\n`));
410 }
411 });
412}
413module.exports = {
414 getTriggerNameList,
415 getTriggerConfig,
416 makeTrigger,
417 deleteTrigger,
418 makeInvocationRole,
419 displayTriggerInfo
420};