weixu365 / serverless-scriptable-plugin

Adding script support to Serverless 1.x which enables you to customize Serverless behavior without writing a plugin.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

scripts should be given a callback to define when work is done

tommedema opened this issue · comments

If I define a script like so:

custom:
  scriptHooks:
    before:aws:package:finalize:saveServiceState: scripts/define-certificate-is-valid.js # define whether the stack's certificate is valid prior to consuming it

It should run BEFORE aws:package:finalize:saveServiceState. SaveServiceState runs code that compiles the cloudformation template. I can then confirm if the script is run at the correct time by adding a log line at saveCompiledTemplate.js:

'use strict';

const BbPromise = require('bluebird');
const path = require('path');

module.exports = {
  saveCompiledTemplate() {
    const compiledTemplateFileName = this.provider.naming.getCompiledTemplateFileName();

    const compiledTemplateFilePath = path.join(
      this.serverless.config.servicePath,
      '.serverless',
      compiledTemplateFileName
    );

    console.log('!!! writing compiled template file')
    console.log(this.serverless.service.provider.compiledCloudFormationTemplate)
    this.serverless.utils.writeFileSync(compiledTemplateFilePath,
      this.serverless.service.provider.compiledCloudFormationTemplate);

    return BbPromise.resolve();
  },
};

And a log line in my script, which should run first:

/* global serverless, options */

log('initializing')

const getServerlessPlugin = require(__dirname + '/lib/get-serverless-plugin')(serverless)
const awsInfo = getServerlessPlugin('AwsInfo')
const getOutput = require(__dirname + '/lib/get-cf-output')(serverless, awsInfo)
const get = require('lodash.get')
const util = require('util')

awsInfo.getStackInfo()
.then(() => {
  
  var condition = get(serverless,
    ['service', 'provider', 'compiledCloudFormationTemplate',
    'Conditions', 'ShouldConsumeCertificate'])
  
  log(`initial certificate condition is ${util.inspect(condition, { depth: 10 })}`)
    
  var updatedCondition = JSON.parse(
    JSON.stringify(condition).replace('%SCRIPT_SUBSTITUTE_CERTIFICATE_IS_VALID%', 'true'))
  
  condition = updatedCondition
  
  serverless.service.provider.compiledCloudFormationTemplate.Conditions.ShouldConsumeCertificate = updatedCondition
  serverless.service.resources.Conditions.ShouldConsumeCertificate = updatedCondition
  
  log(`updated certificate condition is ${util.inspect(condition, { depth: 10 })}`)
})
.catch((err) => console.error(err))

function log(msg) {
  serverless.cli.log(`define-certificate-is-valid: ${msg}`)
}

And the console logs:

Serverless: Invoke aws:package:finalize
Running javascript file: scripts/define-certificate-is-valid.js
Serverless: define-certificate-is-valid: initializing
!!! writing compiled template file
{ ... }
Serverless: Invoke aws:common:moveArtifactsToPackage
Serverless: Invoke aws:common:validate
Serverless: Invoke aws:deploy:deploy
Serverless: define-certificate-is-valid: initial certificate condition is { 'Fn::Equals': [ '%SCRIPT_SUBSTITUTE_CERTIFICATE_IS_VALID%', 'true' ] }
Serverless: define-certificate-is-valid: updated certificate condition is { 'Fn::Equals': [ 'true', 'true' ] }

So, while it outputs initializing at the right time, the rest is executed after awsInfo.getStackInfo() resolves. Meanwhile serverless continues its work before my script can do its job.

Serverless should pause execution while my script its doing its job.

Note that with plugins this can be solved by returning a promise (see serverless/serverless#4557).

But in this case this is not possible since you are calling a node script without a function wrapper, and there is no return statement.

Fixed in the new version 0.7.0, could you please upgrade the module and have a test?

@tommedema Any updates on this issue?

Hey @weixu365 . I actually switched to using plugins, because I didn't like how this plugin requires me to use globals (serverless and options)

Let me know if you really want me to test this anyway