Skip to content

Commit

Permalink
feat: Support params configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
medikoo committed Jan 27, 2022
1 parent c8c9f49 commit 4675b57
Show file tree
Hide file tree
Showing 8 changed files with 130 additions and 44 deletions.
2 changes: 1 addition & 1 deletion docs/guides/cicd/README.md
@@ -1,7 +1,7 @@
<!--
title: Serverless Dashboard - CI/CD
menuText: CI/CD
menuOrder: 3
menuOrder: 4
layout: Doc
-->

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/dashboard.md
@@ -1,5 +1,5 @@
<!--
title: Serverless - Dashboard
title: Serverless Dashboard
menuText: Dashboard
menuOrder: 1
layout: Doc
Expand Down
109 changes: 83 additions & 26 deletions docs/guides/parameters.md
@@ -1,7 +1,7 @@
<!--
title: Serverless Dashboard - Parameters
title: Serverless Framework - Parameters
menuText: Parameters
menuOrder: 6
menuOrder: 2
layout: Doc
-->

Expand All @@ -13,59 +13,116 @@ layout: Doc

# Parameters

The Serverless Framework Dashboard enables you to create and manage parameters, helping you to configure and secure your services by securely storing parameters used by your Serverless Framework services. The [Serverless Framework Dashboard](https://app.serverless.com/) provides an interface to store and encrypt parameters and manage access to those parameters from your services. The Serverless Framework loads the parameters when the service is deployed.
Parameters can be defined in `serverless.yml` or in [Serverless Dashboard](https://www.serverless.com/secrets). They can be used for example to:

All parameters are treated as sensitive values, therefore they are always encrypted at rest, and only decrypted during deployment or to load them in the dashboard.
- adapt the configuration based on the stage
- store secrets securely
- share configuration values between team members

## Managing parameter using the dashboard
## Stage parameters

Parameters can be added to either services or instances.
Parameters can be defined **for each stage** in `serverless.yml` under the `params` key:

To manage parameters on the service, go to the **apps** section of the dashboard, and select **settings** under the **...** menu.
```yaml
params:
prod:
domain: myapp.com
dev:
domain: preview.myapp.com
```

To manage parameters on the instance, go to the **app** section of the dashboard, select the instance, and go to the **params** tab.
Use the `default` key to define parameters that apply to all stages by default:

### Inheritance and overriding
```yaml
params:
default:
domain: ${sls:stage}.preview.myapp.com
prod:
domain: myapp.com
dev:
domain: preview.myapp.com
```

Parameters set on instances take precedence over parameters set on services when deploying. If a parameter with the same key is set on both the instance and the service, then the value set on the instance will be used. If a parameter is set on the service, but not the instance, then the value set on the service will be used.
Parameters can then be used via the `${param:XXX}` variables:

This enables you to treat the parameters on services as defaults. This is especially useful in development when you may deploy instances to ephemeral stages (e.g. "feature-x"). In development the instance might not have any new parameters, therefore it will default to the parameters set on the service. However, in other stages, like "prod", or "staging", you may override the service-level parameters with instance-level parameters to use values unique to that stage.
```yaml
provider:
environment:
APP_DOMAIN: ${param:domain}
```

## Using a Parameter in serverless.yml
The variable will be resolved based on the current stage.

In your `serverless.yml` file add the variable `${param:<key>}` anywhere you would like to use the parameter. The `<key>` references the parameter key configured in the profile.
## Serverless Dashboard parameters

When you run `serverless deploy` the parameter values will be obtained, decrypted and used to replace the variables in the `serverless.yml` for the deployment.
[Serverless Dashboard](https://www.serverless.com/secrets) lets you create and manage parameters, which is perfect for storing secrets securely or sharing configuration values across team members.

## Use parameters from the command line
On top of that, Dashboard parameters can be stored on the service (applies to all stages) or on a specific instance (applies to a specific stage).

Parameters can also be accessed on the CLI. You can use this at development time to look up the parameters without opening the dashboard, or in your CI/CD pipeline to use the parameters in custom scripts.
Dashboard parameters are treated as sensitive values, they are always encrypted at rest, and only decrypted during deployment or to view them in the dashboard.

### List parameters
Just like any other parameter, they can be used in `serverless.yml` via the `${param:XXX}` variables:

```yaml
provider:
environment:
STRIPE_SECRET_KEY: ${param:stripeSecret}
```
sls param list

### Creating Serverless Dashboard parameters

Parameters can be created in the [Dashboard](https://app.serverless.com/) at the service level (applies to all stages) or instance level (stage-specific).

To manage parameters on a service, go to the **apps** section of the dashboard, and select **settings** under the **...** menu.

To manage parameters on an instance, go to the **app** section of the dashboard, select the instance, and go to the **params** tab.

### Retrieving parameters from the command line

Dashboard parameters can also be accessed on the CLI. You can use this at development time to look up the parameters without opening the dashboard, or in your CI/CD pipeline to use the parameters in custom scripts.

#### List parameters

If you are in a directory with a `serverless.yml`, the parameters will be listed for the org, app, and service specified in the `serverless.yml` file:

```bash
serverless param list [--stage <stage>]
```

If you are in a directory without a `serverless.yml`, or if you want to access parameters from another org, app, service, stage, or region, you can pass in the optional flags:

```bash
serverless param list
[--org <org>]
[--app <app>]
[--service <service>]
[--stage <stage>]
[--region <region>]
```

If you are in a working directory with a `serverless.yml` then the parameters will be listed for the org, app, and service specified in the `serverless.yml` file.
#### Get a parameter

If you are not in a working directory, without a `serverless.yml`, or if you want to access parameters from another org, app, service, stage, or region, you can pass in the optional flags.

### Get a parameter
Individual parameters can also be accessed from the CLI using the `param get` sub-command. This command requires the `--name <name>` flag to identify the parameter name. Like the `sls param list`, you can optionally specify a different org, app, service, stage, ore region using flags.

```
sls param get
--name <name>
```bash
serverless param get --name <name>
[--org <org>]
[--app <app>]
[--service <service>]
[--stage <stage>]
[--region <region>]
```

Individual parameters can also be accessed from the CLI using the `param get` sub-command. This command requires the `--name <name>` flag to identify the parameter name. Like the `sls param list`, you can optionally specify a different org, app, service, stage, ore region using flags.
## Inheritance and overriding

Parameters can be defined in `serverless.yml` per stage, as well as in Serverless Dashboard on the service or the instance (stage). Here is the priority used to resolve a `${param:XXX}` variable:

- First, look in `params.<stage>` in `serverless.yml`
- If not found, then look in the instance's parameters in the Dashboard
- If not found, then look in `params.default` in `serverless.yml`
- If not found, then look in the service's parameters in the Dashboard
- If not found, throw an error, or use the fallback value if one was provided: `${param:XXX, 'default value'}`

This gives you flexibility to mix `serverless.yml` parameters as well as secure Serverless Dashboard parameters.

This is especially useful in development when deploying to ephemeral stages (e.g. "feature-x"). The stage might not have any parameter, therefore it will default to the parameters set on the service. However, in other stages, like "prod", or "staging", you may override the service-level parameters with stage-level parameters to use values unique to that stage.
2 changes: 1 addition & 1 deletion docs/guides/plugins/README.md
@@ -1,7 +1,7 @@
<!--
title: Serverless Framework - Plugins
menuText: Plugins
menuOrder: 2
menuOrder: 3
description: How to install plugins to customize the Serverless Framework
layout: Doc
-->
Expand Down
6 changes: 6 additions & 0 deletions docs/providers/aws/guide/serverless.yml.md
Expand Up @@ -296,6 +296,12 @@ provider:
versioningConfiguration:
Status: Enabled

params: # Stage parameters
prod: # Values for the "prod" stage
my-parameter: foo
dev: # Values for the "dev" stage
my-parameter: bar

package: # Optional deployment packaging configuration
patterns: # Specify the directories and files which should be included in the deployment package
- src/**
Expand Down
15 changes: 15 additions & 0 deletions docs/providers/aws/guide/variables.md
Expand Up @@ -41,6 +41,7 @@ You can define your own variable syntax (regex) if it conflicts with CloudFormat
- [Other properties defined in `serverless.yml`](#reference-properties-in-serverlessyml)
- [Serverless Core variables](#referencing-serverless-core-variables)
- [Environment variables](#referencing-environment-variables)
- [Parameters](#referencing-parameters)
- [CLI options](#referencing-cli-options)
- [External YAML/JSON files](#reference-properties-in-other-files)
- [Variables from S3](#referencing-s3-objects)
Expand Down Expand Up @@ -158,6 +159,20 @@ functions:

In the above example you're dynamically adding a prefix to the function names by referencing the `FUNC_PREFIX` env var. So you can easily change that prefix for all functions by changing the `FUNC_PREFIX` env var.

## Referencing Parameters

Parameters can be defined in `serverless.yml` under the `params` key, or in [Serverless Dashboard](https://www.serverless.com/secrets).

To reference parameters, use the `${param:XXX}` syntax in `serverless.yml`.

```yaml
provider:
environment:
APP_DOMAIN: ${param:domain}
```

Read all about parameters in the [Parameters documentation](../../../guides/parameters.md).

## Referencing CLI Options

To reference CLI options that you passed, use the `${opt:<option>}` syntax in your `serverless.yml` configuration file. It is valid to use the empty string in place of `<option>`. This looks like "`${opt:}`" and the result of declaring this in your `serverless.yml` is to embed the complete `options` object (i.e. all the command line options from your `serverless` command).
Expand Down
9 changes: 9 additions & 0 deletions lib/configSchema.js
Expand Up @@ -86,6 +86,15 @@ const schema = {
},
additionalProperties: false,
},
params: {
type: 'object',
patternProperties: {
[stagePattern]: {
type: 'object',
},
},
additionalProperties: false,
},
plugins: {
anyOf: [
{
Expand Down
29 changes: 14 additions & 15 deletions scripts/serverless.js
Expand Up @@ -714,16 +714,18 @@ const processSpanPromise = (async () => {
}

// Register dashboard specific variable source resolvers
if (
// TODO: Remove "tenant" support with next major
(configuration.org || configuration.tenant) &&
serverless.pluginManager.dashboardPlugin
) {
for (const [sourceName, sourceConfig] of Object.entries(
serverless.pluginManager.dashboardPlugin.configurationVariablesSources
)) {
resolverConfiguration.sources[sourceName] = sourceConfig;
resolverConfiguration.fulfilledSources.add(sourceName);
if (serverless.pluginManager.dashboardPlugin) {
if (configuration.org) {
for (const [sourceName, sourceConfig] of Object.entries(
serverless.pluginManager.dashboardPlugin.configurationVariablesSources
)) {
resolverConfiguration.sources[sourceName] = sourceConfig;
resolverConfiguration.fulfilledSources.add(sourceName);
}
} else {
resolverConfiguration.sources.param =
serverless.pluginManager.dashboardPlugin.configurationVariablesSources.param;
resolverConfiguration.fulfilledSources.add('param');
}
}

Expand Down Expand Up @@ -766,7 +768,7 @@ const processSpanPromise = (async () => {
for (const propertyPath of propertyPaths) legacySsmVarPropertyPaths.add(propertyPath);
unresolvedSources.delete(sourceType);
}
if (sourceType === 'param' || sourceType === 'output') {
if (sourceType === 'output') {
logDeprecation(
'NEW_VARIABLES_RESOLVER',
'"param" and "output" variables can only be used in ' +
Expand Down Expand Up @@ -825,10 +827,7 @@ const processSpanPromise = (async () => {
(sourceName) => !recognizedSourceNames.has(sourceName)
);

if (
unrecognizedSourceNames.includes('param') ||
unrecognizedSourceNames.includes('output')
) {
if (unrecognizedSourceNames.includes('output')) {
throw new ServerlessError(
'"Cannot resolve configuration: ' +
'"param" and "output" variables can only be used in ' +
Expand Down

0 comments on commit 4675b57

Please sign in to comment.