corl 0.4.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.
- data/.document +5 -0
- data/.gitmodules +4 -0
- data/Gemfile +24 -0
- data/Gemfile.lock +123 -0
- data/LICENSE.txt +674 -0
- data/README.rdoc +27 -0
- data/Rakefile +78 -0
- data/VERSION +1 -0
- data/bin/corl +55 -0
- data/corl.gemspec +228 -0
- data/lib/corl/action/add.rb +69 -0
- data/lib/corl/action/bootstrap.rb +83 -0
- data/lib/corl/action/clone.rb +40 -0
- data/lib/corl/action/create.rb +55 -0
- data/lib/corl/action/exec.rb +41 -0
- data/lib/corl/action/extract.rb +49 -0
- data/lib/corl/action/image.rb +30 -0
- data/lib/corl/action/images.rb +55 -0
- data/lib/corl/action/lookup.rb +35 -0
- data/lib/corl/action/machines.rb +51 -0
- data/lib/corl/action/provision.rb +37 -0
- data/lib/corl/action/remove.rb +51 -0
- data/lib/corl/action/save.rb +53 -0
- data/lib/corl/action/seed.rb +115 -0
- data/lib/corl/action/spawn.rb +75 -0
- data/lib/corl/action/start.rb +37 -0
- data/lib/corl/action/stop.rb +30 -0
- data/lib/corl/action/update.rb +37 -0
- data/lib/corl/command/shell.rb +164 -0
- data/lib/corl/configuration/file.rb +386 -0
- data/lib/corl/event/puppet.rb +90 -0
- data/lib/corl/event/regex.rb +52 -0
- data/lib/corl/extension/puppetloader.rb +24 -0
- data/lib/corl/machine/fog.rb +310 -0
- data/lib/corl/machine/physical.rb +161 -0
- data/lib/corl/network/default.rb +26 -0
- data/lib/corl/node/aws.rb +90 -0
- data/lib/corl/node/fog.rb +198 -0
- data/lib/corl/node/google.rb +115 -0
- data/lib/corl/node/local.rb +26 -0
- data/lib/corl/node/rackspace.rb +89 -0
- data/lib/corl/project/git.rb +465 -0
- data/lib/corl/project/github.rb +108 -0
- data/lib/corl/provisioner/puppetnode/resource.rb +245 -0
- data/lib/corl/provisioner/puppetnode/resource_group.rb +205 -0
- data/lib/corl/provisioner/puppetnode.rb +407 -0
- data/lib/corl/template/environment.rb +73 -0
- data/lib/corl/template/json.rb +16 -0
- data/lib/corl/template/wrapper.rb +16 -0
- data/lib/corl/template/yaml.rb +16 -0
- data/lib/corl/translator/json.rb +27 -0
- data/lib/corl/translator/yaml.rb +27 -0
- data/lib/corl.rb +173 -0
- data/lib/corl_core/codes.rb +107 -0
- data/lib/corl_core/config/collection.rb +57 -0
- data/lib/corl_core/config/options.rb +70 -0
- data/lib/corl_core/config.rb +337 -0
- data/lib/corl_core/core.rb +59 -0
- data/lib/corl_core/corl.rb +254 -0
- data/lib/corl_core/errors.rb +84 -0
- data/lib/corl_core/facade.rb +126 -0
- data/lib/corl_core/gems.rb +72 -0
- data/lib/corl_core/manager.rb +425 -0
- data/lib/corl_core/mixin/action/commit.rb +58 -0
- data/lib/corl_core/mixin/action/keypair.rb +105 -0
- data/lib/corl_core/mixin/action/node.rb +129 -0
- data/lib/corl_core/mixin/action/project.rb +53 -0
- data/lib/corl_core/mixin/action/push.rb +52 -0
- data/lib/corl_core/mixin/config/collection.rb +53 -0
- data/lib/corl_core/mixin/config/ops.rb +53 -0
- data/lib/corl_core/mixin/config/options.rb +39 -0
- data/lib/corl_core/mixin/lookup.rb +196 -0
- data/lib/corl_core/mixin/macro/object_interface.rb +361 -0
- data/lib/corl_core/mixin/macro/plugin_interface.rb +380 -0
- data/lib/corl_core/mixin/settings.rb +46 -0
- data/lib/corl_core/mixin/sub_config.rb +148 -0
- data/lib/corl_core/mod/hash.rb +29 -0
- data/lib/corl_core/mod/hiera_backend.rb +63 -0
- data/lib/corl_core/plugin/action.rb +381 -0
- data/lib/corl_core/plugin/base.rb +374 -0
- data/lib/corl_core/plugin/command.rb +98 -0
- data/lib/corl_core/plugin/configuration.rb +177 -0
- data/lib/corl_core/plugin/event.rb +53 -0
- data/lib/corl_core/plugin/extension.rb +12 -0
- data/lib/corl_core/plugin/machine.rb +266 -0
- data/lib/corl_core/plugin/network.rb +359 -0
- data/lib/corl_core/plugin/node.rb +904 -0
- data/lib/corl_core/plugin/project.rb +927 -0
- data/lib/corl_core/plugin/provisioner.rb +51 -0
- data/lib/corl_core/plugin/template.rb +80 -0
- data/lib/corl_core/plugin/translator.rb +38 -0
- data/lib/corl_core/util/cli.rb +352 -0
- data/lib/corl_core/util/data.rb +404 -0
- data/lib/corl_core/util/disk.rb +114 -0
- data/lib/corl_core/util/git.rb +47 -0
- data/lib/corl_core/util/interface.rb +319 -0
- data/lib/corl_core/util/liquid.rb +17 -0
- data/lib/corl_core/util/package.rb +93 -0
- data/lib/corl_core/util/shell.rb +239 -0
- data/lib/corl_core/util/ssh.rb +286 -0
- data/lib/facter/corl_config_ready.rb +13 -0
- data/lib/facter/corl_exists.rb +15 -0
- data/lib/facter/corl_network.rb +17 -0
- data/lib/hiera/corl_logger.rb +18 -0
- data/lib/puppet/indirector/corl.rb +27 -0
- data/lib/puppet/indirector/data_binding/corl.rb +6 -0
- data/lib/puppet/parser/functions/config_initialized.rb +26 -0
- data/lib/puppet/parser/functions/corl_include.rb +44 -0
- data/lib/puppet/parser/functions/corl_resources.rb +58 -0
- data/lib/puppet/parser/functions/deep_merge.rb +21 -0
- data/lib/puppet/parser/functions/ensure.rb +29 -0
- data/lib/puppet/parser/functions/file_exists.rb +19 -0
- data/lib/puppet/parser/functions/global_array.rb +35 -0
- data/lib/puppet/parser/functions/global_hash.rb +35 -0
- data/lib/puppet/parser/functions/global_options.rb +23 -0
- data/lib/puppet/parser/functions/global_param.rb +43 -0
- data/lib/puppet/parser/functions/interpolate.rb +26 -0
- data/lib/puppet/parser/functions/is_false.rb +21 -0
- data/lib/puppet/parser/functions/is_true.rb +21 -0
- data/lib/puppet/parser/functions/module_array.rb +38 -0
- data/lib/puppet/parser/functions/module_hash.rb +38 -0
- data/lib/puppet/parser/functions/module_options.rb +23 -0
- data/lib/puppet/parser/functions/module_param.rb +48 -0
- data/lib/puppet/parser/functions/name.rb +21 -0
- data/lib/puppet/parser/functions/render.rb +33 -0
- data/lib/puppet/parser/functions/value.rb +21 -0
- data/locales/en.yml +232 -0
- data/spec/corl_core/interface_spec.rb +489 -0
- data/spec/corl_mock_input.rb +29 -0
- data/spec/corl_test_kernel.rb +22 -0
- data/spec/spec_helper.rb +15 -0
- metadata +406 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
|
2
|
+
module CORL
|
3
|
+
module Mixin
|
4
|
+
module Action
|
5
|
+
module Keypair
|
6
|
+
|
7
|
+
#-----------------------------------------------------------------------------
|
8
|
+
# Options
|
9
|
+
|
10
|
+
def keypair_config
|
11
|
+
register :private_key, :str, nil, 'corl.core.mixins.keypair.options.private_key' do |value|
|
12
|
+
success = true
|
13
|
+
if value
|
14
|
+
file = File.expand_path(value)
|
15
|
+
if File.exists?(file)
|
16
|
+
unless Util::SSH.generate({ :private_key => file })
|
17
|
+
warn('corl.core.mixins.keypair.errors.private_key_parse_error', { :value => file })
|
18
|
+
success = false
|
19
|
+
end
|
20
|
+
else
|
21
|
+
warn('corl.core.mixins.keypair.errors.private_key_not_found', { :value => file })
|
22
|
+
success = false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
success
|
26
|
+
end
|
27
|
+
|
28
|
+
register :require_password, :bool, false, 'corl.core.mixins.keypair.options.require_password'
|
29
|
+
|
30
|
+
register :key_type, :str, 'RSA', 'corl.core.mixins.keypair.options.key_type' do |value|
|
31
|
+
key_type_choices = [ 'RSA', 'DSA' ]
|
32
|
+
unless key_type_choices.include?(value.to_s.upcase)
|
33
|
+
warn('corl.core.mixins.keypair.errors.key_type', { :value => value, :choices => key_type_choices })
|
34
|
+
next false
|
35
|
+
end
|
36
|
+
true
|
37
|
+
end
|
38
|
+
register :key_bits, :int, 2048, 'corl.core.mixins.keypair.options.key_bits' do |value|
|
39
|
+
unless value >= 2048
|
40
|
+
warn('corl.core.mixins.keypair.errors.key_bits', { :value => value, :required => 2048 })
|
41
|
+
next false
|
42
|
+
end
|
43
|
+
true
|
44
|
+
end
|
45
|
+
register :key_comment, :str, '', 'corl.core.mixins.keypair.options.key_comment'
|
46
|
+
|
47
|
+
config_subset(keypair_ignore)
|
48
|
+
end
|
49
|
+
|
50
|
+
#---
|
51
|
+
|
52
|
+
def keypair_ignore
|
53
|
+
[ :require_password, :key_type, :key_bits, :key_comment ]
|
54
|
+
end
|
55
|
+
|
56
|
+
#---
|
57
|
+
|
58
|
+
def keypair_clean
|
59
|
+
remove(keypair_ignore)
|
60
|
+
end
|
61
|
+
|
62
|
+
#-----------------------------------------------------------------------------
|
63
|
+
# Properties
|
64
|
+
|
65
|
+
@keypair = nil
|
66
|
+
|
67
|
+
#---
|
68
|
+
|
69
|
+
def keypair=options
|
70
|
+
config = Config.ensure(options).defaults({
|
71
|
+
:type => settings[:key_type].to_s.upcase,
|
72
|
+
:bits => settings[:key_bits],
|
73
|
+
:comment => settings[:key_comment]
|
74
|
+
})
|
75
|
+
@keypair = Util::SSH.generate(options)
|
76
|
+
settings.import({ :keypair => @keypair })
|
77
|
+
end
|
78
|
+
|
79
|
+
#---
|
80
|
+
|
81
|
+
def keypair(reset = false)
|
82
|
+
if reset || ! @keypair
|
83
|
+
if settings[:private_key]
|
84
|
+
key_options = { :private_key => private_key }
|
85
|
+
else
|
86
|
+
key_options = {}
|
87
|
+
if settings[:require_password]
|
88
|
+
password = ui.password('SSH')
|
89
|
+
if password
|
90
|
+
key_options[:passphrase] = password
|
91
|
+
else
|
92
|
+
warn('corl.core.mixins.keypair.errors.no_password')
|
93
|
+
return nil
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
myself.keypair = key_options
|
98
|
+
end
|
99
|
+
@keypair
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
@@ -0,0 +1,129 @@
|
|
1
|
+
|
2
|
+
module CORL
|
3
|
+
module Mixin
|
4
|
+
module Action
|
5
|
+
module Node
|
6
|
+
|
7
|
+
#-----------------------------------------------------------------------------
|
8
|
+
# Settings
|
9
|
+
|
10
|
+
def node_config
|
11
|
+
node_plugins = Manager.connection.loaded_plugins(:node)
|
12
|
+
|
13
|
+
register :parallel, :bool, true, 'corl.core.mixins.node.options.parallel'
|
14
|
+
register :net_provider, :str, :default, 'corl.core.mixins.node.options.net_provider' do |value|
|
15
|
+
value = value.to_sym
|
16
|
+
network_plugins = Manager.connection.loaded_plugins(:network)
|
17
|
+
|
18
|
+
unless network_plugins.keys.include?(value)
|
19
|
+
warn('corl.core.mixins.node.errors.network_provider', { :value => value, :choices => network_plugins.keys.join(", ") })
|
20
|
+
next false
|
21
|
+
end
|
22
|
+
true
|
23
|
+
end
|
24
|
+
register :node_provider, :str, :local, 'corl.core.mixins.node.options.node_provider' do |value|
|
25
|
+
value = value.to_sym
|
26
|
+
|
27
|
+
unless node_plugins.keys.include?(value)
|
28
|
+
warn('corl.core.mixins.node.errors.node_provider', { :value => value, :choices => node_plugins.keys.join(", ") })
|
29
|
+
next false
|
30
|
+
end
|
31
|
+
true
|
32
|
+
end
|
33
|
+
register :nodes, :array, [], 'corl.core.mixins.node.options.nodes' do |values|
|
34
|
+
success = true
|
35
|
+
values.each do |value|
|
36
|
+
if info = Plugin::Node.translate_reference(value)
|
37
|
+
if ! node_plugins.keys.include?(info[:provider].to_sym) || info[:name].empty?
|
38
|
+
warn('corl.core.mixins.node.errors.nodes', { :value => value, :provider => info[:provider], :name => info[:name] })
|
39
|
+
success = false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
success
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
#---
|
48
|
+
|
49
|
+
def node_ignore
|
50
|
+
[ :parallel, :net_provider, :node_provider, :nodes ]
|
51
|
+
end
|
52
|
+
|
53
|
+
#-----------------------------------------------------------------------------
|
54
|
+
# Operations
|
55
|
+
|
56
|
+
def init_network(path = nil)
|
57
|
+
# Get network configuration path
|
58
|
+
if CORL.admin?
|
59
|
+
network_path = lookup(:corl_network)
|
60
|
+
Dir.mkdir(network_path) unless File.directory?(network_path)
|
61
|
+
else
|
62
|
+
network_path = ( path.nil? ? Dir.pwd : File.expand_path(path) )
|
63
|
+
end
|
64
|
+
|
65
|
+
# Load network if it exists
|
66
|
+
network_config = extended_config(:network, { :directory => network_path })
|
67
|
+
|
68
|
+
network = CORL.network(
|
69
|
+
CORL.sha1(network_config),
|
70
|
+
network_config,
|
71
|
+
settings[:net_provider]
|
72
|
+
)
|
73
|
+
network
|
74
|
+
end
|
75
|
+
|
76
|
+
#---
|
77
|
+
|
78
|
+
def node_exec
|
79
|
+
network = init_network
|
80
|
+
|
81
|
+
#
|
82
|
+
# A fork in the road...
|
83
|
+
#
|
84
|
+
if network.has_nodes? && ! settings[:nodes].empty?
|
85
|
+
# Execute action on remote nodes
|
86
|
+
success = network.batch(settings[:nodes], settings[:node_provider], settings[:parallel]) do |node|
|
87
|
+
exec_config = Config.new(settings)
|
88
|
+
exec_config.delete(:parallel)
|
89
|
+
exec_config.delete(:nodes)
|
90
|
+
exec_config.delete(:node_provider)
|
91
|
+
|
92
|
+
result = node.action(plugin_provider, exec_config) do |op, data|
|
93
|
+
ui_group(node.plugin_name) do
|
94
|
+
case op
|
95
|
+
when :config # Modify seed execution configurations
|
96
|
+
render("Starting remote execution of #{plugin_provider} action")
|
97
|
+
when :process # Process final result
|
98
|
+
render("Successfully finished remote execution of #{plugin_provider} action")
|
99
|
+
end
|
100
|
+
data = execute_remote(node, network, op, data)
|
101
|
+
end
|
102
|
+
data
|
103
|
+
end
|
104
|
+
result.status == code.success
|
105
|
+
end
|
106
|
+
myself.status = code.batch_error unless success
|
107
|
+
else
|
108
|
+
# Execute statement locally
|
109
|
+
node = network.local_node
|
110
|
+
|
111
|
+
if validate(node, network)
|
112
|
+
yield(node, network) if block_given?
|
113
|
+
else
|
114
|
+
puts "\n" + I18n.t('corl.core.exec.help.usage') + ': ' + help + "\n" unless quiet?
|
115
|
+
myself.status = code.validation_failed
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
#---
|
121
|
+
|
122
|
+
def execute_remote(node, network, op, data)
|
123
|
+
# Implement in sub classes if needed
|
124
|
+
data
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
module CORL
|
3
|
+
module Mixin
|
4
|
+
module Action
|
5
|
+
module Project
|
6
|
+
|
7
|
+
#-----------------------------------------------------------------------------
|
8
|
+
# Options
|
9
|
+
|
10
|
+
def project_options(parser, ref_override = false, rev_override = false)
|
11
|
+
parser.option_str(:project_provider, 'git',
|
12
|
+
'--proj-provider PROVIDER',
|
13
|
+
'corl.core.mixins.project.options.provider'
|
14
|
+
)
|
15
|
+
if ref_override
|
16
|
+
parser.option_str(:reference, nil,
|
17
|
+
'--reference PROJECT_REF',
|
18
|
+
'corl.core.mixins.project.options.reference'
|
19
|
+
)
|
20
|
+
end
|
21
|
+
if rev_override
|
22
|
+
parser.option_str(:revision, nil,
|
23
|
+
'--revision PROJECT_REV',
|
24
|
+
'corl.core.mixins.project.options.revision'
|
25
|
+
)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
#-----------------------------------------------------------------------------
|
30
|
+
# Operations
|
31
|
+
|
32
|
+
def project_load(root_dir, update = false)
|
33
|
+
|
34
|
+
# 1. Set a default project provider (reference can override)
|
35
|
+
# 2. Get project from root directory
|
36
|
+
# 3. Initialize project if not yet initialized
|
37
|
+
# 4. Set remote if needed
|
38
|
+
# 5. Checkout revision if needed
|
39
|
+
# 6. Pull down updates if requested
|
40
|
+
|
41
|
+
return CORL.project(extended_config(:project, {
|
42
|
+
:provider => settings[:project_provider],
|
43
|
+
:directory => root_dir,
|
44
|
+
:url => settings[:reference],
|
45
|
+
:revision => settings[:revision],
|
46
|
+
:pull => update
|
47
|
+
}))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
|
2
|
+
module CORL
|
3
|
+
module Mixin
|
4
|
+
module Action
|
5
|
+
module Push
|
6
|
+
|
7
|
+
#-----------------------------------------------------------------------------
|
8
|
+
# Options
|
9
|
+
|
10
|
+
def push_options(parser, optional = true)
|
11
|
+
if optional
|
12
|
+
parser.option_bool(:push, false,
|
13
|
+
'--push',
|
14
|
+
'corl.core.mixins.push.options.push'
|
15
|
+
)
|
16
|
+
else
|
17
|
+
parser.options[:push] = true
|
18
|
+
end
|
19
|
+
|
20
|
+
parser.option_bool(:propogate, false,
|
21
|
+
'--propogate',
|
22
|
+
'corl.core.mixins.push.options.propogate'
|
23
|
+
)
|
24
|
+
parser.option_str(:remote, :edit,
|
25
|
+
'--remote PROJECT_REMOTE',
|
26
|
+
'corl.core.mixins.push.options.remote'
|
27
|
+
)
|
28
|
+
parser.option_str(:revision, :master,
|
29
|
+
'--revision PROJECT_REVISION',
|
30
|
+
'corl.core.mixins.push.options.revision'
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
#-----------------------------------------------------------------------------
|
35
|
+
# Operations
|
36
|
+
|
37
|
+
def push(project, remote = :edit)
|
38
|
+
success = true
|
39
|
+
|
40
|
+
if project && settings[:push]
|
41
|
+
success = project.push(settings[:remote], extended_config(:push, {
|
42
|
+
:revision => settings[:revision],
|
43
|
+
:propogate => settings[:propogate]
|
44
|
+
}))
|
45
|
+
end
|
46
|
+
success
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
# Should be included via extend
|
3
|
+
#
|
4
|
+
# extend Mixin::ConfigCollection
|
5
|
+
#
|
6
|
+
|
7
|
+
module CORL
|
8
|
+
module Mixin
|
9
|
+
module ConfigCollection
|
10
|
+
|
11
|
+
#-----------------------------------------------------------------------------
|
12
|
+
# Configuration collection interface
|
13
|
+
|
14
|
+
def all_properties
|
15
|
+
return Config::Collection.all
|
16
|
+
end
|
17
|
+
|
18
|
+
#---
|
19
|
+
|
20
|
+
def get_property(name)
|
21
|
+
return Config::Collection.get(name)
|
22
|
+
end
|
23
|
+
|
24
|
+
#---
|
25
|
+
|
26
|
+
def set_property(name, value)
|
27
|
+
Config::Collection.set(name, value)
|
28
|
+
return self
|
29
|
+
end
|
30
|
+
|
31
|
+
#---
|
32
|
+
|
33
|
+
def delete_property(name)
|
34
|
+
Config::Collection.delete(name)
|
35
|
+
return self
|
36
|
+
end
|
37
|
+
|
38
|
+
#---
|
39
|
+
|
40
|
+
def clear_properties
|
41
|
+
Config::Collection.clear
|
42
|
+
return self
|
43
|
+
end
|
44
|
+
|
45
|
+
#---
|
46
|
+
|
47
|
+
def save_properties
|
48
|
+
Config::Collection.save
|
49
|
+
return self
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
|
2
|
+
# Should be included via extend
|
3
|
+
#
|
4
|
+
# extend Mixin::ConfigOps
|
5
|
+
#
|
6
|
+
|
7
|
+
module CORL
|
8
|
+
module Mixin
|
9
|
+
module ConfigOps
|
10
|
+
|
11
|
+
#-----------------------------------------------------------------------------
|
12
|
+
# Parsing
|
13
|
+
|
14
|
+
def parse(statement, options = {})
|
15
|
+
config = Config.ensure(options)
|
16
|
+
|
17
|
+
# statement = common->php::apache::memory_limit = 32M
|
18
|
+
# statement = identity -> test -> users::user[admin][shell]
|
19
|
+
# statement = nodes->development->dev.loc->facts[server_location]
|
20
|
+
# statement = corl->nodes[vagrant][dev.loc][vm][private_network]=172.5.5.10
|
21
|
+
# statement = corl->settings[debug][puppet][options] = ["--debug"]
|
22
|
+
|
23
|
+
reference, new_value = statement.split(/\=/)
|
24
|
+
new_value = new_value.join('=').strip if new_value && new_value.is_a?(Array)
|
25
|
+
|
26
|
+
config_elements = reference.gsub(/\s+/, '').split(/\-\>/)
|
27
|
+
property = config_elements.pop
|
28
|
+
config_file = config_elements.pop
|
29
|
+
|
30
|
+
if config_directory = config.get(:directory, nil)
|
31
|
+
config_path = File.join(project.directory, config_directory, *config_elements)
|
32
|
+
else
|
33
|
+
config_path = File.join(project.directory, *config_elements)
|
34
|
+
end
|
35
|
+
|
36
|
+
return nil unless property && config_file
|
37
|
+
|
38
|
+
config_file = "#{config_file}." + config.get(:ext, 'json')
|
39
|
+
property = property.gsub(/\]$/, '').split(/\]?\[/)
|
40
|
+
data = open(config_path, config_file, config)
|
41
|
+
|
42
|
+
return {
|
43
|
+
:path => config_path,
|
44
|
+
:file => config_file,
|
45
|
+
:property => property,
|
46
|
+
:conf => data,
|
47
|
+
:current_value => (data ? data.get(property) : nil),
|
48
|
+
:new_value => eval(new_value)
|
49
|
+
}
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
|
2
|
+
# Should be included via extend
|
3
|
+
#
|
4
|
+
# extend Mixin::ConfigOptions
|
5
|
+
#
|
6
|
+
|
7
|
+
module CORL
|
8
|
+
module Mixin
|
9
|
+
module ConfigOptions
|
10
|
+
|
11
|
+
#-----------------------------------------------------------------------------
|
12
|
+
# Configuration options interface
|
13
|
+
|
14
|
+
def contexts(contexts = [], hierarchy = [])
|
15
|
+
return Config::Options.contexts(contexts, hierarchy)
|
16
|
+
end
|
17
|
+
|
18
|
+
#---
|
19
|
+
|
20
|
+
def get_options(contexts, force = true)
|
21
|
+
return Config::Options.get(contexts, force)
|
22
|
+
end
|
23
|
+
|
24
|
+
#---
|
25
|
+
|
26
|
+
def set_options(contexts, options, force = true)
|
27
|
+
Config::Options.set(contexts, options, force)
|
28
|
+
return self
|
29
|
+
end
|
30
|
+
|
31
|
+
#---
|
32
|
+
|
33
|
+
def clear_options(contexts)
|
34
|
+
Config::Options.clear(contexts)
|
35
|
+
return self
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,196 @@
|
|
1
|
+
|
2
|
+
module CORL
|
3
|
+
module Mixin
|
4
|
+
module Lookup
|
5
|
+
|
6
|
+
#-----------------------------------------------------------------------------
|
7
|
+
# Facter lookup
|
8
|
+
|
9
|
+
def facts
|
10
|
+
fact_map = {}
|
11
|
+
Facter.list.each do |name|
|
12
|
+
fact_map[name] = Facter.value(name)
|
13
|
+
end
|
14
|
+
fact_map
|
15
|
+
end
|
16
|
+
|
17
|
+
def fact(name)
|
18
|
+
Facter.value(name)
|
19
|
+
end
|
20
|
+
|
21
|
+
#-----------------------------------------------------------------------------
|
22
|
+
# Hiera configuration
|
23
|
+
|
24
|
+
@@hiera = nil
|
25
|
+
|
26
|
+
#---
|
27
|
+
|
28
|
+
def hiera_config
|
29
|
+
config_file = CORL.value(:hiera_config_file, nil)
|
30
|
+
config = {}
|
31
|
+
|
32
|
+
if config_file && File.exist?(config_file)
|
33
|
+
config = Hiera::Config.load(config_file)
|
34
|
+
end
|
35
|
+
config[:logger] = :corl
|
36
|
+
|
37
|
+
results = CORL.config(:hiera_config, { :config => config })
|
38
|
+
results[:config]
|
39
|
+
end
|
40
|
+
|
41
|
+
#---
|
42
|
+
|
43
|
+
def hiera
|
44
|
+
@@hiera = Hiera.new(:config => hiera_config) if @@hiera.nil?
|
45
|
+
@@hiera
|
46
|
+
end
|
47
|
+
|
48
|
+
#-----------------------------------------------------------------------------
|
49
|
+
# Configuration lookup interface
|
50
|
+
|
51
|
+
def config_initialized?
|
52
|
+
ready = false
|
53
|
+
if CORL.admin? && hiera && network_path = fact(:corl_network)
|
54
|
+
ready = File.directory?(network_path) && File.directory?(File.join(network_path, 'config')) ? true : false
|
55
|
+
end
|
56
|
+
ready
|
57
|
+
end
|
58
|
+
|
59
|
+
#---
|
60
|
+
|
61
|
+
def lookup(properties, default = nil, options = {})
|
62
|
+
config = Config.ensure(options)
|
63
|
+
value = nil
|
64
|
+
|
65
|
+
provisioner = config.get(:provisioner, nil)
|
66
|
+
|
67
|
+
hiera_scope = config.get(:hiera_scope, {})
|
68
|
+
override = config.get(:override, nil)
|
69
|
+
context = config.get(:context, :priority)
|
70
|
+
|
71
|
+
|
72
|
+
return_property = config.get(:return_property, false)
|
73
|
+
|
74
|
+
unless properties.is_a?(Array)
|
75
|
+
properties = [ properties ].flatten
|
76
|
+
end
|
77
|
+
|
78
|
+
first_property = nil
|
79
|
+
properties.each do |property|
|
80
|
+
property = property.to_sym
|
81
|
+
first_property = property unless first_property
|
82
|
+
|
83
|
+
# Try to load facts first (these can not be overridden)
|
84
|
+
unless value = fact(property)
|
85
|
+
if CORL.admin?
|
86
|
+
if config_initialized?
|
87
|
+
# Try to find in Hiera data store (these might be security sensitive)
|
88
|
+
unless hiera_scope.respond_to?('[]')
|
89
|
+
hiera_scope = Hiera::Scope.new(hiera_scope)
|
90
|
+
end
|
91
|
+
value = hiera.lookup(property, nil, hiera_scope, override, context)
|
92
|
+
end
|
93
|
+
|
94
|
+
if provisioner && Util::Data.undef?(value)
|
95
|
+
# Search the provisioner scope (only admins can provision a machine)
|
96
|
+
value = CORL.provisioner(provisioner).lookup(property, default, config)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
value = default if Util::Data.undef?(value) # Resort to default
|
102
|
+
value = Util::Data.value(value)
|
103
|
+
|
104
|
+
if ! Config.get_property(first_property) || ! Util::Data.undef?(value)
|
105
|
+
Config.set_property(first_property, value)
|
106
|
+
end
|
107
|
+
return value, first_property if return_property
|
108
|
+
value
|
109
|
+
end
|
110
|
+
|
111
|
+
#---
|
112
|
+
|
113
|
+
def lookup_array(properties, default = [], options = {})
|
114
|
+
config = Config.ensure(options)
|
115
|
+
value, property = lookup(properties, nil, config.import({ :return_property => true }))
|
116
|
+
|
117
|
+
if Util::Data.undef?(value)
|
118
|
+
value = default
|
119
|
+
|
120
|
+
elsif ! Util::Data.empty?(default)
|
121
|
+
if config.get(:merge, false)
|
122
|
+
value = Util::Data.merge([default, value], config)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
unless value.is_a?(Array)
|
127
|
+
value = ( Util::Data.empty?(value) ? [] : [ value ] )
|
128
|
+
end
|
129
|
+
|
130
|
+
Config.set_property(property, value)
|
131
|
+
value
|
132
|
+
end
|
133
|
+
|
134
|
+
#---
|
135
|
+
|
136
|
+
def lookup_hash(properties, default = {}, options = {})
|
137
|
+
config = Config.ensure(options)
|
138
|
+
value, property = lookup(properties, nil, config.import({ :return_property => true }))
|
139
|
+
|
140
|
+
if Util::Data.undef?(value)
|
141
|
+
value = default
|
142
|
+
|
143
|
+
elsif ! Util::Data.empty?(default)
|
144
|
+
if config.get(:merge, false)
|
145
|
+
value = Util::Data.merge([default, value], config)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
unless value.is_a?(Hash)
|
150
|
+
value = ( Util::Data.empty?(value) ? {} : { :value => value } )
|
151
|
+
end
|
152
|
+
|
153
|
+
Config.set_property(property, value)
|
154
|
+
value
|
155
|
+
end
|
156
|
+
|
157
|
+
#---
|
158
|
+
|
159
|
+
def normalize(data, override = nil, options = {})
|
160
|
+
config = Config.ensure(options)
|
161
|
+
results = {}
|
162
|
+
|
163
|
+
unless Util::Data.undef?(override)
|
164
|
+
case data
|
165
|
+
when String, Symbol
|
166
|
+
data = [ data, override ] if data != override
|
167
|
+
when Array
|
168
|
+
data << override unless data.include?(override)
|
169
|
+
when Hash
|
170
|
+
data = [ data, override ]
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
case data
|
175
|
+
when String, Symbol
|
176
|
+
results = lookup(data.to_s, {}, config)
|
177
|
+
|
178
|
+
when Array
|
179
|
+
data.each do |item|
|
180
|
+
if item.is_a?(String) || item.is_a?(Symbol)
|
181
|
+
item = lookup(item.to_s, {}, config)
|
182
|
+
end
|
183
|
+
unless Util::Data.undef?(item)
|
184
|
+
results = Util::Data.merge([ results, item ], config)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
when Hash
|
189
|
+
results = data
|
190
|
+
end
|
191
|
+
|
192
|
+
results
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|