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

sam deploy should accept parameter file just like aws cloudformation *-stack #2054

Open
rudpot opened this issue Jun 18, 2020 · 18 comments
Open
Labels
area/deploy sam deploy command maintainer/need-followup stage/pm-review Waiting for review by our Product Manager, please don't work on this yet type/feature Feature request

Comments

@rudpot
Copy link

rudpot commented Jun 18, 2020

Description:

I would like to store configuration is version control and make deployment steps immutable. Instead of changing parameter overrides on the command line I would like to provide template parameters from a file.

There is an idiom for this in aws cloudformation create-stack --parameters file://.

Steps to reproduce the issue:

  1. sam deploy --parameter-overrides file://params.json

Observed result:

Error: Invalid value for '--parameter-overrides':  file://params.json is not in valid format. It must look something like 'ParameterKey=KeyPairName,ParameterValue=MyKey ParameterKey=InstanceType,ParameterValue=t1.micro' or 'KeyPairName=MyKey InstanceType=t1.micro'

Expected result:

	Deploying with following values
	===============================
	Stack name                 : ...
	Region                     : ...
	Confirm changeset          : ...
	Deployment s3 bucket       : ...
	Capabilities               : ...
	Parameter overrides        : {'MyParamOverride': 'MyParamValue'}
@jfuss
Copy link
Contributor

jfuss commented Jun 18, 2020

Why not use the samconfig.toml file? https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html

@jfuss jfuss transferred this issue from aws/serverless-application-model Jun 18, 2020
@rudpot
Copy link
Author

rudpot commented Jun 18, 2020

Why not use the samconfig.toml file? https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html

I am trying to set a parameter that is specified in the template. There is no hint in the documentation that this should be possible but following your suggestion it tried the following:

Parameter defined in the template:

Parameters:
  AllowedSrcIp:
    Type: "String"
    Description: "IP address of the client used for testing. If in doubt, deploy the code and the output will guide you"
    Default: "192.168.0.1"

Updated samconfig.toml with the parameters directly:

version = 0.1
[default]
[default.deploy]
[default.deploy.parameters]
stack_name = "api-unsecured-sam"
s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-10ziytzq60hp8"
s3_prefix = "api-unsecured-sam"
region = "us-west-2"
confirm_changeset = false
capabilities = "CAPABILITY_IAM"
AllowedSrcIp = "205.251.233.178"

The deploy works but doesn't honor the new parameter. Looking at the structure of the config I also tried this line:

parameter_overrides = ParameterKey=AllowedSrcIp,ParameterValue=205.251.233.178

Which breaks the deployment entirely:

sam deploy
Usage: sam deploy [OPTIONS]
Try 'sam deploy --help' for help.

Error: Missing option '--stack-name', 'sam deploy --guided' can be used to provide and save needed parameters for future deploys.

And this:

parameter_overrides = "ParameterKey=AllowedSrcIp,ParameterValue=205.251.233.178"

And this:

parameter_overrides = "AllowedSrcIp=205.251.233.178"

both of which do work but are really hard to maintain if you have more than a couple parameters or if your parameters need complex quoting. In fact it turns out that if you were to enter the data interactively as a result of using sam deploy --guided it will create something like this which highlights the issue:

parameter_overrides = "VpcIdParameter=\"vpc-0000111122223333\" VpcAllowedSecurityGroupIdParameter=\"sg-0000111122223333\" VpcEndpointSubnetIdsParameter=\"subnet-0000111122223333 \""

@awood45 awood45 added the type/feature Feature request label Jun 26, 2020
@what-name
Copy link

As @rudpot mentioned, the following parameter_overrides value is rather tedious to maintain with more than a couple entries:

parameter_overrides = "VpcIdParameter=\"vpc-0000111122223333\" VpcAllowedSecurityGroupIdParameter=\"sg-0000111122223333\" VpcEndpointSubnetIdsParameter=\"subnet-0000111122223333 \""

+1 for a simpler approach.

@rojomisin
Copy link

work around until a file can be used is to wrap w/ shell or make

