dbt cloud - commands in script - unit-testing

is there a possibility in dbt cloud to put some dbt commands into a script file and then execute it ?
e.g.
-- dbt run-operation macro_123
-- dbt run-operation macro_123 --vars 'unit_test_name: test_no_1'
-- dbt run-operation macro_123 --vars 'unit_test_name: test_no_2'
I want to gather all tests, and then run it always at once.

I think the best alternative will be to write a macro to wrap your other macros. Then you can have a job with just one dbt run-operation test_runner. That macro could look like:
{% macro test_runner() %}
{% test_names = [
"test_no_1",
"test_no_2",
...
] %}
{% for t in test_names %}
{{ macro_123(t) }}
{% endfor %}
{% endmacro %}

Related

AnsibleUndefinedVariable in template

i hope you guys can help me.
I want to copy following template with ansible:
IFACE_EXTERNAL="{{ ansible_default_ipv4.interface }}"
IP_EXTERNAL="{{ ansible_default_ipv4.address }}"
IFACE6_EXTERNAL="{{ ansible_default_ipv6.interface }}"
IP6_EXTERNAL="{{ ansible_default_ipv6.address }}"
{% if ansible_interfaces[2] is defined %}
{% set count = 2 %}
{% for iface in ansible_interfaces %}
{% if "tun0" in iface %}
IFACE_INTERNAL_1="{{ iface }}"
{% endif %}
{% if "ens" in iface %}
IFACE_INTERNAL_{{count}}="{{ iface }}"
{% set count = count + 1 %}
{% endif %}
{% if hostvars[inventory_hostname]['ansible_%s'|format(iface)]['ipv4'] is defined %}
IP_INTERNAL_{{loop.index}}="{{ hostvars[inventory_hostname]['ansible_%s'|format(iface)]['ipv4']['address'] }}"
{% endif %}
{% endfor %}
{% endif %}
Now, if i copy this template with ansible, i get following error: "AnsibleUndefinedVariable: 'dict object' has no attribute 'interface'".
I tried for an hour but don't get a solution.
Does anyone know where the error is?
You wrote a very complicated jinja template. Now, live and suffer with it.
It's really bad idea to have a complicated access patterns into dynamic variables within jinja, as you have 0 (zero) debug tools there.
The proper way is to have all computation to be done at ansible level:
tasks:
- debug: var=some_var1
- debug: var=some_var2
- template:
src: foo.j2
dest: foo
vars:
some_var1: '{{...}}'
some_var2: '{{...}}'
By using external (ansible) vars you can debug them. If you use computation in Jinja you need to be 100% sure data are there. How can you be sure that facts are there, if default set of network variables is dependent on where there is default gateway or not on the target system?
To avoid such errors you must use something similar to {{ ansible_default_ipv6.interface | default('foo') }} as there is no guarantee that ansible_default_ipv6 object has the interface attribute.
If you do not do this, you will get templating errors. The other option is to use if conditions like '{% if interface' in ansible_default_ipv6 %}....

Ansible Jinja template variable hostgroup

I use this template to get list of IPs in hostgroups named [web]
{% for h in groups['web'] %}
ssh -i ~/ansible_users_keys/{{ new_user_name_global }}_id_rsa {{ new_user_name_global }}#{{ hostvars[h].ansible_nodename }}
{% endfor %}
Could someone prompt me which variable should I use instead [web] in case if I run this command?
ansible-playbook -i hosts server.yml --limit web
Thanks in advance
'ansible_play_batch' is variablle that has the list of hostnames that apply to the current play.
{% for h in ansible_play_batch %}
ssh -i ~/ansible_users_keys/{{ new_user_name_global }}_id_rsa {{ new_user_name_global }}#{{ hostvars[h].ansible_host }}
{% endfor %}

Ansible: compose list of facts in jinja template

I am setting up a cluster service with Ansible 1.9.2 and need to configure a JSON config file with a list of cluster servers to join.
Currently, I have this working as below. It produces correct, if ugly, output.
{
...
"join": [
{% for host in groups['cluster'] %}
"{{ hostvars[host]['ansible_default_ipv4']['address'] }}{% if not loop.last %}, {% endif %}
{% endfor %}
],
...
}
Is it possible for Ansible to create a list of specific host facts, or for Jinja to compose a list dynamically? I would hope for something I can leave in my template like this:
{
...
"join": {{ list_of_cluster_ips|to_nice_json }},
...
}
I tried some Jinja magic at the top of the template file to generate the list as below:
{% set list_of_cluster_ips = [] %}
{% for host in groups['cluster'] %}
{% do list_of_cluster_ips.append(host) %}
{% endfor %}
{
...
"join": {{ list_of_cluster_ips|to_nice_json }},
...
}
But Ansible doesn't support the 'do' function of Jinja and fails with fatal: [cluster-1] => {'msg': "AnsibleError: file: <template>, line number: 3, error: Encountered unknown tag 'do'. Jinja was looking for the following tags: 'endfor' or 'else'. The innermost block that needs to be closed is 'for'.", 'failed': True}.
Is there a way for Ansible to generate the list that can be used in the template?
Try this:
{%- set list_of_cluster_ips = [] %}
{%- for host in groups['cluster'] %}
{%- if list_of_cluster_ips.append(hostvars[host]['ansible_default_ipv4']['address']) %}
{%- endif %}
{%- endfor %}
{
...
"join": {{ list_of_cluster_ips|to_nice_json }},
...
}

