coral_core 0.2.23 → 0.2.24

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.
@@ -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