Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: enable skill after deploy resources finished #30

Merged
merged 1 commit into from
Aug 30, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion lib/commands/deploy/helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ const SkillMetadataController = require('@src/controllers/skill-metadata-control
const SkillCodeController = require('@src/controllers/skill-code-controller');
const SkillInfrastructureController = require('@src/controllers/skill-infrastructure-controller');
const profileHelper = require('@src/utils/profile-helper');
const Messenger = require('@src/view/messenger');

module.exports = {
deploySkillMetadata,
buildSkillCode,
deploySkillInfrastructure
deploySkillInfrastructure,
enableSkill
};

/**
Expand Down Expand Up @@ -63,3 +65,20 @@ function deploySkillInfrastructure(profile, doDebug, callback) {
callback();
});
}

/**
* Funtion used to enable skill
* @param {string} profile The profile name
* @param {Boolean} doDebug The flag of debug or not
* @param {Function} callback
*/
function enableSkill(profile, doDebug, callback) {
const skillMetaController = new SkillMetadataController({ profile, doDebug });
Messenger.getInstance().info('\n==================== Enable Skill ====================');
skillMetaController.enableSkill((error) => {
if (error) {
return callback(error);
}
callback();
});
}
13 changes: 11 additions & 2 deletions lib/commands/deploy/index.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const path = require('path');

const { AbstractCommand } = require('@src/commands/abstract-command');
const Manifest = require('@src/model/manifest');
const ResourcesConfig = require('@src/model/resources-config');
const Manifest = require('@src/model/manifest');
const Messenger = require('@src/view/messenger');
const SpinnerView = require('@src/view/spinner-view');
const optionModel = require('@src/commands/option-model');
Expand Down Expand Up @@ -55,7 +55,16 @@ class DeployCommand extends AbstractCommand {

ResourcesConfig.getInstance().write();
Manifest.getInstance().write();
cb();

// Post deploy logic
// call smapiClient to enable skill
helper.enableSkill(profile, cmd.debug, (enableError) => {
if (enableError) {
Messenger.getInstance().error(enableError);
return cb(enableError);
}
cb();
});
});
}
}
Expand Down
52 changes: 52 additions & 0 deletions lib/controllers/skill-metadata-controller/index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
const fs = require('fs-extra');
const path = require('path');
const R = require('ramda');

const retryUtils = require('@src/utils/retry-utility');
const ResourcesConfig = require('@src/model/resources-config');
const SmapiClient = require('@src/clients/smapi-client/index.js');
const httpClient = require('@src/clients/http-client');
const Manifest = require('@src/model/manifest');
const Messenger = require('@src/view/messenger');
const jsonView = require('@src/view/json-view');
const stringUtils = require('@src/utils/string-utils');
const zipUtils = require('@src/utils/zip-utils');
Expand Down Expand Up @@ -62,6 +65,55 @@ module.exports = class SkillMetadataController {
});
}

/**
* Function used to enable skill. It calls smapi getSkillEnablement function first to check if skill is already enabled,
* if not, it will enable the skill by calling smapi enableSkill function.
* @param {Function} callback (err, null)
*/
enableSkill(callback) {
const skillId = ResourcesConfig.getInstance().getSkillId(this.profile);
const domainInfo = Manifest.getInstance().getApis();
if (!stringUtils.isNonBlankString(skillId)) {
return callback(`[Fatal]: Failed to find the skillId for profile [${this.profile}],
please make sure the skill metadata deployment has succeeded with result of a valid skillId.`);
}
if (!domainInfo || R.isEmpty(domainInfo)) {
return callback('[Error]: Skill information is not valid. Please make sure "apis" field in the skill.json is not empty.');
}

const domainList = R.keys(domainInfo);
if (domainList.length !== 1) {
return callback('[Warn]: Skill with multiple api domains cannot be enabled. Skip the enable process.');
}
if (CONSTANTS.SKILL.DOMAIN.CAN_ENABLE_DOMAIN_LIST.indexOf(domainList[0]) === -1) {
return callback(`[Warn]: Skill api domain "${domainList[0]}" cannot be enabled. Skip the enable process.`);
}

this.smapiClient.skill.getSkillEnablement(skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (err, response) => {
if (err) {
return callback(err);
}
if (response.statusCode === CONSTANTS.HTTP_REQUEST.STATUS_CODE.NOT_FOUND) {
this.smapiClient.skill.enableSkill(skillId, CONSTANTS.SKILL.STAGE.DEVELOPMENT, (enableErr, enableResponse) => {
if (enableErr) {
return callback(enableErr);
}
if (enableResponse.statusCode >= 300) {
return callback(jsonView.toString(enableResponse.body));
}
Messenger.getInstance().info('Skill is enabled successfully.');

callback();
});
} else if (response.statusCode >= 300) {
callback(jsonView.toString(response.body));
} else {
Messenger.getInstance().info('Skill is already enabled, skip the enable process.');
callback();
}
});
}

