how to use external facts in a template?

110 views
Skip to first unread message

Sans

unread,
Jan 25, 2017, 6:43:14 AM1/25/17
to Puppet Users
Dear all,
I'm having this issue and running out of ideas.
I have this two external facts (defined in /etc/facter/facts.d/extn_git_facts.txt):


root@p19
-d-pmaster-001:~# facter|grep ks_git
ks_git_puppet
-hiera => master                        
ks_git_puppet
-master => develop

I want to use these two facts in a template. Here is my pseudo code:

<%-
    git_repos
= ['puppet-hiera', 'puppet-master']
    git_repos
.each do |g_repo|
        git_branch
= "ks_git_#{g_repo}"
        git_br_name
= Facter.value("ks_git_#{g_repo}")
-%>
GIT_BRANCH      ::
<%= git_branch %>
GIT_BRANCH_NAME ::
<%= git_br_name %>
<%-
   
end
-%>

and I don't get anything returned by `git_br_name` at all. If I use the same code in irb console, it works just fine:

 irb(main):012:0> require 'facter'
 
=> true
 irb
(main):013:0> git_repos = ['puppet-hiera', 'puppet-master']
 
=> ["puppet-hiera", "puppet-master"]
 irb
(main):014:0> git_repos.each do |g_repo|
 irb
(main):015:1* p Facter.value("ks_git_#{g_repo}")
 irb
(main):016:1> end
 
"master"
 
"develop"
 
=> ["puppet-hiera", "puppet-master"]


What am I doing wrong in the template? if I use some other built-in facts instead, e.g. `Facter.value(:hostname)` - it works just okay. Does mean the external facts cannot be used in template? Thanks in advance.

Best,
Santanu

Garrett Honeycutt

unread,
Jan 25, 2017, 8:52:34 AM1/25/17
to puppet...@googlegroups.com
On 1/25/17 6:43 AM, Sans wrote:
> Dear all,
> I'm having this issue and running out of ideas.
> I have this two external facts (defined in
> /etc/facter/facts.d/extn_git_facts.txt):
>
> |
>
> root@p19-d-pmaster-001:~# facter|grep ks_git
> ks_git_puppet-hiera =>master
> ks_git_puppet-master =>develop
> |
>
> I want to use these two facts in a template. Here is my pseudo code:
> |
>
> <%-
> git_repos =['puppet-hiera','puppet-master']
> git_repos.each do|g_repo|
> git_branch ="ks_git_#{g_repo}"
> git_br_name =Facter.value("ks_git_#{g_repo}")
> -%>
> GIT_BRANCH :: <%=git_branch %>
> GIT_BRANCH_NAME :: <%=git_br_name %>
> <%-
> end
> -%>
> |
>
> and I don't get anything returned by `git_br_name` at all. If I use the
> same code in irb console, it works just fine:
>
> |
> irb(main):012:0>require'facter'
> =>true
> irb(main):013:0>git_repos =['puppet-hiera','puppet-master']
> =>["puppet-hiera","puppet-master"]
> irb(main):014:0>git_repos.each do|g_repo|
> irb(main):015:1*p Facter.value("ks_git_#{g_repo}")
> irb(main):016:1>end
> "master"
> "develop"
> =>["puppet-hiera","puppet-master"]
> |
>
>
> What am I doing wrong in the template? if I use some other built-in
> facts instead, e.g. `Facter.value(:hostname)` - it works just okay. Does
> mean the external facts cannot be used in template? Thanks in advance.
>
> Best,
> Santanu
>
> --

Hi Sans,

I think your ERB syntax may be off. Here's an example doing something
similar. Instead of Facter.value() just put an @ in front of the fact name.

<% @nameservers.each do |nameserver| -%>
nameserver <%= nameserver %>
<% end -%>

Best regards,
-g

--
Garrett Honeycutt
@learnpuppet
Puppet Training with LearnPuppet.com
Mobile: +1.206.414.8658

Sans

unread,
Jan 25, 2017, 9:17:19 AM1/25/17
to Puppet Users

Hi Sans,

I think your ERB syntax may be off. Here's an example doing something
similar. Instead of Facter.value() just put an @ in front of the fact name.

<% @nameservers.each do |nameserver| -%>
nameserver <%= nameserver %>
<% end -%>

Best regards,
-g

 
AFAIK (and understand), when you gave this: @nameservers compiler just treat that as variable, regardless of the fact it's actually a Fact or otherwise. Facter.value() is a valid syntax, which I use very often in my template and custom fact. The part of template, also try to determine if the fact is defined at all or not. It's not working for any external fact. As I already mentioned, it works for other facts, like "hostname" etc.

-S
 

R.I.Pienaar

unread,
Jan 25, 2017, 9:20:30 AM1/25/17
to puppet-users
not been following, but if you're on a recent version @facts["foo"] is the
best

Sans

unread,
Jan 25, 2017, 2:01:20 PM1/25/17
to Puppet Users


On Wednesday, January 25, 2017 at 2:20:30 PM UTC, R.I. Pienaar wrote:

not been following, but if you're on a recent version @facts["foo"] is the
best

I didn't know that but will check soon. I'm on v3.8.x - will it work there?

-S

R.I.Pienaar