Read a file in django and find string in file

i am a new to django, and i'm trying to execute a django code in an html template, but it is showing the same error and i dont know how to make it work. I am trying to read some files and find the one that contains the string. This is the code in the template:
{% if documents %}
<ul>
{% for document in documents %}
{% if 'TheString' in open('document.docfile.url').read() %}
<li>{{ document.docfile.name }}</li>
{% else %}
<li></li>
{% endif %}
{% endfor %}
</ul>
{% else %}
<p>No documents available.</p>
{% endif %}
The error is the following:
TemplateSyntaxError at /subir/
Could not parse the remainder: '('document.docfile.url').read()' from 'open('document.docfile.url').read()'
What could it be, or am i doing it wrong? Thanks in advanced.
Your problem is you are trying to use Python code in the template, like your open() call.
Django templates don't work like that - you can only use a very limited set of syntax, and the syntax is not the same as Python.
Everything inside {{ }} and {% %} needs to be special Django template syntax, not Python code.
See the Django Template language documentation for the full details.
You can't use code like this in a template directly see the documentation for available template tags and filters. From what I can tell by the code you have posted in your view.py you'll need something like this:
docs=[]
for document in documents:
if 'TheString' in open('/path/to/document').read():
docs.append(document)
after passing docs to the template you could do this in the template:
{% for doc in docs %}
<li>{{ document.docfile.name }}</li>
{% empty %}
<p>No documents available.</p>
{% endfor %}
I'd need to look at what you are passing from the view to be sure of this, but I'd gladly assist in further help with further information if this doesn't help.

How to pass selected, named arguments to Jinja2's include context?

Using Django templating engine I can include another partial template while setting a custom context using named arguments, like this:
{% include "list.html" with articles=articles_list1 only %}
{% include "list.html" with articles=articles_list2 only %}
As you may be supposing, articles_list1 and articles_list2 are two different lists, but I can reuse the very same list.html template which will be using the articles variable.
I'm trying to achieve the same thing using Jinja2, but I can't see what's the recommended way, as the with keyword is not supported.
Jinja2 has an extension that enables the with keyword - it won't give you the same syntax as Django, and it may not work the way you anticipate but you could do this:
{% with articles=articles_list1 %}
{% include "list.html" %}
{% endwith %}
{% with articles=articles_list2 %}
{% include "list.html" %}
{% endwith %}
However, if list.html is basically just functioning as a way to create a list then you might want to change it to a macro instead - this will give you much more flexibility.
{% macro build_list(articles) %}
<ul>
{% for art in articles %}
<li>{{art}}</li>
{% endfor %}
</ul>
{% endmacro %}
{# And you call it thusly #}
{{ build_list(articles_list1) }}
{{ build_list(articles_list2) }}
To use this macro from another template, import it:
{% from "build_list_macro_def.html" import build_list %}
This way you can pass multiple variables to Jinja2 Include statement - (by splitting variables by comma inside With statement):
{% with var_1=123, var_2="value 2", var_3=500 %}
{% include "your_template.html" %}
{% endwith %}
For readers in 2017+, Jinja as of 2.9 includes the with statement by default. No extension necessary.
http://jinja.pocoo.org/docs/2.9/templates/#with-statement
In older versions of Jinja (before 2.9) it was required to enable this feature with an extension. It’s now enabled by default.
Updated 2021+
Included templates have access to the variables of the active context by default. For more details about context behavior of imports and includes, see Import Context Behavior.
From Jinja 2.2 onwards, you can mark an include with ignore missing; in which case Jinja will ignore the statement if the template to be included does not exist. When combined with with or without context, it must be placed before the context visibility statement. Here are some valid examples:
{% include "sidebar.html" ignore missing %}
{% include "sidebar.html" ignore missing with context %}
{% include "sidebar.html" ignore missing without context %}
Another option, without plugins, is to use macros and include them from another file:
file macro.j2
{% macro my_macro(param) %}
{{ param }}
{% endmacro %}
file main.j2
{% from 'macro.j2' import my_macro %}
{{ my_macro(param) }}