Getting following error on serverless.yaml :can not read a block mapping entry; a multiline key may not be an implicit key - aws-lambda

I am trying to deploy the lambda function along with the serverless.yml file to AWS, but it throw below error
The following is the function defined in the YAML file
functions:
s3-thumbnail-generator:
handler:handler.s3_thumbnail_generator
events:
- s3:
bucket: ${self:custom.bucket}
event: s3.ObjectCreated:*
rules:
- suffix: .png
plugins:
- serverless-python-requirements
Error I am getting:
can not read a block mapping entry; a multiline key may not be an implicit key in serverless.yml" at line 45, column 10:
I would need to understand how to fix this issue in YAML file in order to deploy to the function to AWS?

The problem is that there is no value indicator (:) at the end of the line:
handler:handler.s3_thumbnail_generator
so the parser continues to try and gather a multi-line plain scalar by adding events followed by a value indicator. But a multi-line plain scalar cannot be a key in YAML.
It is unclear what your actual error is. It might be that you need to add the value indicator and have a colon emmbedded in your key:
functions:
s3-thumbnail-generator:
handler:handler.s3_thumbnail_generator:
events:
- s3:
bucket: ${self:custom.bucket}
event: s3.ObjectCreated:*
rules:
- suffix: .png
plugins:
- serverless-python-requirements
Or it could be that that colon should have been a value indicator (which usually needs a following space) and you were sloppy with indentation:
functions:
s3-thumbnail-generator:
handler: handler.s3_thumbnail_generator
events:
- s3:
bucket: ${self:custom.bucket}
event: s3.ObjectCreated:*
rules:
- suffix: .png
plugins:
- serverless-python-requirements

If it is your original file there is a syntax error in your YAML file. I added a note under the line of possible error:
functions:
s3-thumbnail-generator:
handler:handler.s3_thumbnail_generator
events:
- s3:
bucket: ${self:custom.bucket}
event: s3.ObjectCreated:*
rules:
- suffix: .png
^^^ this line should be indented one level
plugins:
- serverless-python-requirements

Related

Azure Pipelines - "While parsing a block mapping, did not find expected key" when setting variables

I have a strange problem that I can't seem to get my head around. I am trying to define some variables for use as part of the job that will deploy bicep files via Azure CLI and execute PowerShell tasks.
I get this validation error when I try and execute the pipeline: While parsing a block mapping, did not find expected key
The line that it refers to is: - name: managementResourceDNSPrivateResolverName
On the research that I have done on this problem, it sounds like an indentation problem but on the face of it, it seems to look fine.
jobs:
- job: 'Deploy_Management_Resources'
pool:
vmImage: ${{ parameters.buildAgent }}
variables:
- name: managementResourceDNSPrivateResolverName
value: 'acme-$[ lower(parameters['environmentCode']) ]-$[ lower(variables['resourceLocationShort']) ]-private-dns-resolver'
- name: managementResourceGroupManagement
value: 'acme-infrastructure-rg-management'
- name: managementResourceRouteTableName
value: 'acme-$[ lower(variables['subscriptionCode']) ]-$[ lower(variables['resourceLocationShort']) ]-route-table'
- name: managementResourceVirtualNetworkName
value: 'acme-$[ lower(variables['subscriptionCode']) ]-$[ lower(variables['resourceLocationShort']) ]-vnet-internal-mng'
Thanks!
The error message ...parsing a block mapping, did not find expected key is usually a side-effect of malformed yaml. You'll see if often with variables if you have mixed formats of arrays and property elements
variables: # an array of objects
# variable group reference object
- group: myvariablegroup
# variable template reference object
- template: my-variables.yml
# variable object
- name: myVariable
value: 'value1'
# variable shorthand syntax
myVariable: 'value1' # this fails because it's a property instead of an array element
While it doesn't appear that the sample you've provided is malformed, I am curious about the use of $[ ] which is a runtime expression. The expression $[ lower(parameters['environmentcode']) ] refers to parameters which is are only available at compile time.
Change:
$[ lower(parameters['environmentCode']) ] to ${{ lower(parameters.environmentCode) }}

Get all children key values in a YAML with PyYAML

Say I have a YAML like:
Resources:
AlarmTopic:
Type: AWS::SNS::Topic
Properties:
Subscription:
- !If
- ShouldAlarm
Protocol: email
How do I get each key and value of all the children if I'm walking over each resource and I want to know if one of the values may contain a certain string? I'm using PyYAML but I'm also open to using some other library.
You can use the low-level event API if you only want to inspect scalar values:
import yaml
import sys
input = """
Resources:
AlarmTopic:
Type: AWS::SNS::Topic
Properties:
Subscription:
- !If
- ShouldAlarm
- Protocol: email
"""
for e in yaml.parse(input):
if isinstance(e, yaml.ScalarEvent):
print(e.value)
(I fixed your YAML because it had a syntax error.) This yields:
Resources
AlarmTopic
Type
AWS::SNS::Topic
Properties
Subscription
ShouldAlarm
Protocol
email

