How to pass in command line arguments to salt state.sls that will be used as the correct input arguments in the cmd.script it runs

3,243 views
Skip to first unread message

Rob Reinhardt

unread,
Dec 18, 2017, 2:58:46 PM12/18/17
to Salt-users

The following works fine if I hard-code my scripts' four command-line arguments as args below:  The four things my script needs, gets passed in, and it runs on the minion fine.

current sample
run_my_setup_script.sls:
run_my_setup_script:
  file.managed:
    - name: /usr/local/bin/myscript.sh
    - source: salt://managed-scripts/myscript.sh
    - user: root
    - group: root
    - mode: 700
    - backup: minion
  cmd.script:
    - source: salt://managed-scripts/myscript.sh
    - args: "mythingsname mythings_file.tar.gz /root/mythings_filedir /opt/mything"
    - user: root
    - group: root
    - shell: /bin/bash

But, that is not what I want to do.  I want to be able to pass in those args from the command line when I run the salt command, because they can be different from one system to another.

current sample using the above that works
command-line:
salt myhost.site.location.mydomain.net state.sls run_my_setup_script

what I want to do instead is something like:
salt myhost.mydom.myplace.net state.sls run_my_setup_script -args "$1" "$2" "$3" "$4"

I don't know if there is some method in salt to do the equivalent of what I want to do here.  The above is just a simple example for illustration, it could be almost anything as long as I get to pass my own arguments into the run of the state.sls and further pass them on into my cmd.script execution.

The only thing I don't want to do is to simply define something in a pillar which then simply moves my hard-coding of the choices from the state.sls to a pillar file. (pillar usage is the only thing I've found that others refer to for similar questions, but from what I've seen it doesn't actually answer my question, I'm not trying to use a pillar at all, simply instruct the behavior of the script my state.sls is going to run.

I want the freedom to pass in anything on the salt state.sls command line that I want to pass into my scripts.

Is this possible?  If so, how?

Thanks,
Rob


Daniel Wallace

unread,
Dec 18, 2017, 5:06:27 PM12/18/17
to Salt-users
If you want to pass stuff to a state run, you would need to pass it in using pillar data.

From the docs.
salt '*' state.apply test pillar='{"foo": "bar"}'

--
You received this message because you are subscribed to the Google Groups "Salt-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to salt-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/salt-users/c10413ff-c047-4f10-b7af-1c8bd49aeb2a%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Rob Reinhardt

unread,
Dec 18, 2017, 5:13:29 PM12/18/17
to salt-...@googlegroups.com
If I do that, doesn't that mean I have to hard-code the value of foo in the pillar or am I just declaring or defining the existence of foo as an argument variable (which I suppose I can live with if I must).

Another way to put it, can the value 'bar' be anything the user needs to pass in to the command or does it have to be a value for 'foo' that is already pre-defined in the pillar file?

In either case, what does that pillar file look like?

I have no personal experience with python and only what jinja2 or yaml that I've encountered with Salt, so none of this syntax is second-nature to me.

Thanks,
Rob

---
VP, Infrastructure and Operations
Healytics, Inc.
E-mail: rrein...@healytics.com
Mobile: 410-776-5835

--
You received this message because you are subscribed to a topic in the Google Groups "Salt-users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/salt-users/-htN8O8vHEU/unsubscribe.
To unsubscribe from this group and all its topics, send an email to salt-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/salt-users/CAA2%2B9hCaHmQOHxE5N%3DTEu%2BvdvQOuxQKZ5puXKSqs%3DWXP2zfVvQ%40mail.gmail.com.

Daniel Wallace

unread,
Dec 18, 2017, 5:38:42 PM12/18/17
to Salt-users
So, the key is foo.  Bar can be whatever you want to pass in.

Then you just reference `pillar['foo']` in your states.  or you can give a default value in jinja with `pillar.get('foo', 'default')` then if you don't pass anything in, it will use the default, but you can pass in foo: bar if you wanted too.

Rob Reinhardt

unread,
Dec 18, 2017, 6:26:31 PM12/18/17
to salt-...@googlegroups.com
Okay, I've tried the following but, I still get the error "Rendering SLS 'base:mysls' failed: Jinja variable 'dict object' has no attribute 'hvar1'

Am I missing a bracket or a quote or something? (right now not bothering with the option of using a default value)

the relevant portion of the cmd.script part of mysls is:

  cmd.script:
    - source: salt://managed-scripts/myscript.sh
    - args: "{{ pillar['hvar1'] }} {{ pillar['hvar2'] }} {{ pillar['hvar3'] }} {{ pillar['hvar4'] }}"

    - user: root
    - group: root
    - shell: /bin/bash

salt myhost.mysite.mylocation.mydomain.net state.apply mysls \
        pillar='{"hvar1": "something1"}' \
        pillar='{"hvar2": "something2"}' \
        pillar='{"hvar3": "something3"}' \
        pillar='{"hvar4": "something4"}'

there are no specific examples of using this with "args" in the doc, just name or source, but of course, if I'm going to pass the values into my script as arguments the pillars have to be set in the "args" portion of cmd.script.  is my syntax for doing that correct?

from this doc:

Thanks,
Rob

---
VP, Infrastructure and Operations
Healytics, Inc.
E-mail: rrein...@healytics.com
Mobile: 410-776-5835

Daniel Wallace

unread,
Dec 18, 2017, 6:36:48 PM12/18/17
to Salt-users
You only send one pillar dictionary.

