Hi
I was thinking about extending set_fact to be able to write the facts given as a local facts file. Something like this:
set_fact: var=value persistent_file=myvars
To create /etc/ansible/facts.d/myvars.fact as a json with the given vars.
Is this something that might be considered for core? Do you guys have opinions on semantics (separate to a different module maybe)?
Thanks
This is a pretty interesting way to do it and I don’t think I’d have an objection to it.
It would probably need to call the “copy” module in the action_plugin to make it work, using the “content” parameter.
Having it the same module seems to make sense to me.
Pull request would definitely be welcome!
Is there a reason to keep it an action plugin and not a normal module? I’m thinking performance, is there something else?
If you look at set_fact now, it’s completely an action plugin, since it only operates on the host running ansible and not on each individual host (others like this are add_host/group_by, template and fetch modules, which work entirely through action plugins). This saves a lot of effort in having to re-implement common functionality like copying a file out to a host.
To me, it sounds like this new module would be dumping the contents of the vars_cache[hostname] to a file, or perhaps just a subset of those variables?
One gotcha I just realized is local facts show up as “ansible_local.factname” to ensure they never override another fact, kind of as a safety feature.
I would think it would write just the one variable to a facts.d/variable_name file, but it should probably raise an error with persistent=yes if the variable name didn’t start with “ansible_local”, since otherwise it would be set and referenced differently when retrieved the second time.
Like so:
works
set_fact: name=ansible_local.foo value=1234 persistent=yes
raises error: “when using persistent=yes, the variable must be prefixed with ‘ansible_local’”
set_fact: name=foo value=1234 persistent=yes
works fine but doesn’t save
set_fact: name=foo value=1234
And then in the docs we could make a note of it.
One gotcha I just realized is local facts show up as “ansible_local.factname” to ensure they never override another fact, kind of as a safety feature.
I would think it would write just the one variable to a facts.d/variable_name file, but it should probably raise an error with persistent=yes if the variable name didn’t start with “ansible_local”, since otherwise it would be set and referenced differently when retrieved the second time.
Like so:
works
set_fact: name=ansible_local.foo value=1234 persistent=yes
This is different than how set_fact is used now - you pass args as key=value, not as name=key value=value. I think that will also make it harder to create more complex facts:
set_fact: name=ansible_local.foo value={{ {key: value, key2:value2} }} persistent=yes # ugh
BTW do people use local facts for single values? I didn’t think about it until now, and the docs don’t give this usage in the examples.
Another option, which may be a bit magic-y, is to set the facts in the ansible_local namespace if they’re persistent:
set_fact: myfact1=123 myfact2=asd # Will set myfact1=123, myfact2=asd
set_fact: myfact=123 myfact2=asd persistent=hkariti # Will set ansible_local.hkariti={myfact1: 123, myfact2: asd} and save
This doesn’t work for single values though.
One gotcha I just realized is local facts show up as
"ansible_local.factname" to ensure they never override another fact, kind
of as a safety feature.
I would think it would write just the one variable to a
facts.d/variable_name file, but it should probably raise an error with
persistent=yes if the variable name didn't start with "ansible_local",
since otherwise it would be set and referenced differently when retrieved
the second time.
Like so:
# works
set_fact: name=ansible_local.foo value=1234 persistent=yes
This is different than how set_fact is used now - you pass args as
key=value, not as name=key value=value. I think that will also make it
harder to create more complex facts:
Sorry, this was just me tying too quickly, conceptually, I mean the same
thing.
set_fact: name=ansible_local.foo value={{ {key: value, key2:value2} }}
persistent=yes # ugh
This isn't a thing with setting a hash like this in a one liner, BTW. You
must use the long form.
set_fact:
key: { key: value, key2: value2 }
And if you want variables, you can template inside, etc.
Another option, which may be a bit magic-y, is to set the facts in the
ansible_local namespace if they're persistent:
set_fact: myfact1=123 myfact2=asd # Will set myfact1=123, myfact2=asd
I'd like to avoid this, because then the usage of the variable would have
to be accessed by ansible_local.foo, which would be unclear
to readers of the playbook because it was set one way and is accessed
another.