Rule governing sequence of fields in a YAML

Checking the validity of a YAML using https://onlineyamltools.com/convert-yaml-to-json
The below YAML is correct
# Valid yaml (field "name" placed at LAST position)
match:
- uri:
prefix: "/mysvc1/"
route:
- destination:
host: myservice1
port:
number: 80
name: "svc1-routes"
However, if I move the field name to first position, the YAML becomes invalid. What is the reason?
# Invalid yaml (field "name" placed at FIRST position)
match:
name: "svc1-routes" # <---- ERROR ----
- uri:
prefix: "/mysvc1/"
route:
- destination:
host: myservice1
port:
number: 80
The error message:
Error: YAMLException: end of the stream or a document separator is expected at line 4, column 1:
- uri:
^
In contrary to your comment, name and match are on the same level because they share the same indentation. name is in no way nested in match (nor is route).
The list items, however, are nested in match since YAML understands the - as parts of the indentation, hence the list items are considered more indented than match and are thus nested in it.
Concerning your error:
name: "svc1-routes"
- uri:
In this part, the mapping key name is assigned the scalar value svc1-routes. Each mapping key may only have one value. On the next line, a sequence starts which is on a deeper indentation level (as explained above) but YAML can't put it anywhere because the key name already has a value. This is why it issues an error.
You can freely switch the mapping keys together with their nested values, e.g.:
route:
- destination:
host: myservice1
port:
number: 80
name: "svc1-routes"
match:
- uri:
prefix: "/mysvc1/"
This will load to the same structure as per YAML spec.

YML with multiple files: Unhandled rejection YAMLException: duplicated mapping key

I tried to separate my resources field in multiple files in project. Most of then worked fine, but only this file, where I declare CognitoUserPool + CognitoUserPoolClient trowed this exception:
Unhandled rejection YAMLException: duplicated mapping key in "/home/uriel/Desktop/Foo/Backend/MultipleFile/backend-foo/resources/cognitoUserPoolFoo.yml" at line 20, column 3:
Type: AWS::Cognito::UserPoolClient
^
at generateError (/home/uriel/.nvm/versions/node/v10.16.0/lib/node_modules/serverless/node_modules/js-yaml/lib/js-yaml/loader.js:167:10)
I've already checked logical and indentation problems. This same lines worked on single file, they only throw this error when I move them to another YML file and import it.
Main YML file importing the another one
plugins:
- serverless-webpack
- serverless-python-requirements
- serverless-offline
resources:
- ${file(resources/cognitoUserPoolFoo.yml)}
File imported, the one that throw error.
Resources:
CognitoUserPoolFoo:
Type: AWS::Cognito::UserPool
Properties:
MfaConfiguration: OFF
UserPoolName: foo-${self:provider.stage}
EmailConfiguration:
ReplyToEmailAddress: foo#test.com
SourceArn: "arn:aws:ses:us-east-1:123456789012:identity/foo#test.com"
AutoVerifiedAttributes:
- email
Policies:
PasswordPolicy:
MinimumLength: 6
RequireLowercase: True
RequireNumbers: True
RequireSymbols: False
RequireUppercase: True
FooCognitoUserPoolClient:
Type: AWS::Cognito::UserPoolClient
Properties:
ClientName: FooWebApp-${self:provider.stage}
GenerateSecret: false
UserPoolId:
Ref: "CognitoUserPoolFoo"

Use globbed string in YAML

I am looking for a way to dynamically set the key using the path of the file below.
For example if I have this YAML:
prospectors.config:
- fields:
queue_name: <somehow get the globbed string below in here>
paths:
- /var/log/casino/*.log
type: log
output.redis:
hosts:
- "producer:6379"
key: "%{[fields.queue_name]}"
And then I had a file called /var/log/casino/test.log, then key would become test.
Im not sure that what you want is possible.
You could use the source field and configure your Redis output using that as the key:
output.redis:
hosts:
- "producer:6379"
key: "%{source}"
This would have the disadvantage of being the absolute path of the source file, not the basename as your question asks for.
If you have a small number of possible basename patterns, and want a queue for each. For example, you have files:
/common/path/test-1.log
/common/path/foo-0.log
/common/path/01-bar.log
/common/path/test-3.log
...
and wanted to have three queues in redis test, foo and bar you could use the source field and the conditionals available in the keys configuration of redis output something like this
output.redis:
hosts:
- "producer:6379"
key: "default_key"
keys:
- key: "test_key"
when.contains:
source: "test"
- key: "foo_key"
when.contains:
source: "foo"
- key: "bar_key"
when.contains:
source: "bar"

Resources