leap_cli 1.7.4 → 1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/bin/leap +6 -13
  3. data/lib/leap/platform.rb +2 -0
  4. data/lib/leap_cli.rb +2 -1
  5. data/lib/leap_cli/bootstrap.rb +197 -0
  6. data/lib/leap_cli/commands/common.rb +61 -0
  7. data/lib/leap_cli/commands/new.rb +5 -1
  8. data/lib/leap_cli/commands/pre.rb +1 -66
  9. data/lib/leap_cli/config/environment.rb +180 -0
  10. data/lib/leap_cli/config/manager.rb +100 -197
  11. data/lib/leap_cli/config/node.rb +2 -2
  12. data/lib/leap_cli/config/object.rb +56 -43
  13. data/lib/leap_cli/config/object_list.rb +6 -3
  14. data/lib/leap_cli/config/provider.rb +11 -0
  15. data/lib/leap_cli/config/secrets.rb +14 -1
  16. data/lib/leap_cli/config/tag.rb +2 -2
  17. data/lib/leap_cli/leapfile.rb +1 -0
  18. data/lib/leap_cli/log.rb +1 -0
  19. data/lib/leap_cli/logger.rb +16 -12
  20. data/lib/leap_cli/markdown_document_listener.rb +3 -1
  21. data/lib/leap_cli/path.rb +12 -0
  22. data/lib/leap_cli/remote/leap_plugin.rb +9 -34
  23. data/lib/leap_cli/remote/puppet_plugin.rb +0 -40
  24. data/lib/leap_cli/remote/tasks.rb +9 -34
  25. data/lib/leap_cli/ssh_key.rb +5 -2
  26. data/lib/leap_cli/version.rb +2 -2
  27. metadata +5 -18
  28. data/lib/leap_cli/commands/ca.rb +0 -518
  29. data/lib/leap_cli/commands/clean.rb +0 -16
  30. data/lib/leap_cli/commands/compile.rb +0 -340
  31. data/lib/leap_cli/commands/db.rb +0 -65
  32. data/lib/leap_cli/commands/deploy.rb +0 -368
  33. data/lib/leap_cli/commands/env.rb +0 -76
  34. data/lib/leap_cli/commands/facts.rb +0 -100
  35. data/lib/leap_cli/commands/inspect.rb +0 -144
  36. data/lib/leap_cli/commands/list.rb +0 -132
  37. data/lib/leap_cli/commands/node.rb +0 -165
  38. data/lib/leap_cli/commands/node_init.rb +0 -169
  39. data/lib/leap_cli/commands/ssh.rb +0 -220
  40. data/lib/leap_cli/commands/test.rb +0 -74
  41. data/lib/leap_cli/commands/user.rb +0 -136
  42. data/lib/leap_cli/commands/util.rb +0 -50
  43. data/lib/leap_cli/commands/vagrant.rb +0 -197
