moose-inventory 0.1.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.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +0 -0
  3. data/.gitignore +17 -0
  4. data/.rubocop.yml +793 -0
  5. data/Gemfile +3 -0
  6. data/Guardfile +38 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +31 -0
  9. data/README.md.orig +35 -0
  10. data/Rakefile +1 -0
  11. data/bin/moose_inventory +10 -0
  12. data/config/dotfiles/coveralls.yml +0 -0
  13. data/config/dotfiles/gitignore +17 -0
  14. data/config/dotfiles/rubocop.yml +793 -0
  15. data/lib/moose/inventory/cli/application.rb +30 -0
  16. data/lib/moose/inventory/cli/formatter.rb +92 -0
  17. data/lib/moose/inventory/cli/group.rb +23 -0
  18. data/lib/moose/inventory/cli/group_add.rb +98 -0
  19. data/lib/moose/inventory/cli/group_addchild.rb +21 -0
  20. data/lib/moose/inventory/cli/group_addhost.rb +97 -0
  21. data/lib/moose/inventory/cli/group_addvar.rb +72 -0
  22. data/lib/moose/inventory/cli/group_get.rb +52 -0
  23. data/lib/moose/inventory/cli/group_list.rb +41 -0
  24. data/lib/moose/inventory/cli/group_rm.rb +77 -0
  25. data/lib/moose/inventory/cli/group_rmchild.rb +20 -0
  26. data/lib/moose/inventory/cli/group_rmhost.rb +89 -0
  27. data/lib/moose/inventory/cli/group_rmvar.rb +65 -0
  28. data/lib/moose/inventory/cli/host.rb +24 -0
  29. data/lib/moose/inventory/cli/host_add.rb +93 -0
  30. data/lib/moose/inventory/cli/host_addgroup.rb +88 -0
  31. data/lib/moose/inventory/cli/host_addvar.rb +76 -0
  32. data/lib/moose/inventory/cli/host_get.rb +59 -0
  33. data/lib/moose/inventory/cli/host_list.rb +40 -0
  34. data/lib/moose/inventory/cli/host_rm.rb +62 -0
  35. data/lib/moose/inventory/cli/host_rmgroup.rb +80 -0
  36. data/lib/moose/inventory/cli/host_rmvar.rb +69 -0
  37. data/lib/moose/inventory/config/config.rb +169 -0
  38. data/lib/moose/inventory/db/db.rb +249 -0
  39. data/lib/moose/inventory/db/exceptions.rb +14 -0
  40. data/lib/moose/inventory/db/models.rb +32 -0
  41. data/lib/moose/inventory/moose_inventory_cli.rb +25 -0
  42. data/lib/moose/inventory/version.rb +7 -0
  43. data/moose-inventory.gemspec +45 -0
  44. data/scripts/guard_quality.sh +3 -0
  45. data/scripts/guard_test.sh +2 -0
  46. data/scripts/reports.sh +4 -0
  47. data/spec/config/config.yml +12 -0
  48. data/spec/lib/moose/inventory/cli/application_spec.rb +15 -0
  49. data/spec/lib/moose/inventory/cli/cli_spec.rb +26 -0
  50. data/spec/lib/moose/inventory/cli/formatter_spec.rb +63 -0
  51. data/spec/lib/moose/inventory/cli/group_add_spec.rb +398 -0
  52. data/spec/lib/moose/inventory/cli/group_addhost_spec.rb +251 -0
  53. data/spec/lib/moose/inventory/cli/group_addvar_spec.rb +235 -0
  54. data/spec/lib/moose/inventory/cli/group_get_spec.rb +107 -0
  55. data/spec/lib/moose/inventory/cli/group_list_spec.rb +79 -0
  56. data/spec/lib/moose/inventory/cli/group_rm_spec.rb +191 -0
  57. data/spec/lib/moose/inventory/cli/group_rmhost_spec.rb +215 -0
  58. data/spec/lib/moose/inventory/cli/group_rmvar_spec.rb +202 -0
  59. data/spec/lib/moose/inventory/cli/group_spec.rb +15 -0
  60. data/spec/lib/moose/inventory/cli/host_add_spec.rb +330 -0
  61. data/spec/lib/moose/inventory/cli/host_addgroup_spec.rb +248 -0
  62. data/spec/lib/moose/inventory/cli/host_addvar_spec.rb +233 -0
  63. data/spec/lib/moose/inventory/cli/host_get_spec.rb +106 -0
  64. data/spec/lib/moose/inventory/cli/host_list_spec.rb +83 -0
  65. data/spec/lib/moose/inventory/cli/host_rm_spec.rb +132 -0
  66. data/spec/lib/moose/inventory/cli/host_rmgroup_spec.rb +245 -0
  67. data/spec/lib/moose/inventory/cli/host_rmvar_spec.rb +206 -0
  68. data/spec/lib/moose/inventory/cli/host_spec.rb +12 -0
  69. data/spec/lib/moose/inventory/config/config_spec.rb +80 -0
  70. data/spec/lib/moose/inventory/db/db_spec.rb +184 -0
  71. data/spec/lib/moose/inventory/db/models_spec.rb +150 -0
  72. data/spec/shared/shared_config_setup.rb +21 -0
  73. data/spec/spec_helper.rb +110 -0
  74. metadata +386 -0
