leap_cli 1.7.4 → 1.8
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/bin/leap +6 -13
- data/lib/leap/platform.rb +2 -0
- data/lib/leap_cli.rb +2 -1
- data/lib/leap_cli/bootstrap.rb +197 -0
- data/lib/leap_cli/commands/common.rb +61 -0
- data/lib/leap_cli/commands/new.rb +5 -1
- data/lib/leap_cli/commands/pre.rb +1 -66
- data/lib/leap_cli/config/environment.rb +180 -0
- data/lib/leap_cli/config/manager.rb +100 -197
- data/lib/leap_cli/config/node.rb +2 -2
- data/lib/leap_cli/config/object.rb +56 -43
- data/lib/leap_cli/config/object_list.rb +6 -3
- data/lib/leap_cli/config/provider.rb +11 -0
- data/lib/leap_cli/config/secrets.rb +14 -1
- data/lib/leap_cli/config/tag.rb +2 -2
- data/lib/leap_cli/leapfile.rb +1 -0
- data/lib/leap_cli/log.rb +1 -0
- data/lib/leap_cli/logger.rb +16 -12
- data/lib/leap_cli/markdown_document_listener.rb +3 -1
- data/lib/leap_cli/path.rb +12 -0
- data/lib/leap_cli/remote/leap_plugin.rb +9 -34
- data/lib/leap_cli/remote/puppet_plugin.rb +0 -40
- data/lib/leap_cli/remote/tasks.rb +9 -34
- data/lib/leap_cli/ssh_key.rb +5 -2
- data/lib/leap_cli/version.rb +2 -2
- metadata +5 -18
- data/lib/leap_cli/commands/ca.rb +0 -518
- data/lib/leap_cli/commands/clean.rb +0 -16
- data/lib/leap_cli/commands/compile.rb +0 -340
- data/lib/leap_cli/commands/db.rb +0 -65
- data/lib/leap_cli/commands/deploy.rb +0 -368
- data/lib/leap_cli/commands/env.rb +0 -76
- data/lib/leap_cli/commands/facts.rb +0 -100
- data/lib/leap_cli/commands/inspect.rb +0 -144
- data/lib/leap_cli/commands/list.rb +0 -132
- data/lib/leap_cli/commands/node.rb +0 -165
- data/lib/leap_cli/commands/node_init.rb +0 -169
- data/lib/leap_cli/commands/ssh.rb +0 -220
- data/lib/leap_cli/commands/test.rb +0 -74
- data/lib/leap_cli/commands/user.rb +0 -136
- data/lib/leap_cli/commands/util.rb +0 -50
- 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 ||=
|
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
|
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
|
59
|
+
# The default accessors
|
60
|
+
#
|
77
61
|
# For these defaults, use 'default' environment, or whatever
|
78
62
|
# environment is pinned.
|
79
63
|
#
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
def
|
84
|
-
|
85
|
-
end
|
86
|
-
def provider
|
87
|
-
|
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
|
-
|
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
|
-
|
112
|
-
|
113
|
-
|
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
|
129
|
-
# of all the environments
|
130
|
-
|
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
|
-
#
|
119
|
+
# load environments
|
140
120
|
environment_names.each do |ename|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
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
|
-
|
129
|
+
env.nodes.each do |name, node|
|
156
130
|
Util::assert! name =~ /^[0-9a-z-]+$/, "Illegal character(s) used in node name '#{name}'"
|
157
|
-
|
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
|
-
|
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 =
|
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
|
228
|
-
Util.write_file!([:secrets_config, @provider_dir],
|
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
|
-
|
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
|
-
|
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
|
-
|
268
|
+
##
|
269
|
+
## CONNECTIONS
|
270
|
+
##
|
317
271
|
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
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
|
336
|
-
|
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
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
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(
|
402
|
-
name
|
403
|
-
|
404
|
-
|
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!(
|
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
|
-
|
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
|
-
|
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
|