@@ -238,9 +238,7 @@ class Apigw {
238238 return secretIdsOutput
239239 }
240240
241- async setupApiUsagePlan ( { endpoint } ) {
242- const { usagePlan = { } } = endpoint
243-
241+ async setupApiUsagePlan ( { usagePlan } ) {
244242 const usageInputs = {
245243 usagePlanName : usagePlan . usagePlanName || '' ,
246244 usagePlanDesc : usagePlan . usagePlanDesc || '' ,
@@ -249,15 +247,16 @@ class Apigw {
249247 }
250248
251249 const usagePlanOutput = {
252- created : false ,
253- id : usagePlan . usagePlanId
250+ created : usagePlan . created || false ,
251+ id : usagePlan . id
254252 }
255253
256- if ( ! usagePlan . usagePlanId ) {
257- usagePlanOutput . id = await this . request ( {
254+ if ( ! usagePlan . id ) {
255+ const createUsagePlan = await this . request ( {
258256 Action : 'CreateUsagePlan' ,
259257 ...usageInputs
260258 } )
259+ usagePlanOutput . id = createUsagePlan . usagePlanId
261260 usagePlanOutput . created = true
262261 console . debug ( `Usage plan with ID ${ usagePlanOutput . id } created.` )
263262 } else {
@@ -272,6 +271,35 @@ class Apigw {
272271 return usagePlanOutput
273272 }
274273
274+ /**
275+ * get all unbound secretids
276+ */
277+ async getUnboundSecretIds ( { usagePlanId, secretIds } ) {
278+ const getAllBoundSecrets = async ( res = [ ] , { limit, offset = 0 } ) => {
279+ const { secretIdList } = await this . request ( {
280+ Action : 'DescribeUsagePlanSecretIds' ,
281+ usagePlanId,
282+ limit,
283+ offset
284+ } )
285+ if ( secretIdList . length < limit ) {
286+ return res
287+ }
288+ return getAllBoundSecrets ( res , { limit, offset : offset + secretIdList . length } )
289+ }
290+ const allBoundSecretObjs = await getAllBoundSecrets ( [ ] , { limit : 100 } )
291+ const allBoundSecretIds = allBoundSecretObjs . map ( ( item ) => item . secretId )
292+ const unboundSecretIds = secretIds . filter ( ( item ) => {
293+ if ( allBoundSecretIds . indexOf ( item ) === - 1 ) {
294+ return true
295+ }
296+ console . log ( `Usage plan ${ usagePlanId } secret id ${ item } already bound` )
297+ return false
298+ } )
299+ return unboundSecretIds
300+ }
301+
302+ // bind custom domains
275303 async bindCustomDomain ( { serviceId, subDomain, inputs } ) {
276304 const { customDomains, oldState = { } } = inputs
277305 // 1. unbind all custom domain
@@ -338,8 +366,44 @@ class Apigw {
338366 return customDomainOutput
339367 }
340368
369+ // bind environment fo usage plan
370+ async bindUsagePlanEnvironment ( {
371+ environment,
372+ bindType = 'API' ,
373+ serviceId,
374+ apiId,
375+ endpoint,
376+ usagePlan
377+ } ) {
378+ const { usagePlanList } = await this . request ( {
379+ Action : 'DescribeApiUsagePlan' ,
380+ serviceId,
381+ apiIds : [ apiId ]
382+ } )
383+
384+ const oldUsagePlan = usagePlanList . find ( ( item ) => item . usagePlanId === usagePlan . id )
385+ if ( oldUsagePlan ) {
386+ console . debug (
387+ `Usage plan with id ${ usagePlan . id } already bind to api id ${ apiId } path ${ endpoint . method } ${ endpoint . path } .`
388+ )
389+ } else {
390+ console . debug (
391+ `Binding usage plan with id ${ usagePlan . id } to api id ${ apiId } path ${ endpoint . method } ${ endpoint . path } .`
392+ )
393+ await this . request ( {
394+ Action : 'BindEnvironment' ,
395+ serviceId,
396+ environment,
397+ bindType : bindType ,
398+ usagePlanIds : [ usagePlan . id ] ,
399+ apiIds : [ apiId ]
400+ } )
401+ console . debug ( 'Binding successed.' )
402+ }
403+ }
404+
341405 async deploy ( inputs ) {
342- const { oldState = { } } = inputs
406+ const { environment , oldState = { } } = inputs
343407 inputs . protocols = this . getProtocolString ( inputs . protocols )
344408
345409 const { serviceId, serviceName, subDomain, serviceCreated } = await this . createOrUpdateService (
@@ -369,10 +433,51 @@ class Apigw {
369433 curApi . created = true
370434 }
371435
372- // TODO: set api auth and use plan
373- // if (endpoint.auth) {
374- // await this.setupUsagePlan
375- // }
436+ // set api auth and use plan
437+ if ( endpoint . auth ) {
438+ curApi . bindType = endpoint . bindType || 'API'
439+ const usagePlan = await this . setupApiUsagePlan ( {
440+ usagePlan : {
441+ ...( ( exist && exist . usagePlan ) || { } ) ,
442+ ...endpoint . usagePlan
443+ }
444+ } )
445+ // store in api list
446+ curApi . usagePlan = usagePlan
447+
448+ const { secretIds = [ ] } = endpoint . auth
449+ const secrets = await this . setupUsagePlanSecret ( {
450+ secretName : endpoint . auth . secretName ,
451+ secretIds
452+ } )
453+ const unboundSecretIds = await this . getUnboundSecretIds ( {
454+ usagePlanId : usagePlan . id ,
455+ secretIds : secrets . secretIds
456+ } )
457+ if ( unboundSecretIds . length > 0 ) {
458+ console . debug (
459+ `Binding secret key ${ unboundSecretIds } to usage plan with id ${ usagePlan . id } .`
460+ )
461+ await this . request ( {
462+ Action : 'BindSecretIds' ,
463+ usagePlanId : usagePlan . id ,
464+ secretIds : unboundSecretIds
465+ } )
466+ console . debug ( 'Binding secret key successed.' )
467+ }
468+ // store in api list
469+ curApi . usagePlan . secrets = secrets
470+
471+ // bind environment
472+ await this . bindUsagePlanEnvironment ( {
473+ environment,
474+ serviceId,
475+ apiId : curApi . apiId ,
476+ bindType : curApi . bindType ,
477+ usagePlan,
478+ endpoint
479+ } )
480+ }
376481
377482 apiList . push ( curApi )
378483 console . debug (
@@ -413,11 +518,63 @@ class Apigw {
413518
414519 async remove ( inputs ) {
415520 const { created, environment, serviceId, apiList, customDomains } = inputs
416- // remove all apis
521+ // 1. remove all apis
417522 for ( let i = 0 ; i < apiList . length ; i ++ ) {
418523 const curApi = apiList [ i ]
419- // TODO: remove usagePlan and api auth(secretIds)
420- // delete only apis created by serverless framework
524+
525+ // 1. remove usage plan
526+ if ( curApi . usagePlan ) {
527+ // 1.1 unbind secrete ids
528+ const { secrets } = curApi . usagePlan
529+ if ( secrets && secrets . secretIds ) {
530+ await this . request ( {
531+ Action : 'UnBindSecretIds' ,
532+ secretIds : secrets . secretIds ,
533+ usagePlanId : curApi . usagePlan . id
534+ } )
535+ console . debug ( `Unbinding secret key to usage plan with ID ${ curApi . usagePlan . id } .` )
536+
537+ // delelet all created api key
538+ if ( curApi . usagePlan . secrets . created === true ) {
539+ for ( let sIdx = 0 ; sIdx < secrets . secretIds . length ; sIdx ++ ) {
540+ const secretId = secrets . secretIds [ sIdx ]
541+ await this . request ( {
542+ Action : 'DisableApiKey' ,
543+ secretId
544+ } )
545+ await this . request ( {
546+ Action : 'DeleteApiKey' ,
547+ secretId
548+ } )
549+ console . debug ( `Removing any previously deployed secret key. ${ secretId } ` )
550+ }
551+ }
552+ }
553+
554+ // 1.2 unbind environment
555+ await this . request ( {
556+ Action : 'UnBindEnvironment' ,
557+ serviceId,
558+ usagePlanIds : [ curApi . usagePlan . id ] ,
559+ environment,
560+ bindType : curApi . bindType ,
561+ apiIds : [ curApi . apiId ]
562+ } )
563+ console . debug (
564+ `Unbinding usage plan with ID ${ curApi . usagePlan . id } to service with ID ${ serviceId } .`
565+ )
566+
567+ // 1.3 delete created usage plan
568+ if ( curApi . usagePlan . created === true ) {
569+ console . debug ( `Removing any previously deployed usage plan ids ${ curApi . usagePlan . id } ` )
570+ await this . request ( {
571+ Action : 'DeleteUsagePlan' ,
572+ usagePlanId : curApi . usagePlan . id
573+ } )
574+ }
575+ }
576+
577+ // 2. delete only apis created by serverless framework
421578 if ( curApi . apiId && curApi . created === true ) {
422579 console . debug ( `Removing api: ${ curApi . apiId } ` )
423580 await this . request ( {
@@ -427,7 +584,8 @@ class Apigw {
427584 } )
428585 }
429586 }
430- // unbind all custom domains
587+
588+ // 2. unbind all custom domains
431589 if ( customDomains ) {
432590 for ( let i = 0 ; i < customDomains . length ; i ++ ) {
433591 const curDomain = customDomains [ i ]
@@ -442,7 +600,7 @@ class Apigw {
442600 }
443601 }
444602
445- // unrelease service
603+ // 3. unrelease service
446604 console . debug ( `Unreleasing service: ${ serviceId } , environment: ${ environment } ` )
447605 await this . request ( {
448606 Action : 'UnReleaseService' ,
0 commit comments