dop_common 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +176 -0
  6. data/Gemfile +11 -0
  7. data/LICENSE.txt +177 -0
  8. data/README.md +48 -0
  9. data/Rakefile +49 -0
  10. data/Vagrantfile +25 -0
  11. data/bin/dop-puppet-autosign +56 -0
  12. data/doc/examples/example_deploment_plan_v0.0.1.yaml +302 -0
  13. data/doc/plan_format_v0.0.1.md +919 -0
  14. data/doc/plan_format_v0.0.2_snippets.md +56 -0
  15. data/dop_common.gemspec +44 -0
  16. data/lib/dop_common/affinity_group.rb +57 -0
  17. data/lib/dop_common/cli/global_options.rb +37 -0
  18. data/lib/dop_common/cli/log.rb +51 -0
  19. data/lib/dop_common/cli/node_selection.rb +62 -0
  20. data/lib/dop_common/command.rb +125 -0
  21. data/lib/dop_common/config/helper.rb +39 -0
  22. data/lib/dop_common/config.rb +66 -0
  23. data/lib/dop_common/configuration.rb +37 -0
  24. data/lib/dop_common/credential.rb +152 -0
  25. data/lib/dop_common/data_disk.rb +62 -0
  26. data/lib/dop_common/dns.rb +55 -0
  27. data/lib/dop_common/hash_parser.rb +241 -0
  28. data/lib/dop_common/hooks.rb +81 -0
  29. data/lib/dop_common/infrastructure.rb +160 -0
  30. data/lib/dop_common/infrastructure_properties.rb +185 -0
  31. data/lib/dop_common/interface.rb +113 -0
  32. data/lib/dop_common/log.rb +78 -0
  33. data/lib/dop_common/network.rb +85 -0
  34. data/lib/dop_common/node/config.rb +159 -0
  35. data/lib/dop_common/node.rb +442 -0
  36. data/lib/dop_common/node_filter.rb +74 -0
  37. data/lib/dop_common/plan.rb +188 -0
  38. data/lib/dop_common/plan_cache.rb +83 -0
  39. data/lib/dop_common/plan_store.rb +263 -0
  40. data/lib/dop_common/pre_processor.rb +73 -0
  41. data/lib/dop_common/run_options.rb +56 -0
  42. data/lib/dop_common/signal_handler.rb +58 -0
  43. data/lib/dop_common/state_store.rb +95 -0
  44. data/lib/dop_common/step.rb +200 -0
  45. data/lib/dop_common/step_set.rb +41 -0
  46. data/lib/dop_common/thread_context_logger.rb +77 -0
  47. data/lib/dop_common/utils.rb +106 -0
  48. data/lib/dop_common/validator.rb +53 -0
  49. data/lib/dop_common/version.rb +3 -0
  50. data/lib/dop_common.rb +32 -0
  51. data/lib/hiera/backend/dop_backend.rb +94 -0
  52. data/lib/hiera/dop_logger.rb +20 -0
  53. data/spec/data/fake_hook_file_invalid +1 -0
  54. data/spec/data/fake_hook_file_valid +5 -0
  55. data/spec/data/fake_keyfile +1 -0
  56. data/spec/dop-puppet-autosign_spec_disable.rb +33 -0
  57. data/spec/dop_common/affinity_group_spec.rb +41 -0
  58. data/spec/dop_common/command_spec.rb +83 -0
  59. data/spec/dop_common/credential_spec.rb +73 -0
  60. data/spec/dop_common/data_disk_spec.rb +165 -0
  61. data/spec/dop_common/dns_spec.rb +33 -0
  62. data/spec/dop_common/hash_parser_spec.rb +181 -0
  63. data/spec/dop_common/hooks_spec.rb +33 -0
  64. data/spec/dop_common/infrastructure_properties_spec.rb +224 -0
  65. data/spec/dop_common/infrastructure_spec.rb +77 -0
  66. data/spec/dop_common/interface_spec.rb +192 -0
  67. data/spec/dop_common/network_spec.rb +92 -0
  68. data/spec/dop_common/node_filter_spec.rb +70 -0
  69. data/spec/dop_common/node_spec.rb +623 -0
  70. data/spec/dop_common/plan_cache_spec.rb +46 -0
  71. data/spec/dop_common/plan_spec.rb +136 -0
  72. data/spec/dop_common/plan_store_spec.rb +194 -0
  73. data/spec/dop_common/pre_processor_spec.rb +27 -0
  74. data/spec/dop_common/run_options_spec.rb +65 -0
  75. data/spec/dop_common/signal_handler_spec.rb +31 -0
  76. data/spec/dop_common/step_set_spec.rb +21 -0
  77. data/spec/dop_common/step_spec.rb +175 -0
  78. data/spec/dop_common/utils_spec.rb +27 -0
  79. data/spec/dop_common/validator_spec.rb +47 -0
  80. data/spec/example_plans_spec.rb +16 -0
  81. data/spec/fixtures/example_ssh_key +27 -0
  82. data/spec/fixtures/example_ssh_key.pub +1 -0
  83. data/spec/fixtures/incl/root_part.yaml +1 -0
  84. data/spec/fixtures/incl/some_list.yaml +2 -0
  85. data/spec/fixtures/other_plan_same_nodes.yaml +19 -0
  86. data/spec/fixtures/simple_include.yaml +6 -0
  87. data/spec/fixtures/simple_include_with_errors.yaml +4 -0
  88. data/spec/fixtures/simple_plan.yaml +19 -0
  89. data/spec/fixtures/simple_plan_invalid.yaml +18 -0
  90. data/spec/fixtures/simple_plan_modified.yaml +21 -0
  91. data/spec/spec_helper.rb +106 -0
  92. 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
+
@@ -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