```
salt myhost.mysite.mylocation.mydomain.net state.apply mysls \
        pillar='{hvar1: something1, hvar2: something2, hvar3: something3, hvar4: something4}'
```

You can also pass it in as yaml if you wanted

```
salt myhost.mysite.mylocation.mydomain.net state.apply mysls pillar="
hvar1: something1
hvar2: something2
hvar3: something3
hvar4: something4
"
```

Rob Reinhardt

unread,
Dec 18, 2017, 6:52:25 PM12/18/17
to salt-...@googlegroups.com
That worked, except despite the fact that the script did what it was supposed to and set -x showed all the arguments made it into their variables just fine,

salt gave me the following error, before reporting success of the changes anyway:

    Data failed to compile:
----------

    Rendering SLS 'base:mysls' failed: Jinja variable 'dict object' has no attribute 'hvar1'
ERROR: Minions returned with non-zero exit code



---
VP, Infrastructure and Operations
Healytics, Inc.
E-mail: rrein...@healytics.com
Mobile: 410-776-5835

Rob Reinhardt

unread,
Dec 19, 2017, 10:16:35 AM12/19/17
to salt-...@googlegroups.com
Further testing shows that if I run the same command but as a salt-call from the minion instead of as salt from the master, it works but does not throw the error?

What does that tell us?


Rendering SLS 'base:mysls' failed: Jinja variable 'dict object' has no attribute 'hvar1'
ERROR: Minions returned with non-zero exit code

---
VP, Infrastructure and Operations
Healytics, Inc.
E-mail: rrein...@healytics.com
Mobile: 410-776-5835

Rob Reinhardt

unread,
Dec 19, 2017, 10:34:05 AM12/19/17
to salt-...@googlegroups.com
I figured it out.  It works fine now.  Thanks for your help Daniel.  The problem was in my testing methodology, not the actual salt code/syntax.

Rob

---
VP, Infrastructure and Operations
Healytics, Inc.
E-mail: rrein...@healytics.com
Mobile: 410-776-5835

Daniel Wallace

unread,
Dec 19, 2017, 10:36:51 AM12/19/17
to Salt-users

Rob Reinhardt

unread,
Dec 19, 2017, 11:26:11 AM12/19/17
to salt-...@googlegroups.com
Now that works, I am left with one more question.  My state.sls file now just has pillar "variables" in it.  so, a call to the state.sls without passing variables (such as state.highstate) will fail to render.

I think the state.sls needs default values for these to prevent that failure.  I've tried the following at the top of my state.sls file but it doesn't help.  I thought this would declare an initial value (i.e. default) for these that then would get over-written when I call it from the command line with arguments.

{% set hvar1 = 'default' %}
{% set hvar2 = 'default' %}
{% set hvar3 = 'default' %}
{% set hvar4 = 'default' %}

then if/when it is not called from command-line the dict will still render with those default values and I can have my script handle the defaults and the state will work even in that case.

Thanks,
Rob



---
VP, Infrastructure and Operations
Healytics, Inc.
E-mail: rrein...@healytics.com
Mobile: 410-776-5835

Daniel Wallace

unread,
Dec 19, 2017, 11:28:49 AM12/19/17
to Salt-users
set the value when pulling the variable out of the pillar.

{{ pillar.get('hvar1', 'default') }}

Rob Reinhardt

unread,
Dec 19, 2017, 12:06:22 PM12/19/17
to salt-...@googlegroups.com
Works perfectly.  Thanks again. -Rob

---
VP, Infrastructure and Operations
Healytics, Inc.
E-mail: rrein...@healytics.com
Mobile: 410-776-5835

Suresh V

unread,
Nov 1, 2019, 1:07:58 PM11/1/19
to Salt-users
Hi Guys,

I am trying to pass variables defined in init.sls file  to persue in shell script. Below is the error, can someone please assist

[root@ip-172-16-42-53 ~]# salt '172.16.50.104*' state.apply common.appTags.Test                                                                                                                        
172.16.50.104:                                                                                                                                                                                         
    - Rendering SLS 'base:common.appTags.Test' failed: Jinja variable 'dict object' has no attribute 'hvar1'                                                                                           
ERROR: Minions returned with non-zero exit code                                                                                                                                                        

  


Init.sls:

{% set hvar1 = 'testing' %}
{% set hvar2 = 'AWSDailyBackup' %}

addTags:
  file.managed:
    - name: /tmp/Tags.sh
    - source: salt://common/appTags/Test/applicationTags.sh
    - user: root
    - group: root
    - mode: 755
    - makedirs: True
    - template: jinja
    - defaults:
        STACKAPP: {{ pillar.get('hvar1', 'default') }}
        FREQUENCY: {{ pillar.get('hvar2', 'default') }}
  cmd.run:
    - args:"{{ pillar['hvar1'] }} {{ pillar['hvar2'] }}"
    - shell: /bin/bash
    - name: sh /tmp/Tags.sh 
    - require:
      - file: addTags

applicationTags.sh or Tags.sh 

#!/bin/bash


aws ec2 create-tags --resources $INSTANCEID --tags Key=app,Value=$STACKAPP

VOLUME=$(aws ec2 describe-volumes --region us-east-1 --filters Name=attachment.instance-id,Values=instance-id,$INSTANCEID | sed -n 's/.*"VolumeId": "\(.*\)",/\1/p' | uniq)
        for i in $VOLUME; do
        aws ec2 create-tags --resources $i --tags Key=app,Value=$STACKAPP
        aws ec2 create-tags --resources $i --tags Key=$FREQUENCY,Value=true
        done

Reply all
Reply to author
Forward
0 new messages