1
1
const { Component } = require ( '@serverless/core' )
2
- const { MultiApigw , Scf, Apigw, Cns } = require ( 'tencent-component-toolkit' )
2
+ const { Scf, Apigw, Cns } = require ( 'tencent-component-toolkit' )
3
3
const { TypeError } = require ( 'tencent-component-toolkit/src/utils/error' )
4
- const { uploadCodeToCos, getDefaultProtocol, deleteRecord , prepareInputs } = require ( './utils' )
4
+ const { uploadCodeToCos, getDefaultProtocol, prepareInputs , deepClone } = require ( './utils' )
5
5
const CONFIGS = require ( './config' )
6
6
7
7
class ServerlessComponent extends Component {
@@ -27,135 +27,141 @@ class ServerlessComponent extends Component {
27
27
}
28
28
29
29
async deployFunction ( credentials , inputs , regionList ) {
30
- const uploadCodeHandler = [ ]
31
30
const outputs = { }
32
31
const appId = this . getAppId ( )
33
32
34
- for ( let eveRegionIndex = 0 ; eveRegionIndex < regionList . length ; eveRegionIndex ++ ) {
35
- const curRegion = regionList [ eveRegionIndex ]
36
- const funcDeployer = async ( ) => {
37
- const code = await uploadCodeToCos ( this , appId , credentials , inputs , curRegion )
38
- const scf = new Scf ( credentials , curRegion )
39
- const tempInputs = {
40
- ...inputs ,
41
- code
42
- }
43
- const scfOutput = await scf . deploy ( tempInputs )
44
- outputs [ curRegion ] = {
45
- functionName : scfOutput . FunctionName ,
46
- runtime : scfOutput . Runtime ,
47
- namespace : scfOutput . Namespace
48
- }
49
-
50
- this . state [ curRegion ] = {
51
- ...( this . state [ curRegion ] ? this . state [ curRegion ] : { } ) ,
52
- ...outputs [ curRegion ]
53
- }
33
+ const funcDeployer = async ( curRegion ) => {
34
+ const code = await uploadCodeToCos ( this , appId , credentials , inputs , curRegion )
35
+ const scf = new Scf ( credentials , curRegion )
36
+ const tempInputs = {
37
+ ...inputs ,
38
+ code
39
+ }
40
+ const scfOutput = await scf . deploy ( deepClone ( tempInputs ) )
41
+ outputs [ curRegion ] = {
42
+ functionName : scfOutput . FunctionName ,
43
+ runtime : scfOutput . Runtime ,
44
+ namespace : scfOutput . Namespace
45
+ }
54
46
55
- // default version is $LATEST
56
- outputs [ curRegion ] . lastVersion = scfOutput . LastVersion
57
- ? scfOutput . LastVersion
58
- : this . state . lastVersion || '$LATEST'
59
-
60
- // default traffic is 1.0, it can also be 0, so we should compare to undefined
61
- outputs [ curRegion ] . traffic =
62
- scfOutput . Traffic !== undefined
63
- ? scfOutput . Traffic
64
- : this . state . traffic !== undefined
65
- ? this . state . traffic
66
- : 1
67
-
68
- if ( outputs [ curRegion ] . traffic !== 1 && scfOutput . ConfigTrafficVersion ) {
69
- outputs [ curRegion ] . configTrafficVersion = scfOutput . ConfigTrafficVersion
70
- this . state . configTrafficVersion = scfOutput . ConfigTrafficVersion
71
- }
47
+ this . state [ curRegion ] = {
48
+ ...( this . state [ curRegion ] ? this . state [ curRegion ] : { } ) ,
49
+ ...outputs [ curRegion ]
50
+ }
72
51
73
- this . state . lastVersion = outputs [ curRegion ] . lastVersion
74
- this . state . traffic = outputs [ curRegion ] . traffic
52
+ // default version is $LATEST
53
+ outputs [ curRegion ] . lastVersion = scfOutput . LastVersion
54
+ ? scfOutput . LastVersion
55
+ : this . state . lastVersion || '$LATEST'
56
+
57
+ // default traffic is 1.0, it can also be 0, so we should compare to undefined
58
+ outputs [ curRegion ] . traffic =
59
+ scfOutput . Traffic !== undefined
60
+ ? scfOutput . Traffic
61
+ : this . state . traffic !== undefined
62
+ ? this . state . traffic
63
+ : 1
64
+
65
+ if ( outputs [ curRegion ] . traffic !== 1 && scfOutput . ConfigTrafficVersion ) {
66
+ outputs [ curRegion ] . configTrafficVersion = scfOutput . ConfigTrafficVersion
67
+ this . state . configTrafficVersion = scfOutput . ConfigTrafficVersion
75
68
}
76
- uploadCodeHandler . push ( funcDeployer ( ) )
69
+
70
+ this . state . lastVersion = outputs [ curRegion ] . lastVersion
71
+ this . state . traffic = outputs [ curRegion ] . traffic
72
+ }
73
+
74
+ for ( let i = 0 ; i < regionList . length ; i ++ ) {
75
+ const curRegion = regionList [ i ]
76
+ await funcDeployer ( curRegion )
77
77
}
78
- await Promise . all ( uploadCodeHandler )
79
78
this . save ( )
80
79
return outputs
81
80
}
82
81
82
+ // try to add dns record
83
+ async tryToAddDnsRecord ( credentials , customDomains ) {
84
+ try {
85
+ const cns = new Cns ( credentials )
86
+ for ( let i = 0 ; i < customDomains . length ; i ++ ) {
87
+ const item = customDomains [ i ]
88
+ if ( item . domainPrefix ) {
89
+ await cns . deploy ( {
90
+ domain : item . subDomain . replace ( `${ item . domainPrefix } .` , '' ) ,
91
+ records : [
92
+ {
93
+ subDomain : item . domainPrefix ,
94
+ recordType : 'CNAME' ,
95
+ recordLine : '默认' ,
96
+ value : item . cname ,
97
+ ttl : 600 ,
98
+ mx : 10 ,
99
+ status : 'enable'
100
+ }
101
+ ]
102
+ } )
103
+ }
104
+ }
105
+ } catch ( e ) {
106
+ console . log ( 'METHOD_tryToAddDnsRecord' , e . message )
107
+ }
108
+ }
109
+
83
110
async deployApigateway ( credentials , inputs , regionList ) {
84
111
if ( inputs . isDisabled ) {
85
112
return { }
86
113
}
87
- const apigw = new MultiApigw ( credentials , regionList )
88
- const oldState = this . state [ regionList [ 0 ] ] || { }
89
- inputs . oldState = {
90
- apiList : oldState . apiList || [ ] ,
91
- customDomains : oldState . customDomains || [ ]
114
+
115
+ const getServiceId = ( instance , region ) => {
116
+ const regionState = instance . state [ region ]
117
+ return inputs . serviceId || ( regionState && regionState . serviceId )
92
118
}
93
- const apigwOutputs = await apigw . deploy ( inputs )
94
- const outputs = { }
95
- Object . keys ( apigwOutputs ) . forEach ( ( curRegion ) => {
96
- const curOutput = apigwOutputs [ curRegion ]
97
- outputs [ curRegion ] = {
98
- serviceId : curOutput . serviceId ,
99
- subDomain : curOutput . subDomain ,
100
- environment : curOutput . environment ,
101
- url : `${ getDefaultProtocol ( inputs . protocols ) } ://${ curOutput . subDomain } /${
102
- curOutput . environment
103
- } /`
104
- }
105
- if ( curOutput . customDomains ) {
106
- outputs [ curRegion ] . customDomains = curOutput . customDomains
107
- }
108
- this . state [ curRegion ] = {
109
- created : curOutput . created ,
110
- ...( this . state [ curRegion ] ? this . state [ curRegion ] : { } ) ,
111
- ...outputs [ curRegion ] ,
112
- apiList : curOutput . apiList
113
- }
114
- } )
115
- this . save ( )
116
- return outputs
117
- }
118
119
119
- async deployCns ( credentials , inputs , regionList , apigwOutputs ) {
120
- const cns = new Cns ( credentials )
121
- const cnsRegion = { }
120
+ const deployTasks = [ ]
121
+ const outputs = { }
122
122
regionList . forEach ( ( curRegion ) => {
123
- const curApigwOutput = apigwOutputs [ curRegion ]
124
- cnsRegion [ curRegion ] = curApigwOutput . subDomain
125
- } )
123
+ const apigwDeployer = async ( ) => {
124
+ const apigw = new Apigw ( credentials , curRegion )
126
125
127
- const state = [ ]
128
- const outputs = { }
129
- const tempJson = { }
130
- for ( let i = 0 ; i < inputs . length ; i ++ ) {
131
- const curCns = inputs [ i ]
132
- for ( let j = 0 ; j < curCns . records . length ; j ++ ) {
133
- curCns . records [ j ] . value =
134
- cnsRegion [ curCns . records [ j ] . value . replace ( 'temp_value_about_' , '' ) ]
135
- }
136
- const tencentCnsOutputs = await cns . deploy ( curCns )
137
- outputs [ curCns . domain ] = tencentCnsOutputs . DNS
138
- ? tencentCnsOutputs . DNS
139
- : 'The domain name has already been added.'
140
- tencentCnsOutputs . domain = curCns . domain
141
- state . push ( tencentCnsOutputs )
142
- }
126
+ const oldState = this . state [ curRegion ] || { }
127
+ const apigwInputs = {
128
+ ...inputs ,
129
+ oldState : {
130
+ apiList : oldState . apiList || [ ] ,
131
+ customDomains : oldState . customDomains || [ ]
132
+ }
133
+ }
134
+ // different region deployment has different service id
135
+ apigwInputs . serviceId = getServiceId ( this , curRegion )
136
+ const apigwOutput = await apigw . deploy ( deepClone ( apigwInputs ) )
137
+ outputs [ curRegion ] = {
138
+ serviceId : apigwOutput . serviceId ,
139
+ subDomain : apigwOutput . subDomain ,
140
+ environment : apigwOutput . environment ,
141
+ url : `${ getDefaultProtocol ( inputs . protocols ) } ://${ apigwOutput . subDomain } /${
142
+ apigwOutput . environment
143
+ } /`
144
+ }
143
145
144
- // 删除serverless创建的但是不在本次列表中
145
- try {
146
- for ( let i = 0 ; i < state . length ; i ++ ) {
147
- tempJson [ state [ i ] . domain ] = state [ i ] . records
148
- }
149
- const recordHistory = this . state . cns || [ ]
150
- for ( let i = 0 ; i < recordHistory . length ; i ++ ) {
151
- const delList = deleteRecord ( tempJson [ recordHistory [ i ] . domain ] , recordHistory [ i ] . records )
152
- if ( delList && delList . length > 0 ) {
153
- await cns . remove ( { deleteList : delList } )
146
+ if ( apigwOutput . customDomains ) {
147
+ // TODO: need confirm add cns authentication
148
+ if ( inputs . autoAddDnsRecord === true ) {
149
+ // await this.tryToAddDnsRecord(credentials, apigwOutput.customDomains)
150
+ }
151
+ outputs [ curRegion ] . customDomains = apigwOutput . customDomains
152
+ }
153
+ this . state [ curRegion ] = {
154
+ created : true ,
155
+ ...( this . state [ curRegion ] ? this . state [ curRegion ] : { } ) ,
156
+ ...outputs [ curRegion ] ,
157
+ apiList : apigwOutput . apiList
154
158
}
155
159
}
156
- } catch ( e ) { }
160
+ deployTasks . push ( apigwDeployer ( ) )
161
+ } )
162
+
163
+ await Promise . all ( deployTasks )
157
164
158
- this . state [ 'cns' ] = state
159
165
this . save ( )
160
166
return outputs
161
167
}
@@ -166,7 +172,7 @@ class ServerlessComponent extends Component {
166
172
const credentials = this . getCredentials ( )
167
173
168
174
// 对Inputs内容进行标准化
169
- const { regionList, functionConf, apigatewayConf, cnsConf } = await prepareInputs (
175
+ const { regionList, functionConf, apigatewayConf } = await prepareInputs (
170
176
this ,
171
177
credentials ,
172
178
inputs
@@ -198,11 +204,6 @@ class ServerlessComponent extends Component {
198
204
outputs [ 'scf' ] = functionOutputs
199
205
}
200
206
201
- // cns depends on apigw, so if disabled apigw, just ignore it.
202
- if ( cnsConf . length > 0 && apigatewayConf . isDisabled !== true ) {
203
- outputs [ 'cns' ] = await this . deployCns ( credentials , cnsConf , regionList , apigwOutputs )
204
- }
205
-
206
207
this . state . region = regionList [ 0 ]
207
208
this . state . regionList = regionList
208
209
this . state . lambdaArn = functionConf . name
0 commit comments