Skip to content

Commit 8276490

Browse files
committed
fix(scf): delete apigw trigger logical
1 parent 80a1530 commit 8276490

File tree

8 files changed

+208
-9
lines changed

8 files changed

+208
-9
lines changed

__tests__/scf.test.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,13 @@ describe('Scf', () => {
120120
];
121121
});
122122

123-
afterAll(async () => {
123+
afterAll(async (done) => {
124124
await cfs.remove({
125125
fsName: cfsInputs.fsName,
126126
fileSystemId: inputs.cfs[0].cfsId,
127127
});
128128
await layer.remove(inputs.layers[0]);
129+
done();
129130
});
130131

131132
test('should deploy SCF success', async () => {

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,15 @@
6868
"eslint-plugin-import": "^2.20.1",
6969
"eslint-plugin-prettier": "^3.1.2",
7070
"husky": "^4.2.3",
71-
"jest": "^26.4.2",
71+
"jest": "^26.6.3",
7272
"lint-staged": "^10.0.8",
7373
"prettier": "^1.19.1",
7474
"semantic-release": "^17.0.4"
7575
},
7676
"dependencies": {
7777
"@tencent-sdk/capi": "^1.1.5",
7878
"@tencent-sdk/cls": "^0.1.7",
79-
"@ygkit/request": "^0.1.1",
79+
"@ygkit/request": "^0.1.3",
8080
"cos-nodejs-sdk-v5": "^2.6.2",
8181
"moment": "^2.25.3",
8282
"tencent-cloud-sdk": "^1.0.5"

src/modules/apigw/index.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const { Capi } = require('@tencent-sdk/capi');
22
const Apis = require('./apis');
3+
const { ApigwTrigger } = require('../triggers');
34
const { uniqueArray, camelCaseProperty, isArray } = require('../../utils/index');
45

56
class Apigw {
@@ -13,6 +14,7 @@ class Apigw {
1314
SecretKey: this.credentials.SecretKey,
1415
Token: this.credentials.Token,
1516
});
17+
this.trigger = new ApigwTrigger(credentials, this.region);
1618
}
1719

1820
getProtocolString(protocols) {
@@ -38,6 +40,7 @@ class Apigw {
3840
} catch (e) {
3941
// no op
4042
}
43+
return true;
4144
}
4245

4346
marshalServiceConfig(endpoint, apiInputs) {
@@ -871,6 +874,10 @@ class Apigw {
871874
// 2. delete only apis created by serverless framework
872875
if (apiConfig.apiId && apiConfig.created === true) {
873876
console.log(`Removing api ${apiConfig.apiId}`);
877+
await this.trigger.remove({
878+
serviceId,
879+
apiId: apiConfig.apiId,
880+
});
874881
await this.removeOrUnbindRequest({
875882
Action: 'DeleteApi',
876883
apiId: apiConfig.apiId,

src/modules/scf/index.js

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { sleep } = require('@ygkit/request');
1+
const { sleep, waitResponse } = require('@ygkit/request');
22
const { Capi } = require('@tencent-sdk/capi');
33
const { TypeError, ApiError } = require('../../utils/error');
44
const { deepClone, strip } = require('../../utils');
@@ -293,13 +293,28 @@ class Scf {
293293
});
294294
}
295295

296-
// 删除函数
296+
// delete function
297297
async deleteFunction(namespace, functionName) {
298-
await this.request({
298+
namespace = namespace || CONFIGS.defaultNamespace;
299+
const res = await this.request({
299300
Action: 'DeleteFunction',
300301
FunctionName: functionName,
301-
Namespace: namespace || CONFIGS.defaultNamespace,
302+
Namespace: namespace,
302303
});
304+
305+
try {
306+
await waitResponse({
307+
callback: async () => this.getFunction(namespace, functionName),
308+
targetResponse: null,
309+
timeout: 120 * 1000,
310+
});
311+
} catch (e) {
312+
throw new ApiError({
313+
type: 'API_SCF_DeleteFunction',
314+
message: `Cannot delete function in 2 minutes, (reqId: ${res.RequestId})`,
315+
});
316+
}
317+
return true;
303318
}
304319

305320
/**
@@ -616,8 +631,6 @@ class Scf {
616631
return false;
617632
}
618633

619-
await this.deleteFunction(namespace, functionName);
620-
621634
try {
622635
await this.isOperationalStatus(namespace, functionName);
623636
} catch (e) {}
@@ -636,6 +649,8 @@ class Scf {
636649
}
637650
}
638651

652+
await this.deleteFunction(namespace, functionName);
653+
639654
console.log(`Remove function ${functionName} and it's triggers success`);
640655

641656
return true;

src/modules/triggers/apigw.js

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
const BaseTrigger = require('./base');
2+
const Apis = require('./apis');
3+
4+
class ApigwTrigger extends BaseTrigger {
5+
async removeScfTrigger({ serviceId, apiId, functionName, namespace, qualifier }) {
6+
// 1. get all trigger list
7+
const allList = await this.getTriggerList({
8+
functionName,
9+
namespace,
10+
qualifier,
11+
});
12+
13+
// 2. get apigw trigger list
14+
const apigwList = allList.filter((item) => item.Type === 'apigw');
15+
16+
const [curApiTrigger] = apigwList.filter(({ ResourceId }) => {
17+
return ResourceId.indexOf(`service/${serviceId}/API/${apiId}`) !== -1;
18+
});
19+
20+
// 3. remove current apigw trigger
21+
if (curApiTrigger) {
22+
try {
23+
await Apis.SCF.DeleteTrigger(this.capi, {
24+
Type: 'apigw',
25+
FunctionName: functionName,
26+
Namespace: namespace,
27+
Qualifier: qualifier,
28+
TriggerDesc: curApiTrigger.TriggerDesc,
29+
TriggerName: curApiTrigger.TriggerName,
30+
});
31+
} catch (e) {
32+
console.log(e);
33+
}
34+
}
35+
}
36+
async remove({ serviceId, apiId }) {
37+
// get api detail
38+
const apiDetail = await Apis.APIGW.DescribeApi(this.capi, {
39+
ServiceId: serviceId,
40+
ApiId: apiId,
41+
});
42+
if (!apiDetail) {
43+
return true;
44+
}
45+
46+
// 1. scf type
47+
if (apiDetail.ServiceScfFunctionName) {
48+
await this.removeScfTrigger({
49+
serviceId,
50+
apiId,
51+
functionName: apiDetail.ServiceScfFunctionName,
52+
namespace: apiDetail.ServiceScfFunctionNamespace,
53+
qualifier: apiDetail.ServiceScfFunctionQualifier,
54+
});
55+
}
56+
57+
// 2. ws type
58+
if (apiDetail.ServiceWebsocketRegisterFunctionName) {
59+
await this.removeScfTrigger({
60+
serviceId,
61+
apiId,
62+
functionName: apiDetail.ServiceWebsocketRegisterFunctionName,
63+
namespace: apiDetail.ServiceWebsocketRegisterFunctionNamespace,
64+
qualifier: apiDetail.ServiceWebsocketRegisterFunctionQualifier,
65+
});
66+
}
67+
if (apiDetail.ServiceWebsocketCleanupFunctionName) {
68+
await this.removeScfTrigger({
69+
serviceId,
70+
apiId,
71+
functionName: apiDetail.ServiceWebsocketCleanupFunctionName,
72+
namespace: apiDetail.ServiceWebsocketCleanupFunctionNamespace,
73+
qualifier: apiDetail.ServiceWebsocketCleanupFunctionQualifier,
74+
});
75+
}
76+
if (apiDetail.ServiceWebsocketTransportFunctionName) {
77+
await this.removeScfTrigger({
78+
serviceId,
79+
apiId,
80+
functionName: apiDetail.ServiceWebsocketTransportFunctionName,
81+
namespace: apiDetail.ServiceWebsocketTransportFunctionNamespace,
82+
qualifier: apiDetail.ServiceWebsocketTransportFunctionQualifier,
83+
});
84+
}
85+
return true;
86+
}
87+
}
88+
89+
module.exports = ApigwTrigger;

src/modules/triggers/apis.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
const { ApiFactory } = require('../../utils/api');
2+
const { ApiError } = require('../../utils/error');
3+
4+
const SCF_ACTIONS = ['CreateTrigger', 'DeleteTrigger', 'ListTriggers'];
5+
const APIGW_ACTIONS = ['DescribeApi'];
6+
7+
const SCF = ApiFactory({
8+
// debug: true,
9+
serviceType: 'scf',
10+
version: '2018-04-16',
11+
actions: SCF_ACTIONS,
12+
});
13+
14+
const APIGW = ApiFactory({
15+
// debug: true,
16+
serviceType: 'apigateway',
17+
version: '2018-08-08',
18+
actions: APIGW_ACTIONS,
19+
responseHandler(Response) {
20+
return Response.Result || Response;
21+
},
22+
errorHandler(action, Response) {
23+
if (Response.Error.Code.indexOf('ResourceNotFound') === -1) {
24+
throw new ApiError({
25+
type: `API_APIGW_${action}`,
26+
message: `${Response.Error.Message} (reqId: ${Response.RequestId})`,
27+
reqId: Response.RequestId,
28+
code: Response.Error.Code,
29+
});
30+
}
31+
return null;
32+
},
33+
});
34+
35+
module.exports = {
36+
SCF,
37+
APIGW,
38+
};

src/modules/triggers/base.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const { Capi } = require('@tencent-sdk/capi');
2+
3+
const Apis = require('./apis');
4+
5+
class BaseTrigger {
6+
constructor(credentials = {}, region) {
7+
this.region = region || 'ap-guangzhou';
8+
this.credentials = credentials;
9+
10+
this.credentials = credentials;
11+
this.capi = new Capi({
12+
Region: this.region,
13+
AppId: this.credentials.AppId,
14+
SecretId: this.credentials.SecretId,
15+
SecretKey: this.credentials.SecretKey,
16+
Token: this.credentials.Token,
17+
});
18+
}
19+
20+
async getTriggerList({ functionName, namespace = 'default', qualifier }) {
21+
const listOptions = {
22+
FunctionName: functionName,
23+
Namespace: namespace,
24+
Limit: 100,
25+
};
26+
if (qualifier) {
27+
listOptions.Filters = [
28+
{
29+
Name: 'Qualifier',
30+
Values: [qualifier],
31+
},
32+
];
33+
}
34+
const { Triggers = [], TotalCount } = await Apis.SCF.ListTriggers(this.capi, listOptions);
35+
if (TotalCount > 100) {
36+
const res = await this.getTriggerList(functionName, namespace, qualifier);
37+
return Triggers.concat(res);
38+
}
39+
40+
return Triggers;
41+
}
42+
}
43+
44+
module.exports = BaseTrigger;

src/modules/triggers/index.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
const ApigwTrigger = require('./apigw');
2+
3+
module.exports = {
4+
ApigwTrigger,
5+
};

0 commit comments

Comments
 (0)