@@ -0,0 +1,180 @@
1
+ #
2
+ # All configurations files can be isolated into separate environments.
3
+ #
4
+ # Each config json in each environment inherits from the default environment,
5
+ # which in term inherits from the "_base_" environment:
6
+ #
7
+ # _base_ -- base provider in leap_platform
8
+ # '- default -- environment in provider dir when no env is set
9
+ # '- production -- example environment
10
+ #
11
+
12
+ module LeapCli; module Config
13
+
14
+ class Environment
15
+ # the String name of the environment
16
+ attr_accessor :name
17
+
18
+ # the shared Manager object
19
+ attr_accessor :manager
20
+
21
+ # hashes of {name => Config::Object}
22
+ attr_accessor :services, :tags, :partials
23
+
24
+ # a Config::Provider
25
+ attr_accessor :provider
26
+
27
+ # a Config::Object
28
+ attr_accessor :common
29
+
30
+ # shared, non-inheritable
31
+ def nodes; @@nodes; end
32
+ def secrets; @@secrets; end
33
+
34
+ def initialize(manager, name, search_dir, parent, options={})
35
+ @@nodes ||= nil
36
+ @@secrets ||= nil
37
+
38
+ @manager = manager
39
+ @name = name
40
+
41
+ load_provider_files(search_dir, options)
42
+
43
+ if parent
44
+ @services.inherit_from! parent.services, self
45
+ @tags.inherit_from! parent.tags , self
46
+ @partials.inherit_from! parent.partials, self
47
+ @common.inherit_from! parent.common
48
+ @provider.inherit_from! parent.provider
49
+ end
50
+
51
+ if @provider
52
+ @provider.set_env(name)
53
+ @provider.validate!
54
+ end
55
+ end
56
+
57
+ def load_provider_files(search_dir, options)
58
+ #
59
+ # load empty environment if search_dir doesn't exist
60
+ #
61
+ if search_dir.nil? || !Dir.exist?(search_dir)
62
+ @services = Config::ObjectList.new
63
+ @tags = Config::ObjectList.new
64
+ @partials = Config::ObjectList.new
65
+ @provider = Config::Provider.new
66
+ @common = Config::Object.new
67
+ return
68
+ end
69
+
70
+ #
71
+ # inheritable
72
+ #
73
+ if options[:scope]
74
+ scope = options[:scope]
75
+ @services = load_all_json(Path.named_path([:service_env_config, '*', scope], search_dir), Config::Tag, options)
76
+ @tags = load_all_json(Path.named_path([:tag_env_config, '*', scope], search_dir), Config::Tag, options)
77
+ @partials = load_all_json(Path.named_path([:service_env_config, '_*', scope], search_dir), Config::Tag, options)
78
+ @provider = load_json( Path.named_path([:provider_env_config, scope], search_dir), Config::Provider, options)
79
+ @common = load_json( Path.named_path([:common_env_config, scope], search_dir), Config::Object, options)
80
+ else
81
+ @services = load_all_json(Path.named_path([:service_config, '*'], search_dir), Config::Tag, options)
82
+ @tags = load_all_json(Path.named_path([:tag_config, '*'], search_dir), Config::Tag, options)
83
+ @partials = load_all_json(Path.named_path([:service_config, '_*'], search_dir), Config::Tag, options)
84
+ @provider = load_json( Path.named_path(:provider_config, search_dir), Config::Provider, options)
85
+ @common = load_json( Path.named_path(:common_config, search_dir), Config::Object, options)
86
+ end
87
+
88
+ # remove 'name' from partials, since partials get merged with nodes
89
+ @partials.values.each {|partial| partial.delete('name'); }
90
+
91
+ #
92
+ # shared: currently non-inheritable
93
+ # load the first ones we find, and only those.
94
+ #
95
+ if @@nodes.nil? || @@nodes.empty?
96
+ @@nodes = load_all_json(Path.named_path([:node_config, '*'], search_dir), Config::Node, options)
97
+ end
98
+ if @@secrets.nil? || @@secrets.empty?
99
+ @@secrets = load_json(Path.named_path(:secrets_config, search_dir), Config::Secrets, options)
100
+ end
101
+ end
102
+
103
+ #
104
+ # Loads a json template file as a Hash (used only when creating a new node .json
105
+ # file for the first time).
106
+ #
107
+ def template(template)
108
+ path = Path.named_path([:template_config, template], Path.provider_base)
109
+ if File.exists?(path)
110
+ return load_json(path, Config::Object)
111
+ else
112
+ return nil
113
+ end
114
+ end
115
+
116
+ private
117
+
118
+ def load_all_json(pattern, object_class, options={})
119
+ results = Config::ObjectList.new
120
+ Dir.glob(pattern).each do |filename|
121
+ next if options[:no_dots] && File.basename(filename) !~ /^[^\.]*\.json$/
122
+ obj = load_json(filename, object_class)
123
+ if obj
124
+ name = File.basename(filename).force_encoding('utf-8').sub(/^([^\.]+).*\.json$/,'\1')
125
+ obj['name'] ||= name
126
+ if options[:env]
127
+ obj.environment = options[:env]
128
+ end
129
+ results[name] = obj
130
+ end
131
+ end
132
+ results
133
+ end
134
+
135
+ def load_json(filename, object_class, options={})
136
+ if !File.exists?(filename)
137
+ return object_class.new(self)
138
+ end
139
+
140
+ Util::log :loading, filename, 3
141
+
142
+ #
143
+ # Read a JSON file, strip out comments.
144
+ #
145
+ # UTF8 is the default encoding for JSON, but others are allowed:
146
+ # https://www.ietf.org/rfc/rfc4627.txt
147
+ #
148
+ buffer = StringIO.new
149
+ File.open(filename, "rb", :encoding => 'UTF-8') do |f|
150
+ while (line = f.gets)
151
+ next if line =~ /^\s*\/\//
152
+ buffer << line
153
+ end
154
+ end
155
+
156
+ #
157
+ # force UTF-8
158
+ #
159
+ if $ruby_version >= [1,9]
160
+ string = buffer.string.force_encoding('utf-8')
161
+ else
162
+ string = Iconv.conv("UTF-8//IGNORE", "UTF-8", buffer.string)
163
+ end
164
+
165
+ # parse json
166
+ begin
167
+ hash = JSON.parse(string, :object_class => Hash, :array_class => Array) || {}
168
+ rescue SyntaxError, JSON::ParserError => exc
169
+ Util::log 0, :error, 'in file "%s":' % filename
170
+ Util::log 0, exc.to_s, :indent => 1
171
+ return nil
172
+ end
173
+ object = object_class.new(self)
174
+ object.deep_merge!(hash)
175
+ return object
176
+ end
177
+
178
+ end # end Environment
179
+
180
+ end; end
@@ -9,10 +9,6 @@ end
9
9
  module LeapCli
