11const { 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' )
33const { TypeError } = require ( 'tencent-component-toolkit/src/utils/error' )
4- const { uploadCodeToCos, getDefaultProtocol, deleteRecord , prepareInputs } = require ( './utils' )
4+ const { uploadCodeToCos, getDefaultProtocol, prepareInputs , deepClone } = require ( './utils' )
55const CONFIGS = require ( './config' )
66
77class ServerlessComponent extends Component {
@@ -39,135 +39,141 @@ class ServerlessComponent extends Component {
3939 }
4040 }
4141
42- const uploadCodeHandler = [ ]
4342 const outputs = { }
4443 const appId = this . getAppId ( )
4544
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+ }
6658
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+ }
8463
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
8780 }
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 )
8989 }
90- await Promise . all ( uploadCodeHandler )
9190 this . save ( )
9291 return outputs
9392 }
9493
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+
95122 async deployApigateway ( credentials , inputs , regionList ) {
96123 if ( inputs . isDisabled ) {
97124 return { }
98125 }
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 )
104130 }
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- }
130131
131- async deployCns ( credentials , inputs , regionList , apigwOutputs ) {
132- const cns = new Cns ( credentials )
133- const cnsRegion = { }
132+ const deployTasks = [ ]
133+ const outputs = { }
134134 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 )
138137
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+ }
155157
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
166170 }
167171 }
168- } catch ( e ) { }
172+ deployTasks . push ( apigwDeployer ( ) )
173+ } )
174+
175+ await Promise . all ( deployTasks )
169176
170- this . state [ 'cns' ] = state
171177 this . save ( )
172178 return outputs
173179 }
@@ -178,7 +184,7 @@ class ServerlessComponent extends Component {
178184 const credentials = this . getCredentials ( )
179185
180186 // 对Inputs内容进行标准化
181- const { regionList, functionConf, apigatewayConf, cnsConf } = await prepareInputs (
187+ const { regionList, functionConf, apigatewayConf } = await prepareInputs (
182188 this ,
183189 credentials ,
184190 inputs
@@ -210,11 +216,6 @@ class ServerlessComponent extends Component {
210216 outputs [ 'scf' ] = functionOutputs
211217 }
212218
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-
218219 this . state . region = regionList [ 0 ]
219220 this . state . regionList = regionList
220221 this . state . lambdaArn = functionConf . name
0 commit comments