hiera-browser 1.2.2 → 1.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- Y2ZhZTJkYTg0OTQyODg5MWFiZGJjNzJiNTFhZTdiYTgwYjU3NjI1Yg==
4
+ MTJjYmRkM2QwZmU3N2M3OGFhNjM3YjhhZDNkNGNmMGI3NTBiODJhMw==
5
5
  data.tar.gz: !binary |-
6
- YjllOTYxNDRhYjJjZDY3YTZmYWQ3MGRhN2Y2OTRhNThlMGVkMTZkNg==
6
+ OWY4MWM2M2ViOTg3MWFlMzA2MGYxN2I1MTk2YTE3MTI3MTkyMzc0Mw==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- MGJmNjFiYWM1YjFhYzAyYzI5NzZlYWFmZGFjZDQ1ZjI0OTA0MDQ1ZmQ5M2Jm
10
- NTczNzM1NTk1YWMzMjQ0ZDFjMzgzZGE5Njk3M2NhMjUwNWRkMmZhMTIyYmZh
11
- MjUxZTYwNTVjOTg3YzU4YmQ2OGMxOWRhYjFhZTQ2YjcxMDM3OTY=
9
+ NjQ1OGY4NDU5MmQ2NmVjN2EwNzAyNTlkN2I2NWM4M2Q3ZDk1ODczMWQ3YmE1
10
+ YWM5Mzg4YTRlODdjZjMzOTJiYjM5ODZmYzc4NDJhMDUyNjkzNGNkOGFiMzgz
11
+ OWZlY2U1OTAwMDg0ZGRlNjQ1YjlhNmZiMzQ5NGZiY2Q2MTZjZTY=
12
12
  data.tar.gz: !binary |-
13
- M2VlNmU1NGZkYzlhNzY1MzExZGZkZDhiNTAzNTVlNWY4YjAzNDQ3Y2JjOTJj
14
- YzRjMjBlYmExZmMzODM5NTdmZGU0NTY4NjQyYjNmNWM3NThjYWExMDQwOWJh
15
- MGUzZDNiZGQxMjYyOGU2NGZjMWI1ZWIwOTE5YTM5YTJmMzJkYTI=
13
+ NTE1MjMxOGFmN2YwODlkN2E2YWRjOWYwOTE0N2QxY2RlMDAyMzNhMGE4NGM0
14
+ ZDEzMjk4YzY3ZmZiOWQ5NzllYjk3OWNlODY1ZGViNmZlMTA1OWIyMWNhMGZj
15
+ ODk1NmM5ODM2OGJhNzM3MDFhMTU5ZjRhYzgwMTI0OTQyMmM3MTE=
@@ -12,7 +12,7 @@ use Rack::Session::Cookie, :secret => '4zENWx0ruhWU3ZN'
12
12
  class HieraBrowserUI < Sinatra::Application
13
13
  # api
14
14
  get '/api/v1/nodes' do
15
- @nodes = Node.list
15
+ @nodes = YamlDir.new.node_list
16
16
  JSON.generate(@nodes)
17
17
  end
18
18
 
@@ -35,7 +35,7 @@ class HieraBrowserUI < Sinatra::Application
35
35
 
36
36
  get '/nodes' do
37
37
  @title = "node list"
38
- @nodes = Node.list
38
+ @nodes = YamlDir.new.node_list
39
39
  slim :nodes
40
40
  end
41
41
 
@@ -2,4 +2,5 @@ require 'hiera'
2
2
  require 'hiera_browser/hiera_controller'
3
3
  require 'hiera_browser/data'
4
4
  require 'hiera_browser/node'
5
-
5
+ require 'hiera_browser/yamldir'
6
+ require 'hiera_browser/parameters'
@@ -1,37 +1,43 @@
1
1
  require 'yaml'
2
2
 
3
3
  class DataDir
4
- attr_reader :path
4
+ attr_reader :paths
5
5
 
6
+ # @return [void]
6
7
  def initialize(args={})