@@ -0,0 +1,76 @@
1
+ require 'thor'
2
+ require 'json'
3
+
4
+ require_relative './formatter.rb'
5
+ require_relative '../db/exceptions.rb'
6
+
7
+ module Moose
8
+ module Inventory
9
+ module Cli
10
+ ##
11
+ # implementation of the "host addvar" method of the CLI
12
+ class Host
13
+ #==========================
14
+ desc 'addvar', 'Add a variable to the host'
15
+ # rubocop:disable Metrics/LineLength
16
+ def addvar(*args) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
17
+ # rubocop:enable Metrics/LineLength
18
+ if args.length < 2
19
+ abort('ERROR: Wrong number of arguments, '\
20
+ "#{args.length} for 2 or more.")
21
+ end
22
+
23
+ # Convenience
24
+ db = Moose::Inventory::DB
25
+ fmt = Moose::Inventory::Cli::Formatter
26
+
27
+ # Arguments
28
+ name = args[0].downcase
29
+ vars = args.slice(1, args.length - 1).uniq
30
+
31
+ # Transaction
32
+ db.transaction do # Transaction start
33
+ puts "Add variables '#{vars.join(",")}' to host '#{name}':"
34
+ fmt.puts 2,"- retrieve host '#{name}'..."
35
+ host = db.models[:host].find(name: name)
36
+ if host.nil?
37
+ fail db.exceptions[:moose],
38
+ "The host '#{name}' does not exist."
39
+ end
40
+ fmt.puts 4, '- OK'
41
+
42
+ hostvars_ds = host.hostvars_dataset
43
+ vars.each do |v|
44
+ fmt.puts 2, "- add variable '#{v}'..."
45
+ vararray = v.split('=')
46
+ if v.start_with?('=') || v.end_with?('=') || vararray.length != 2
47
+ fail db.exceptions[:moose],
48
+ "Incorrect format in '{#{v}}'. Expected 'key=value'."
49
+ end
50
+
51
+ # Check against existing associations
52
+ hostvar = hostvars_ds[name: vararray[0]]
53
+ if !hostvar.nil?
54
+ unless hostvar[:value] == vararray[1]
55
+ fmt.puts 4, '- already exists, applying as an update...'
56
+ update = db.models[:hostvar].find(id: hostvar[:id])
57
+ update[:value] = vararray[1]
58
+ update.save
59
+ end
60
+ else
61
+ # hostvar doesn't exist, so create and associate
62
+ hostvar = db.models[:hostvar].create(name: vararray[0],
63
+ value: vararray[1])
64
+ host.add_hostvar(hostvar)
65
+ end
66
+ fmt.puts 4, '- OK'
67
+ end
68
+ fmt.puts 2, '- all OK'
69
+ end # Transaction end
70
+
71
+ puts 'Succeeded.'
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,59 @@
1
+ require 'thor'
2
+ require 'json'
3
+
4
+ require_relative './formatter.rb'
5
+ require_relative '../db/exceptions.rb'
6
+
7
+ module Moose
8
+ module Inventory
9
+ module Cli
10
+ ##
11
+ # Class implementing the "host get" method of the CLI
12
+ class Host
13
+ require_relative 'host_add'
14
+
15
+ #==========================
16
+ desc 'get HOST_1 [HOST_2 ...]',
17
+ 'Get hosts HOST_n from the inventory'
18
+ def get(*argv) # rubocop:disable Metrics/AbcSize
19
+ if argv.length < 1
20
+ abort('ERROR: Wrong number of arguments, '\
21
+ "#{argv.length} for 1 or more")
22
+ end
23
+
24
+ # Convenience
25
+ db = Moose::Inventory::DB
26
+ fmt = Moose::Inventory::Cli::Formatter
27
+
28
+ # Arguments
29
+ names = argv.uniq.map(&:downcase)
30
+
31
+ # Process
32
+ results = {}
33
+ names.each do |name| # rubocop:disable Style/Next
34
+ host = db.models[:host].find(name: name)
35
+
36
+ unless host.nil?
37
+ groups = host.groups_dataset.map(:name)
38
+
39
+ hostvars = {}
40
+ host.hostvars_dataset.each do |hv|
41
+ hostvars[hv[:name].to_sym] = hv[:value]
42
+ end
43
+
44
+ results[host[:name].to_sym] = {}
45
+ unless groups.length == 0
46
+ results[host[:name].to_sym][:groups] = groups
47
+ end
48
+ unless hostvars.length == 0
49
+ results[host[:name].to_sym][:hostvars] = hostvars
50
+ end
51
+ end
52
+ end
53
+
54
+ fmt.dump(results)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,40 @@
1
+ require 'thor'
2
+ require 'json'
3
+
4
+ require_relative './formatter.rb'
5
+ require_relative '../db/exceptions.rb'
6
+
7
+ module Moose
8
+ module Inventory
9
+ module Cli
10
+ ##
11
+ # Implementation of the "host list" method of the CLI
12
+ class Host
13
+ desc 'list', 'List the contents of the inventory by host'
14
+ def list # rubocop:disable Metrics/AbcSize
15
+ # Convenience
16
+ db = Moose::Inventory::DB
17
+ fmt = Moose::Inventory::Cli::Formatter
18
+
19
+ # Process
20
+ results = {}
21
+ db.models[:host].all.each do |host|
22
+ groups = host.groups_dataset.map(:name)
23
+ results[host[:name].to_sym] = {}
24
+ results[host[:name].to_sym][:groups] = groups
25
+
26
+ hostvars = {}
27
+ host.hostvars_dataset.each do |hv|
28
+ hostvars[hv[:name].to_sym] = hv[:value]
29
+ end
30
+
31
+ unless hostvars.length == 0
32
+ results[host[:name].to_sym][:hostvars] = hostvars
33
+ end
34
+ end
35
+ fmt.dump(results)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,62 @@
1
+ require 'thor'
2
+ require 'json'
3
+
4
+ require_relative './formatter.rb'
5
+ require_relative '../db/exceptions.rb'
6
+
7
+ module Moose
8
+ module Inventory
9
+ module Cli
10
+ ##
11
+ # implementation of the "host rm" method of the CLI
12
+ class Host
13
+ #==========================
14
+ desc 'rm HOSTNAME_1 [HOSTNAME_2 ...]',
15
+ 'Remove hosts HOSTNAME_n from the inventory'
16
+ def rm(*argv) # rubocop:disable Metrics/AbcSize
17
+ #
18
+ # Sanity
19
+ if argv.length < 1
20
+ abort('ERROR: Wrong number of arguments, '\
21
+ "#{argv.length} for 1 or more.")
22
+ end
23
+
24
+ # Convenience
25
+ db = Moose::Inventory::DB
26
+ fmt = Moose::Inventory::Cli::Formatter
27
+
28
+ # Arguments
29
+ names = argv.uniq.map(&:downcase)
30
+
31
+ # Transaction
32
+ warn_count = 0
33
+ db.transaction do # Transaction start
34
+ names.each do |name|
35
+ puts "Remove host '#{name}':"
36
+ fmt.puts 2, "- Retrieve host '#{name}'..."
37
+ host = db.models[:host].find(name: name)
38
+ if host.nil?
39
+ warn_count += 1
40
+ fmt.warn "Host '#{name}' does not exist, skipping.\n"
41
+ fmt.puts 4, "- No such host, skipping."
42
+ end
43
+ fmt.puts 4, "- OK"
44
+ unless host.nil?
45
+ fmt.puts 2, "- Destroy host '#{name}'..."
46
+ host.remove_all_groups
47
+ host.destroy
48
+ fmt.puts 4, "- OK"
49
+ end
50
+ fmt.puts 2, "- All OK"
51
+ end
52
+ end # Transaction end
53
+ if warn_count == 0
54
+ puts "Succeeded."
55
+ else
56
+ puts "Succeeded, with warnings."
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,80 @@
1
+ require 'thor'
2
+ require 'json'
3
+
4
+ require_relative './formatter.rb'
5
+ require_relative '../db/exceptions.rb'
6
+
7
+ module Moose
8
+ module Inventory
9
+ module Cli
10
+ ##
11
+ # implementation the "host rmgroup" methods of the CLI
12
+ class Host
13
+ #==========================
14
+ desc 'rmgroup HOSTNAME GROUPNAME [GROUPNAME ...]',
15
+ 'dissociation the host from a group'
16
+ # rubocop:disable Metrics/LineLength
17
+ def rmgroup(*args) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
18
+ # rubocop:enable Metrics/LineLength
19
+ if args.length < 2
20
+ abort('ERROR: Wrong number of arguments, '\
21
+ "#{args.length} for 2 or more.")
22
+ end
23
+
24
+ # Convenience
25
+ db = Moose::Inventory::DB
26
+ fmt = Moose::Inventory::Cli::Formatter
27
+
28
+ # arguments
29
+ name = args[0].downcase
30
+ groups = args.slice(1, args.length - 1).uniq.map(&:downcase)
31
+
32
+ # Sanity
33
+ if groups.include?('ungrouped')
34
+ abort 'ERROR: Cannot manually manipulate the automatic '\
35
+ 'group \'ungrouped\'.'
36
+ end
37
+
38
+ # Transaction
39
+ db.transaction do # Transaction start
40
+ puts "Dissociate host '#{name}' from groups '#{groups.join(',')}':"
41
+ fmt.puts 2, "- Retrieve host '#{name}'..."
42
+ host = db.models[:host].find(name: name)
43
+ if host.nil?
44
+ fail db.exceptions[:moose],
45
+ "The host '#{name}' was not found in the database."
46
+ end
47
+ fmt.puts 4, '- OK'
48
+
49
+ # dissociate host from the groups
50
+ groups_ds = host.groups_dataset
51
+ groups.each do |g|
52
+ fmt.puts 2, "- Remove association {host:#{name} <-> group:#{g}}..."
53
+
54
+ # Check against existing associations
55
+ if groups_ds[name: g].nil?
56
+ fmt.warn "Association {host:#{name} <-> group:#{g}} doesn't exist, skipping.\n"
57
+ fmt.puts 4, "- Doesn't exist, skipping."
58
+ else
59
+ group = db.models[:group].find(name: g)
60
+ host.remove_group(group) unless group.nil?
61
+ end
62
+ fmt.puts 4, '- OK'
63
+ end
64
+
65
+ # Handle 'ungrouped' group automation
66
+ if host.groups_dataset.count == 0
67
+ fmt.puts 2, '- Add automatic association '\
68
+ "{host:#{name} <-> group:ungrouped}..."
69
+ ungrouped = db.models[:group].find_or_create(name: 'ungrouped')
70
+ host.add_group(ungrouped) unless ungrouped.nil?
71
+ fmt.puts 4, '- OK'
72
+ end
73
+ fmt.puts 2, '- All OK'
74
+ end # End transaction
75
+ puts 'Succeeded'
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,69 @@
1
+ require 'thor'
2
+ require 'json'
3
+
4
+ require_relative './formatter.rb'
5
+ require_relative '../db/exceptions.rb'
6
+
7
+ module Moose
8
+ module Inventory
9
+ module Cli
10
+ ##
11
+ # implementation of the "host rmvar" method of the CLI
12
+ class Host
13
+ #==========================
14
+ desc 'rmvar', 'Remove a variable from the host'
15
+ # rubocop:disable Metrics/LineLength
16
+ def rmvar(*args) # rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize
17
+ # rubocop:enableMetrics/LineLength
18
+ if args.length < 2
19
+ abort('ERROR: Wrong number of arguments, ' \
20
+ "#{args.length} for 2 or more.")
21
+ end
22
+
23
+ # Convenience
24
+ db = Moose::Inventory::DB
25
+ fmt = Moose::Inventory::Cli::Formatter
26
+
27
+ # Arguments
28
+ name = args[0].downcase
29
+ vars = args.slice(1, args.length - 1).uniq
30
+
31
+ # Transaction
32
+ db.transaction do # Transaction start
33
+ puts "Remove variable(s) '#{vars.join(",")}' from host '#{name}':"
34
+
35
+ fmt.puts 2, "- retrieve host '#{name}'..."
36
+ host = db.models[:host].find(name: name)
37
+ if host.nil?
38
+ fail db.exceptions[:moose],
39
+ "The host '#{name}' does not exist."
40
+ end
41
+ fmt.puts 4, '- OK'
42
+
43
+ hostvars_ds = host.hostvars_dataset
44
+ vars.each do |v|
45
+ fmt.puts 2, "- remove variable '#{v}'..."
46
+ vararray = v.split('=')
47
+ if v.start_with?('=') || v.scan('=').count > 1
48
+ fail db.exceptions[:moose],
49
+ "Incorrect format in {#{v}}. " \
50
+ 'Expected \'key\' or \'key=value\'.'
51
+ end
52
+
53
+ # Check against existing associations
54
+ hostvar = hostvars_ds[name: vararray[0]]
55
+ unless hostvar.nil?
56
+ # remove the association
57
+ host.remove_hostvar(hostvar)
58
+ hostvar.destroy
59
+ end
60
+ fmt.puts 4, '- OK'
61
+ end
62
+ fmt.puts 2, '- all OK'
63
+ end # Transaction end
64
+ puts 'Succeeded.'
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,169 @@
1
+ # Configuration
2
+
3
+ require 'yaml'
4
+
5
+ module Moose
6
+ module Inventory
7
+ ##
8
+ # This Modules manages application-wide configuration options
9
+ module Config
10
+ # rubocop:disable Style/ModuleFunction
11
+ extend self
12
+ # rubocop:enable Style/ModuleFunction
13
+
14
+ @_argv = []
15
+ @_confopts = {}
16
+ @_settings = {}
17
+
18
+ attr_reader :_argv
19
+ attr_reader :_confopts
20
+ attr_reader :_settings
21
+
22
+ #----------------------
23
+ def self.init(args)
24
+ @_argv = args.dup
25
+
26
+ top_level_args
27
+ # ansible_args
28
+ resolve_config_file
29
+ load
30
+ end
31
+
32
+ #----------------------
33
+ def self.top_level_args
34
+ # Certain top level flags affect the configuration.
35
+ # --config FILE => sets the configuration file to be used.
36
+ # Default is to search standard locations.
37
+ # --env ENV => sets the section to be used as the configuration.
38
+ # Defaults to ""
39
+ # --format FORMAT=> See formatter for supported types.
40
+ # Defaults to json.
41
+
42
+ @_confopts = { env: '', format: 'json', trace: false }
43
+
44
+ # The following are a O(n^m) approach. TODO: O(n) version?
45
+
46
+ # Check for two-part flags
47
+ %w(env config format).each do |var|
48
+ @_argv.each_with_index do |val, index|
49
+ next if val != "--#{var}"
50
+ @_confopts[var.to_sym] = @_argv[index + 1]
51
+ 1.downto(0) { |offset| @_argv.delete_at(index + offset) }
52
+ break
53
+ end
54
+ end
55
+
56
+ # Check for one-part flags
57
+ %w(trace).each do |var|
58
+ @_argv.each_with_index do |val, index|
59
+ next if val != "--#{var}"
60
+ @_confopts[var.to_sym] = true
61
+ @_argv.delete_at(index)
62
+ break
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+ #----------------------
69
+ def self.ansible_args # rubocop:disable Metrics/AbcSize
70
+ # Handle Ansible flags
71
+ # --hosts => list all hosts
72
+ # --hosts HOSTNAME => get host name
73
+ # --groups => list all groups
74
+
75
+ if @_argv[0] == '--hosts'
76
+ host = @_argv[1]
77
+ if !host.nil?
78
+ @_argv.clear
79
+ ['host', 'get', "#{host}", '--ansiblestyle'].each do |arg|
80
+ @_argv << arg
81
+ end
82
+ else
83
+ @_argv.clear
84
+ ['host', 'list', '--ansiblestyle'].each do |arg|
85
+ @_argv << arg
86
+ end
87
+ end
88
+ elsif @_argv[0] == '--groups'
89
+ ['group', 'list', '--ansiblestyle'].each do |arg|
90
+ @_argv << arg
91
+ end
92
+ end
93
+ end
94
+
95
+ #----------------------
96
+ def self.resolve_config_file # rubocop:disable Metrics/AbcSize
97
+ if ! @_confopts[:config].nil?
98
+ path = File.expand_path(@_confopts[:config])
99
+ if File.exist?(path)
100
+ @_confopts[:config] = path
101
+ else
102
+ fail("The configuration file #{path} does not exist")
103
+ end
104
+ else
105
+ possibles = ['./.moose-tools/inventory/config',
106
+ '~/.moose-tools/inventory/config',
107
+ '~/local/etc/moose-tools/inventory/config',
108
+ '/etc/moose-tools/inventory/config'
109
+ ]
110
+ possibles.each do |f|
111
+ file = File.expand_path(f)
112
+ @_confopts[:config] = file if File.exist?(file)
113
+ end
114
+ end
115
+
116
+ if @_confopts[:config].nil?
117
+ fail('No configuration either given or found in standard locations.')
118
+ end
119
+ end
120
+
121
+ #----------------------
122
+ def self.symbolize_keys(hash)
123
+ # rubocop:disable Style/EachWithObject
124
+ hash.inject({}) do |result, (key, value)|
125
+ new_key = case key
126
+ when String then key.to_sym
127
+ else key
128
+ end
129
+ new_value = case value
130
+ when Hash then symbolize_keys(value)
131
+ else value
132
+ end
133
+ result[new_key] = new_value
134
+ result
135
+ end
136
+ # rubocop:enable Style/EachWithObject
137
+ end
138
+
139
+ #----------------------
140
+ # rubocop:disable PerceivedComplexity
141
+ # rubocop:disable Metrics/CyclomaticComplexity, Metrics/AbcSize
142
+ def self.load
143
+ newsets = symbolize_keys(YAML.load_file(@_confopts[:config]))
144
+
145
+ path = @_confopts[:config]
146
+
147
+ # Get the "general" section
148
+ @_settings[:general] = newsets[:general]
149
+ @_settings[:general].nil? && fail("Missing 'general' root in #{path}")
150
+
151
+ # Get the config for the correct environment
152
+
153
+ if @_confopts[:env] && !@_confopts[:env].empty?
154
+ env = @_confopts[:env]
155
+ @_settings[:config] = newsets[@_confopts[:env].to_sym]
156
+ else
157
+ env = @_settings[:general][:defaultenv]
158
+ (env.nil? || env.empty?) && fail("No defaultenv set in #{path}")
159
+ @_settings[:config] = newsets[env.to_sym]
160
+ end
161
+
162
+ @_settings[:config].nil? && fail("Missing '#{env}' root in #{path}")
163
+
164
+ # And now we should have a valid config stuffed into @_options[:config]
165
+ end
166
+ # rubocop:enable Metrics/CyclomaticComplexity, Metrics/AbcSize
167
+ end
168
+ end
169
+ end