A valid option to satisfy the declaration could not be found in serverless framework - serverless-framework

I'm using serverless framework and using bitbucket-pipeline to configure CI/CD.
I have the following configuration in the serverless.yml file
provider:
name: aws
runtime: nodejs10.x
region: ${opt:region, ${env:AWS_REGION, 'ap-south-1'}}
memorySize: ${opt:memory, ${env:MEMORY_SIZE, 512}}tracing:
apiGateway: ${env:TRACING_API_GATEWAY, true}
I want to be able to pass the variables from the CLI as well as environment variables.
I have set up environment variable for AWS_REGION in the bitbucket pipeline variables but not for MEMORY_SIZE as want to use the default value.
But this gives error while running the pipeline.
Serverless Warning --------------------------------------
A valid option to satisfy the declaration 'opt:region,ap-south-1' could not be found.
Serverless Warning --------------------------------------
A valid environment variable to satisfy the declaration 'env:MEMORY_SIZE,512' could not be found.
Serverless Warning --------------------------------------
A valid environment variable to satisfy the declaration 'env:TRACING_API_GATEWAY,true' could not be found.

First, those are warnings not errors. A Serverless error would be something like:
Serverless Error ---------------------------------------
Trying to populate non string value into a string for variable ${opt:stage}. Please make sure the value of the property is a string.
This specific error happens because in the custom tag I've declared: var: ${opt:stage}-something which should be changed like:
provider:
stage: ${opt:stage, 'local'}
custom:
var: ${self:provider.stage}-something
I think in your case, you need to update region like this:
region: ${opt:region, env:AWS_REGION, 'ap-south-1'}
I couldn't reproduce the last warning though but I reckon ENV variables should be defined in bitbucket-pipelines.yml (or similar CI pipeline YAML) under args or variables and then they can be accessed using ${env:VAR}.

Related

reference a variable in serverless framework

I'm trying to define my serverless framework deployment bucket.
My serverless.yml looks like this:
provider:
name: aws
runtime: nodejs14.x
region: us-east-1
stage: dev
deploymentBucket:
name: ${self:environment.DEPLOYMENT_BUCKET}
environment:
${file(../evn.${opt:stage, 'dev'}.json)}
and the evn.dev.json file looks like this:
{
"DEPLOYMENT_BUCKET": "myBucketName"
}
(both of these files have non-relevant parts removed)
I'm getting a "cannot resolve variable at "provicer.deploymentBucket.name" error when trying to deploy.
How do I reference the DEPLOYMENT_BUCKET variable in the serverless.yml file?
EDIT: Other errors:
${environment}:DEPLOYMENT_BUCKET -> Could not locate deployment bucket. Error: The specified bucket is not valid
name: ${environment:DEPLOYMENT_BUCKET}1 -> Unrecognized configuration variable sources: "environment"
name: ${self:provider.environment:DEPLOYMENT_BUCKET}
and
name: ${self:environment:DEPLOYMENT_BUCKET}
-> Cannot resolve serverless.yml: Variables resolution errored with - Cannot resolve variable at "provider.deploymentBucket.name": Value not found at "self" source
I was able to solve the problem with this:
${file(../evn.${opt:stage, 'dev'}.json):DEPLOYMENT_BUCKET}
But 'reading' that file twice -- both here and in the 'environment' area seems to somewhat defeat the purpose of the environments area.

Spread all dotenv keys and values to process.env without having to define it one by one in serverless.yml

I am using node & expressjs as an app. I have problem in deploying it to serverless with dotenv (without using any dotenv plugin).
My serverless.yml is this:
functions:
server:
handler: index.server
events:
- http: ANY /
- http: "ANY /{proxy+}"
environment:
ENV_VAR1: ${env:ENV_VAR1}
and my .env.staging is this:
ENV_VAR1='ENV_VAR1 using .env.staging'
ENV_VAR2='ENV_VAR2 using .env.staging'
I use AWS Lambda and deploy it using sls deploy --stage staging. So far I can read the ENV_VAR1from .env.staging by calling process.env.ENV_VAR1 because I explicitly define it in the serverless.yml file. But that's not the case with ENV_VAR2.
My question is, how to load all the .env.{stage} file without defining the key one by one?
I hope to load it similar to something like this:
environment: ${file(.env.${self:stage})}
Thank you in advance.
As I know, there is no way, you'll have to do it one by one (you have to have an object with key-value pairs inside environment, but you are trying to give it a string - even if it is going to be interpreted as a file containing something, it is still a string when you are referencing it).
I'm not an expert, so there still might be some tricks.

