Skip to content

Commit 0fe4f4b

Browse files
authored
Merge pull request #3 from github/kpaulisse-document-indexing
Document indexing and ENCs, and add reindex action
2 parents 16bd93b + cb01199 commit 0fe4f4b

File tree

6 files changed

+97
-16
lines changed

6 files changed

+97
-16
lines changed

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ This pull request [introduces/changes/removes] [functionality/feature].
1919
## Checklist
2020

2121
- [ ] Make sure that all of the tests pass, and fix any that don't. Just run `bundle exec rake` in your checkout directory, or review the CI job triggered whenever you push to a pull request.
22-
- [ ] Make sure that there is 100% test coverage (the CI job will test for this). You can ignore untestable sections of code with `# :nocov` comments. If you need help getting to 100% coverage please ask; however, don't just submit code with no tests.
22+
- [ ] Make sure that there is 100% test coverage (the CI job will test for this). You can ignore untestable sections of code with `# :nocov:` comments. If you need help getting to 100% coverage please ask; however, don't just submit code with no tests.
2323
- [ ] If you have added any new gem dependencies, make sure those gems are licensed under the MIT or Apache 2.0 license. We cannot add any dependencies on gems licensed under GPL.
2424
- [ ] If you have added any new gem dependencies, make sure you've checked in a copy of the `.gem` file into the [vendor/cache](/vendor/cache) directory.
2525

.version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.5.0
1+
0.5.1

Gemfile.lock

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
PATH
22
remote: .
33
specs:
4-
octofacts (0.5.0)
5-
octofacts-updater (0.5.0)
4+
octofacts (0.5.1)
5+
octofacts-updater (0.5.1)
66
diffy (>= 3.1.0)
77
net-ssh (>= 2.9)
88
octocatalog-diff (>= 1.4.1)

doc/octofacts-updater.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,55 @@ Note that `facter` may need to run as root to gather all of the facts for the sy
9999

100100
Also, if you are using Puppet 4 or later, but are relying on "legacy" facts that were used in Puppet 3, you may need to add `--show-legacy` to the `facter` command line.
101101

102+
## Indexing facts
103+
104+
`octofacts` supports an index of facts, allowing you to select fixtures dynamically based on parameters, rather than by specifying the name of a specific file in your tests. When properly set up, the use of an index in rspec-puppet tests will look like this example:
105+
106+
```
107+
let(:facts) { Octofacts.from_index(app: "my_app", role: "my_role") }
108+
```
109+
110+
To set up the index, you need to configure three settings:
111+
112+
- `file`: The absolute or relative path to the index file.
113+
- `node_path`: The absolute or relative path to the directory where fixtures for nodes are stored.
114+
- `indexed_facts`: An array of facts that you want to index. For the example above, you would need to index the `app` and `role` facts.
115+
116+
In your configuration, this might look like:
117+
118+
```title=octofacts-updater.yaml
119+
index:
120+
file: ../spec/fixtures/facts/octofacts-index.yaml
121+
node_path: ../spec/fixtures/facts/octofacts
122+
indexed_facts:
123+
- app
124+
- role
125+
```
126+
127+
Once you have configured the index, you can use `octofacts-updater` to build the index from the node fixtures you already have.
128+
129+
```
130+
touch spec/fixtures/facts/octofacts-index.yaml
131+
octofacts-updater --config octofacts-updater.yaml --action reindex
132+
```
133+
134+
:information_source: If a file or directory path starts with `.` or `..`, the path is treated as relative to the configuration file itself. This allows you to specify locations within a Puppet code repository, without regard to where on the system `octofacts-updater` is actually installed. Of course, you can also use absolute paths (starting with `/`).
135+
136+
## Using an External Node Classifier (ENC)
137+
138+
If your Puppet setup uses an external node classifier (ENC), it may supply settings in its `parameters` hash that are treated as top level variables by Puppet code (like facts), and can be accessed in Puppet manifests. For example, if your ENC sets a top level parameter `app: application_name` then in your Puppet code, `$::app` will equal "application_name". Furthermore, `%{::app}` will be interpolated in a Hiera configuration file.
139+
140+
To configure `octofacts-updater` to run your ENC when updating facts for a node, add the path to your ENC in the configuration file.
141+
142+
```title=octofacts-updater.yaml
143+
enc:
144+
path: /usr/local/sbin/enc.sh
145+
```
146+
147+
Note that per conventions, all ENCs must take exactly one parameter (the hostname) and return output in YAML format. You do not need to indicate the hostname (via `%%NODE%%` or hard-coding) when configuring the ENC, because this is assumed.
148+
149+
If the ENC returns `parameters` at the top level, these are merged in to the facts gathered for the node. In the case that the node and the ENC both contain the same key, the key from the ENC will be used.
150+
102151
## Anonymizing and rewriting facts
103152

