How to get a list of all salt minions in a template? - configuration-management

Basically I am creating a Salt state describing Munin server configuration and I need to get a list of all minions known to the master, something like this:
{% for host in pillar['munin_clients'] %}
[{{ host.fqdn }}]
address {{ host.ip }}
use_node_name yes
{% endfor %}
The only difference is that I don't want to use pillar for that, I need this list to be populated dynamically. ret.get_minions seems to be relevant but I can't make it work for some reason. What are my options?

I managed to achieve this using Salt Mine system (thanks to members of Salt-users Google group):
{% for host, hostinfo in salt['mine.get']('*', 'network.interfaces').items() %}
[{{ host }}]
address {{ hostinfo['eth0']['inet'][0]['address'] if hostinfo['eth0'].has_key('inet') else hostinfo['br0']['inet'][0]['address'] }}
use_node_name yes
{% endfor %}
I had to add
mine_functions:
network.interfaces: []
to the end of /etc/salt/minion on every node to enable Salt Mine.

Alex's answer is great. The Salt Mine will give you the list of minions that's correct as of the last time the Mine was executed.
If you want live up to the second data you can use the peer interface by using the publish module. Publish module docs are here: http://docs.saltstack.com/ref/modules/all/salt.modules.publish.html#module-salt.modules.publish
{% for host in salt['publish.publish']('*', 'network.ip_addrs', 'eth0') %}
[{{ host.fqdn }}]
address {{ host.ip }}
use_node_name yes
{% endfor %}
Make sure to set your master config to allow the minions to execute network.ip_addrs.
EDIT:
To answer a question below you must enable the host to query other minions through the peer publish interface. To allow all minions to query the ip addresses of all other minions, add this to your /etc/salt/master:
peer:
.*:
- network.ip_addrs

Why not use minion.list module?
In our pillar environment we have pillar that are private to each minion (/srv/pillar/hosts/[server_A, server_B, server_C...]/some_pillar.sls).
To make things easier (since some people keep forgetting to add new pillars to the top file) our pillar top file looks like this:
{{ saltenv }}:
{% for minion in salt['minion.list']()['minions'] -%}
{{ minion + '*' }}:
- hosts.{{ minion.split('.')[0] }}
{% endfor -%}
This way I can get a list of all minions known to the master every time the pillar enviorment is updated.

Related

Change materialization name(-prefix) of seed data in the warehouse

Currently the seed are automaticaly generated in the warehouse with the name dbt_{schema_name}_seed_data, with {schema_name} being the schema name specified in the profiles.yml.
I want to specify a different name, e.g. dbt_processing_seed_data, without changing the schema name in profile.yml to 'processing'.
Reason behind all this, different devs want to have their own schema so they don't interfere with each other. But it is unnecessary that the (same) seed data is stored multiple times in the warehouse.
You can set the schema for a seed in your dbt_project.yml file. See the docs.
To get the behavior you describe, where the target name is not prepended to the schema, you need to override the generate_schema_name macro by creating a new macro with that name in your project. Docs on that are here. You can use the node's resource type so that this behavior is only applied to seeds.
{% macro generate_schema_name(custom_schema_name, node) -%}
{%- set default_schema = target.schema -%}
{%- if custom_schema_name is none -%}{{ default_schema }}
{%- elif node.resource_type == "seed" -%}{{ custom_schema_name | trim }}
{%- else -%}{{ default_schema }}_{{ custom_schema_name | trim }}
{%- endif -%}
{%- endmacro %}
I'd caution against this, though. Seeds are version-controlled, and really aren't intended to be used for large raw datasets (see the docs again). Since they get checked in alongside code, they should really share the same separation of environments that the code has.

Changing shopify labels in theme