/**
* Put skill package based on the input of skillId and vendorId:
* when vendorId is set but skillId is not, create skill package;
Expand Down
3 changes: 3 additions & 0 deletions lib/utils/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ module.exports.SKILL = {
SUCCESS: 'SUCCESSFUL',
FAILURE: 'FAILED',
IN_PROGRESS: 'IN_PROGRESS'
},
DOMAIN: {
CAN_ENABLE_DOMAIN_LIST: ['custom', 'music']
}
};

Expand Down
39 changes: 39 additions & 0 deletions test/unit/commands/deploy/helper-test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
const { expect } = require('chai');
const sinon = require('sinon');
const Messenger = require('@src/view/messenger');

const helper = require('@src/commands/deploy/helper');
const SkillMetadataController = require('@src/controllers/skill-metadata-controller');
Expand Down Expand Up @@ -112,4 +113,42 @@ describe('Commands deploy test - helper test', () => {
});
});
});

describe('# test helper method - enableSkill', () => {
let infoStub;
beforeEach(() => {
infoStub = sinon.stub();
sinon.stub(Messenger, 'getInstance').returns({
info: infoStub,
});
});

afterEach(() => {
sinon.restore();
});

it('| skillMetaController enableSkill fails, expect callback error', (done) => {
// setup
sinon.stub(SkillMetadataController.prototype, 'enableSkill').callsArgWith(0, 'error');
// call
helper.enableSkill(TEST_PROFILE, TEST_DO_DEBUG, (err) => {
expect(err).equal('error');
expect(infoStub.args[0][0]).equal('\n==================== Enable Skill ====================');
done();
});
});

it('| skillMetaController enableSkill passes, expect no error callback', (done) => {
// setup
sinon.stub(SkillMetadataController.prototype, 'enableSkill').callsArgWith(0);
// call
helper.enableSkill(TEST_PROFILE, TEST_DO_DEBUG, (err, res) => {
// verify
expect(err).equal(undefined);
expect(res).equal(undefined);
expect(infoStub.args[0][0]).equal('\n==================== Enable Skill ====================');
done();
});
});
});
});
80 changes: 40 additions & 40 deletions test/unit/commands/deploy/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,17 @@ describe('Commands deploy test - command class test', () => {
debug: TEST_DEBUG
};
let instance;
beforeEach(() => {
sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE);
sinon.stub(path, 'join').returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH);
instance = new DeployCommand(optionModel);
});

describe('command handle - before deploy resources', () => {
beforeEach(() => {
sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE);
sinon.stub(path, 'join').returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH);
instance = new DeployCommand(optionModel);
});
afterEach(() => {
sinon.restore();
});

afterEach(() => {
sinon.restore();
});
describe('command handle - before deploy resources', () => {

it('| when profile is not correct, expect throw error', (done) => {
// setup
Expand Down Expand Up @@ -121,16 +121,6 @@ describe('Commands deploy test - command class test', () => {
});

describe('command handle - deploy skill metadata', () => {
beforeEach(() => {
sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE);
sinon.stub(path, 'join').returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH);
instance = new DeployCommand(optionModel);
});

afterEach(() => {
sinon.restore();
});

it('| helper deploy skill metadata fails, expect throw error', (done) => {
// setup
sinon.stub(helper, 'deploySkillMetadata').callsArgWith(2, 'error');
Expand Down Expand Up @@ -165,16 +155,6 @@ describe('Commands deploy test - command class test', () => {
});

describe('command handle - build skill code', () => {
beforeEach(() => {
sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE);
sinon.stub(path, 'join').returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH);
instance = new DeployCommand(optionModel);
});

afterEach(() => {
sinon.restore();
});

it('| helper build skill code fails, expect throw error', (done) => {
// setup
sinon.stub(helper, 'deploySkillMetadata').callsArgWith(2);
Expand All @@ -195,16 +175,6 @@ describe('Commands deploy test - command class test', () => {
});

describe('command handle - deploy skill infrastructure', () => {
beforeEach(() => {
sinon.stub(profileHelper, 'runtimeProfile').returns(TEST_PROFILE);
sinon.stub(path, 'join').returns(FIXTURE_RESOURCES_CONFIG_FILE_PATH);
instance = new DeployCommand(optionModel);
});

afterEach(() => {
sinon.restore();
});

const TEST_CODE_BUILD_RESULT = [{
src: 'codeSrc',
build: {
Expand All @@ -221,6 +191,7 @@ describe('Commands deploy test - command class test', () => {
sinon.stub(helper, 'deploySkillMetadata').callsArgWith(2);
sinon.stub(helper, 'buildSkillCode').callsArgWith(2, null, TEST_CODE_BUILD_RESULT);
sinon.stub(helper, 'deploySkillInfrastructure').callsArgWith(2, 'error');
sinon.stub(helper, 'enableSkill').callsArgWith(2);
sinon.stub(stringUtils, 'isNonBlankString').returns(true);
stringUtils.isNonBlankString.withArgs('@ask-cli/cfn-deployer').returns(false);
sinon.stub(path, 'resolve').returns(TEST_CODE_SRC_BASENAME);
Expand Down Expand Up @@ -250,6 +221,7 @@ with build flow ${TEST_CODE_BUILD_RESULT[0].buildFlow}.`);
sinon.stub(helper, 'deploySkillMetadata').callsArgWith(2);
sinon.stub(helper, 'buildSkillCode').callsArgWith(2, null, TEST_CODE_BUILD_RESULT);
sinon.stub(helper, 'deploySkillInfrastructure').callsArgWith(2, 'error');
sinon.stub(helper, 'enableSkill').callsArgWith(2);
sinon.stub(path, 'resolve').returns(TEST_CODE_SRC_BASENAME);
sinon.stub(fs, 'statSync').returns({
isDirectory: () => true
Expand All @@ -273,11 +245,12 @@ with build flow ${TEST_CODE_BUILD_RESULT[0].buildFlow}.`);
});
});

it('| deploy skill all pass, expect deploy succeeds', (done) => {
it('| deploy skill all pass, expect deploy succeeds and enbalSkill get called', (done) => {
// setup
sinon.stub(helper, 'deploySkillMetadata').callsArgWith(2);
sinon.stub(helper, 'buildSkillCode').callsArgWith(2, null, TEST_CODE_BUILD_RESULT);
sinon.stub(helper, 'deploySkillInfrastructure').callsArgWith(2);
sinon.stub(helper, 'enableSkill').callsArgWith(2);
sinon.stub(path, 'resolve').returns(TEST_CODE_SRC_BASENAME);
sinon.stub(fs, 'statSync').returns({
isDirectory: () => true
Expand All @@ -299,6 +272,33 @@ with build flow ${TEST_CODE_BUILD_RESULT[0].buildFlow}.`);
expect(infoStub.args[6][0]).equal('\n==================== Deploy Skill Infrastructure ====================');
expect(infoStub.args[7][0]).equal('Skill infrastructures deployed successfully through @ask-cli/cfn-deployer.');
expect(warnStub.callCount).equal(0);
expect(helper.enableSkill.calledOnce).equal(true);
done();
});
});
});

describe('command handle - enable skill', () => {
const TEST_CODE_BUILD_RESULT = [{
src: 'codeSrc',
build: {
file: 'buildFile',
folder: 'buildFolder'
},
buildFlow: 'build-flow',
regionsList: ['default', 'NA']
}];

it('| can callbcak error when enable fails', (done) => {
// setup
const TEST_ERROR = 'error';
sinon.stub(helper, 'deploySkillMetadata').callsArgWith(2);
sinon.stub(helper, 'buildSkillCode').callsArgWith(2, null, TEST_CODE_BUILD_RESULT);
sinon.stub(helper, 'deploySkillInfrastructure').callsArgWith(2);
sinon.stub(helper, 'enableSkill').callsArgWith(2, 'error');
instance.handle(TEST_CMD, (err) => {
expect(errorStub.args[0][0]).equal(TEST_ERROR);
expect(err).equal(TEST_ERROR);
done();
});
});
Expand Down
Loading