unread,
Jan 25, 2017, 2:05:03 PM1/25/17
to puppet-users


----- Original Message -----
> From: "Sans" <r.sant...@gmail.com>
> To: "puppet-users" <puppet...@googlegroups.com>
> Sent: Wednesday, 25 January, 2017 20:01:20
> Subject: Re: [Puppet Users] how to use external facts in a template?

only if you enable structured facts and have a new facter

Sans

unread,
Jan 25, 2017, 2:20:21 PM1/25/17
to Puppet Users


On Wednesday, January 25, 2017 at 7:05:03 PM UTC, R.I. Pienaar wrote:


only if you enable structured facts and have a new facter

Well, it's not "structured" i.e. it returns only a string. and didn't work as expected.
It also an "external fact", not sure if that's the main issue. Facter.value() works fine with other  fact, like "hostname" etc.

-San

R.I.Pienaar

unread,
Jan 25, 2017, 2:23:59 PM1/25/17
to puppet...@googlegroups.com
regardless, for @facts to exist you have to enable that feature.  It's not about *your specific fact*

Henrik Lindberg

unread,
Jan 25, 2017, 6:23:06 PM1/25/17
to puppet...@googlegroups.com
Do not ever reference Facter directly on the master side from functions
or ERB templates used when compiling. Only reference Facter in logic
that implements facts. It should be safe to reference Facter on the
agent side in provider logic.

If you have been advised to use Facter directly in templates I would
like to know where that advice came from.

You want to reference @facts['factname'] in an ERB if you are on a
modern puppet, otherwise individual top scope variables.

- henrik


--

Visit my Blog "Puppet on the Edge"
http://puppet-on-the-edge.blogspot.se/

Sans

unread,
Jan 26, 2017, 2:35:03 AM1/26/17
to Puppet Users
Hi Henrik,

Thanks for commenting. Could you elaborate "Only reference Facter in logic that implements facts" pls? Does it mean when defining, e.g. a custom-fact, it's okay to reference another fact but not anywhere else? People gave me so many advice about dos and don'ts but no one actually explain why it's not working or how can I do it. Regardless of it should be done or not, why it works for thing like Facter.value(:hostname) but not with like: Facter.value(:my_external_fact)?

Basically, I have some external facts setup, during the initial machine provisioning and then I wanna make sure those facts are defined, if not put those facts in the external_fact file with some default value. That template is to maintain that external_fact file - that's my case.

-San

Henrik Lindberg

unread,
Jan 26, 2017, 6:06:31 AM1/26/17
to puppet...@googlegroups.com
On 26/01/17 08:35, Sans wrote:
> Hi Henrik,
>
> Thanks for commenting. Could you elaborate "Only reference Facter in
> logic that implements facts" pls? Does it mean when defining, e.g. a
> custom-fact, it's okay to reference another fact but not anywhere else?
> People gave me so many advice about dos and don'ts but no one actually
> explain why it's not working or how can I do it. Regardless of it should
> be done or not, why it works for thing like /Facter.value(:hostname)/
> but not with like: /Facter.value(:my_external_fact)/?
>
> Basically, I have some external facts setup, during the initial machine
> provisioning and then I wanna make sure those facts are defined, if not
> put those facts in the external_fact file with some default value. That
> template is to maintain that external_fact file - that's my case.
>
> -San
>


The process is that "facter" runs on the agent, it computes the values
of all the facts for the node. It then sends those to the master which
produces a catalog by compiling manifests. The catalog compiler logic
makes the facts for the node available in $facts hash and in individual
top scope variables (for backwards compatibility reasons). Those are the
fact values that all logic on the master should use. They may not come
directly from facter. So... don't call Facter methods in your templates.

The master is also a node, and running Facter on it may produce the
facts for the master!

Facter is a singleton and it is undefined what happens if you call it
from different environments on the same server.

So, repeating - where did you get the advice (or idea) to call Facter
methods? I want to make sure that place gets updated.

It is obviously easy to confuse "computing the value of a fact x", with
"what is the value of fact x for node y".

- henrik


> On Wednesday, January 25, 2017 at 11:23:06 PM UTC, Henrik Lindberg wrote:
>
>
> Do not ever reference Facter directly on the master side from functions
> or ERB templates used when compiling. Only reference Facter in logic
> that implements facts. It should be safe to reference Facter on the
> agent side in provider logic.
>
> If you have been advised to use Facter directly in templates I would
> like to know where that advice came from.
>
> You want to reference @facts['factname'] in an ERB if you are on a
> modern puppet, otherwise individual top scope variables.
>
> - henrik
>
>
> --
>
> Visit my Blog "Puppet on the Edge"
> http://puppet-on-the-edge.blogspot.se/
> <http://puppet-on-the-edge.blogspot.se/>
>
> --
> You received this message because you are subscribed to the Google
> Groups "Puppet Users" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to puppet-users...@googlegroups.com
> <mailto:puppet-users...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/puppet-users/e45d81c5-f66a-4c29-960b-c52cbc334486%40googlegroups.com
> <https://groups.google.com/d/msgid/puppet-users/e45d81c5-f66a-4c29-960b-c52cbc334486%40googlegroups.com?utm_medium=email&utm_source=footer>.
> For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages