dop_common 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +23 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/CHANGELOG.md +176 -0
- data/Gemfile +11 -0
- data/LICENSE.txt +177 -0
- data/README.md +48 -0
- data/Rakefile +49 -0
- data/Vagrantfile +25 -0
- data/bin/dop-puppet-autosign +56 -0
- data/doc/examples/example_deploment_plan_v0.0.1.yaml +302 -0
- data/doc/plan_format_v0.0.1.md +919 -0
- data/doc/plan_format_v0.0.2_snippets.md +56 -0
- data/dop_common.gemspec +44 -0
- data/lib/dop_common/affinity_group.rb +57 -0
- data/lib/dop_common/cli/global_options.rb +37 -0
- data/lib/dop_common/cli/log.rb +51 -0
- data/lib/dop_common/cli/node_selection.rb +62 -0
- data/lib/dop_common/command.rb +125 -0
- data/lib/dop_common/config/helper.rb +39 -0
- data/lib/dop_common/config.rb +66 -0
- data/lib/dop_common/configuration.rb +37 -0
- data/lib/dop_common/credential.rb +152 -0
- data/lib/dop_common/data_disk.rb +62 -0
- data/lib/dop_common/dns.rb +55 -0
- data/lib/dop_common/hash_parser.rb +241 -0
- data/lib/dop_common/hooks.rb +81 -0
- data/lib/dop_common/infrastructure.rb +160 -0
- data/lib/dop_common/infrastructure_properties.rb +185 -0
- data/lib/dop_common/interface.rb +113 -0
- data/lib/dop_common/log.rb +78 -0
- data/lib/dop_common/network.rb +85 -0
- data/lib/dop_common/node/config.rb +159 -0
- data/lib/dop_common/node.rb +442 -0
- data/lib/dop_common/node_filter.rb +74 -0
- data/lib/dop_common/plan.rb +188 -0
- data/lib/dop_common/plan_cache.rb +83 -0
- data/lib/dop_common/plan_store.rb +263 -0
- data/lib/dop_common/pre_processor.rb +73 -0
- data/lib/dop_common/run_options.rb +56 -0
- data/lib/dop_common/signal_handler.rb +58 -0
- data/lib/dop_common/state_store.rb +95 -0
- data/lib/dop_common/step.rb +200 -0
- data/lib/dop_common/step_set.rb +41 -0
- data/lib/dop_common/thread_context_logger.rb +77 -0
- data/lib/dop_common/utils.rb +106 -0
- data/lib/dop_common/validator.rb +53 -0
- data/lib/dop_common/version.rb +3 -0
- data/lib/dop_common.rb +32 -0
- data/lib/hiera/backend/dop_backend.rb +94 -0
- data/lib/hiera/dop_logger.rb +20 -0
- data/spec/data/fake_hook_file_invalid +1 -0
- data/spec/data/fake_hook_file_valid +5 -0
- data/spec/data/fake_keyfile +1 -0
- data/spec/dop-puppet-autosign_spec_disable.rb +33 -0
- data/spec/dop_common/affinity_group_spec.rb +41 -0
- data/spec/dop_common/command_spec.rb +83 -0
- data/spec/dop_common/credential_spec.rb +73 -0
- data/spec/dop_common/data_disk_spec.rb +165 -0
- data/spec/dop_common/dns_spec.rb +33 -0
- data/spec/dop_common/hash_parser_spec.rb +181 -0
- data/spec/dop_common/hooks_spec.rb +33 -0
- data/spec/dop_common/infrastructure_properties_spec.rb +224 -0
- data/spec/dop_common/infrastructure_spec.rb +77 -0
- data/spec/dop_common/interface_spec.rb +192 -0
- data/spec/dop_common/network_spec.rb +92 -0
- data/spec/dop_common/node_filter_spec.rb +70 -0
- data/spec/dop_common/node_spec.rb +623 -0
- data/spec/dop_common/plan_cache_spec.rb +46 -0
- data/spec/dop_common/plan_spec.rb +136 -0
- data/spec/dop_common/plan_store_spec.rb +194 -0
- data/spec/dop_common/pre_processor_spec.rb +27 -0
- data/spec/dop_common/run_options_spec.rb +65 -0
- data/spec/dop_common/signal_handler_spec.rb +31 -0
- data/spec/dop_common/step_set_spec.rb +21 -0
- data/spec/dop_common/step_spec.rb +175 -0
- data/spec/dop_common/utils_spec.rb +27 -0
- data/spec/dop_common/validator_spec.rb +47 -0
- data/spec/example_plans_spec.rb +16 -0
- data/spec/fixtures/example_ssh_key +27 -0
- data/spec/fixtures/example_ssh_key.pub +1 -0
- data/spec/fixtures/incl/root_part.yaml +1 -0
- data/spec/fixtures/incl/some_list.yaml +2 -0
- data/spec/fixtures/other_plan_same_nodes.yaml +19 -0
- data/spec/fixtures/simple_include.yaml +6 -0
- data/spec/fixtures/simple_include_with_errors.yaml +4 -0
- data/spec/fixtures/simple_plan.yaml +19 -0
- data/spec/fixtures/simple_plan_invalid.yaml +18 -0
- data/spec/fixtures/simple_plan_modified.yaml +21 -0
- data/spec/spec_helper.rb +106 -0
- metadata +381 -0
@@ -0,0 +1,56 @@
|
|
1
|
+
|
2
|
+
If you want to create a lot of nodes of the same kind it can be quite repetitive to write them all down individually. Instead you can create multiple nodes in one step:
|
3
|
+
|
4
|
+
```yaml
|
5
|
+
nodes:
|
6
|
+
mysql01.example.com:
|
7
|
+
…
|
8
|
+
web{i}.example.com:
|
9
|
+
range: 1..4
|
10
|
+
digits: 2
|
11
|
+
…
|
12
|
+
```
|
13
|
+
|
14
|
+
This will create a number of nodes in the given range. The string “{i}” will be replaced with the amount of digits given. The above example will create the following nodes:
|
15
|
+
|
16
|
+
- mysql01.example.com
|
17
|
+
- web01.example.com
|
18
|
+
- web02.example.com
|
19
|
+
- web03.example.com
|
20
|
+
- web04.example.com
|
21
|
+
|
22
|
+
|
23
|
+
|
24
|
+
----
|
25
|
+
|
26
|
+
### Nodes
|
27
|
+
|
28
|
+
the nodes configuration hash assigns variables to an individual node or to a selected set of nodes. Here are some examples:
|
29
|
+
|
30
|
+
```yaml
|
31
|
+
configuration:
|
32
|
+
nodes:
|
33
|
+
mysql01.example.com:
|
34
|
+
role: mysql
|
35
|
+
my_var: my_value
|
36
|
+
'/web\d+\.example\.com/':
|
37
|
+
role: httpd_basic
|
38
|
+
web04.example.com:
|
39
|
+
role: httpd_special
|
40
|
+
'/haproxy\d+\.example\.com/':
|
41
|
+
role: haproxy
|
42
|
+
'/.example.com/'
|
43
|
+
my_other_var: my_other_value
|
44
|
+
```
|
45
|
+
|
46
|
+
You can assign different variables to the same node with different regular expressions, but you can not overwrite the values this way. dop_common will throw an error if two regular expression who match the same node set the same variable. On the other hand you can overwrite a value if you set it with a specific fqdn entry.
|
47
|
+
|
48
|
+
The only relevant setting here for DOP is the role variable. The name of the role variable can be configured but defaults to 'role'. If hiera is configured and activated, then dop_common will take the role specified in hiera if found. The hierarchy for the role resolution is as follows:
|
49
|
+
|
50
|
+
1. Hiera
|
51
|
+
2. fqdn match in nodes configuration in Plan file
|
52
|
+
3. Regular expression match in nodes configuration in Plan file
|
53
|
+
4. Default
|
54
|
+
|
55
|
+
A node always needs a role. If the parser finds no value for one of the specified nodes in the plan file and if no default is set, the dop_common will throw an error.
|
56
|
+
|
data/dop_common.gemspec
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'dop_common/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "dop_common"
|
8
|
+
spec.version = DopCommon::VERSION
|
9
|
+
spec.authors = ["Andreas Zuber", "Pavol Dilung"]
|
10
|
+
spec.email = ["zuber@puzzle.ch", "pavol.dilung@swisscom.com"]
|
11
|
+
spec.description = <<-EOF
|
12
|
+
This gem is part of the Deployment and Orchestration for Puppet
|
13
|
+
or DOP for short. dop_common is a library for the parsing and
|
14
|
+
validation of DOP plan files.
|
15
|
+
EOF
|
16
|
+
spec.summary = %q{DOP plan file parser and validation library}
|
17
|
+
spec.homepage = ""
|
18
|
+
spec.license = 'Apache-2.0'
|
19
|
+
|
20
|
+
spec.files = `git ls-files`.split($/)
|
21
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
22
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
23
|
+
spec.require_paths = ["lib"]
|
24
|
+
|
25
|
+
spec.required_ruby_version = '>= 1.8.7'
|
26
|
+
|
27
|
+
spec.add_dependency 'hashdiff', '~> 0.3', '>= 0.3.1'
|
28
|
+
spec.add_dependency 'lockfile', '~> 2'
|
29
|
+
spec.add_dependency 'rb-inotify', '~> 0.9'
|
30
|
+
spec.add_dependency 'hiera', '~> 3'
|
31
|
+
|
32
|
+
spec.add_development_dependency "bundler"
|
33
|
+
spec.add_development_dependency "rake"
|
34
|
+
spec.add_development_dependency "rspec"
|
35
|
+
spec.add_development_dependency "rspec-legacy_formatters"
|
36
|
+
spec.add_development_dependency "rspec-mocks"
|
37
|
+
spec.add_development_dependency "rspec-collection_matchers"
|
38
|
+
# no ruby 1.8.7 support
|
39
|
+
#spec.add_development_dependency "rspec-command"
|
40
|
+
spec.add_development_dependency "simplecov"
|
41
|
+
spec.add_development_dependency "pry"
|
42
|
+
spec.add_development_dependency "pry-doc"
|
43
|
+
spec.add_development_dependency "pry-byebug"
|
44
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#
|
2
|
+
# DOP Common infrastructure hash parser
|
3
|
+
#
|
4
|
+
|
5
|
+
module DopCommon
|
6
|
+
class AffinityGroup
|
7
|
+
include Validator
|
8
|
+
include HashParser
|
9
|
+
|
10
|
+
attr_reader :name
|
11
|
+
|
12
|
+
def initialize(name, hash)
|
13
|
+
@name = name
|
14
|
+
@hash = symbolize_keys(hash)
|
15
|
+
end
|
16
|
+
|
17
|
+
def validate
|
18
|
+
log_validation_method(:positive_valid?)
|
19
|
+
log_validation_method(:enforce_valid?)
|
20
|
+
log_validation_method(:cluster_valid?)
|
21
|
+
end
|
22
|
+
|
23
|
+
def positive
|
24
|
+
@positive ||= positive_valid? ? @hash[:positive] : nil
|
25
|
+
end
|
26
|
+
alias_method :positive?, :positive
|
27
|
+
|
28
|
+
def enforce
|
29
|
+
@enforce ||= enforce_valid? ? @hash[:enforce] : nil
|
30
|
+
end
|
31
|
+
alias_method :enforced?, :enforce
|
32
|
+
|
33
|
+
def cluster
|
34
|
+
@ip_pool ||= cluster_valid? ? @hash[:cluster] : nil
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def positive_valid?
|
40
|
+
raise PlanParsingError, "Affinity group #{@name}: positive flag must be one of 'true' or 'false'" unless
|
41
|
+
@hash[:positive].kind_of?(TrueClass) || @hash[:positive].kind_of?(FalseClass)
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
def enforce_valid?
|
46
|
+
raise PlanParsingError, "Affinity group #{@name}: enforce flag must be one of 'true' or 'false'" unless
|
47
|
+
@hash[:enforce].kind_of?(TrueClass) || @hash[:enforce].kind_of?(FalseClass)
|
48
|
+
true
|
49
|
+
end
|
50
|
+
|
51
|
+
def cluster_valid?
|
52
|
+
raise PlanParsingError, "Affinity group #{@name}: cluster must be a string" unless
|
53
|
+
@hash[:cluster].kind_of?(String)
|
54
|
+
true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# DOPi CLI gloable options
|
3
|
+
#
|
4
|
+
|
5
|
+
module DopCommon
|
6
|
+
module Cli
|
7
|
+
|
8
|
+
def self.global_options(base)
|
9
|
+
base.class_eval do
|
10
|
+
desc 'Verbosity of the command line tool'
|
11
|
+
default_value 'INFO'
|
12
|
+
arg_name 'Verbosity'
|
13
|
+
flag [:verbosity, :v]
|
14
|
+
|
15
|
+
desc 'Show stacktrace on crash'
|
16
|
+
default_value DopCommon.config.trace
|
17
|
+
switch [:trace, :t]
|
18
|
+
|
19
|
+
desc 'Specify the directory where the plans and their state will be stored'
|
20
|
+
default_value DopCommon.config.plan_store_dir
|
21
|
+
arg_name 'DIR'
|
22
|
+
flag [:plan_store_dir, :s]
|
23
|
+
|
24
|
+
desc 'Directory for the log files'
|
25
|
+
default_value DopCommon.config.log_dir
|
26
|
+
arg_name 'LOGDIR'
|
27
|
+
flag [:log_dir]
|
28
|
+
|
29
|
+
desc 'Log level for the logfiles'
|
30
|
+
default_value DopCommon.config.log_level
|
31
|
+
arg_name 'LOGLEVEL'
|
32
|
+
flag [:log_level, :l]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'dop_common/log'
|
2
|
+
|
3
|
+
module DopCommon
|
4
|
+
module Cli
|
5
|
+
|
6
|
+
# Default quiet log formatter for the CLI
|
7
|
+
class DefaultFormatter < Logger::Formatter
|
8
|
+
def call(severity, time, progname, msg)
|
9
|
+
"#{msg2str(msg)}\n"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# This adds code line context to the log output
|
14
|
+
class TraceFormatter < Logger::Formatter
|
15
|
+
def call(severity, datetime, progname, msg)
|
16
|
+
timestamp = datetime.strftime("%Y-%m-%d %H:%M:%S.%L")
|
17
|
+
hostname = ::Socket.gethostname.split('.').first
|
18
|
+
file, line, method = caller[11].sub(/.*\/([0-9a-zA-Z_\-.]+):(\d+):.+`(.+)'/, "\\1-\\2-\\3").gsub(":", " ").split("-")
|
19
|
+
pid = "[#{::Process.pid}]".ljust(7)
|
20
|
+
"#{timestamp} #{hostname} #{progname}#{pid} #{severity.ljust(5)} #{file}:#{line}:#{method}: #{msg2str(msg)}\n"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.initialize_logger(name, log_level, verbosity, trace)
|
25
|
+
# create a dummy logger and use the lowest log level configured
|
26
|
+
DopCommon.logger = Logger.new('/dev/null')
|
27
|
+
file_log_level = ::Logger.const_get(log_level.upcase)
|
28
|
+
cli_log_level = ::Logger.const_get(verbosity.upcase)
|
29
|
+
min_log_level = file_log_level < cli_log_level ? file_log_level : cli_log_level
|
30
|
+
DopCommon.log.level = min_log_level
|
31
|
+
|
32
|
+
# create the cli console logger
|
33
|
+
logger = Logger.new(STDOUT)
|
34
|
+
logger.level = cli_log_level
|
35
|
+
if trace
|
36
|
+
logger.formatter = DopCommon::Cli::TraceFormatter.new
|
37
|
+
else
|
38
|
+
logger.formatter = DopCommon::Cli::DefaultFormatter.new
|
39
|
+
end
|
40
|
+
DopCommon.add_log_junction(logger)
|
41
|
+
|
42
|
+
# create the cli file logger
|
43
|
+
FileUtils.mkdir_p(DopCommon.config.log_dir)
|
44
|
+
log_file = File.join(DopCommon.config.log_dir, name)
|
45
|
+
logger = Logger.new(log_file , 10, 1024000)
|
46
|
+
logger.level = ::Logger.const_get(DopCommon.config.log_level.upcase)
|
47
|
+
DopCommon.add_log_junction(logger)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module DopCommon
|
4
|
+
module Cli
|
5
|
+
|
6
|
+
def node_select_options(command)
|
7
|
+
command.desc 'Run plans for this nodes only'
|
8
|
+
command.default_value ""
|
9
|
+
command.arg_name 'node01.example.com,node02.example.com,/example\.com$/'
|
10
|
+
command.flag [:nodes]
|
11
|
+
|
12
|
+
command.desc 'Run plans for this roles only'
|
13
|
+
command.default_value ""
|
14
|
+
command.arg_name 'role01,role01,/^rolepattern/'
|
15
|
+
command.flag [:roles]
|
16
|
+
|
17
|
+
command.desc 'Exclude this nodes from the run'
|
18
|
+
command.default_value ""
|
19
|
+
command.arg_name 'node01.example.com,node02.example.com,/example\.com$/'
|
20
|
+
command.flag [:exclude_nodes]
|
21
|
+
|
22
|
+
command.desc 'Exclude this roles from the run'
|
23
|
+
command.default_value ""
|
24
|
+
command.arg_name 'role01,role01,/^rolepattern/'
|
25
|
+
command.flag [:exclude_roles]
|
26
|
+
|
27
|
+
command.desc 'Run plans for this nodes with this config only (You have to specify a JSON hash here)'
|
28
|
+
command.default_value "{}"
|
29
|
+
command.arg_name '\'{"var1": ["val1", "/val2/"], "var2": "val2"}\''
|
30
|
+
command.flag [:nodes_by_config]
|
31
|
+
|
32
|
+
command.desc 'Exclude nodes with this config from the run (You have to specify a JSON hash here)'
|
33
|
+
command.default_value "{}"
|
34
|
+
command.arg_name '\'{"var1": ["val1", "/val2/"], "var2": "val2"}\''
|
35
|
+
command.flag [:exclude_nodes_by_config]
|
36
|
+
end
|
37
|
+
module_function :node_select_options
|
38
|
+
|
39
|
+
def parse_node_select_options(options)
|
40
|
+
pattern_hash = {}
|
41
|
+
[:nodes, :roles, :exclude_nodes, :exclude_roles].each do |key|
|
42
|
+
hash = { key => options[key].split(',')}
|
43
|
+
pattern_hash[key] = DopCommon::HashParser.pattern_list_valid?(hash, key) ?
|
44
|
+
DopCommon::HashParser.parse_pattern_list(hash, key) : []
|
45
|
+
end
|
46
|
+
[:nodes_by_config, :exclude_nodes_by_config].each do |key|
|
47
|
+
hash = {key => JSON.parse(options[key])}
|
48
|
+
pattern_hash[key] = DopCommon::HashParser.hash_of_pattern_lists_valid?(hash, key) ?
|
49
|
+
DopCommon::HashParser.parse_hash_of_pattern_lists(hash, key) : {}
|
50
|
+
end
|
51
|
+
# Select all nodes if nothing is included
|
52
|
+
if [:nodes, :roles, :nodes_by_config].all?{|k| pattern_hash[k].empty?}
|
53
|
+
pattern_hash[:nodes] = :all
|
54
|
+
end
|
55
|
+
OpenStruct.new(pattern_hash)
|
56
|
+
rescue DopCommon::PlanParsingError => e
|
57
|
+
raise StandardError, "Error while parsing the node selection options: #{e.message}"
|
58
|
+
end
|
59
|
+
module_function :parse_node_select_options
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
#
|
2
|
+
# DOP Common command hash parser
|
3
|
+
#
|
4
|
+
|
5
|
+
module DopCommon
|
6
|
+
class Command
|
7
|
+
include Validator
|
8
|
+
include HashParser
|
9
|
+
|
10
|
+
attr_reader :hash
|
11
|
+
|
12
|
+
def initialize(hash)
|
13
|
+
@hash = symbolize_keys(hash)
|
14
|
+
@defaults = {
|
15
|
+
:plugin_timeout => 300,
|
16
|
+
:verify_after_run => false,
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate
|
21
|
+
log_validation_method('plugin_valid?')
|
22
|
+
log_validation_method('verify_after_run_valid?')
|
23
|
+
if @hash.kind_of?(Hash)
|
24
|
+
log_validation_method('plugin_timeout_valid?')
|
25
|
+
log_validation_method('verify_commands_valid?')
|
26
|
+
r_plugin = @plugin || 'unknown' # name may not be set because of a previous error
|
27
|
+
try_validate_obj("Command #{r_plugin}: Can't validate the verify_commands part because of a previous error"){verify_commands}
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def overwrite_defaults=(defaults_hash)
|
32
|
+
@defaults.merge!(defaults_hash)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Add the plugin specific validator
|
36
|
+
def extended_validator=(obj)
|
37
|
+
@extended_validator = obj if obj.respond_to?(:validate)
|
38
|
+
end
|
39
|
+
|
40
|
+
def plugin
|
41
|
+
@plugin ||= plugin_valid? ? parse_plugin : nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def title
|
45
|
+
@title ||= title_valid? ? @hash[:title] : plugin
|
46
|
+
end
|
47
|
+
|
48
|
+
def plugin_timeout
|
49
|
+
@plugin_timeout = plugin_timeout_valid? ? @hash[:plugin_timeout] : @defaults[:plugin_timeout]
|
50
|
+
end
|
51
|
+
|
52
|
+
def verify_commands
|
53
|
+
@verify_commands ||= verify_commands_valid? ? create_verify_commands : []
|
54
|
+
end
|
55
|
+
|
56
|
+
def verify_after_run
|
57
|
+
@verify_after_run = verify_after_run_valid? ? @hash[:verify_after_run] : @defaults[:verify_after_run]
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def plugin_valid?
|
63
|
+
if @hash.kind_of?(String)
|
64
|
+
@hash.empty? and
|
65
|
+
raise PlanParsingError, "The value for 'command' can not be an empty string"
|
66
|
+
elsif @hash.kind_of?(Hash)
|
67
|
+
@hash.empty? and
|
68
|
+
raise PlanParsingError, "The value for 'command' can not be an empty hash"
|
69
|
+
@hash[:plugin] or
|
70
|
+
raise PlanParsingError, "The 'plugin key is missing in the 'command' hash"
|
71
|
+
@hash[:plugin].kind_of?(String) or
|
72
|
+
raise PlanParsingError, "The value for 'plugin' has to be a String with valid plugin name"
|
73
|
+
@hash[:plugin].empty? and
|
74
|
+
raise PlanParsingError, "The value for 'plugin' can not be an empty string"
|
75
|
+
else
|
76
|
+
raise PlanParsingError, "The value for 'command' must be a String with a plugin name or a hash"
|
77
|
+
end
|
78
|
+
true
|
79
|
+
end
|
80
|
+
|
81
|
+
def parse_plugin
|
82
|
+
case @hash
|
83
|
+
when String then @hash
|
84
|
+
when Hash then @hash[:plugin]
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def title_valid?
|
89
|
+
return false unless @hash.kind_of?(Hash)
|
90
|
+
return false if @hash[:title].nil?
|
91
|
+
@hash[:title].kind_of?(String) or
|
92
|
+
raise PlanParsingError, "The command title has to be a string"
|
93
|
+
end
|
94
|
+
|
95
|
+
def plugin_timeout_valid?
|
96
|
+
return false unless @hash.kind_of?(Hash)
|
97
|
+
return false if @hash[:plugin_timeout].nil? # plugin_timeout is optional
|
98
|
+
@hash[:plugin_timeout].kind_of?(Fixnum) or
|
99
|
+
raise PlanParsingError, "The value for 'plugin_timeout' has to be a number"
|
100
|
+
end
|
101
|
+
|
102
|
+
def verify_commands_valid?
|
103
|
+
return false unless @hash.kind_of?(Hash)
|
104
|
+
return false if @hash[:verify_commands].nil?
|
105
|
+
[Array, Hash, String].include? @hash[:verify_commands].class or
|
106
|
+
raise PlanParsingError, "The value for 'verify_commands' has to be a String, Hash or an Array"
|
107
|
+
end
|
108
|
+
|
109
|
+
def create_verify_commands
|
110
|
+
case @hash[:verify_commands]
|
111
|
+
when String, Hash then [ ::DopCommon::Command.new(@hash[:verify_commands]) ]
|
112
|
+
when Array then @hash[:verify_commands].map {|c| ::DopCommon::Command.new(c)}
|
113
|
+
else []
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def verify_after_run_valid?
|
118
|
+
return false unless @hash.kind_of?(Hash)
|
119
|
+
return false if @hash[:verify_after_run].nil?
|
120
|
+
@hash[:verify_after_run].kind_of?(TrueClass) or @hash[:verify_after_run].kind_of?(FalseClass) or
|
121
|
+
raise PlanParsingError, "The value for 'verify_after_run' must be boolean"
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#
|
2
|
+
# Dop configurator helper functions
|
3
|
+
#
|
4
|
+
module DopCommon
|
5
|
+
class Config
|
6
|
+
module Helper
|
7
|
+
def self.included(base)
|
8
|
+
base.send(:extend, ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods
|
12
|
+
def user
|
13
|
+
Etc.getpwuid(Process.uid)
|
14
|
+
end
|
15
|
+
|
16
|
+
def is_root?
|
17
|
+
user.name == 'root'
|
18
|
+
end
|
19
|
+
|
20
|
+
def dop_home
|
21
|
+
File.join(user.dir, '.dop')
|
22
|
+
end
|
23
|
+
|
24
|
+
def conf_var(variable, options = {})
|
25
|
+
define_method(variable) do
|
26
|
+
unless instance_variable_defined?("@#{variable}")
|
27
|
+
default = default.call(self) if default.kind_of?(Proc)
|
28
|
+
instance_variable_set "@#{variable}", options[:default]
|
29
|
+
end
|
30
|
+
instance_variable_get "@#{variable}"
|
31
|
+
end
|
32
|
+
attr_writer variable
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,66 @@
|
|
1
|
+
#
|
2
|
+
# Configration for DopCommon
|
3
|
+
#
|
4
|
+
# Configure the module in a block:
|
5
|
+
#
|
6
|
+
# DopCommon.configure do |config|
|
7
|
+
# config.use_hiera = true
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
require 'etc'
|
11
|
+
require 'dop_common/config/helper'
|
12
|
+
|
13
|
+
module DopCommon
|
14
|
+
|
15
|
+
def self.config
|
16
|
+
@config ||= Config.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.configure
|
20
|
+
yield config
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.configure=(options_hash)
|
24
|
+
options_hash.each do |key, value|
|
25
|
+
variable_name = '@' + key.to_s
|
26
|
+
if config.instance_variable_defined?( variable_name )
|
27
|
+
config.instance_variable_set( variable_name , value )
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class Config
|
33
|
+
include DopCommon::Config::Helper
|
34
|
+
|
35
|
+
conf_var :trace,
|
36
|
+
default: false
|
37
|
+
conf_var :config_file,
|
38
|
+
default: is_root? ? '/etc/dop/dop.conf' : File.join(dop_home, 'dop.conf')
|
39
|
+
conf_var :plan_store_dir,
|
40
|
+
default: is_root? ? '/var/lib/dop/cache' : File.join(dop_home, 'cache')
|
41
|
+
conf_var :use_hiera,
|
42
|
+
default: true
|
43
|
+
conf_var :hiera_yaml,
|
44
|
+
default: is_root? ? '/etc/puppet/hiera.yaml' : File.join(user.dir, '.puppet', 'hiera.yaml')
|
45
|
+
conf_var :load_facts,
|
46
|
+
default: false
|
47
|
+
conf_var :facts_dir,
|
48
|
+
default: is_root? ? '/var/lib/puppet/yaml/facts' : File.join(user.dir, '.puppet', 'var', 'yaml', 'facts')
|
49
|
+
conf_var :role_variable,
|
50
|
+
default: 'role'
|
51
|
+
conf_var :role_default,
|
52
|
+
default: nil
|
53
|
+
conf_var :connection_check_timeout,
|
54
|
+
default: 5
|
55
|
+
conf_var :mco_config,
|
56
|
+
default: is_root? ? '/etc/mcollective/client.cfg' : File.join(user.dir, '.mcollective')
|
57
|
+
conf_var :mco_dopi_logger,
|
58
|
+
default: true
|
59
|
+
conf_var :log_dir,
|
60
|
+
default: is_root? ? '/var/log/dop/' : File.join(dop_home, 'log')
|
61
|
+
conf_var :log_level,
|
62
|
+
default: 'DEBUG'
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#
|
2
|
+
# DOP Common configuration lookup
|
3
|
+
#
|
4
|
+
|
5
|
+
module DopCommon
|
6
|
+
class ConfigurationValueNotFound < StandardError
|
7
|
+
end
|
8
|
+
|
9
|
+
class Configuration
|
10
|
+
|
11
|
+
def initialize(hash)
|
12
|
+
@hash = hash
|
13
|
+
end
|
14
|
+
|
15
|
+
def lookup(source, key, scope)
|
16
|
+
element = traverse_hash(source)
|
17
|
+
if element.has_key?(key)
|
18
|
+
element[key]
|
19
|
+
else
|
20
|
+
raise DopCommon::ConfigurationValueNotFound
|
21
|
+
end
|
22
|
+
rescue => e
|
23
|
+
raise DopCommon::ConfigurationValueNotFound
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def traverse_hash(source)
|
29
|
+
element = @hash
|
30
|
+
source.split('/').each do |level|
|
31
|
+
element = element[level]
|
32
|
+
end
|
33
|
+
element
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|