7
- @hiera = args[:hiera]
8
- @paths = render_paths(:path => args[:path])
8
+ @node_dir = args[:node_dir] || YamlDir.new
9
+ @paths = render_paths(:path => args[:path])
9
10
  end
10
11
 
12
+ # @return [Array]
11
13
  def render_paths(args)
12
14
  begin
13
- variables = args[:path].match(/\%\{([a-z_\:]+)\}/).captures
14
- variables.map{|v|
15
- Node.parameters[v].map{|param|
16
- args[:path].gsub(/\%\{#{v}\}/, param)}.flatten
15
+ interpolated_variables = args[:path].match(/\%\{([a-z_\:]+)\}/).captures
16
+ collected_parameters = @node_dir.collected_parameters
17
+ # collected_parameters is a ParameterCollection
18
+ # interpolated_variables might look like ['::environment']
19
+ interpolated_variables.map{|v|
20
+ collected_parameters[v].map{|param|
21
+ args[:path].gsub(/%{#{v}}/, param)}
17
22
  }.flatten
18
23
  rescue NoMethodError
19
24
  [args[:path]]
20
25
  end
21
26
  end
22
27
 
28
+ # @return [Array]
23
29
  def yaml_files
24
- @paths.map{|p|
25
- Dir.chdir(p) { Dir.glob('**/*.yaml') }
26
- }.flatten
30
+ @paths.map{|p| Dir.chdir(p) { Dir.glob('**/*.yaml') } }.flatten
27
31
  end
28
32
 
33
+ # @return [Array]
29
34
  def datafiles
30
35
  @paths.map{|path|
31
- yaml_files.map{|f| DataFile.new(:path => File.join(path,f))}.flatten
36
+ yaml_files.map{|f| DataFile.new(:path => File.join(path,f))}
32
37
  }.flatten
33
38
  end
34
39
 
40
+ # @return [Array]
35
41
  def keys
36
42
  datafiles.map{|datafile| datafile.keys}.flatten.uniq.sort
37
43
  end
@@ -40,11 +46,13 @@ end
40
46
  class DataFile
41
47
  attr_reader :path
42
48
 
49
+ # @return [void]
43
50
  def initialize(args={})
44
51
  @path = args[:path]
45
52
  @keys = keys
46
53
  end
47
54
 
55
+ # @return [Array]
48
56
  def keys
49
57
  YAML.load_file(@path).keys
50
58
  end
@@ -1,22 +1,30 @@
1
1
  require 'yaml'
2
2
 
3
+ # HieraController gives us a reasonably limited interface for Hiera
4
+ #
5
+ # @author David Gwilliam
3
6
  class HieraController
4
- @@hiera_yaml = ENV['HIERA_YAML'] || './hiera.yaml'
5
7
  attr_reader :hiera_yaml
6
8
 
9
+ # @param args [{:hiera_yaml => String}] path to `hiera.yaml`
10
+ # @return [void]
7
11
  def initialize(args={})
8
- @hiera_yaml = args[:hiera_yaml] || @@hiera_yaml
9
- @hiera = hiera(:config => @hiera_yaml)
12
+ @hiera_yaml = args[:hiera_yaml] || ENV['HIERA_YAML']
13
+ @hiera = hiera(:config => @hiera_yaml)
10
14
  end
11
15
 
16
+ # @param args [Hash] arguments to pass to Hiera.new()
17
+ # @return [Hiera]
12
18
  def hiera(args={})
13
19
  @hiera || Hiera.new(args)
14
20
  end
15
21
 
22
+ # @return [Hash]
16
23
  def config
17
24
  hiera.config
18
25
  end
19
26
 
27
+ # @return [Array]
20
28
  def datadirs
21
29
  config[:backends].map{|b|
22
30
  path = config[b.to_sym][:datadir]
@@ -27,40 +35,59 @@ class HieraController
27
35
  }
28
36
  end
29
37
 
38
+ # @return [Array]
30
39
  def keys
31
40
  datadirs.map{|d| d.keys}.flatten.uniq.sort
32
41
  end
33
42
 
43
+ # @return [Array]
34
44
  def hierarchy
35
45
  config[:hierarchy]
36
46
  end
37
47
 
38
- def top_scopify(args)
39
- scope = args[:scope]
40
- fix_keys = hierarchy.map{|datasource|
48
+ def hierarchy_variables
49
+ hierarchy.map{|datasource|
41
50
  begin
42
51
  datasource.match(/\%\{([\:a-z_]+)\}/)[1]
43
52
  rescue NoMethodError
44
53
  datasource
45
54
  end
46
55
  }
47
- fix_keys.select!{|datasource| datasource.start_with?("::")} unless fix_keys.empty?
56
+ end
57
+
58
+ # Return the scope but with the addition of fully qualified
59
+ # variable keys for any level of the hierarchy that's formatted that way, e.g.:
60
+ # { 'datacenter' => 'pdx', '::datacenter' => 'pdx' }
61
+ #
62
+ # @note needs to be moved to Node
63
+ # @param args [{:scope => Hash}]
64
+ # @return [Hash]
65
+ def top_scopify(args)
66
+ scope = args[:scope]
67
+ fix_keys = hierarchy_variables.select{|datasource| datasource.start_with?(Parameter.top_scope)}
48
68
  scope.inject({}){|a,fact|
49
- if fix_keys.include?("::#{fact.first}")
50
- a["::#{fact.first}"] = fact.last
51
- end
69
+ a[Parameter.top_scope(fact.first)] = fact.last if fix_keys.include?(Parameter.top_scope(fact.first))
52
70
  a[fact.first] = fact.last
53
- a
54
- }
71
+ a }
55
72
  end
56
73
 
57
- def lookup(args)
74
+ # Basically shadows the Hiera#lookup method
75
+ #
76
+ # @note needs to be moved to Node#lookup
77
+ # @param args [{:key => String, :scope => Hash, :resolution_type => Symbol}]
78
+ # @return [Hash]
79
+ def lookup(args = {})
80
+ raise ArgumentError, 'HieraController#lookup requires both :key and :scope args' unless args[:key] and args[:scope]
58
81
  key = args[:key]
59
82
  scope = top_scopify(:scope => args[:scope])
60
83
  resolution_type = args[:resolution_type] || :priority
61
84
  Hash[*[key,hiera.lookup(key, nil, scope, nil, resolution_type)]]
62
85
  end
63
86
 
87
+ # Retrieve all node values for all known hiera keys
88
+ #
89
+ # @param args [{:scope => Hash}]
90
+ # @return [Hash]
64
91
  def get_all(args)
65
92
  scope = top_scopify(:scope => args[:scope])
66
93
  values = keys.inject({}){|a, k|
@@ -73,6 +100,11 @@ class HieraController
73
100
  values
74
101
  end
75
102
 
103
+ # Check return value of priority lookup in order to determine which "additive"
104
+ # resolution type to use, then repeat the lookup with the correct resolution type
105
+ #
106
+ # @param args [{:key => String, :scope => Hash}]
107
+ # @return [Hash]
76
108
  def lookup_additive(args)
77
109
  key = args[:key]
78
110
  scope = top_scopify(:scope => args[:scope])
@@ -1,71 +1,69 @@
1
1
  require 'yaml'
2
2
  require 'puppet'
3
3
 
4
+ # A Node represents all that is known about a node in your infrastructure
4
5
  class Node
5
- attr_reader :certname, :facts, :node_dir
6
+ # @return [String] e.g., 'testnode.puppetlabs.com'
7
+ attr_reader :certname
8
+ # @return [Hash] e.g., { 'datacenter' => 'pdx', 'environment' => 'dev' }
9
+ attr_reader :facts
10
+ # @return [YamlDir]
11
+ attr_reader :node_dir
6
12
 
7
- @@node_dir =
8
- if ENV['YAML_DIR']
9
- ENV['YAML_DIR']
10
- elsif File.exist?('/var/opt/lib/pe-puppet/yaml')
11
- '/var/opt/lib/pe-puppet/yaml/node'
12
- else
13
- '/var/lib/puppet/yaml/node'
14
- end
15
13
 
14
+ # @param args [Hash{:certname => String, :node_dir => String}]
16
15
  def initialize(args)
17
16
  @certname = args[:certname]
17
+ @node_dir = YamlDir.new(:node_dir => args[:node_dir])
18
18
  @facts = facts_yaml
19
19
  @hiera = args[:hiera] || HieraController.new
20
20
  end
21
21
 
22
+ # @return [ParameterCollection]
23
+ def parameters
24
+ collection = ParameterCollection.new
25
+ facts_yaml.each {|k,v|
26
+ collection << Parameter.new(:key => k, :value => v)}
27
+ collection
28
+ end
29
+
30
+ # @return [Hash]
31
+ def load_yaml
32
+ path = File.join(@node_dir.path,"#{@certname}.yaml")
33
+ YAML.load_file(path)
34
+ end
35
+
36
+ # @return [Hash] parameters and facts merged from node cache
22
37
  def facts_yaml
23
- path = File.join(@@node_dir,"#{@certname}.yaml")
24
- node = YAML.load_file(path)
25
- node.parameters.merge(node.facts.values)
38
+ yaml = load_yaml
39
+ yaml.parameters.merge(yaml.facts.values)
26
40
  end
27
41
 
28
- def hiera_values(args={})
42
+ # @param args [Hash{:additive_keys => Array}]
43
+ # @return [Hash] all values for all keys, including additive lookups
44
+ # for any keys included in :additive_keys
45
+ def hiera_values(args = {})
29
46
  additive_keys = args[:additive_keys] || []
30
47
  @hiera.get_all(:scope => @facts, :additive_keys => additive_keys).
31
48
  values.inject({}){|a,v| a.merge!(v)}
32
49
  end
33
50
 
34
- def sorted_values(args)
51
+ # @param args [{:keys => Array}]
52
+ # @return [Array] flattened collection of all {#hiera_values} sorted alphabetically by key
53
+ # e.g. [['datacenter', 'pdx'], ['environment', 'dev']]
54
+ def sorted_values(args = {})
35
55
  keys = args[:keys]
36
56
  hiera_values(:additive_keys => keys).sort_by{|k,v|k}
37
57
  end
38
58
 
59
+ # @return [String]
39
60
  def environment
40
61
  @facts['environment']
41
62
  end
42
63
 
43
- def self.files
44
- begin
45
- Dir.chdir(@@node_dir) { Dir.glob('**/*.yaml') }
46
- rescue Errno::ENOENT => e
47
- raise "Can't find your $yamldir: #{e}"
48
- end
49
- end
50
-
51
- def self.list
52
- files = self.files
53
- files.map{|f| f.split('.yaml')}.flatten
54
- end
55
-
56
- def self.parameters
57
- files = self.files
58
- files.map{|f| YAML.load_file(File.join(@@node_dir,f)).parameters}.
59
- inject({}){|a,params|
60
- params.each {|key, value|
61
- a[key] = [] unless a[key]
62
- a[key] << value unless a[key].include? value
63
- }
64
- a
65
- }
66
- end
67
-
68
- def self.environments
69
- self.parameters["environment"]
64
+ # @param args [Hash{:key => String}]
65
+ # @return [Hash]
66
+ def lookup(args)
67
+ @hiera.lookup_additive(:key => args[:key], :scope => @facts)
70
68
  end
71
69
  end
@@ -0,0 +1,114 @@
1
+ # A collection of {Parameter}s, based on Arrays
2
+ class ParameterCollection
3
+ # @return [void]
4
+ def initialize
5
+ @collection = collection
6
+ end
7
+
8
+ # @return [Array]
9
+ def collection
10
+ @collection || []
11
+ end
12
+
13
+ def [](index)
14
+ stripped_index = index.sub(/^::/,'')
15
+ collection.select{|param| param.key == stripped_index }.map{|param|param.value}
16
+ end
17
+
18
+ # @param parameter [Parameter]
19
+ # @return [ParameterCollection]
20
+ def << (parameter)
21
+ collection << parameter
22
+ dedupe!
23
+ self
24
+ end
25
+
26
+ # @return [Array] all keys in this ParameterCollection
27
+ def keys
28
+ collection.map{|param| param.key}.uniq
29
+ end
30
+
31
+ # @param param [Parameter]
32
+ # @return [TrueClass, FalseClass] True if this ParameterCollection includes a Parameter
33
+ def include?(param)
34
+ truth = false
35
+ collection.each{|p| truth = true if p == param}
36
+ truth
37
+ end
38
+
39
+ # @return [Fixnum] the number of Parameters in the ParameterCollection
40
+ def count
41
+ collection.count
42
+ end
43
+
44
+ # @return [Hash] the parameter collection condensed to a Hash, multiple values
45
+ # for the same key condensed into an Array, all keys duplicated
46
+ def to_h
47
+ self.keys.inject({}){|a, k|
48
+ a[k] = self[k]
49
+ a[Parameter.top_scope(k)] = self[k]
50
+ a }
51
+ end
52
+
53
+ private
54
+
55
+ def dedupe!
56
+ @collection = collection.inject([]){|a, param|
57
+ if a.include?(param)
58
+ a
59
+ else
60
+ a << param
61
+ end }
62
+ end
63
+ end
64
+
65
+ # Structured object for holding key/value parameters, whether they are facts or not
66
+ class Parameter
67
+ # @param args [Hash{:key => String, :value => Object}]
68
+ # @return [void]
69
+ def initialize(args = {})
70
+ raise ArgumentError, "A Parameter must have both :key and :value" unless
71
+ args[:key] && args[:value]
72
+ @key = descope(args[:key])
73
+ @value = args[:value]
74
+ end
75
+
76
+ # @return [String] fully qualified {#key}
77
+ # e.g. `::datacenter`
78
+ def top_scope_key
79
+ Parameter.top_scope(@key)
80
+ end
81
+
82
+ # @param param [Parameter]
83
+ # @return [TrueClass, FalseClass]
84
+ def == (param)
85
+ if param.class == Parameter && @key == param.key && @value == param.value
86
+ true
87
+ else
88
+ false
89
+ end
90
+ end
91
+
92
+ # @return [String]
93
+ attr_reader :key
94
+
95
+ # @return [Object]
96
+ attr_reader :value
97
+
98
+ class << self
99
+ # @param key [String]
100
+ # @return [String] the provided key, fully qualified, e.g. "::key"
101
+ def top_scope(key = '')
102
+ "::#{key}"
103
+ end
104
+ end
105
+
106
+ private
107
+
108
+ # @param key [String] a top-scope variable name / parameter key, e.g. ::key
109
+ # @return [String] the provided key with any top-scoping removed, e.g. key
110
+ def descope(key)
111
+ key.sub(/^::/,'')
112
+ end
113
+ end
114
+
@@ -0,0 +1,58 @@
1
+ require 'puppet'
2
+
3
+ # YamlDir allows you to retrieve information from Puppet's node cache
4
+ class YamlDir
5
+ @@node_dir =
6
+ if ENV['YAML_DIR']
7
+ ENV['YAML_DIR']
8
+ elsif File.directory?('/var/opt/lib/pe-puppet/yaml')
9
+ '/var/opt/lib/pe-puppet/yaml/node'
10
+ else
11
+ '/var/lib/puppet/yaml/node'
12
+ end
13
+
14
+ def initialize(args = {})
15
+ @node_dir = args[:node_dir] || @@node_dir
16
+ raise Exception.new "Can't find your $yamldir: #{@node_dir}" unless File.directory?(@node_dir)
17
+ end
18
+
19
+ def path
20
+ @node_dir
21
+ end
22
+
23
+ def file_list
24
+ Dir.chdir(@node_dir) { Dir.glob('**/*.yaml') }
25
+ end
26
+
27
+ def node_list
28
+ file_list.map{|f| f.split('.yaml')}.flatten
29
+ end
30
+
31
+ def load_files
32
+ file_list.map{|f| YAML.load_file(File.join(@node_dir,f))}
33
+ end
34
+
35
+ # @note #parameters is provided for temporary backwards compatibility
36
+ # @see #collected_parameters
37
+ def parameters
38
+ collected_parameters_hash
39
+ end
40
+
41
+ # @note #collected_parameters is preferred over #parameters
42
+ def collected_parameters
43
+ collection = ParameterCollection.new
44
+ load_files.map{|f| f.parameters}.
45
+ each{|params| params.each {|key, value|
46
+ collection << Parameter.new(:key => key, :value => value) } }
47
+ collection
48
+ end
49
+
50
+ def collected_parameters_hash
51
+ collected_parameters.to_h
52
+ end
53
+
54
+ def environments
55
+ collected_parameters["environment"]
56
+ end
57
+ end
58
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hiera-browser
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.2
4
+ version: 1.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Gwilliam
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-05 00:00:00.000000000 Z
11
+ date: 2014-06-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hiera
@@ -192,6 +192,76 @@ dependencies:
192
192
  - - ! '>='
193
193
  - !ruby/object:Gem::Version
194
194
  version: '0'
195
+ - !ruby/object:Gem::Dependency
196
+ name: yard
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ! '>='
200
+ - !ruby/object:Gem::Version
201
+ version: '0'
202
+ type: :development
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ! '>='
207
+ - !ruby/object:Gem::Version
208
+ version: '0'
209
+ - !ruby/object:Gem::Dependency
210
+ name: redcarpet
211
+ requirement: !ruby/object:Gem::Requirement
212
+ requirements:
213
+ - - ! '>='
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ type: :development
217
+ prerelease: false
218
+ version_requirements: !ruby/object:Gem::Requirement
219
+ requirements:
220
+ - - ! '>='
221
+ - !ruby/object:Gem::Version
222
+ version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: guard
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ! '>='
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ! '>='
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
237
+ - !ruby/object:Gem::Dependency
238
+ name: guard-rspec
239
+ requirement: !ruby/object:Gem::Requirement
240
+ requirements:
241
+ - - ! '>='
242
+ - !ruby/object:Gem::Version
243
+ version: '0'
244
+ type: :development
245
+ prerelease: false
246
+ version_requirements: !ruby/object:Gem::Requirement
247
+ requirements:
248
+ - - ! '>='
249
+ - !ruby/object:Gem::Version
250
+ version: '0'
251
+ - !ruby/object:Gem::Dependency
252
+ name: simplecov
253
+ requirement: !ruby/object:Gem::Requirement
254
+ requirements:
255
+ - - ~>
256
+ - !ruby/object:Gem::Version
257
+ version: 0.7.1
258
+ type: :development
259
+ prerelease: false
260
+ version_requirements: !ruby/object:Gem::Requirement
261
+ requirements:
262
+ - - ~>
263
+ - !ruby/object:Gem::Version
264
+ version: 0.7.1
195
265
  description: Tries to guess what values hiera will return for any existing node in
196
266
  your infrastructure
197
267
  email: dhgwilliam@gmail.com
@@ -210,6 +280,8 @@ files:
210
280
  - lib/hiera_browser/data.rb
211
281
  - lib/hiera_browser/hiera_controller.rb
212
282
  - lib/hiera_browser/node.rb
283
+ - lib/hiera_browser/parameters.rb
284
+ - lib/hiera_browser/yamldir.rb
213
285
  homepage:
214
286
  licenses:
215
287
  - APACHE 2.0