coral_core 0.2.23 → 0.2.24

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,244 @@
1
+
2
+ module Coral
3
+ class Command < Core
4
+
5
+ #-----------------------------------------------------------------------------
6
+ # Properties
7
+
8
+ attr_accessor :name
9
+ attr_reader :subcommand
10
+
11
+ #-----------------------------------------------------------------------------
12
+ # Constructor / Destructor
13
+
14
+ def initialize(options = {})
15
+
16
+ if options.is_a?(String) || options.is_a?(Symbol)
17
+ options = string(options)
18
+ options = { :name => options, :command => options }
19
+ end
20
+
21
+ config = Config.ensure(options)
22
+
23
+ super(config)
24
+
25
+ @properties = {}
26
+
27
+ self.subcommand = config.get(:subcommand, nil)
28
+
29
+ @name = config.get(:name, '')
30
+
31
+ @properties = config.options
32
+ @properties[:command] = executable(config)
33
+ end
34
+
35
+ #-----------------------------------------------------------------------------
36
+ # Property accessors / modifiers
37
+
38
+ def command_base
39
+ return @properties[:command]
40
+ end
41
+
42
+ #---
43
+
44
+ def command=command
45
+ @properties[:command] = executable({ :command => command })
46
+ end
47
+
48
+ #---
49
+
50
+ def vagrant=command
51
+ @properties[:command] = executable({ :vagrant => command })
52
+ end
53
+
54
+ #---
55
+
56
+ def coral=command
57
+ @properties[:command] = executable({ :coral => command })
58
+ end
59
+
60
+ #---
61
+
62
+ def args
63
+ return array(@properties[:args])
64
+ end
65
+
66
+ #---
67
+
68
+ def args=args
69
+ @properties[:args] = array(args)
70
+ end
71
+
72
+ #---
73
+
74
+ def flags
75
+ return array(@properties[:flags])
76
+ end
77
+
78
+ #---
79
+
80
+ def flags=flags
81
+ @properties[:flags] = array(flags)
82
+ end
83
+
84
+ #---
85
+
86
+ def data
87
+ return hash(@properties[:data])
88
+ end
89
+
90
+ #---
91
+
92
+ def data=data
93
+ @properties[:data] = hash(data)
94
+ end
95
+
96
+ #---
97
+
98
+ def subcommand=subcommand
99
+ unless Util::Data.empty?(subcommand)
100
+ @properties[:subcommand] = hash(subcommand)
101
+ @subcommand = self.class.new(@properties[:subcommand])
102
+ end
103
+ end
104
+
105
+ #-----------------------------------------------------------------------------
106
+ # Import / Export
107
+
108
+ def export
109
+ return symbol_map(@properties)
110
+ end
111
+
112
+ #-----------------------------------------------------------------------------
113
+ # Command functions
114
+
115
+ def build(components = {}, overrides = nil, override_key = false)
116
+
117
+ command = string(components[:command])
118
+ flags = array( components.has_key?(:flags) ? components[:flags] : [] )
119
+ data = string_map(hash( components.has_key?(:data) ? components[:data] : {} ))
120
+ args = array( components.has_key?(:args) ? components[:args] : [] )
121
+ subcommand = hash( components.has_key?(:subcommand) ? components[:subcommand] : {} )
122
+
123
+ override_key = command unless override_key
124
+ override_key = override_key.to_sym
125
+
126
+ command_string = command.dup
127
+ subcommand_string = ''
128
+
129
+ escape_characters = /[\'\"]+/
130
+ escape_replacement = '\"'
131
+
132
+ dash_pattern = /^([\-]+)/
133
+ assignment_pattern = /\=$/
134
+
135
+ # Flags
136
+ if overrides && overrides.has_key?(:flags)
137
+ if overrides[:flags].is_a?(Hash)
138
+ if overrides[:flags].has_key?(override_key)
139
+ flags = array(overrides[:flags][override_key])
140
+ end
141
+ else
142
+ flags = array(overrides[:flags])
143
+ end
144
+ end
145
+ flags.each do |flag|
146
+ flag = string(flag)
147
+ if ! flag.empty?
148
+ if flag.match(dash_pattern)
149
+ dashes = $1
150
+ else
151
+ dashes = ( flag.size == 1 ? '-' : '--' )
152
+ end
153
+ command_string << " #{dashes}#{flag}"
154
+ end
155
+ end
156
+
157
+ # Data
158
+ if overrides && overrides.has_key?(:data)
159
+ if overrides[:data].has_key?(override_key)
160
+ data = hash(overrides[:data][override_key])
161
+ else
162
+ override = true
163
+ overrides[:data].each do |key, value|
164
+ if ! value.is_a?(String)
165
+ override = false
166
+ end
167
+ end
168
+ data = hash(overrides[:data]) if override
169
+ end
170
+ end
171
+ data.each do |key, value|
172
+ key = string(key)
173
+ value = string(value).strip.sub(escape_characters, escape_replacement)
174
+
175
+ if key.match(dash_pattern)
176
+ dashes = $1
177
+ else
178
+ dashes = ( key.size == 1 ? '-' : '--' )
179
+ end
180
+ space = ( key.match(assignment_pattern) ? '' : ' ' )
181
+
182
+ command_string << " #{dashes}#{key}#{space}'#{value}'"
183
+ end
184
+
185
+ # Arguments
186
+ if overrides && overrides.has_key?(:args)
187
+ if overrides[:args].is_a?(Hash)
188
+ if overrides[:args].has_key?(override_key)
189
+ args = array(overrides[:args][override_key])
190
+ end
191
+ else
192
+ args = array(overrides[:args])
193
+ end
194
+ end
195
+ args.each do |arg|
196
+ arg = string(arg).sub(escape_characters, escape_replacement)
197
+ command_string << " '#{arg}'"
198
+ end
199
+
200
+ # Subcommand
201
+ subcommand_overrides = ( overrides ? overrides[:subcommand] : nil )
202
+ if subcommand && subcommand.is_a?(Hash) && ! subcommand.empty?
203
+ subcommand_string = build(subcommand, subcommand_overrides)
204
+ end
205
+
206
+ return (command_string + ' ' + subcommand_string).strip
207
+ end
208
+
209
+ #-----------------------------------------------------------------------------
210
+
211
+ def exec!(options = {}, overrides = nil)
212
+ config = Config.ensure(options)
213
+
214
+ config[:ui] = @ui
215
+ success = Coral::Util::Shell.exec!(build(export, overrides), config) do |line|
216
+ block_given? ? yield(line) : true
217
+ end
218
+ return success
219
+ end
220
+
221
+ #---
222
+
223
+ def exec(options = {}, overrides = nil)
224
+ return exec!(options, overrides)
225
+ end
226
+
227
+ #-----------------------------------------------------------------------------
228
+ # Utilities
229
+
230
+ def executable(options)
231
+ config = Config.ensure(options)
232
+
233
+ if config.get(:coral, false)
234
+ return 'vagrant coral ' + config[:coral]
235
+
236
+ elsif config.get(:vagrant, false)
237
+ return 'vagrant ' + config[:vagrant]
238
+
239
+ elsif config.get(:command, false)
240
+ return config[:command]
241
+ end
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,360 @@
1
+
2
+ module Coral
3
+ class Config
4
+
5
+ #-----------------------------------------------------------------------------
6
+ # Global configuration
7
+
8
+ @@options = {}
9
+
10
+ #---
11
+
12
+ def self.options(contexts, force = true)
13
+ options = {}
14
+
15
+ unless contexts.is_a?(Array)
16
+ contexts = [ contexts ]
17
+ end
18
+ contexts.each do |name|
19
+ if @@options.has_key?(name)
20
+ options = Util::Data.merge([ options, @@options[name] ], force)
21
+ end
22
+ end
23
+ return options
24
+ end
25
+
26
+ #---
27
+
28
+ def self.set_options(context, options, force = true)
29
+ current_options = ( @@options.has_key?(context) ? @@options[context] : {} )
30
+ @@options[context] = Util::Data.merge([ current_options, options ], force)
31
+ end
32
+
33
+ #---
34
+
35
+ def self.clear_options(contexts)
36
+ unless contexts.is_a?(Array)
37
+ contexts = [ contexts ]
38
+ end
39
+ contexts.each do |name|
40
+ @@options.delete(name)
41
+ end
42
+ end
43
+
44
+ #-----------------------------------------------------------------------------
45
+
46
+ @@properties = {}
47
+
48
+ #---
49
+
50
+ def self.properties
51
+ return @@properties
52
+ end
53
+
54
+ #---
55
+
56
+ def self.set_property(name, value)
57
+ #dbg(value, "result -> #{name}")
58
+ @@properties[name] = value
59
+ save_properties
60
+ end
61
+
62
+ #---
63
+
64
+ def self.clear_property(name)
65
+ @@properties.delete(name)
66
+ save_properties
67
+ end
68
+
69
+ #---
70
+
71
+ def self.save_properties
72
+ log_options = options('coral_log')
73
+
74
+ unless Util::Data.empty?(log_options['config_log'])
75
+ config_log = log_options['config_log']
76
+
77
+ Util::Disk.write(config_log, JSON.pretty_generate(@@properties))
78
+ Util::Disk.close(config_log)
79
+ end
80
+ end
81
+
82
+ #-----------------------------------------------------------------------------
83
+ # Hiera configuration
84
+
85
+ @@hiera = nil
86
+
87
+ #---
88
+
89
+ def self.hiera_config
90
+ config_file = Puppet.settings[:hiera_config]
91
+ config = {}
92
+
93
+ if File.exist?(config_file)
94
+ config = Hiera::Config.load(config_file)
95
+ else
96
+ Coral.ui.warn("Config file #{config_file} not found, using Hiera defaults")
97
+ end
98
+
99
+ config[:logger] = 'puppet'
100
+ return config
101
+ end
102
+
103
+ #---
104
+
105
+ def self.hiera
106
+ @@hiera = Hiera.new(:config => hiera_config) unless @@hiera
107
+ return @@hiera
108
+ end
109
+
110
+ #---
111
+
112
+ def hiera
113
+ return self.class.hiera
114
+ end
115
+
116
+ #-----------------------------------------------------------------------------
117
+ # Configuration lookup
118
+
119
+ def self.initialized?(options = {})
120
+ config = Config.ensure(options)
121
+ begin
122
+ require 'hiera_puppet'
123
+
124
+ scope = config.get(:scope, {})
125
+
126
+ sep = config.get(:sep, '::')
127
+ prefix = config.get(:prefix, true)
128
+ prefix_text = prefix ? sep : ''
129
+
130
+ init_fact = prefix_text + config.get(:init_fact, 'hiera_ready')
131
+ coral_fact = prefix_text + config.get(:coral_fact, 'coral_exists')
132
+
133
+ if Puppet::Parser::Functions.function('hiera')
134
+ if scope.respond_to?('[]')
135
+ return true if Util::Data.true?(scope[init_fact]) && Util::Data.true?(scope[coral_fact])
136
+ else
137
+ return true
138
+ end
139
+ end
140
+
141
+ rescue Exception # Prevent abortions.
142
+ end
143
+ return false
144
+ end
145
+
146
+ #---
147
+
148
+ def self.lookup(name, default = nil, options = {})
149
+ config = Config.ensure(options)
150
+ value = nil
151
+
152
+ context = config.get(:context, :priority)
153
+ scope = config.get(:scope, {})
154
+ override = config.get(:override, nil)
155
+
156
+ base_names = config.get(:search, nil)
157
+ sep = config.get(:sep, '::')
158
+ prefix = config.get(:prefix, true)
159
+ prefix_text = prefix ? sep : ''
160
+
161
+ search_name = config.get(:search_name, true)
162
+ reverse_lookup = config.get(:reverse_lookup, true)
163
+
164
+ #dbg(default, "lookup -> #{name}")
165
+
166
+ if Config.initialized?(options)
167
+ unless scope.respond_to?("[]")
168
+ scope = Hiera::Scope.new(scope)
169
+ end
170
+ value = hiera.lookup(name, default, scope, override, context)
171
+ #dbg(value, "hiera -> #{name}")
172
+ end
173
+
174
+ if Util::Data.undef?(value) && ( scope.respond_to?("[]") || scope.respond_to?("lookupvar") )
175
+ log_level = Puppet::Util::Log.level
176
+ Puppet::Util::Log.level = :err # Don't want failed parameter lookup warnings here.
177
+
178
+ if base_names
179
+ if base_names.is_a?(String)
180
+ base_names = [ base_names ]
181
+ end
182
+ base_names = base_names.reverse if reverse_lookup
183
+
184
+ #bg(base_names, 'search path')
185
+ base_names.each do |item|
186
+ if scope.respond_to?("lookupvar")
187
+ value = scope.lookupvar("#{prefix_text}#{item}#{sep}#{name}")
188
+ else
189
+ value = scope["#{prefix_text}#{item}#{sep}#{name}"]
190
+ end
191
+ #dbg(value, "#{prefix_text}#{item}#{sep}#{name}")
192
+ break unless Util::Data.undef?(value)
193
+ end
194
+ end
195
+ if Util::Data.undef?(value) && search_name
196
+ if scope.respond_to?("lookupvar")
197
+ value = scope.lookupvar("#{prefix_text}#{name}")
198
+ else
199
+ value = scope["#{prefix_text}#{name}"]
200
+ end
201
+ #dbg(value, "#{prefix_text}#{name}")
202
+ end
203
+ Puppet::Util::Log.level = log_level
204
+ end
205
+ value = default if Util::Data.undef?(value)
206
+ value = Util::Data.value(value)
207
+
208
+ if ! @@properties.has_key?(name) || ! Util::Data.undef?(value)
209
+ set_property(name, value)
210
+ end
211
+
212
+ #dbg(value, "result -> #{name}")
213
+ return value
214
+ end
215
+
216
+ #---
217
+
218
+ def self.normalize(data, override = nil, options = {})
219
+ config = Config.ensure(options)
220
+ results = {}
221
+
222
+ unless Util::Data.undef?(override)
223
+ case data
224
+ when String, Symbol
225
+ data = [ data, override ] if data != override
226
+ when Array
227
+ data << override unless data.include?(override)
228
+ when Hash
229
+ data = [ data, override ]
230
+ end
231
+ end
232
+
233
+ case data
234
+ when String, Symbol
235
+ results = Config.lookup(data.to_s, {}, config)
236
+
237
+ when Array
238
+ data.each do |item|
239
+ if item.is_a?(String) || item.is_a?(Symbol)
240
+ item = Config.lookup(item.to_s, {}, config)
241
+ end
242
+ unless Util::Data.undef?(item)
243
+ results = Util::Data.merge([ results, item ], config)
244
+ end
245
+ end
246
+
247
+ when Hash
248
+ results = data
249
+ end
250
+
251
+ return results
252
+ end
253
+
254
+ #-----------------------------------------------------------------------------
255
+ # Instance generators
256
+
257
+ def self.ensure(config)
258
+ case config
259
+ when Coral::Config
260
+ return config
261
+ when Hash
262
+ return Config.new(config)
263
+ end
264
+ return Config.new
265
+ end
266
+
267
+ #---
268
+
269
+ def self.init(options, contexts = [], defaults = {})
270
+ config = Coral::Config.new(Coral::Config.options(contexts), defaults)
271
+ config.import(options) unless Coral::Util::Data.empty?(options)
272
+ return config
273
+ end
274
+
275
+ #-----------------------------------------------------------------------------
276
+ # Configuration instance
277
+
278
+ def initialize(data = {}, defaults = {}, force = true)
279
+ @force = force
280
+ @options = {}
281
+
282
+ if defaults.is_a?(Hash) && ! defaults.empty?
283
+ symbolized = {}
284
+ defaults.each do |key, value|
285
+ symbolized[key.to_sym] = value
286
+ end
287
+ defaults = symbolized
288
+ end
289
+
290
+ case data
291
+ when Coral::Config
292
+ @options = Util::Data.merge([ defaults, data.options ], force)
293
+ when Hash
294
+ @options = {}
295
+ if data.is_a?(Hash)
296
+ symbolized = {}
297
+ data.each do |key, value|
298
+ symbolized[key.to_sym] = value
299
+ end
300
+ @options = Util::Data.merge([ defaults, symbolized ], force)
301
+ end
302
+ end
303
+ end
304
+
305
+ #---
306
+
307
+ def import(data, options = {})
308
+ config = Config.new(options, { :force => @force }).set(:context, :hash)
309
+
310
+ case data
311
+ when Hash
312
+ symbolized = {}
313
+ data.each do |key, value|
314
+ symbolized[key.to_sym] = value
315
+ end
316
+ @options = Util::Data.merge([ @options, symbolized ], config)
317
+
318
+ when String
319
+ data = Util::Data.lookup(data, {}, config)
320
+ Util::Data.merge([ @options, data ], config)
321
+
322
+ when Array
323
+ data.each do |item|
324
+ import(item, config)
325
+ end
326
+ end
327
+
328
+ return self
329
+ end
330
+
331
+ #---
332
+
333
+ def set(name, value)
334
+ @options[name.to_sym] = value
335
+ return self
336
+ end
337
+
338
+ def []=(name, value)
339
+ set(name, value)
340
+ end
341
+
342
+ #---
343
+
344
+ def get(name, default = nil)
345
+ name = name.to_sym
346
+ return @options[name] if @options.has_key?(name)
347
+ return default
348
+ end
349
+
350
+ def [](name, default = nil)
351
+ get(name, default)
352
+ end
353
+
354
+ #---
355
+
356
+ def options
357
+ return @options
358
+ end
359
+ end
360
+ end