104153
To avoid committing sensitive information into source control, and to prevent rspec-puppet tests from inadvertently contacting actual systems, `octofacts-updater` supports anonymizing and rewriting facts. For example, you might remove or scramble SSH keys, delete or hard-code facts like system uptime that change upon each run, or change IP addresses.

examples/config/quickstart.yaml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,20 @@
3131
# without explicitly naming a node, list the facts here that you would like to have indexed.
3232
# You can also specify the path to the index file. Be sure to adjust it for your site.
3333
index:
34-
file: /var/lib/jenkins/workspace/puppet/spec/fixtures/facts/octofacts-index.yaml
34+
file: ../spec/fixtures/facts/octofacts-index.yaml
35+
node_path: ../spec/fixtures/facts/octofacts
3536
indexed_facts:
37+
- app
38+
- role
3639
- virtual
3740

41+
# If you are using an external node classifier (ENC) you can import its results into octofacts
42+
# by having the octofacts-updater run the ENC as the node's facts are obtained. Anything in the
43+
# ENC's "parameters" hash will be configured as a fact and override the facts from the data source.
44+
# Provide the path to your ENC script here.
45+
# enc:
46+
# path: ./config/enc.sh
47+
3848
# This section cleans up and anonymizes facts. We have added a number of facts to this list
3949
# that contain sensitive information or change frequently. You should add any facts from your
4050
# site as needed.

lib/octofacts_updater/cli.rb

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ def initialize(argv)
1616
end
1717

1818
opts.on("-c", "--config <config_file>", String, "Path to configuration file") do |f|
19-
raise "Invalid configuration file" unless File.file?(f)
20-
@opts[:config] = f
19+
@opts[:config] = File.expand_path(f)
20+
raise "Invalid configuration file #{@opts[:config].inspect}" unless File.file?(@opts[:config])
2121
end
2222

2323
opts.on("-H", "--hostname <hostname>", String, "FQDN of the host whose facts are to be gathered") do |h|
@@ -67,11 +67,12 @@ def initialize(argv)
6767
end
6868

6969
def usage
70-
puts "Usage: octofacts-updater --action <action> [--config-file /path/to/config.yaml] [other options]"
70+
puts "Usage: octofacts-updater --action <action> [--config /path/to/config.yaml] [other options]"
7171
puts ""
7272
puts "Available actions:"
73-
puts " bulk: Update fixtures and index in bulk"
74-
puts " facts: Obtain facts for one node (requires --hostname <hostname>)"
73+
puts " bulk: Update fixtures and index in bulk"
74+
puts " facts: Obtain facts for one node (requires --hostname <hostname>)"
75+
puts " reindex: Build a new index from the existing fact fixtures"
7576
puts ""
7677
end
7778

@@ -106,6 +107,7 @@ def run
106107

107108
return handle_action_bulk if opts[:action] == "bulk"
108109
return handle_action_facts if opts[:action] == "facts"
110+
return handle_action_bulk if opts[:action] == "reindex"
109111

110112
usage
111113
exit 255
@@ -126,19 +128,39 @@ def substitute_relative_paths!(object_in, basedir)
126128
end
127129
end
128130

129-
def handle_action_bulk
130-
facts_to_index = @config.fetch("index", {})["indexed_facts"]
131-
unless facts_to_index.is_a?(Array)
132-
raise ArgumentError, "Must declare index:indexed_facts in configuration to use bulk update"
133-
end
131+
def nodes_for_bulk
132+
if opts[:action] == "reindex"
133+
@opts[:quick] = true
134+
135+
path = if opts[:path]
136+
File.expand_path(opts[:path])
137+
elsif @config.fetch("index", {})["node_path"]
138+
File.expand_path(@config.fetch("index", {})["node_path"], File.dirname(opts[:config]))
139+
else
140+
raise ArgumentError, "Must set --path, or define index:node_path to a valid directory in configuration"
141+
end
142+
143+
unless File.directory?(path)
144+
raise Errno::ENOENT, "--path must be a directory (#{path.inspect} is not)"
145+
end
134146

135-
nodes = if opts[:host_list]
147+
Dir.glob("#{path}/*.yaml").map { |f| File.basename(f, ".yaml") }
148+
elsif opts[:host_list]
136149
opts[:host_list]
137150
elsif opts[:hostname]
138151
[opts[:hostname]]
139152
else
140153
OctofactsUpdater::FactIndex.load_file(index_file).nodes(true)
141154
end
155+
end
156+
157+
def handle_action_bulk
158+
facts_to_index = @config.fetch("index", {})["indexed_facts"]
159+
unless facts_to_index.is_a?(Array)
160+
raise ArgumentError, "Must declare index:indexed_facts in configuration to use bulk update"
161+
end
162+
163+
nodes = nodes_for_bulk
142164
if nodes.empty?
143165
raise ArgumentError, "Cannot run bulk update with no nodes to check"
144166
end

0 commit comments

Comments
 (0)