inspec 0.24.0 → 0.25.0
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 +4 -4
- data/CHANGELOG.md +14 -2
- data/README.md +1 -0
- data/examples/profile-attribute.yml +2 -0
- data/examples/profile-attribute/README.md +14 -0
- data/examples/profile-attribute/controls/example.rb +11 -0
- data/examples/profile-attribute/inspec.yml +8 -0
- data/lib/inspec/cli.rb +4 -1
- data/lib/inspec/objects.rb +1 -0
- data/lib/inspec/objects/attribute.rb +35 -0
- data/lib/inspec/plugins.rb +1 -0
- data/lib/inspec/plugins/secret.rb +15 -0
- data/lib/inspec/profile.rb +7 -0
- data/lib/inspec/profile_context.rb +15 -4
- data/lib/inspec/runner.rb +24 -1
- data/lib/inspec/secrets.rb +19 -0
- data/lib/inspec/secrets/yaml.rb +23 -0
- data/lib/inspec/version.rb +1 -1
- data/lib/utils/base_cli.rb +2 -0
- data/test/functional/inspec_exec_json_test.rb +1 -1
- metadata +11 -8
- data/lib/utils/hash_map.rb +0 -37
- data/test/unit/mock/profiles/resource-tiny/inspec.yml +0 -10
- data/test/unit/mock/profiles/resource-tiny/libraries/resource.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee0308ac7f5c85399e7ad0a3854ff85bbc94d765
|
4
|
+
data.tar.gz: 85d09ad742b7744f075b8aa8326192d6fc09cc35
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: db34bc62e3bb9789ed7974617814a5249ff4ebc0175e70275b87b398bc2ffc47c63ac665d6ee1ac34059c4041c7a0dc57c1a57b1913a9e2e4893d34ecaf0cad4
|
7
|
+
data.tar.gz: d7490e64740e145aa8fafeb1d821988d841c7d05542ba1fa73a57f88f171b5bf349c961140c04804344b9edaeecfa5e08609e2b50b033d4e794df6fdf8ba28b0
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,19 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
-
## [0.
|
4
|
-
[Full Changelog](https://github.com/chef/inspec/compare/v0.
|
3
|
+
## [0.25.0](https://github.com/chef/inspec/tree/0.25.0) (2016-06-14)
|
4
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v0.24.0...0.25.0)
|
5
|
+
|
6
|
+
**Closed issues:**
|
7
|
+
|
8
|
+
- Why mode matcher doesn't work on a file resource [\#781](https://github.com/chef/inspec/issues/781)
|
9
|
+
|
10
|
+
**Merged pull requests:**
|
11
|
+
|
12
|
+
- Update readme with Annie's Tutorial Day 5 [\#785](https://github.com/chef/inspec/pull/785) ([anniehedgpeth](https://github.com/anniehedgpeth))
|
13
|
+
- Feature: Implementation of RFC Attributes [\#723](https://github.com/chef/inspec/pull/723) ([chris-rock](https://github.com/chris-rock))
|
14
|
+
|
15
|
+
## [v0.24.0](https://github.com/chef/inspec/tree/v0.24.0) (2016-06-03)
|
16
|
+
[Full Changelog](https://github.com/chef/inspec/compare/v0.23...v0.24.0)
|
5
17
|
|
6
18
|
**Implemented enhancements:**
|
7
19
|
|
data/README.md
CHANGED
@@ -222,6 +222,7 @@ Blogs:
|
|
222
222
|
* [InSpec Tutorial: Day 2 - Command Resource Blog Logo](http://www.anniehedgie.com/inspec-basics-2)
|
223
223
|
* [InSpec Tutorial: Day 3 - File Resource](http://www.anniehedgie.com/inspec-basics-3)
|
224
224
|
* [InSpec Tutorial: Day 4 - Custom Matchers](http://www.anniehedgie.com/inspec-basics-4)
|
225
|
+
* [InSpec Tutorial: Day 5 - Creating a Profile](http://www.anniehedgie.com/inspec-basics-5)
|
225
226
|
* [Windows infrastructure testing using InSpec – Part I](http://datatomix.com/?p=236)
|
226
227
|
* [Windows infrastructure testing using InSpec and Profiles – Part II](http://datatomix.com/?p=238)
|
227
228
|
* [Testing Ansible with Inspec](http://scienceofficersblog.blogspot.de/2016/02/testing-ansible-with-inspec.html)
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Example InSpec Profile with Attributes
|
2
|
+
|
3
|
+
This profile uses InSpec attributes to parameterize a profile.
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
```
|
8
|
+
$ inspec exec examples/profile-attribute --attrs examples/profile-attribute.yml
|
9
|
+
....
|
10
|
+
|
11
|
+
Finished in 0.00178 seconds (files took 0.48529 seconds to load)
|
12
|
+
4 examples, 0 failures
|
13
|
+
|
14
|
+
```
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
val_user = attribute('user', default: 'alice', description: 'An identification for the user')
|
3
|
+
val_password = attribute('password', description: 'A value for the password')
|
4
|
+
|
5
|
+
describe val_user do
|
6
|
+
it { should eq 'bob' }
|
7
|
+
end
|
8
|
+
|
9
|
+
describe val_password do
|
10
|
+
it { should eq 'secret' }
|
11
|
+
end
|
data/lib/inspec/cli.rb
CHANGED
@@ -108,7 +108,10 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
|
|
108
108
|
exec_options
|
109
109
|
def exec(*targets)
|
110
110
|
diagnose
|
111
|
-
|
111
|
+
o = opts.dup
|
112
|
+
|
113
|
+
# run tests
|
114
|
+
run_tests(targets, o)
|
112
115
|
end
|
113
116
|
|
114
117
|
desc 'detect', 'detect the target OS'
|
data/lib/inspec/objects.rb
CHANGED
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding:utf-8
|
2
|
+
|
3
|
+
module Inspec
|
4
|
+
class Attribute
|
5
|
+
attr_accessor :name
|
6
|
+
def initialize(name, options)
|
7
|
+
@name = name
|
8
|
+
@opts = options
|
9
|
+
@value = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
# implicit call is done by inspec to determine the value of an attribute
|
13
|
+
def value(newvalue = nil)
|
14
|
+
unless newvalue.nil?
|
15
|
+
@value = newvalue
|
16
|
+
end
|
17
|
+
@value || default
|
18
|
+
end
|
19
|
+
|
20
|
+
def default
|
21
|
+
@opts[:default]
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_hash
|
25
|
+
{
|
26
|
+
name: @name,
|
27
|
+
options: @opts,
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_s
|
32
|
+
"Attribute #{@name} with #{@value}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/inspec/plugins.rb
CHANGED
@@ -11,6 +11,7 @@ module Inspec
|
|
11
11
|
autoload :CLI, 'inspec/plugins/cli'
|
12
12
|
autoload :Fetcher, 'inspec/plugins/fetcher'
|
13
13
|
autoload :SourceReader, 'inspec/plugins/source_reader'
|
14
|
+
autoload :Secret, 'inspec/plugins/secret'
|
14
15
|
end
|
15
16
|
|
16
17
|
# PLEASE NOTE: The Plugin system is an internal mechanism for connecting
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# author: Dominik Richter
|
3
|
+
# author: Christoph Hartmann
|
4
|
+
|
5
|
+
require 'utils/plugin_registry'
|
6
|
+
|
7
|
+
module Inspec
|
8
|
+
module Plugins
|
9
|
+
class Secret < PluginRegistry::Plugin
|
10
|
+
def self.plugin_registry
|
11
|
+
Inspec::SecretsBackend
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/inspec/profile.rb
CHANGED
@@ -57,6 +57,7 @@ module Inspec
|
|
57
57
|
|
58
58
|
def info
|
59
59
|
res = params.dup
|
60
|
+
# add information about the controls
|
60
61
|
controls = res[:controls].map do |id, rule|
|
61
62
|
next if id.to_s.empty?
|
62
63
|
data = rule.dup
|
@@ -67,6 +68,9 @@ module Inspec
|
|
67
68
|
[id, data]
|
68
69
|
end
|
69
70
|
res[:controls] = Hash[controls.compact]
|
71
|
+
|
72
|
+
# add information about the required attributes
|
73
|
+
res[:attributes] = res[:attributes].map(&:to_hash) unless res[:attributes].nil? || res[:attributes].empty?
|
70
74
|
res
|
71
75
|
end
|
72
76
|
|
@@ -248,13 +252,16 @@ module Inspec
|
|
248
252
|
f = load_rule_filepath(prefix, rule)
|
249
253
|
load_rule(rule, f, controls, groups)
|
250
254
|
end
|
255
|
+
params[:attributes] = runner.attributes
|
251
256
|
else
|
252
257
|
# load from context
|
253
258
|
@runner_context.rules.values.each do |rule|
|
254
259
|
f = load_rule_filepath(prefix, rule)
|
255
260
|
load_rule(rule, f, controls, groups)
|
256
261
|
end
|
262
|
+
params[:attributes] = @runner_context.attributes
|
257
263
|
end
|
264
|
+
params
|
258
265
|
end
|
259
266
|
|
260
267
|
def load_rule_filepath(prefix, rule)
|
@@ -6,10 +6,12 @@ require 'inspec/rule'
|
|
6
6
|
require 'inspec/dsl'
|
7
7
|
require 'inspec/require_loader'
|
8
8
|
require 'securerandom'
|
9
|
+
require 'inspec/objects/attribute'
|
9
10
|
|
10
11
|
module Inspec
|
11
12
|
class ProfileContext # rubocop:disable Metrics/ClassLength
|
12
13
|
attr_reader :rules
|
14
|
+
attr_reader :attributes
|
13
15
|
def initialize(profile_id, backend, conf)
|
14
16
|
if backend.nil?
|
15
17
|
fail 'ProfileContext is initiated with a backend == nil. ' \
|
@@ -21,7 +23,7 @@ module Inspec
|
|
21
23
|
@conf = conf.dup
|
22
24
|
@rules = {}
|
23
25
|
@require_loader = ::Inspec::RequireLoader.new
|
24
|
-
|
26
|
+
@attributes = []
|
25
27
|
reload_dsl
|
26
28
|
end
|
27
29
|
|
@@ -84,6 +86,15 @@ module Inspec
|
|
84
86
|
end
|
85
87
|
end
|
86
88
|
|
89
|
+
def register_attribute(name, options = {})
|
90
|
+
# we need to return an attribute object, to allow dermination of default values
|
91
|
+
attr = Attribute.new(name, options)
|
92
|
+
# read value from given gived values
|
93
|
+
attr.value(@conf['attributes'][attr.name]) unless @conf['attributes'].nil?
|
94
|
+
@attributes.push(attr)
|
95
|
+
attr.value
|
96
|
+
end
|
97
|
+
|
87
98
|
def set_header(field, val)
|
88
99
|
@current_load[field] = val
|
89
100
|
end
|
@@ -180,9 +191,9 @@ module Inspec
|
|
180
191
|
profile_context_owner.register_rule(control, &block) unless control.nil?
|
181
192
|
end
|
182
193
|
|
183
|
-
#
|
184
|
-
define_method :
|
185
|
-
|
194
|
+
# method for attributes; import attribute handling
|
195
|
+
define_method :attribute do |name, options|
|
196
|
+
profile_context_owner.register_attribute(name, options)
|
186
197
|
end
|
187
198
|
|
188
199
|
define_method :skip_control do |id|
|
data/lib/inspec/runner.rb
CHANGED
@@ -10,12 +10,13 @@ require 'inspec/backend'
|
|
10
10
|
require 'inspec/profile_context'
|
11
11
|
require 'inspec/profile'
|
12
12
|
require 'inspec/metadata'
|
13
|
+
require 'inspec/secrets'
|
13
14
|
# spec requirements
|
14
15
|
|
15
16
|
module Inspec
|
16
17
|
class Runner # rubocop:disable Metrics/ClassLength
|
17
18
|
extend Forwardable
|
18
|
-
attr_reader :backend, :rules
|
19
|
+
attr_reader :backend, :rules, :attributes
|
19
20
|
def initialize(conf = {})
|
20
21
|
@rules = {}
|
21
22
|
@conf = conf.dup
|
@@ -26,6 +27,10 @@ module Inspec
|
|
26
27
|
RunnerRspec.new(@conf)
|
27
28
|
end
|
28
29
|
|
30
|
+
# list of profile attributes
|
31
|
+
@attributes = []
|
32
|
+
|
33
|
+
load_attributes(@conf)
|
29
34
|
configure_transport
|
30
35
|
end
|
31
36
|
|
@@ -45,6 +50,21 @@ module Inspec
|
|
45
50
|
@backend = Inspec::Backend.create(@conf)
|
46
51
|
end
|
47
52
|
|
53
|
+
# determine all attributes before the execution, fetch data from secrets backend
|
54
|
+
def load_attributes(options)
|
55
|
+
attributes = {}
|
56
|
+
# read endpoints for secrets eg. yml file
|
57
|
+
secrets_targets = options['attrs']
|
58
|
+
unless secrets_targets.nil?
|
59
|
+
secrets_targets.each do |target|
|
60
|
+
secrets = Inspec::SecretsBackend.resolve(target)
|
61
|
+
# merge hash values
|
62
|
+
attributes = attributes.merge(secrets.attributes) unless secrets.nil? || secrets.attributes.nil?
|
63
|
+
end
|
64
|
+
end
|
65
|
+
options['attributes'] = attributes
|
66
|
+
end
|
67
|
+
|
48
68
|
def add_target(target, options = {})
|
49
69
|
profile = Inspec::Profile.for_target(target, options)
|
50
70
|
fail "Could not resolve #{target} to valid input." if profile.nil?
|
@@ -110,6 +130,9 @@ module Inspec
|
|
110
130
|
tests = [tests] unless tests.is_a? Array
|
111
131
|
tests.each { |t| add_test_to_context(t, ctx) }
|
112
132
|
|
133
|
+
# merge all collect all attributes
|
134
|
+
@attributes |= ctx.attributes
|
135
|
+
|
113
136
|
# process the resulting rules
|
114
137
|
filter_controls(ctx.rules, options[:controls]).each do |rule_id, rule|
|
115
138
|
register_rule(rule_id, rule)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# author: Christoph Hartmann
|
3
|
+
# author: Dominik Richter
|
4
|
+
|
5
|
+
require 'inspec/plugins'
|
6
|
+
require 'utils/plugin_registry'
|
7
|
+
|
8
|
+
module Inspec
|
9
|
+
SecretsBackend = PluginRegistry.new
|
10
|
+
|
11
|
+
def self.secrets(version)
|
12
|
+
if version != 1
|
13
|
+
fail 'Only secrets version 1 is supported!'
|
14
|
+
end
|
15
|
+
Inspec::Plugins::Secret
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'inspec/secrets/yaml'
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
module Secrets
|
6
|
+
class YAML < Inspec.secrets(1)
|
7
|
+
name 'yaml'
|
8
|
+
|
9
|
+
attr_reader :attributes
|
10
|
+
|
11
|
+
def self.resolve(target)
|
12
|
+
unless target.is_a?(String) && File.file?(target) && target.end_with?('.yml')
|
13
|
+
return nil
|
14
|
+
end
|
15
|
+
new(target)
|
16
|
+
end
|
17
|
+
|
18
|
+
# array of yaml file paths
|
19
|
+
def initialize(target)
|
20
|
+
@attributes = ::YAML.load_file(target)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/inspec/version.rb
CHANGED
data/lib/utils/base_cli.rb
CHANGED
@@ -55,6 +55,8 @@ module Inspec
|
|
55
55
|
desc: 'Which formatter to use: progress, documentation, json'
|
56
56
|
option :color, type: :boolean, default: true,
|
57
57
|
desc: 'Use colors in output.'
|
58
|
+
option :attrs, type: :array,
|
59
|
+
desc: 'Load attributes file (experimental)'
|
58
60
|
end
|
59
61
|
|
60
62
|
private
|
@@ -39,7 +39,6 @@ describe 'inspec exec with json formatter' do
|
|
39
39
|
actual = profile.dup
|
40
40
|
key = actual.delete('controls').keys
|
41
41
|
.find { |x| x =~ /generated from example.rb/ }
|
42
|
-
|
43
42
|
actual.must_equal({
|
44
43
|
"name" => "profile",
|
45
44
|
"title" => "InSpec Example Profile",
|
@@ -55,6 +54,7 @@ describe 'inspec exec with json formatter' do
|
|
55
54
|
"controls/example.rb" => {"title"=>"/tmp profile", "controls"=>["tmp-1.0", key]},
|
56
55
|
"controls/gordon.rb" => {"title"=>"Gordon Config Checks", "controls"=>["gordon-1.0"]},
|
57
56
|
},
|
57
|
+
"attributes" => []
|
58
58
|
})
|
59
59
|
end
|
60
60
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inspec
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.25.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dominik Richter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-06-
|
11
|
+
date: 2016-06-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: r-train
|
@@ -220,6 +220,10 @@ files:
|
|
220
220
|
- examples/kitchen-puppet/manifests/site.pp
|
221
221
|
- examples/kitchen-puppet/metadata.json
|
222
222
|
- examples/kitchen-puppet/test/integration/default/web_spec.rb
|
223
|
+
- examples/profile-attribute.yml
|
224
|
+
- examples/profile-attribute/README.md
|
225
|
+
- examples/profile-attribute/controls/example.rb
|
226
|
+
- examples/profile-attribute/inspec.yml
|
223
227
|
- examples/profile/README.md
|
224
228
|
- examples/profile/controls/example.rb
|
225
229
|
- examples/profile/controls/gordon.rb
|
@@ -267,6 +271,7 @@ files:
|
|
267
271
|
- lib/inspec/log.rb
|
268
272
|
- lib/inspec/metadata.rb
|
269
273
|
- lib/inspec/objects.rb
|
274
|
+
- lib/inspec/objects/attribute.rb
|
270
275
|
- lib/inspec/objects/control.rb
|
271
276
|
- lib/inspec/objects/each_loop.rb
|
272
277
|
- lib/inspec/objects/list.rb
|
@@ -278,6 +283,7 @@ files:
|
|
278
283
|
- lib/inspec/plugins/cli.rb
|
279
284
|
- lib/inspec/plugins/fetcher.rb
|
280
285
|
- lib/inspec/plugins/resource.rb
|
286
|
+
- lib/inspec/plugins/secret.rb
|
281
287
|
- lib/inspec/plugins/source_reader.rb
|
282
288
|
- lib/inspec/polyfill.rb
|
283
289
|
- lib/inspec/profile.rb
|
@@ -289,6 +295,8 @@ files:
|
|
289
295
|
- lib/inspec/runner.rb
|
290
296
|
- lib/inspec/runner_mock.rb
|
291
297
|
- lib/inspec/runner_rspec.rb
|
298
|
+
- lib/inspec/secrets.rb
|
299
|
+
- lib/inspec/secrets/yaml.rb
|
292
300
|
- lib/inspec/shell.rb
|
293
301
|
- lib/inspec/source_reader.rb
|
294
302
|
- lib/inspec/version.rb
|
@@ -360,7 +368,6 @@ files:
|
|
360
368
|
- lib/utils/filter_array.rb
|
361
369
|
- lib/utils/find_files.rb
|
362
370
|
- lib/utils/hash.rb
|
363
|
-
- lib/utils/hash_map.rb
|
364
371
|
- lib/utils/json_log.rb
|
365
372
|
- lib/utils/modulator.rb
|
366
373
|
- lib/utils/object_traversal.rb
|
@@ -557,8 +564,6 @@ files:
|
|
557
564
|
- test/unit/mock/profiles/library/inspec.yml
|
558
565
|
- test/unit/mock/profiles/library/libraries/gordonlib.rb
|
559
566
|
- test/unit/mock/profiles/library/libraries/testlib.rb
|
560
|
-
- test/unit/mock/profiles/resource-tiny/inspec.yml
|
561
|
-
- test/unit/mock/profiles/resource-tiny/libraries/resource.rb
|
562
567
|
- test/unit/mock/profiles/simple-metadata/inspec.yml
|
563
568
|
- test/unit/mock/profiles/skippy-profile-os/controls/one.rb
|
564
569
|
- test/unit/mock/profiles/skippy-profile-os/inspec.yml
|
@@ -647,7 +652,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
647
652
|
version: '0'
|
648
653
|
requirements: []
|
649
654
|
rubyforge_project:
|
650
|
-
rubygems_version: 2.
|
655
|
+
rubygems_version: 2.4.6
|
651
656
|
signing_key:
|
652
657
|
specification_version: 4
|
653
658
|
summary: Infrastructure and compliance testing.
|
@@ -841,8 +846,6 @@ test_files:
|
|
841
846
|
- test/unit/mock/profiles/library/inspec.yml
|
842
847
|
- test/unit/mock/profiles/library/libraries/gordonlib.rb
|
843
848
|
- test/unit/mock/profiles/library/libraries/testlib.rb
|
844
|
-
- test/unit/mock/profiles/resource-tiny/inspec.yml
|
845
|
-
- test/unit/mock/profiles/resource-tiny/libraries/resource.rb
|
846
849
|
- test/unit/mock/profiles/simple-metadata/inspec.yml
|
847
850
|
- test/unit/mock/profiles/skippy-profile-os/controls/one.rb
|
848
851
|
- test/unit/mock/profiles/skippy-profile-os/inspec.yml
|
data/lib/utils/hash_map.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# author: Dominik Richter
|
3
|
-
# author: Christoph Hartmann
|
4
|
-
|
5
|
-
class HashMap
|
6
|
-
class << self
|
7
|
-
def [](hash, *keys)
|
8
|
-
return hash if keys.empty? || hash.nil?
|
9
|
-
key = keys.shift
|
10
|
-
if hash.is_a?(Array)
|
11
|
-
map = hash.map { |i| [i, key] }
|
12
|
-
else
|
13
|
-
map = hash[key]
|
14
|
-
end
|
15
|
-
[map, *keys]
|
16
|
-
rescue NoMethodError => _
|
17
|
-
nil
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class StringMap
|
23
|
-
class << self
|
24
|
-
def [](hash, *keys)
|
25
|
-
return hash if keys.empty? || hash.nil?
|
26
|
-
key = keys.shift
|
27
|
-
if hash.is_a?(Array)
|
28
|
-
map = hash.map { |i| [i, key] }
|
29
|
-
else
|
30
|
-
map = hash[key]
|
31
|
-
end
|
32
|
-
[map, *keys]
|
33
|
-
rescue NoMethodError => _
|
34
|
-
nil
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,10 +0,0 @@
|
|
1
|
-
name: complete
|
2
|
-
title: complete example profile
|
3
|
-
maintainer: Chef Software, Inc.
|
4
|
-
copyright: Chef Software, Inc.
|
5
|
-
copyright_email: support@chef.io
|
6
|
-
license: Proprietary, All rights reserved
|
7
|
-
summary: Testing stub
|
8
|
-
version: 1.0.0
|
9
|
-
supports:
|
10
|
-
- os-family: linux
|