Skip to content

Commit

Permalink
refactor(Variables): Seclude resolution of sources from external plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
medikoo committed Jun 2, 2021
1 parent 1b90dfb commit 6efc161
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 60 deletions.
@@ -0,0 +1,66 @@
'use strict';

const ensurePlainObject = require('type/plain-object/ensure');
const ensurePlainFunction = require('type/plain-function/ensure');
const ServerlessError = require('../../../serverless-error');
const logDeprecation = require('../../../utils/logDeprecation');

module.exports = (configuration, resolverConfiguration, externalPlugins) => {
for (const externalPlugin of externalPlugins) {
const pluginName = externalPlugin.constructor.name;
if (externalPlugin.configurationVariablesSources != null) {
ensurePlainObject(externalPlugin.configurationVariablesSources, {
errorMessage:
'Invalid "configurationVariablesSources" ' +
`configuration on "${pluginName}", expected object, got: %v"`,
Error: ServerlessError,
errorCode: 'INVALID_VARIABLE_SOURCES_CONFIGURATION',
});

for (const [sourceName, sourceConfig] of Object.entries(
externalPlugin.configurationVariablesSources
)) {
if (resolverConfiguration.sources[sourceName]) {
throw new ServerlessError(
`Cannot add "${sourceName}" configuration variable source ` +
`(through "${pluginName}" plugin) as resolution rules ` +
'for this source name are already configured',
'DUPLICATE_VARIABLE_SOURCE_CONFIGURATION'
);
}
ensurePlainFunction(
ensurePlainObject(sourceConfig, {
errorMessage:
`Invalid "configurationVariablesSources.${sourceName}" ` +
`configuration on "${pluginName}", expected object, got: %v"`,
Error: ServerlessError,
errorCode: 'INVALID_VARIABLE_SOURCE_CONFIGURATION',
}).resolve,
{
errorMessage:
`Invalid "configurationVariablesSources.${sourceName}.resolve" ` +
`value on "${pluginName}", expected function, got: %v"`,
Error: ServerlessError,
errorCode: 'INVALID_VARIABLE_SOURCE_RESOLVER_CONFIGURATION',
}
);

resolverConfiguration.sources[sourceName] = sourceConfig;
resolverConfiguration.fulfilledSources.add(sourceName);
}
} else if (
externalPlugin.variableResolvers &&
configuration.variablesResolutionMode < 20210326
) {
logDeprecation(
'NEW_VARIABLES_RESOLVER',
`Plugin "${pluginName}" attempts to extend old variables resolver. ` +
'Ensure to rely on latest version of a plugin and if this warning is ' +
'still displayed please report the problem at plugin issue tracker' +
'Starting with next major release, ' +
'old variables resolver will not be supported.\n',
{ serviceConfig: configuration }
);
}
}
};
66 changes: 6 additions & 60 deletions scripts/serverless.js
Expand Up @@ -554,67 +554,13 @@ const processSpanPromise = (async () => {
}
}

const ensurePlainFunction = require('type/plain-function/ensure');
const ensurePlainObject = require('type/plain-object/ensure');

