pytest-dev / pytest-testinfra

Testinfra test your infrastructures
https://testinfra.readthedocs.io
Apache License 2.0
2.37k stars 355 forks source link

How to call host.salt() with keyword arguments ? #223

Open marco-m opened 7 years ago

marco-m commented 7 years ago

Hello, documentation shows that I can call with a list of strings:

host.salt("grains.item", ["osarch", "mem_total", "num_cpus"])

I have two questions:

  1. How do I transform the following command-line salt invocation into a Testinfra call:

    salt 'minion' state.apply foo pillar='{"cheese": "spam"}'
  2. Is there a way to pass, say, a Python dictionary (the pillar in the previous example) or do I have to convert everything to a string ?

thanks!

philpep commented 7 years ago

Maybe: host.salt('sate.apply', 'foo', pillar={'cheese': 'spam'} ?

marco-m commented 7 years ago

If I use your suggestion

host.salt('state.apply', 'foo', pillar={'cheese': 'spam'})

I get from pytest:

>     host.salt('state.apply', 'foo', pillar={'cheese': 'spam'})
E     TypeError: __call__() got an unexpected keyword argument 'pillar'

On the other hand if I put everything inside a list AND stringify the dictionary I don't get any errors:

host.salt('state.apply', ['foo', "pillar={'cheese': 'spam'}"])

And it seems to be working! If I use pillar.items to get all the pillar data, the assert passes:

    assert {'cheese': 'spam'} == host.salt('pillar.items',
                                           ["pillar={'cheese': 'spam'}"])

I can now proceed with my code, thanks!

I suggest to add this example to the documentation, it shows how powerful Testinfra is, because you can test states that require custom pillars without fiddling with temporarily moving into place a pillar file, you can just pass the pillar dictionary as a string from the test!

tacerus commented 1 year ago

Hi,

does this still work for you?

If I try

host.salt('state.show_sls', ['suse_ha', "pillar={'test': false}"])

it results in a broken command with lots of escaped quotation marks:

command=b'sudo /bin/sh -c \'salt-call --out=json state.show_sls suse_ha \'"\'"\'pillar={\'"\'"\'"\'"\'"\'"\'"\'"\'test\'"\'"\'"\'"\'"\'"\'"\'"\': {\'"\'"\'"\'"\'"\'"\'"\'"\'with_fencing\'"\'"\'"\'"\'"\'"\'"\'"\': False}}\'"\'"\'\''

If I swap the single and double quotes in my call:

host.salt('state.show_sls', ['suse_ha', 'pillar={"test": false}']

the quote mess is shorter, but still wrong

command=b'sudo /bin/sh -c \'salt-call --out=json state.show_sls suse_ha \'"\'"\'pillar={"test": false}\'"\'"\'\''

I tried the pillar.items example, but the pillar does not seem to be passed, as it does not show up.

Edit: the same happens if I use a string instead of a boolean in my pillar dictionary.