Deploy warning calling external JS function in `serverless.yml`

So, in my serverless.yml file I have this:
custom:
my_attr: ${file(./serverless/get-custom-value.js):my_attr}
And in that file (located in ./serverless/get-custom-value.js) is this JavaScript code:
module.exports.my_attr = async function(slsArg) {
const stage = slsArg.providers.aws.getStage()
console.debug(`### stage: "${stage}".`)
return stage
}
When doing a sls package -s {stage} or sls deploy -s {stage} (which are both successful), I see this warning:
Serverless: Deprecation warning: Variables resolver reports following resolution errors:
- Cannot resolve variable at "custom.my_attr": Cannot resolve "my_attr" out of "get-custom-value.js": Resolved a JS function not confirmed to work with a new parser, falling back to old resolver
Yet, despite the warning it works exactly as expected…
It's a deprecation warning, which serves to inform you that in the next version of the Serverless Framework, this specific resolver syntax is deprecated (and will error) as internally the process for resolving variables has changed.
You can adopt the new custom resolver very simply by changing the declaration in the serverless.yml and modifying the function arguments in get-custom-value.js, then you can set
variablesResolutionMode: 20210326
in your serverless.yml to indicate you have migrated. That will instruct the Serverless Framework to use the new resolver, as indicated by the warning message.
The full overview is in the documentation

Serverless: Importing file to custom + other variables

I have a serverless.common.yml, with properties that should be shared by all the services, with that:
service: ixxxx
custom:
stage: ${opt:stage, self:provider.stage}
resourcesStages:
prod: prod
dev: dev
resourcesStage: ${self:custom.resourcesStages.${self:custom.stage}, self:custom.resourcesStages.dev}
lambdaPolicyXRay:
Effect: Allow
Action:
- xray:PutTraceSegments
- xray:PutTelemetryRecords
Resource: "*"
And, another serverless.yml inside a services folder, which uses properties on the common file:
...
custom: ${file(../../serverless.common.yml):custom}
...
environment:
stage: ${self:custom.stage}
...
In that way, I can access the custom variables (from the common file) without a problem.
Now, I want to continue to import this file to custom, but adding new variables, related to this service, to it, so I tried that:
custom:
common: ${file(../../serverless.common.yml):custom}
wsgi:
app: app.app
packRequirements: false
pythonRequirements:
dockerizePip: non-linux
And it seems it's possible to access, for example:
environment:
stage: ${self:custom.common.stage}
But now, I'm receiving the error:
Serverless Warning --------------------------------------
A valid service attribute to satisfy the declaration 'self:custom.stage' could not be found.
Serverless Warning --------------------------------------
A valid service attribute to satisfy the declaration 'self:custom.stage' could not be found.
Serverless Error ---------------------------------------
Trying to populate non string value into a string for variable ${self:custom.stage}. Please make sure the value of the property is a strin
What am I doing wrong?
In your serverless.common.yml you must reference as if it were serverless.yml. In this case ${self:custom.stage} does not exist, but ${self:custom.common.stage} does exist.
service: ixxxx
custom:
stage: ${opt:stage, self:provider.stage}
resourcesStages:
prod: prod
dev: dev
resourcesStage: ${self:custom.common.resourcesStages.${self:custom.common.stage}, self:custom.resourcesStages.dev}
lambdaPolicyXRay:
Effect: Allow
Action:
- xray:PutTraceSegments
- xray:PutTelemetryRecords
Resource: "*"

Serverless provider.environment variables not available in custom

I am trying to reference variables in self:provider.environment in my custom variables block; however, I get the following warning:
Serverless Warning --------------------------------------
A valid service attribute to satisfy the declaration
'self:provider.environment.myVar' could not be found.
We are using serverless 1.28.0, here's a sample config:
service: testing-vars
provider:
region: 'us-west-2'
environment:
myVar: ${env:myVar, self:custom.dotenv.myVar}
custom:
refToAbove: ${self:provider.environment.myVar}
...
I would like to reference the provider.environment vars in my custom block.
This was due a plugin not handling variables properly and has been fixed.