// Register variable source resolvers provided by external plugins
for (const externalPlugin of serverless.pluginManager.externalPlugins) {
const pluginName = externalPlugin.constructor.name;
if (externalPlugin.configurationVariablesSources != null) {
ensurePlainObject(externalPlugin.configurationVariablesSources, {
errorMessage:
'Invalid "configurationVariablesSources" ' +
`configuration on "${pluginName}", expected object, got: %v"`,
Error: ServerlessError,
errorCode: 'INVALID_VARIABLE_SOURCES_CONFIGURATION',
});

for (const [sourceName, sourceConfig] of Object.entries(
externalPlugin.configurationVariablesSources
)) {
if (resolverConfiguration.sources[sourceName]) {
throw new ServerlessError(
`Cannot add "${sourceName}" configuration variable source ` +
`(through "${pluginName}" plugin) as resolution rules ` +
'for this source name are already configured',
'DUPLICATE_VARIABLE_SOURCE_CONFIGURATION'
);
}
ensurePlainFunction(
ensurePlainObject(sourceConfig, {
errorMessage:
`Invalid "configurationVariablesSources.${sourceName}" ` +
`configuration on "${pluginName}", expected object, got: %v"`,
Error: ServerlessError,
errorCode: 'INVALID_VARIABLE_SOURCE_CONFIGURATION',
}).resolve,
{
errorMessage:
`Invalid "configurationVariablesSources.${sourceName}.resolve" ` +
`value on "${pluginName}", expected function, got: %v"`,
Error: ServerlessError,
errorCode: 'INVALID_VARIABLE_SOURCE_RESOLVER_CONFIGURATION',
}
);

resolverConfiguration.sources[sourceName] = sourceConfig;
resolverConfiguration.fulfilledSources.add(sourceName);
}
} else if (
externalPlugin.variableResolvers &&
configuration.variablesResolutionMode < 20210326
) {
logDeprecation(
'NEW_VARIABLES_RESOLVER',
`Plugin "${pluginName}" attempts to extend old variables resolver. ` +
'Ensure to rely on latest version of a plugin and if this warning is ' +
'still displayed please report the problem at plugin issue tracker' +
'Starting with next major release, ' +
'old variables resolver will not be supported.\n',
{ serviceConfig: configuration }
);
}
}
const resolverExternalPluginSources = require('../lib/configuration/variables/sources/resolve-external-plugin-sources');
resolverExternalPluginSources(
configuration,
resolverConfiguration,
serverless.pluginManager.externalPlugins
);

// Having all source resolvers configured, resolve variables
await resolveVariables(resolverConfiguration);
Expand Down
@@ -0,0 +1,90 @@
'use strict';

const { expect } = require('chai');

const ServerlessError = require('../../../../../../lib/serverless-error');
const resolveExternalPluginSources = require('../../../../../../lib/configuration/variables/sources/resolve-external-plugin-sources');

describe('test/unit/lib/configuration/variables/sources/resolve-external-plugin-resources.test.js', () => {
it('should resolve external plugin sources', () => {
const sources = {};
const fulfilledSources = new Set();
const externalPlugins = [
{
configurationVariablesSources: {
ext1: { resolve: () => {} },
ext2: { resolve: () => {} },
},
},
{
configurationVariablesSources: {
ext3: { resolve: () => {} },
},
},
];
resolveExternalPluginSources({}, { sources, fulfilledSources }, new Set(externalPlugins));
expect(sources).to.deep.equal({
...externalPlugins[0].configurationVariablesSources,
...externalPlugins[1].configurationVariablesSources,
});
expect(fulfilledSources).to.deep.equal(new Set(Object.keys(sources)));
});

it('should reject meaningfully invalid sources configuration', () => {
expect(() =>
resolveExternalPluginSources(
{},
{ sources: {}, fulfilledSources: new Set() },
new Set([
{
configurationVariablesSources: 'foo',
},
])
)
)
.to.throw(ServerlessError)
.with.property('code', 'INVALID_VARIABLE_SOURCES_CONFIGURATION');

expect(() =>
resolveExternalPluginSources(
{},
{ sources: { existing: { resolve: () => {} } }, fulfilledSources: new Set(['existing']) },
new Set([
{
configurationVariablesSources: { existing: { resolve: () => {} } },
},
])
)
)
.to.throw(ServerlessError)
.with.property('code', 'DUPLICATE_VARIABLE_SOURCE_CONFIGURATION');

expect(() =>
resolveExternalPluginSources(
{},
{ sources: {}, fulfilledSources: new Set() },
new Set([
{
configurationVariablesSources: { source: 'foo' },
},
])
)
)
.to.throw(ServerlessError)
.with.property('code', 'INVALID_VARIABLE_SOURCE_CONFIGURATION');

expect(() =>
resolveExternalPluginSources(
{},
{ sources: {}, fulfilledSources: new Set() },
new Set([
{
configurationVariablesSources: { source: { resolve: 'foo ' } },
},
])
)
)
.to.throw(ServerlessError)
.with.property('code', 'INVALID_VARIABLE_SOURCE_RESOLVER_CONFIGURATION');
});
});

0 comments on commit 6efc161

Please sign in to comment.