10
10
  module Config
11
11
 
12
- class Environment
13
- attr_accessor :services, :tags, :provider
14
- end
15
-
16
12
  #
17
13
  # A class to manage all the objects in all the configuration files.
18
14
  #
@@ -20,15 +16,6 @@ module LeapCli
20
16
 
21
17
  def initialize
22
18
  @environments = {} # hash of `Environment` objects, keyed by name.
23
-
24
- # load macros and other custom ruby in provider base
25
- platform_ruby_files = Dir[Path.provider_base + '/lib/*.rb']
26
- if platform_ruby_files.any?
27
- $: << Path.provider_base + '/lib'
28
- platform_ruby_files.each do |rb_file|
29
- require rb_file
30
- end
31
- end
32
19
  Config::Object.send(:include, LeapCli::Macro)
33
20
  end
34
21
 
@@ -36,9 +23,6 @@ module LeapCli
36
23
  ## ATTRIBUTES
37
24
  ##
38
25
 
39
- attr_reader :nodes, :common, :secrets
40
- attr_reader :base_services, :base_tags, :base_provider, :base_common
41
-
42
26
  #
43
27
  # returns the Hash of the contents of facts.json
44
28
  #
@@ -59,32 +43,36 @@ module LeapCli
59
43
  # the returned array includes nil (for the default environment)
60
44
  #
61
45
  def environment_names
62
- @environment_names ||= [nil] + env.tags.collect {|name, tag| tag['environment']}.compact
46
+ @environment_names ||= begin
47
+ [nil] + (env.tags.field('environment') + env.nodes.field('environment')).compact.uniq
48
+ end
63
49
  end
64
50
 
65
51
  #
66
52
  # Returns the appropriate environment variable
67
53
  #
68
54
  def env(env=nil)
69
- env ||= 'default'
70
- e = @environments[env] ||= Environment.new
71
- yield e if block_given?
72
- e
55
+ @environments[env || 'default']
73
56
  end
74
57
 
75
58
  #
76
- # The default accessors for services, tags, and provider.
59
+ # The default accessors
60
+ #
77
61
  # For these defaults, use 'default' environment, or whatever
78
62
  # environment is pinned.
79
63
  #
80
- def services
81
- env(default_environment).services
82
- end
83
- def tags
84
- env(default_environment).tags
85
- end
86
- def provider
87
- env(default_environment).provider
64
+ # I think it might be an error that these are ever used
65
+ # and I would like to get rid of them.
66
+ #
67
+ def services; env(default_environment).services; end
68
+ def tags; env(default_environment).tags; end
69
+ def partials; env(default_environment).partials; end
70
+ def provider; env(default_environment).provider; end
71
+ def common; env(default_environment).common; end
72
+ def secrets; env(default_environment).secrets; end
73
+ def nodes; env(default_environment).nodes; end
74
+ def template(*args)
75
+ self.env.template(*args)
88
76
  end
89
77
 
90
78
  def default_environment
@@ -95,6 +83,21 @@ module LeapCli
95
83
  ## IMPORT EXPORT
96
84
  ##
97
85
 
86
+ def add_environment(args)
87
+ if args[:inherit]
88
+ parent = @environments[args.delete(:inherit)]
89
+ else
90
+ parent = nil
91
+ end
92
+ @environments[args[:name]] = Environment.new(
93
+ self,
94
+ args.delete(:name),
95
+ args.delete(:dir),
96
+ parent,
97
+ args
98
+ )
99
+ end
100
+
98
101
  #