...
		--parameter-overrides \
			DBUsername=$(DBUSER) \
			DBPassword=\"$(shell get-db-pass)\" \
			Subnets=$(SUBNETS) \
			VpcId=$(VPC_ID)

load up a config file with k/v pairs and use make's include

ifndef CONFIG
include config/$(CONFIG)
endif

make sam-deploy CONFIG=dev

@jveldboom
Copy link

We use a similar pattern to @rojomisin but use a standard environment variable file format.

.sam-params

DBUsername=admin
DBPassword=password123
Subnets=subnet-12345
VpcId=vpc-1234

Then in our Makefile, we cat that file and pass them in as --parameter-overrides

sam deploy --parameter-overrides $(shell cat .sam-params)

@jaridspokes
Copy link

I've used the above workaround for now, but it would be great to get some consistency with cloudformation in this regard.

@benkehoe
Copy link

#2253 proposes parameter overrides should get their own section in samconfig.toml (and should be individually overridden by --parameter-overrides)

@ghost
Copy link

ghost commented Dec 11, 2020

The trick by @jveldboom works just as well in a shell-script, except with --parameter-overrides $(cat path-to-file).

@HFR1994
Copy link

HFR1994 commented Jan 19, 2021

I'm using jq as an alternative.... Having the following structure

// parameters.json

[
  {
    "ParameterKey": "ApplicationName",
    "ParameterValue": "Foo"
  },
  {
    "ParameterKey": "ApplicationKey",
    "ParameterValue": "Bar"
  }
]

I can do

SAM_PARAMETERS=$( cat ${DIR}/parameters.json | jq -r '.[] | "\(.ParameterKey)=\(.ParameterValue)"' )
sam deploy ... --parameter-overrides $SAM_PARAMETERS

The good thing is that file can be shared with Cloudformation templates with:

aws cloudformation deploy ... --parameter-overrides "file://${DIR}/parameters.json"

@whereisaaron
Copy link

whereisaaron commented Apr 5, 2021

samconfig.toml is yet another different and, and as others pointed out, worse way to maintain AWS parameters, using yet another file format on top of YAML and JSON! Why are we trying so hard to make life more complicated 😄

cloudformation deploy has added support for --parameter-overrides file://my-params.json in aws/aws-cli#5443, including the also different and incompatible CodePipeline parameters format.

if sam is a wrapper for cloudformation deploy which now, or soon, supports --parameter-overrides files://my-params.json, can sam pick up on that and resolve this issue?

@mountHouli
Copy link

mountHouli commented Jun 4, 2021

I need to use a SAM parameter to upload a private RSA key in PEM format to AWS SecretsManager.

I've been trying all kinds of things on the CLI (including everything above) to get this to work. I ended up giving up and writing this workaround in my python code:

import base64
import boto3

# AWS CLI can't (easily) take params with newlines or spaces. Thus, we base64 encode our RSA PEM
# to make it single line before we upload it to Secrets Manager. See docs/design-notes.md
def get_lighthouse_rsa_key(awsSecretArn):  # pragma: no cover
    smClient = boto3.client("secretsmanager")
    base64EncodedPem = smClient.get_secret_value(SecretId=awsSecretArn)["SecretString"]

    resultBytes = base64.b64decode(base64EncodedPem)

    return resultBytes.decode()

I would be thankful if the SAM CLI maintainers incorporate @whereisaaron 's suggestion above on April 5th, 2021.

Note: Another part of the problem plaguing with (most) PEM files is the fact that CloudFormation parameters can be 4096 bytes, max. To support PEM files (at least those that are more than 4096 bytes) CloudFormation would need to provide an attribute to each parameter to override the 4096 byte max. Perhaps an attribute like MaxBytes: AN_INTEGER. But that's a different topic than this thread.

@PalituxD
Copy link

I resolved this scenario using options below:

"scripts": { "invoke": "sam ... --parameter-overrides \"$(jq -j 'to_entries[] | \"\\(.key)='\\\\\\\"'\\(.value)'\\\\\\\"''\\ '\"' params.json)\"" }

Or

sam ... --parameter-overrides "$(jq -j 'to_entries[] | "\(.key)='\\\"'\(.value)'\\\"''\ '"' params.json)"

