Using variables in Serverless resource name - serverless-framework

In my serverless.yml I have:
public-function:
handler: function.Handler
I want to parametrise the public-function line but I'm not sure how to do this. I know I can add a name: attribute to the function and use the ${} syntax documented at https://www.serverless.com/framework/docs/providers/aws/guide/variables/ but this only half solves my problem as public-function is used by Serverless as a basis for the names of other resources which I also want to have parametrised names.
Is there some way of using variables in the resource name?

The declared function key (i.e. public-function) is only a reference in the stack. There is no reason to change it at build time as the name is arbitrary.
If you want to customise the details of the deployed function, change its configuration.
For example, change the name of the function to something else using environment variables:
functions:
main:
handler: function.Handler
name: ${self:provider.stage}-${env:FUNCTION_NAME}
If you are exporting the resource to another stack, you can define the export name like so:
resources:
Outputs:
MainFunction:
Value:
Fn::GetAtt: [MainLambdaFunction, Arn]
Export:
Name: ${self:provider.stage}-${env:CUSTOM_EXPORT_NAME}
The stage scoping to both of these examples is recommended but not required; you can name your functions, resources, and outputs anything you want.

Related

DBT dynamic config

I have a generic test and need it to be always saved under a particular name for the given table it is running on, e.g. on table report_revenue the generated generic test name will always be diff_check_report_revenue. Right now the default dbt naming behavior for generic tests is kinda messy (it sets the test name based on the test config, which is a great idea for most cases, but unfortunately not for my particular one).
According to the docs it looks like the [alias]https://docs.getdbt.com/reference/resource-configs/alias is exactly what I need. However, I also need to set the name dynamically based on the table that is tested. I know it can be set in the yml config by setting the field alias, but I hope there might be a more elegant solution.
When I try the following:
{{
config({
"severity": 'warn',
"tags": ["diff_check"],
"alias": 'diff_check_' + {{ model | replace("XXXXXXX") | trim }}
})
}}
It just doesn't work and dbt completely ignores the alias property. model is the relation on which the test is running. It's probably just my own wrong syntax, but I'm stuck and humbly asking for advice. Thanks a lot in advance!
The docs are super confusing on test config, since they group together generic tests and singular tests, and the behavior is different.
You can use a config() block inside the definition for a generic test to configure it, and some keys (e.g., severity) work fine, but alias is not one of them.
I think alias is meant for singular tests only. To give generic tests a unique identifier (only possible since v1.1), you are supposed to use the name property (not config). Docs. Does this make sense? No. Does it make it easy for you to do what you want to do? Also no.
I'll point out that the default naming convention for a generic test includes the name of the test followed by the name of the model, but assuming that isn't good enough, your only option will be to add a name property to every test, where you define the test in the properties (fka schema.yml) file. And it looks like the name property doesn't jinja-template its value (so you can't use jinja to populate the test name). So you'll have to do a lot of this:
models:
- name: my_model
tests:
- diff_check:
name: diff_check_my_model
You could fork dbt-core. The relevant code is here.

Define variables per folder in dbt

I'm trying to have a structure to run a dbt project, where I have multiple entities (bank, names, cars). I'm going to have exactly the same code for them all.
Based on that, I'm trying to have several folder with the same code, where I can define inside the dbt_project.yamlfile. The idea is something like this:
vars:
db_name: 'db_official'
staging:
bank: 'variable_bank'
car: 'variable_car'
name: 'variable_name'
The variable "db_name" works. So, my the two problems I'm having are:
How to have this structure inside the the yaml file?
How to reference this structure inside each file?
(extra) Any other ideas how to handle this?
Thanks!
vars are basically globals. They can be scoped to your whole project, or to a package within your project, but not more specifically than that (they share a flat namespace). See the docs.
I would pull out the common code into a macro, then call that macro from each model file, passing in the unique values as string literals in the model file:
-- models/staging/bank.sql
{{ my_model_template('variable_bank') }}
-- models/staging/car.sql
{{ my_model_template('variable_car') }}

saving an ansible fact as a local variable

I'm trying to create a local variable (local as inside a task) using a variable gathered from a fact. Basically the opposite of sect_fact....
something like:
- name: create a variable from a fact
create_var:
name: myprivatevar
value: {{ ansible_eth0.ipv4.address }}
in order to be able to use that var later, in relation to another host.
I know I can use magic variables an hostvars in order to access other hosts' facts but I dont know the names of the hosts I want to refer to when I play the book...

How to make resource in Serverless Framework reusable?

I am trying to set up my serverless.yml file with only an API Gateway, and there are several resources that I need to reuse throughout the file, and I'd like to not copy and paste the same lines of code per resource like 100 times.
For example, I want to reuse TestId resource below and dynamically pass in the Ref under ParentId so I can reuse the resource for multiple parent resources. How can I do that?
TestResource:
Type: AWS::ApiGateway::Resource
Properties:
ParentId:
Fn::GetAtt:
- TestApi
- RootResourceId
PathPart: test
RestApiId:
Ref: TestApi
TestId:
Type: AWS::ApiGateway::Resource
Properties:
ParentId:
Ref: TestResource
PathPart: '{id}'
RestApiId:
Ref: TestApi
Ideally I would want the resuable TestId resource in a separate file and then reference it, and also pass in the dynamic value that I want to insert in. Something like:
TestId: ${file(testid.yml):TestId} somehow override the TestId.Properties.ParentId.Ref: <somevalue>
Does anyone know if this is possible?
In case you are using NodeJs (if not maybe something like this exists in your programming language), I think you should take a look at this plugin : https://www.npmjs.com/package/yamlinc
It allow to compose YAML files using $include tag.
Hope this helps you.

Declaring resources in multiple files in Serverless framework

Is there any way to split the resource definitions in serverless framework into multiple files? Something like:
resources:
- ${resources/base.yml}
- ${resources/foo.yml}
I have been trying multiple combinations but I keep getting errors about references not being found.
Even though dashmug's answer is correct, I found that the way I was trying to make it work was quite close to a valid solution too. As explained in this github comment it is possible to reference other files in the resources section:
resources:
- ${file(resources/first-cf-resources.yml)}
- ${file(resources/second-cf-resources.yml)}
Provided that each those files defines a "Resources" key of its own, like:
---
Resources:
MyCFResource:
Type:.....
What I didn't manage is to have a mixed approach such as:
resources:
- ${file(resources/first-cf-resources.yml)}
- ${file(resources/second-cf-resources.yml)}
SomeResource:
Type: ...
So I just have a resources/base.yml for that instead.
I can't comment but I'd like to extend Jesuspc's answer.
There is a way to achieve that 'mixed' approach, in serverless.yml:
resources:
- ${file(resources/first-cf-resources.yml)}
- ${file(resources/second-cf-resources.yml)}
- Resources:
SomeResource:
Type: ...
In this case files first-cf-resources.yml and second-cf-resources.yml must have the next structure:
Resources:
SomeResourceA:
...
AnotherResourceB:
...
Take note that the resources property has to be an object containing a Resources property, NOT an array of resources like what you wanted in your code snippet.
So, to use external file references, you can do something like...
resources
Resources:
UsersTable: ${file(../resources/base.yml):UsersTable}
FooTable: ${file(../resources/foo.yml):FooTable}
Reference: Reference variables in other files