99
102
  # load .json configuration files
100
103
  #
@@ -102,66 +105,37 @@ module LeapCli
102
105
  @provider_dir = Path.provider
103
106
 
104
107
  # load base
105
- @base_services = load_all_json(Path.named_path([:service_config, '*'], Path.provider_base), Config::Tag)
106
- @base_tags = load_all_json(Path.named_path([:tag_config, '*'], Path.provider_base), Config::Tag)
107
- @base_common = load_json( Path.named_path(:common_config, Path.provider_base), Config::Object)
108
- @base_provider = load_json( Path.named_path(:provider_config, Path.provider_base), Config::Provider)
108
+ add_environment(name: '_base_', dir: Path.provider_base)
109
109
 
110
110
  # load provider
111
- @nodes = load_all_json(Path.named_path([:node_config, '*'], @provider_dir), Config::Node)
112
- @common = load_json( Path.named_path(:common_config, @provider_dir), Config::Object)
113
- @secrets = load_json( Path.named_path(:secrets_config, @provider_dir), Config::Secrets)
114
- @common.inherit_from! @base_common
115
-
116
- # For the default environment, load provider services, tags, and provider.json
117
- log 3, :loading, 'default environment...'
118
- env('default') do |e|
119
- e.services = load_all_json(Path.named_path([:service_config, '*'], @provider_dir), Config::Tag, :no_dots => true)
120
- e.tags = load_all_json(Path.named_path([:tag_config, '*'], @provider_dir), Config::Tag, :no_dots => true)
121
- e.provider = load_json( Path.named_path(:provider_config, @provider_dir), Config::Provider, :assert => true)
122
- e.services.inherit_from! @base_services
123
- e.tags.inherit_from! @base_tags
124
- e.provider.inherit_from! @base_provider
125
- validate_provider(e.provider)
126
- end
111
+ Util::assert_files_exist!(Path.named_path(:provider_config, @provider_dir))
112
+ add_environment(name: 'default', dir: @provider_dir,
113
+ inherit: '_base_', no_dots: true)
127
114
 
128
- # create a special '_all_' environment, used for tracking the union
129
- # of all the environments
130
- env('_all_') do |e|
131
- e.services = Config::ObjectList.new
132
- e.tags = Config::ObjectList.new
133
- e.provider = Config::Provider.new
134
- e.services.inherit_from! env('default').services
135
- e.tags.inherit_from! env('default').tags
136
- e.provider.inherit_from! env('default').provider
137
- end
115
+ # create a special '_all_' environment, used for tracking
116
+ # the union of all the environments
117
+ add_environment(name: '_all_', inherit: 'default')
138
118
 
139
- # For each defined environment, load provider services, tags, and provider.json.
119
+ # load environments
140
120
  environment_names.each do |ename|
141
- next unless ename
142
- log 3, :loading, '%s environment...' % ename
143
- env(ename) do |e|
144
- e.services = load_all_json(Path.named_path([:service_env_config, '*', ename], @provider_dir), Config::Tag, :env => ename)
145
- e.tags = load_all_json(Path.named_path([:tag_env_config, '*', ename], @provider_dir), Config::Tag, :env => ename)
146
- e.provider = load_json( Path.named_path([:provider_env_config, ename], @provider_dir), Config::Provider, :env => ename)
147
- e.services.inherit_from! env('default').services
148
- e.tags.inherit_from! env('default').tags
149
- e.provider.inherit_from! env('default').provider
150
- validate_provider(e.provider)
121
+ if ename
122
+ log 3, :loading, '%s environment...' % ename
123
+ add_environment(name: ename, dir: @provider_dir,
124
+ inherit: 'default', scope: ename)
151
125
  end
152
126
  end
153
127
 
154
128
  # apply inheritance
155
- @nodes.each do |name, node|
129
+ env.nodes.each do |name, node|
156
130
  Util::assert! name =~ /^[0-9a-z-]+$/, "Illegal character(s) used in node name '#{name}'"
157
- @nodes[name] = apply_inheritance(node)
131
+ env.nodes[name] = apply_inheritance(node)
158
132
  end
159
133
 
160
134
  # do some node-list post-processing
161
135
  cleanup_node_lists(options)
162
136
 
163
137
  # apply control files
164
- @nodes.each do |name, node|
138
+ env.nodes.each do |name, node|
165
139
  control_files(node).each do |file|
166
140
  begin