@manraog
Copy link

manraog commented Apr 18, 2022

I'm using jq as an alternative.... Having the following structure

// parameters.json

[
  {
    "ParameterKey": "ApplicationName",
    "ParameterValue": "Foo"
  },
  {
    "ParameterKey": "ApplicationKey",
    "ParameterValue": "Bar"
  }
]

I can do

SAM_PARAMETERS=$( cat ${DIR}/parameters.json | jq -r '.[] | "\(.ParameterKey)=\(.ParameterValue)"' )
sam deploy ... --parameter-overrides $SAM_PARAMETERS

The good thing is that file can be shared with Cloudformation templates with:

aws cloudformation deploy ... --parameter-overrides "file://${DIR}/parameters.json"

Line breaks didn't let me use this option

Result:

ApplicationName=Foo
ApplicationKey=Bar

I had to change it to this

SAM_PARAMETERS=$( cat params.json | jq -r '[ .[] | "\(.ParameterKey)=\(.ParameterValue)" ] | join(" ")' )

Result:

ApplicationName=Foo ApplicationKey=Bar

@yigiterinc
Copy link

I would love to see SAM having a built-in easier way to do this. It becomes a maintenance hell unless the developers implement workarounds like @HFR1994 and @jveldboom suggested.

@JaimySmets
Copy link

Perhaps an easier workaround than custom wrapper scripts, is to use TOML's multiline support in the samconfig.toml file.

[default.deploy.parameters]
parameter_overrides = """
    ApplicationName='Foo'
    ApplicationKey='Bar'
    """

Which it seems to parse just fine during sam deploy:

Deploying with following values
===============================
...
Parameter overrides          : {"ApplicationName": "Foo", "ApplicationKey": "Bar"}

Although I agree putting it in a separate file would look cleaner, at least this way it remains the default sam deploy.

@benkehoe
Copy link

benkehoe commented Nov 6, 2022

@JaimySmets as mentioned in #2253 (comment) it also works with a list

parameter_overrides=[
  "ApplicationName=Foo",
  "ApplicationKey=Bar"
]

either way it doesn't solve for the parameters needing to be managed separately from the samconfig.toml file

@jhonatanacelas
Copy link

How should configure it in a pipeline without load credentials to git if I need the value of the Parameters in build phase, because the lambda download an private pypi package which require authentication?

@liamfit
Copy link

liamfit commented Mar 3, 2023

I'm using jq as an alternative.... Having the following structure
// parameters.json

[
  {
    "ParameterKey": "ApplicationName",
    "ParameterValue": "Foo"
  },
  {
    "ParameterKey": "ApplicationKey",
    "ParameterValue": "Bar"
  }
]

I can do

SAM_PARAMETERS=$( cat ${DIR}/parameters.json | jq -r '.[] | "\(.ParameterKey)=\(.ParameterValue)"' )
sam deploy ... --parameter-overrides $SAM_PARAMETERS

The good thing is that file can be shared with Cloudformation templates with:

aws cloudformation deploy ... --parameter-overrides "file://${DIR}/parameters.json"

Line breaks didn't let me use this option

Result:

ApplicationName=Foo
ApplicationKey=Bar

I had to change it to this

SAM_PARAMETERS=$( cat params.json | jq -r '[ .[] | "\(.ParameterKey)=\(.ParameterValue)" ] | join(" ")' )

Result:

ApplicationName=Foo ApplicationKey=Bar

This worked great for me until I started trying to use parameters whose values were lists:

[
  {
    "ParameterKey": "VpcId",
    "ParameterValue": "vpc-xxx"
  },
  {
    "ParameterKey": "VpcPrivateSubnets",
    "ParameterValue": [
      "subnet-xxx",
      "subnet-xxx",
      "subnet-xxx"
    ]
  },
  {
    "ParameterKey": "LambdaSecurityGroup",
    "ParameterValue": "sg-xxx"
  }
]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/deploy sam deploy command maintainer/need-followup stage/pm-review Waiting for review by our Product Manager, please don't work on this yet type/feature Feature request
Projects
None yet
Development

No branches or pull requests