Skip to content

Commit

Permalink
allow configurable master alias
Browse files Browse the repository at this point in the history
  • Loading branch information
Aleksander Dikanski authored and Aleksander Dikanski committed May 10, 2019
1 parent 162f371 commit 94ae91a
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 17 deletions.
21 changes: 18 additions & 3 deletions lib/aliasRestructureStack.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,15 +73,30 @@ module.exports = {
return BbPromise.resolve([ currentTemplate, aliasStackTemplates, currentAliasStackTemplate ]);
},

aliasRestructureStack(currentTemplate, aliasStackTemplates, currentAliasStackTemplate) {
addMasterAliasName(currentTemplate, aliasStackTemplates, currentAliasStackTemplate) {
const stageStack = this._serverless.service.provider.compiledCloudFormationTemplate;
if (stageStack && !stageStack.Outputs.MasterAliasName) {
const masterAlias = this._masterAlias || currentTemplate.Outputs.MasterAliasName.Value;
stageStack.Outputs.MasterAliasName = {
Description: 'Master Alias name (serverless-aws-alias plugin)',
Value: masterAlias,
Export: {
Name: `${this._provider.naming.getStackName()}-MasterAliasName`
}
};
}
return BbPromise.resolve([ currentTemplate, aliasStackTemplates, currentAliasStackTemplate ]);
},

aliasRestructureStack(currentTemplate, aliasStackTemplates, currentAliasStackTemplate) {
this._serverless.cli.log('Preparing alias ...');

if (_.isEmpty(aliasStackTemplates) && this._stage !== this._alias) {
throw new this._serverless.classes.Error(new Error('You have to deploy the master alias at least once with "serverless deploy"'));
if (_.isEmpty(aliasStackTemplates) && this._masterAlias !== this._alias) {
throw new this._serverless.classes.Error(new Error('You have to deploy the master alias at least once with "serverless deploy [--masterAlias]"'));
}

return BbPromise.resolve([ currentTemplate, aliasStackTemplates, currentAliasStackTemplate ]).bind(this)
.spread(this.addMasterAliasName)
.spread(this.aliasInit)
.spread(this.aliasHandleUserResources)
.spread(this.aliasHandleLambdaRole)
Expand Down
13 changes: 7 additions & 6 deletions lib/removeAlias.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,26 +221,27 @@ module.exports = {
this._serverless.cli.log('noDeploy option active - will do nothing');
return BbPromise.resolve();
}

if (this._stage && this._stage === this._alias) {

this._masterAlias = currentTemplate.Outputs.MasterAliasName.Value;
if (this._stage && this._masterAlias === this._alias) {
// Removal of the master alias is requested -> check if any other aliases are still deployed.
const aliases = _.map(aliasStackTemplates, aliasTemplate => _.get(aliasTemplate, 'Outputs.ServerlessAliasName.Value'));
if (!_.isEmpty(aliases)) {
throw new this._serverless.classes.Error(`Remove the other deployed aliases before removing the service: ${_.without(aliases, this._alias)}`);
throw new this._serverless.classes.Error(`Remove the other deployed aliases before removing the service: ${_.without(aliases, this._masterAlias)}`);
}
if (_.isEmpty(currentAliasStackTemplate)) {
throw new this._serverless.classes.Error(`Internal error: Stack for master alias ${this._alias} is not deployed. Try to solve the problem by manual interaction with the AWS console.`);
throw new this._serverless.classes.Error(`Internal error: Stack for master alias ${this._masterAlias} is not deployed. Try to solve the problem by manual interaction with the AWS console.`);
}

// We're ready for removal
this._serverless.cli.log(`Removing master alias and stage ${this._alias} ...`);
this._serverless.cli.log(`Removing master alias and stage ${this._masterAlias} ...`);

return BbPromise.resolve([ currentTemplate, aliasStackTemplates, currentAliasStackTemplate ]).bind(this)
.spread(this.aliasRemoveAliasStack)
.then(() => this._serverless.pluginManager.spawn('remove'));
}

this._serverless.cli.log(`Removing alias ${this._alias} ...`);
this._serverless.cli.log(`Removing alias ${this._masterAlias} ...`);

return BbPromise.resolve([ currentTemplate, aliasStackTemplates, currentAliasStackTemplate ]).bind(this)
.spread(this.aliasCreateStackChanges)
Expand Down
3 changes: 2 additions & 1 deletion lib/validate.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ module.exports = {

// Set configuration
this._stage = this._provider.getStage();
this._alias = this._options.alias || this._stage;
this._masterAlias = this._options.masterAlias || this._stage;
this._alias = this._options.alias || this._masterAlias;
this._stackName = this._provider.naming.getStackName();

// Make alias available as ${self:provider.alias}
Expand Down
41 changes: 41 additions & 0 deletions test/aliasRestructureStack.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,45 @@ describe('aliasRestructureStack', () => {
sandbox.restore();
});

describe('#addMasterAliasName', () => {
it('should add the master alias name as output from command line option', () => {
serverless.service.provider.compiledCloudFormationTemplate = _.cloneDeep({
Resources: {},
Outputs: {}
});
awsAlias._masterAlias = 'master'
return expect(awsAlias.addMasterAliasName()).to.be.fulfilled
.then(() =>
expect(serverless.service.provider.compiledCloudFormationTemplate.Outputs.MasterAliasName.Value)
.to.equal('master')
);
});

it('should add the master alias name as output from existing stack', () => {
const masterAliasStackOutput = {
MasterAliasName: {
Description: 'Master Alias name (serverless-aws-alias plugin)',
Value: 'master',
Export: {
Name: 'sls-test-project-dev-master'
}
}
};
const currentTemplate = {
Outputs: masterAliasStackOutput
};
serverless.service.provider.compiledCloudFormationTemplate = _.cloneDeep({
Resources: {},
Outputs: {}
});
return expect(awsAlias.addMasterAliasName(currentTemplate)).to.be.fulfilled
.then(() =>
expect(serverless.service.provider.compiledCloudFormationTemplate.Outputs.MasterAliasName.Value)
.to.equal('master')
);
});
});

describe('#aliasFinalize()', () => {
it('should stringify flags', () => {
serverless.service.provider.compiledCloudFormationAliasTemplate = {
Expand Down Expand Up @@ -85,6 +124,7 @@ describe('aliasRestructureStack', () => {
});

it('should propagate templates through all stack operations', () => {
const addMasterAliasNameSpy = sandbox.spy(awsAlias, 'addMasterAliasName');
const aliasInitSpy = sandbox.spy(awsAlias, 'aliasInit');
const aliasHandleUserResourcesSpy = sandbox.spy(awsAlias, 'aliasHandleUserResources');
const aliasHandleLambdaRoleSpy = sandbox.spy(awsAlias, 'aliasHandleLambdaRole');
Expand All @@ -102,6 +142,7 @@ describe('aliasRestructureStack', () => {
return expect(awsAlias.aliasRestructureStack(currentTemplate, [ aliasTemplate ], currentAliasStackTemplate))
.to.be.fulfilled
.then(() => BbPromise.all([
expect(addMasterAliasNameSpy).to.have.been.calledWithExactly(currentTemplate, [ aliasTemplate ], currentAliasStackTemplate),
expect(aliasInitSpy).to.have.been.calledWithExactly(currentTemplate, [ aliasTemplate ], currentAliasStackTemplate),
expect(aliasHandleUserResourcesSpy).to.have.been.calledWithExactly(currentTemplate, [ aliasTemplate ], currentAliasStackTemplate),
expect(aliasHandleLambdaRoleSpy).to.have.been.calledWithExactly(currentTemplate, [ aliasTemplate ], currentAliasStackTemplate),
Expand Down
7 changes: 7 additions & 0 deletions test/data/sls-stack-2.json
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,13 @@
]
]
}
},
"MasterAliasName": {
"Description": "Master Alias name (serverless-aws-alias plugin)",
"Value": "master",
"Export": {
"Name": "sls-test-project-dev-master"
}
}
}
}
18 changes: 15 additions & 3 deletions test/removeAlias.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ describe('removeAlias', () => {

it('should error if an alias is deployed on stage removal', () => {
awsAlias._options = { alias: 'myStage' };
awsAlias._alias = 'myStage';
awsAlias._alias = 'master';
slsStack1.Outputs.MasterAliasName = {
Value: 'master'
};

expect(() => awsAlias.removeAlias(slsStack1, [ aliasStack1 ], aliasStack2)).to.throw(/myAlias/);
return BbPromise.all([
Expand All @@ -103,7 +106,10 @@ describe('removeAlias', () => {

it('should error if the master alias is not deployed on stage removal', () => {
awsAlias._options = { alias: 'myStage' };
awsAlias._alias = 'myStage';
awsAlias._alias = 'master';
slsStack1.Outputs.MasterAliasName = {
Value: 'master'
};

expect(() => awsAlias.removeAlias(slsStack1, [], {})).to.throw(/Internal error/);
return BbPromise.all([
Expand All @@ -116,7 +122,10 @@ describe('removeAlias', () => {

it('should remove alias and service stack on stage removal', () => {
awsAlias._options = { alias: 'myStage' };
awsAlias._alias = 'myStage';
awsAlias._alias = 'master';
slsStack1.Outputs.MasterAliasName = {
Value: 'master'
};

return expect(awsAlias.removeAlias(slsStack1, [], aliasStack2)).to.be.fulfilled
.then(() => BbPromise.all([
Expand All @@ -128,6 +137,9 @@ describe('removeAlias', () => {
});

it('should remove alias stack', () => {
slsStack1.Outputs.MasterAliasName = {
Value: 'master'
};
aliasApplyStackChangesStub.returns([ slsStack1, [ aliasStack2 ], aliasStack1 ]);
aliasCreateStackChangesStub.returns([ slsStack1, [ aliasStack2 ], aliasStack1 ]);
aliasRemoveAliasStackStub.returns([ slsStack1, [ aliasStack2 ], aliasStack1 ]);
Expand Down
4 changes: 0 additions & 4 deletions test/updateAliasStack.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,6 @@ describe('updateAliasStack', () => {
it('should resolve in case no updates are performed', () => {
providerRequestStub.returns(BbPromise.resolve("done"));
monitorStackStub.rejects(new Error('No updates are to be performed.'));
<<<<<<< HEAD
=======

>>>>>>> 2b80fe1... useless exception messages are removed while mocha ci
return expect(awsAlias.updateAlias()).to.be.fulfilled
.then(() => expect(providerRequestStub).to.have.been.calledOnce);
});
Expand Down

0 comments on commit 94ae91a

Please sign in to comment.