167
141
  node.eval_file file
@@ -189,7 +163,7 @@ module LeapCli
189
163
  existing_files = nil
190
164
 
191
165
  unless node_list
192
- node_list = self.nodes
166
+ node_list = env.nodes
193
167
  existing_hiera = Dir.glob(Path.named_path([:hiera, '*'], @provider_dir))
194
168
  existing_files = Dir.glob(Path.named_path([:node_files_dir, '*'], @provider_dir))
195
169
  end
@@ -224,8 +198,8 @@ module LeapCli
224
198
  end
225
199
 
226
200
  def export_secrets(clean_unused_secrets = false)
227
- if @secrets.any?
228
- Util.write_file!([:secrets_config, @provider_dir], @secrets.dump_json(clean_unused_secrets) + "\n")
201
+ if env.secrets.any?
202
+ Util.write_file!([:secrets_config, @provider_dir], env.secrets.dump_json(clean_unused_secrets) + "\n")
229
203
  end
230
204
  end
231
205
 
@@ -270,7 +244,7 @@ module LeapCli
270
244
  # so, take the part before the first period as the node name
271
245
  name = name.split('.').first
272
246
  end
273
- @nodes[name]
247
+ env.nodes[name]
274
248
  end
275
249
 
276
250
  #
@@ -284,137 +258,48 @@ module LeapCli
284
258
  # yields each node, in sorted order
285
259
  #
286
260
  def each_node(&block)
287
- nodes.each_node &block
261
+ env.nodes.each_node &block
288
262
  end
289
263
 
290
264
  def reload_node!(node)
291
- @nodes[node.name] = apply_inheritance!(node)
292
- end
293
-
294
- #
295
- # returns all the partial data for the specified partial path.
296
- # partial path is always relative to provider root, but there must be multiple files
297
- # that match because provider root might be the base provider or the local provider.
298
- #
299
- def partials(partial_path)
300
- @partials ||= {}
301
- if @partials[partial_path].nil?
302
- [Path.provider_base, Path.provider].each do |provider_dir|
303
- path = File.join(provider_dir, partial_path)
304
- if File.exists?(path)
305
- @partials[partial_path] ||= []
306
- @partials[partial_path] << load_json(path, Config::Object)
307
- end
308
- end
309
- if @partials[partial_path].nil?
310
- raise RuntimeError, 'no such partial path `%s`' % partial_path, caller
311
- end
312
- end
313
- @partials[partial_path]
265
+ env.nodes[node.name] = apply_inheritance!(node)
314
266
  end
315
267
 
316
- private
268
+ ##
269
+ ## CONNECTIONS
270
+ ##
317
271
 
318
- def load_all_json(pattern, object_class, options={})
319
- results = Config::ObjectList.new
320
- Dir.glob(pattern).each do |filename|
321
- next if options[:no_dots] && File.basename(filename) !~ /^[^\.]*\.json$/
322
- obj = load_json(filename, object_class)
323
- if obj
324
- name = File.basename(filename).force_encoding('utf-8').sub(/^([^\.]+).*\.json$/,'\1')
325
- obj['name'] ||= name
326
- if options[:env]
327
- obj.environment = options[:env]
328
- end
329
- results[name] = obj
330
- end
272
+ class ConnectionList < Array
273
+ def add(data={})
274
+ self << {
275
+ "from" => data[:from],
276
+ "to" => data[:to],
277
+ "port" => data[:port]
278
+ }
331
279
  end
332
- results
333
280
  end
334
281
 
335
- def load_json(filename, object_class, options={})
336
- if options[:assert]
337
- Util::assert_files_exist!(filename)
338
- end
339
- if !File.exists?(filename)
340
- return object_class.new(self)
341
- end
342
-
343
- log :loading, filename, 3
344
-
345
- #
346
- # Read a JSON file, strip out comments.
347
- #
348
- # UTF8 is the default encoding for JSON, but others are allowed:
349
- # https://www.ietf.org/rfc/rfc4627.txt
350
- #
351
- buffer = StringIO.new
352
- File.open(filename, "rb", :encoding => 'UTF-8') do |f|
353
- while (line = f.gets)
354
- next if line =~ /^\s*\/\//
355
- buffer << line
356
- end
357
- end
358
-
359
- #
360
- # force UTF-8
361
- #
362
- if $ruby_version >= [1,9]
363
- string = buffer.string.force_encoding('utf-8')
364
- else
365
- string = Iconv.conv("UTF-8//IGNORE", "UTF-8", buffer.string)
366
- end
367
-
368
- # parse json
369
- begin
370
- hash = JSON.parse(string, :object_class => Hash, :array_class => Array) || {}
371
- rescue SyntaxError, JSON::ParserError => exc
372
- log 0, :error, 'in file "%s":' % filename
373
- log 0, exc.to_s, :indent => 1
374
- return nil
375
- end
376
- object = object_class.new(self)
377
- object.deep_merge!(hash)
378
- return object
282
+ def connections
283
+ @connections ||= ConnectionList.new
379
284
  end
