diff --git a/README.md b/README.md index 9e9bb81f..e2277fe5 100644 --- a/README.md +++ b/README.md @@ -748,7 +748,7 @@ factory.create(config).then(model => { | config.labels | Array | No | Labels attached to the template | #### Get -Get an template based on id. +Get a template based on id. ```js factory.get(id).then(model => { // do stuff with template model @@ -758,6 +758,22 @@ factory.get(id).then(model => { | Parameter | Type | Description | | :------------- | :---- | :-------------| | id | String | The unique ID for the Template | + +#### Get Template +Get the latest template by name, version with/without label. The version can be in any valid version format. It can can be only major, or major.minor, or major.minor.patch. If label is specified, then the latest version with that label will be resolved. If no match found, the function will resolve undefined. +```js +factory.get(config).then(model => { + // do stuff with template model +}); +``` + +| Parameter | Type | Required | Description | +| :------------- | :---- | :-------------| :-------------| +| config | Object | Yes | Configuration Object | +| config.name | String | Yes | The template name | +| config.version | String | Yes | Version of the template | +| config.label | String | No | Label of the template | + ## Testing ```bash diff --git a/lib/templateFactory.js b/lib/templateFactory.js index 67185ca1..3caa4c97 100644 --- a/lib/templateFactory.js +++ b/lib/templateFactory.js @@ -2,6 +2,7 @@ const BaseFactory = require('./baseFactory'); const Template = require('./template'); +const compareVersions = require('compare-versions'); let instance; class TemplateFactory extends BaseFactory { @@ -51,6 +52,36 @@ class TemplateFactory extends BaseFactory { return super.create(config); } + /** + * Get a the latest template by config + * @method getTemplate + * @param {Object} config Config object + * @param {String} config.name The template name + * @param {String} config.version Version of the template + * @param {String} [config.label] Label of template + * @return {Promise} Resolves template model or undefined if not found + */ + getTemplate(config) { + // get all templates with the same name + return super.list({ name: config.name }) + .then((templates) => { + // get templates that have version prefix as config.version + const filtered = templates.filter(template => + template.version.startsWith(config.version)); + + // Sort templates by descending order + filtered.sort((a, b) => compareVersions(b.version, a.version)); + + // If no config.label, return latest one + if (filtered.length > 0 && !config.label) { + return filtered[0]; + } + + // Loop through filtered to find the first match for config.label + return filtered.find(template => template.labels.includes(config.label)); + }); + } + /** * Get an instance of the TemplateFactory * @method getInstance diff --git a/package.json b/package.json index 78d03446..f9f2d77a 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ }, "dependencies": { "async": "^2.0.1", + "compare-versions": "^3.0.0", "hoek": "^4.0.1", "iron": "^4.0.1", "screwdriver-config-parser": "^3.0.1", diff --git a/test/lib/templateFactory.test.js b/test/lib/templateFactory.test.js index fb1f0490..ecc504eb 100644 --- a/test/lib/templateFactory.test.js +++ b/test/lib/templateFactory.test.js @@ -38,7 +38,8 @@ describe('Template Factory', () => { beforeEach(() => { datastore = { save: sinon.stub(), - get: sinon.stub() + get: sinon.stub(), + scan: sinon.stub() }; // eslint-disable-next-line global-require @@ -122,4 +123,77 @@ describe('Template Factory', () => { Error, 'No datastore provided to TemplateFactory'); }); }); + + describe('getTemplate', () => { + let config; + let expected; + let returnValue; + + beforeEach(() => { + config = { + name: 'testTemplateName', + version: '1.0' + }; + + returnValue = [ + { + id: '151c9b11e4a9a27e9e374daca6e59df37d8cf00f', + name: 'testTemplateName', + version: '1.0.1', + labels: ['testLabel', 'otherLabel'] + }, + { + id: 'd398fb192747c9a0124e9e5b4e6e8e841cf8c71c', + name: 'testTemplateName', + version: '1.0.3', + labels: ['otherLabel'] + }, + { + id: '151c9b11e4a9a27e9e374daca6e59df37d8cf00f', + name: 'testTemplateName', + version: '1.0.2', + labels: ['testLabel', 'otherLabel'] + }, + { + id: '151c9b11e4a9a27e9e374daca6e59df37d8cf00f', + name: 'testTemplateName', + version: '2.0.1', + labels: ['testLabel', 'otherLabel'] + } + ]; + }); + + it('should get the correct template for a given config with label', () => { + expected = Object.assign({}, returnValue[2]); + config.label = 'testLabel'; + datastore.scan.resolves(returnValue); + + return factory.getTemplate(config).then((model) => { + assert.instanceOf(model, Template); + Object.keys(expected).forEach((key) => { + assert.strictEqual(model[key], expected[key]); + }); + }); + }); + + it('should get the correct template for a given config without label', () => { + expected = Object.assign({}, returnValue[1]); + datastore.scan.resolves(returnValue); + + return factory.getTemplate(config).then((model) => { + assert.instanceOf(model, Template); + Object.keys(expected).forEach((key) => { + assert.strictEqual(model[key], expected[key]); + }); + }); + }); + + it('should return undefined if no template returned by list ', () => { + datastore.scan.resolves([]); + + return factory.getTemplate(config).then((model) => { + assert.equal(model, undefined); + }); + }); + }); });