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