380
285
 
381
- #
382
- # remove all the nesting from a hash.
383
- #
384
- # def flatten_hash(input = {}, output = {}, options = {})
385
- # input.each do |key, value|
386
- # key = options[:prefix].nil? ? "#{key}" : "#{options[:prefix]}#{options[:delimiter]||"_"}#{key}"
387
- # if value.is_a? Hash
388
- # flatten_hash(value, output, :prefix => key, :delimiter => options[:delimiter])
389
- # else
390
- # output[key] = value
391
- # end
392
- # end
393
- # output.replace(input)
394
- # output
395
- # end
286
+ ##
287
+ ## PRIVATE
288
+ ##
289
+
290
+ private
396
291
 
397
292
  #
398
293
  # makes a node inherit options from appropriate the common, service, and tag json files.
399
294
  #
400
295
  def apply_inheritance(node, throw_exceptions=false)
401
- new_node = Config::Node.new(self)
402
- name = node.name
403
-
404
- # Guess the environment of the node from the tag names.
405
- # (Technically, this is wrong: a tag that sets the environment might not be
406
- # named the same as the environment. This code assumes that it is).
407
- node_env = self.env
408
- if node['tags']
409
- node['tags'].to_a.each do |tag|
410
- if self.environment_names.include?(tag)
411
- node_env = self.env(tag)
412
- end
413
- end
414
- end
296
+ new_node = Config::Node.new(nil)
297
+ name = node.name
298
+ node_env = guess_node_env(node)
299
+ new_node.set_environment(node_env, new_node)
415
300
 
416
301
  # inherit from common
417
- new_node.deep_merge!(@common)
302
+ new_node.deep_merge!(node_env.common)
418
303
 
419
304
  # inherit from services
420
305
  if node['services']
@@ -456,6 +341,28 @@ module LeapCli
456
341
  apply_inheritance(node, true)
457
342
  end
458
343
 
344
+ #
345
+ # Guess the environment of the node from the tag names.
346
+ #
347
+ # Technically, this is wrong: a tag that sets the environment might not be
348
+ # named the same as the environment. This code assumes that it is.
349
+ #
350
+ # Unfortunately, it is a chicken and egg problem. We need to know the nodes
351
+ # likely environment in order to apply the inheritance that will actually
352
+ # determine the node's properties.
353
+ #
354
+ def guess_node_env(node)
355
+ environment = self.env(default_environment)
356
+ if node['tags']
357
+ node['tags'].to_a.each do |tag|
358
+ if self.environment_names.include?(tag)
359
+ environment = self.env(tag)
360
+ end
361
+ end
362
+ end
363
+ return environment
364
+ end
365
+
459
366
  #
460
367
  # does some final clean at the end of loading nodes.
461
368
  # this includes removing disabled nodes, and populating
@@ -463,7 +370,7 @@ module LeapCli
463
370
  #
464
371
  def cleanup_node_lists(options)
465
372
  @disabled_nodes = Config::ObjectList.new
466
- @nodes.each do |name, node|
373
+ env.nodes.each do |name, node|
467
374
  if node.enabled || options[:include_disabled]
468
375
  if node['services']
469
376
  node['services'].to_a.each do |node_service|
@@ -479,16 +386,12 @@ module LeapCli
479
386
  end
480
387
  elsif !options[:include_disabled]
481
388
  log 2, :skipping, "disabled node #{name}."
482
- @nodes.delete(name)
389
+ env.nodes.delete(name)
483
390
  @disabled_nodes[name] = node
484
391
  end
485
392
  end
486
393
  end
487
394
 
488
- def validate_provider(provider)
489
- # nothing yet.
490
- end
491
-
492
395
  #
493
396
  # returns a list of 'control' files for this node.
494
397
  # a control file is like a service or a tag JSON file, but it contains