I'm quite new to Shopify themes and I'm needing to change the label for the Shopify "Product Size" & "Color" in the theme i'm using but i'm confused by the loop where i change it.
This is the code which im closest to
{% form 'product', product, class:form_classes, novalidate: 'novalidate' %}
{% unless product.has_only_default_variant %}
{% for option in product.options_with_values %}
<div class="selector-wrapper js product-form__item">
<label {% if option.name == 'default' %}class="label--hidden" {% endif %}for="SingleOptionSelector-{{ forloop.index0 }}">
{{ option.name }}
</label>
{% assign optionName = option.name | downcase %}
If i change the option.name it changes both of the label names not just individual ones. I've attached a screenshot of the product page to help explain this. I assume this is a daft question for a seasoned shopify pro. Any help is really appreciated.
BTW the reason it's using these labels is because all stock is being imported from a third party stock management system.
It sounds like you will have to rely on string manipulation to convert the external names to customer-friendly ones. There are several ways to do so - the best way forward will probably depend on how consistent or varied the imported option names are.
For a full list of string manipulation functions available to you in Liquid, I will also point you towards the Shopify Liquid Reference where you will be able to find a lot more detail.
Approach 1: Simple removal filters
Use | remove to get rid of known bits that we don't want to keep. Like all filters, these can be chained together.
Example:
{{ option.name | remove: 'PA_' | remove: 'CLOTHING-' }}
Approach 2: Split on delimiter characters
The | split filter might be useful if there are lots of different prefixes that you need to remove. This command breaks the string up into an array of pieces, and we can grab the bits that we need using things like the first and last filters.
Example:
{{ option.name | split: '_' | last | split: '-' | last }}
Approach 3: Extensive manual mapping
If the values coming in for your products don't follow any regular patterns, you may be stuck in a position where you have to manually map some or all of your option names to friendly values. If you find yourself in a corner, the case statement is probably your best-of-the-bad options:
Example:
{% case option.name %}
{% when 'PA_CLOTHING-SIZE' %}
{% assign friendly_name = 'Size' %}
{% when 'PA_COLOR' %}
{% assign friendly_name = 'Color' %}
{% default %}
{% assign friendly_name = option.name %}
{% endcase %}
{{ friendly_name }}

How to access variable from the variable

I have added a Metafields Guru app in my shopify store. I have created some metafields there And I want them to access in my template. All these are easily accessible if I access them individually. But problem is that how could I access if the key field come from another variable. I want code snippet something like below one.
{{product.metafields.productmeta.{block.settings.patitle | downcase }}}
block.settings.patitle comes from section block in a loop. And same downcased title is used as an key in metafields.
You can capture that string as something like a key:
{% capture mykey %}{{ block.settings.patitle | downcase }}{% endcapture %}
Then you can try accessing your metafield with that variable as in:
{{ product.metafields.productmeta.mykey }}
If that does not work, then why not try the string interpelation:
{{ product.metafields.productmeta['{{block.settings.patitle | downcase }}'] }}
Enough experimenting should get you what you want.

Printing Product Variant HS Codes

I am trying to create an automated Commercial Invoice within Shopify, using the Liquid template language. I have everything working, except for the IMPORT/EXPORT Harmonized Codes (HS Tariff Codes) that are stored as variant meta-fields. Whenever I try to print them out using the following code, I get blanks:
{% for line_item in line_items %}
{{ line_item.variant.metafields.global_harmonized_system_code }}
{% endfor %}
Can someone help me pull these HS Codes for each product variant and print them on the Commercial Invoice using liquid to pull the meta-field?
Global is a namespace, try :
{{ line_item.variant.metafields.global.harmonized_system_code }}
The syntax is :
{{ your_object.metafields.namespace.key }}
Your Liquid is insufficient for the task at hand.
{{ line_item.variant.metafields.global_harmonized_system_code }}
That output is not valid. It might point to a set of one or more key value pairs, so you should really iterate on that. Example:
{% for mf in line_item.variant.metafields.global %}
{% if mf | first == 'harmonized_system_code' %}
<p> {{ mf | last }} how is that for some value! </p>
{% endif %}
{% endfor %}
Something like that is more precise and will go through the variant metafields allowning you to choose which ones to print out.
I am able to get the value using this
{{ line_item.variant.metafields.harmonized_system_code.value }}

Shopify link directly to other item

I have some items in my shopify store that have similar themed items that compliment it well.
I know I could just add an <a href link in there, but I'd like to do something that is actually part of liquid, and would also be easier for my non-programmer partner (who also has the authority to make me sleep on the couch :-( ...) to add these links. Is there a way to add a link using the liquid formatting? Something like This would go great with ${items.ellington-coffee-table-set}!?
It would be great to be able to access a product like this collections.my-collection-handle.products.my-product-handle, but unfortunately it is not possible to get a product by its handle in liquid.
You would have to loop through the collection to find the product like this:
{% for product in collections.my-collection-handle.products %}
{% if product.handle == 'my-product-handle' %}
{{ 'my product' | link_to: product.url }}
{% endif %}
{% endfor %}
But that looks pretty messy if all you want is a link to the product, and you still have to hard-code the product's handle. This would be simpler:
{{ 'my product' | link_to: '/products/my-product-handle' }}
Still not ideal, but probably a better alternative than coding an <a href=... link manually.