dop_common 0.13.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.
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,58 @@
1
+ #
2
+ # Defered signal handling
3
+ #
4
+ # This class will handle the trapping of signals
5
+ #
6
+ # This code uses tricks from http://timuruski.net/blog/2014/graceful-shutdown
7
+ # for setup and teardown of the signal handlers. And the self pipe trick from
8
+ # http://www.sitepoint.com/the-self-pipe-trick-explained
9
+ #
10
+
11
+ module DopCommon
12
+ class SignalHandler
13
+ DEFAULT_SIGNALS = [:INT, :QUIT, :TERM]
14
+
15
+ def initialize
16
+ @signal_queue = []
17
+ @self_reader, @self_writer = IO.pipe
18
+ end
19
+
20
+ def handle_signals(*signals)
21
+ signals = DEFAULT_SIGNALS if signals.empty?
22
+ old_handlers = setup_signal_traps(signals)
23
+ loop do
24
+ begin
25
+ if @signal_queue.any?
26
+ yield(@signal_queue.shift) if block_given?
27
+ else
28
+ IO.select([@self_reader])
29
+ @self_reader.read_nonblock(1)
30
+ end
31
+ rescue
32
+ break
33
+ end
34
+ end
35
+ teardown_signal_traps(old_handlers)
36
+ end
37
+
38
+ private
39
+
40
+ def setup_signal_traps(signals)
41
+ signals.each_with_object({}) do |signal, old_handlers|
42
+ DopCommon.log.debug("Installing trap for signal #{signal.to_s}")
43
+ old_handlers[signal] = Signal.trap(signal) do
44
+ @signal_queue << { signal => Time.now }
45
+ @self_writer.write_nonblock('.')
46
+ end
47
+ end
48
+ end
49
+
50
+ def teardown_signal_traps(old_handlers)
51
+ old_handlers.each do |signal, old_handler|
52
+ DopCommon.log.debug("Removing trap for signal #{signal.to_s}")
53
+ Signal.trap(signal, old_handler)
54
+ end
55
+ end
56
+
57
+ end
58
+ end
@@ -0,0 +1,95 @@
1
+ #
2
+ # This is a simple wrapper around YAML::Store to make versioning
3
+ # and updating easier.
4
+ #
5
+ require 'yaml/store'
6
+ require 'rb-inotify'
7
+
8
+ module DopCommon
9
+ class UnknownVersionError < StandardError
10
+ end
11
+
12
+ class StateStore < YAML::Store
13
+
14
+ def initialize(state_file, plan_name, plan_cache)
15
+ @plan_name = plan_name
16
+ @plan_cache = plan_cache
17
+ @state_file = state_file
18
+ @write_mutex = Mutex.new
19
+ super(@state_file)
20
+ end
21
+
22
+ # This is a wrapper around transaction to make sure we have a run lock.
23
+ # This will ensure that only ever one instance can write to this store.
24
+ def transaction(read_only = false, &block)
25
+ if read_only
26
+ super(read_only, &block)
27
+ else
28
+ @write_mutex.synchronize do
29
+ if @plan_cache.run_lock?(@plan_name)
30
+ # save the version on first write
31
+ super do
32
+ self[:version] = latest_version if self[:version].nil?
33
+ end
34
+ super(&block)
35
+ else
36
+ raise StandardError, "Not possible to write to #{@state_file} because we have no run lock"
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+ def version
43
+ transaction(true) do
44
+ self[:version] || :new
45
+ end
46
+ end
47
+
48
+ def pending_updates?
49
+ case version
50
+ when :new, latest_version then false
51
+ else true
52
+ end
53
+ end
54
+
55
+ # update the state file. This takes a block which will receive a
56
+ # hash diff from the state version to the newest plan version.
57
+ # If the plan is new or already on the latest version the block will
58
+ # not be executed.
59
+ #
60
+ # The block is already inside a transaction. The version will be bumped
61
+ # to the latest version only if the transaction is successful.
62
+ def update
63
+ ver = version
64
+ return if ver == latest_version
65
+ return if ver == :new
66
+ raise UnknownVersionError.new(ver) unless version_exists?(ver)
67
+ DopCommon.log.info("Updating plan #{@plan_name} from version #{ver} to #{latest_version}")
68
+ transaction do
69
+ yield(@plan_cache.get_plan_hash_diff(@plan_name, ver, latest_version))
70
+ self[:version] = latest_version
71
+ end
72
+ end
73
+
74
+ # This method will take a block which will be executet every time the
75
+ # state file changes.
76
+ def on_change
77
+ notifier = INotify::Notifier.new
78
+ notifier.watch(@state_file, :modify) do
79
+ yield
80
+ end
81
+ notifier.run
82
+ end
83
+
84
+ private
85
+
86
+ def latest_version
87
+ @plan_cache.show_versions(@plan_name).last
88
+ end
89
+
90
+ def version_exists?(version)
91
+ @plan_cache.show_versions(@plan_name).include?(version)
92
+ end
93
+
94
+ end
95
+ end
@@ -0,0 +1,200 @@
1
+ #
2
+ # DOP common step hash parser
3
+ #
4
+
5
+ module DopCommon
6
+ class Step
7
+ include Validator
8
+ include RunOptions
9
+
10
+ def initialize(hash)
11
+ @hash = HashParser.symbolize_keys(hash)
12
+ HashParser.key_aliases(@hash, :commands, [:command])
13
+ end
14
+
15
+ def name
16
+ @name ||= @hash[:name] or
17
+ raise PlanParsingError, "Every step needs to have a 'name' key defined"
18
+ end
19
+
20
+ def validate
21
+ valitdate_shared_options
22
+ log_validation_method('name')
23
+ log_validation_method('nodes_valid?')
24
+ log_validation_method('exclude_nodes_valid?')
25
+ log_validation_method('nodes_by_config_valid?')
26
+ log_validation_method('exclude_nodes_by_config_valid?')
27
+ log_validation_method('roles_valid?')
28
+ log_validation_method('exclude_roles_valid?')
29
+ log_validation_method('commands_valid?')
30
+ r_name = @name || 'unknown' # name may not be set because of a previous error
31
+ try_validate_obj("Step #{r_name}: Can't validate the commands part because of a previous error"){commands}
32
+ end
33
+
34
+ def nodes
35
+ @nodes ||= nodes_valid? ?
36
+ HashParser.parse_pattern_list(@hash, :nodes) : []
37
+ end
38
+
39
+ def exclude_nodes
40
+ @exclude_nodes ||= exclude_nodes_valid? ?
41
+ HashParser.parse_pattern_list(@hash, :exclude_nodes) : []
42
+ end
43
+
44
+ def nodes_by_config
45
+ @nodes_by_config ||= nodes_by_config_valid? ?
46
+ HashParser.parse_hash_of_pattern_lists(@hash, :nodes_by_config) : {}
47
+ end
48
+
49
+ def exclude_nodes_by_config
50
+ @exclude_nodes_by_config ||= exclude_nodes_by_config_valid? ?
51
+ HashParser.parse_hash_of_pattern_lists(@hash, :exclude_nodes_by_config) : {}
52
+ end
53
+
54
+ def roles
55
+ @roles ||= roles_valid? ?
56
+ HashParser.parse_pattern_list(@hash, :roles) : []
57
+ end
58
+
59
+ def exclude_roles
60
+ @exclude_roles ||= exclude_roles_valid? ?
61
+ HashParser.parse_pattern_list(@hash, :exclude_roles) : []
62
+ end
63
+
64
+ def commands
65
+ @commands ||= commands_valid? ? create_commands : nil
66
+ end
67
+
68
+ def set_plugin_defaults
69
+ @set_plugin_defaults ||= set_plugin_defaults_valid? ?
70
+ parse_plugin_pattern_array(:set_plugin_defaults) : []
71
+ end
72
+
73
+ def delete_plugin_defaults
74
+ @delete_plugin_defaults ||= delete_plugin_defaults_valid? ?
75
+ parse_plugin_pattern_array(:delete_plugin_defaults) : []
76
+ end
77
+
78
+ private
79
+
80
+ def nodes_valid?
81
+ pattern_list_valid?(@hash, :nodes)
82
+ end
83
+
84
+ def exclude_nodes_valid?
85
+ pattern_list_valid?(@hash, :exclude_nodes)
86
+ end
87
+
88
+ def nodes_by_config_valid?
89
+ hash_of_pattern_lists_valid?(@hash, :nodes_by_config)
90
+ end
91
+
92
+ def exclude_nodes_by_config_valid?
93
+ hash_of_pattern_lists_valid?(@hash, :exclude_nodes_by_config)
94
+ end
95
+
96
+ def roles_valid?
97
+ pattern_list_valid?(@hash, :roles)
98
+ end
99
+
100
+ def exclude_roles_valid?
101
+ pattern_list_valid?(@hash, :exclude_roles)
102
+ end
103
+
104
+ def pattern_list_valid?(hash, key, optional = true)
105
+ HashParser.pattern_list_valid?(hash, key, optional)
106
+ rescue PlanParsingError => e
107
+ raise PlanParsingError, "Step #{@name}: #{e.message}"
108
+ end
109
+
110
+ def hash_of_pattern_lists_valid?(hash, key, optional = true)
111
+ HashParser.hash_of_pattern_lists_valid?(hash, key, optional)
112
+ rescue PlanParsingError => e
113
+ raise PlanParsingError, "Step #{@name}: #{e.message}"
114
+ end
115
+
116
+ def commands_valid?
117
+ @hash[:commands] or
118
+ raise PlanParsingError, "Step #{@name}: A commands key has to be defined"
119
+ case @hash[:commands]
120
+ when String, Hash
121
+ true
122
+ when Array
123
+ @hash[:commands].all?{|c| c.kind_of?(String) or c.kind_of?(Hash)} or
124
+ raise PlanParsingError, "Step #{@name}: All commands must be Strings or Hashes"
125
+ else
126
+ raise PlanParsingError,
127
+ "Step #{@name}: The value for commands has to be a string, a hash or an array"
128
+ end
129
+ end
130
+
131
+ def create_commands
132
+ [@hash[:commands]].flatten.map do |command|
133
+ ::DopCommon::Command.new(command)
134
+ end
135
+ end
136
+
137
+ def plugin_pattern_array_valid?(key)
138
+ @hash[key].all? do |entry|
139
+ entry.kind_of?(Hash) or
140
+ raise PlanParsingError, "Step #{@name}: Each entry in the '#{key}' array has to be a hash"
141
+ HashParser.key_aliases(entry, :plugins, ['plugins', :plugin, 'plugin'])
142
+ pattern_list_valid?(entry, :plugins, false)
143
+ end
144
+ end
145
+
146
+ def set_plugin_defaults_valid?
147
+ return false if @hash[:set_plugin_defaults].nil? # is optional
148
+ @hash[:set_plugin_defaults].kind_of?(Array) or
149
+ raise PlanParsingError, "Step #{@name}: The value of 'set_plugin_defaults' has to be an array"
150
+ plugin_pattern_array_valid?(:set_plugin_defaults)
151
+ end
152
+
153
+ def delete_plugin_defaults_valid?
154
+ return false if @hash[:delete_plugin_defaults].nil? # is optional
155
+ @hash[:delete_plugin_defaults].kind_of?(Array) or
156
+ @hash[:delete_plugin_defaults].kind_of?(String) or
157
+ @hash[:delete_plugin_defaults].kind_of?(Symbol) or
158
+ raise PlanParsingError, "Step #{@name}: The value of 'delete_plugin_defaults' has to be an array or :all"
159
+ unless @hash[:delete_plugin_defaults].kind_of?(Array)
160
+ ['all', 'All', 'ALL', :all].include?(@hash[:delete_plugin_defaults]) or
161
+ raise PlanParsingError, "Step #{@name}: The value of 'delete_plugin_defaults' has to be an array or :all"
162
+ else
163
+ return false unless plugin_pattern_array_valid?(:delete_plugin_defaults)
164
+ @hash[:delete_plugin_defaults].all? do |entry|
165
+ HashParser.key_aliases(entry, :delete_keys, ['delete_keys', :delete_key, 'delete_key'])
166
+ entry[:delete_keys].nil? and
167
+ raise PlanParsingError, "Step #{@name}: Each entry in the 'delete_plugin_defaults' array needs a valid value for 'delete_keys'"
168
+ entry[:delete_keys].kind_of?(Array) or
169
+ entry[:delete_keys].kind_of?(String) or
170
+ entry[:delete_keys].kind_of?(Symbol) or
171
+ raise PlanParsingError, "Step #{@name}: The value for 'delete_keys' in 'delete_plugin_defaults' has to be a string or an array"
172
+ if entry[:delete_keys].kind_of?(Array)
173
+ entry[:delete_keys].all?{|e| e.kind_of?(String) or e.kind_of?(Symbol)} or
174
+ raise PlanParsingError, "Step #{@name}: The elements in 'delete_keys' in 'delete_plugin_defaults' have to me strings or symbols"
175
+ end
176
+ end
177
+ end
178
+ true
179
+ end
180
+
181
+ def parse_plugin_pattern_array(key)
182
+ unless @hash[key].kind_of?(Array)
183
+ :all
184
+ else
185
+ @hash[key].map do |entry|
186
+ result = entry.dup
187
+ result[:plugins] = HashParser.parse_pattern_list(entry, :plugins)
188
+ delete_keys = case entry[:delete_keys]
189
+ when 'all', 'All', 'ALL', :all then :all
190
+ when String, Array then [entry[:delete_keys]].flatten
191
+ else nil
192
+ end
193
+ result[:delete_keys] = delete_keys if delete_keys
194
+ result
195
+ end
196
+ end
197
+ end
198
+
199
+ end
200
+ end
@@ -0,0 +1,41 @@
1
+ #
2
+ # DOP common step set hash parser
3
+ #
4
+
5
+ module DopCommon
6
+ class StepSet
7
+ include Validator
8
+
9
+ attr_reader :name
10
+
11
+ def initialize(name, steps_array)
12
+ @name = name
13
+ @steps_array = steps_array
14
+ end
15
+
16
+ def validate
17
+ log_validation_method(:steps_valid?)
18
+ try_validate_obj("StepSet #{name}: Can't validate the steps part because of a previous error"){steps}
19
+ end
20
+
21
+ def steps
22
+ @steps ||= steps_valid? ? create_steps : nil
23
+ end
24
+
25
+ private
26
+
27
+ def steps_valid?
28
+ @steps_array.any? or
29
+ raise PlanParsingError, "StepSet #{name}: no steps defined"
30
+ @steps_array.all?{|s| s.kind_of?(Hash)} or
31
+ raise PlanParsingError, "StepSet #{name}: steps array must only contain hashes"
32
+ end
33
+
34
+ def create_steps
35
+ @steps_array.map do |hash|
36
+ ::DopCommon::Step.new(hash)
37
+ end
38
+ end
39
+
40
+ end
41
+ end
@@ -0,0 +1,77 @@
1
+ #
2
+ # This is log formatter which will log to different files based on the context
3
+ # which was set for the current thread. if no context was set then it will log
4
+ # to the 'all' context.
5
+ #
6
+ # This is used to separate log for different nodes even for logs which are
7
+ # generated in some external library which is not aware of the context.
8
+ #
9
+ module DopCommon
10
+ class ThreadContextLogger
11
+ def initialize(log_path, contexts, all = true)
12
+ @log_path = log_path
13
+ @contexts = contexts
14
+ @all = all
15
+ @mutex = Mutex.new
16
+ @loggers = {}
17
+ @threads = {}
18
+
19
+ FileUtils.mkdir_p(@log_path)
20
+ create
21
+ end
22
+
23
+ def create
24
+ @mutex.synchronize do
25
+ add('all') if @all
26
+ @contexts.each{|context| add(context)}
27
+ end
28
+ end
29
+
30
+ def cleanup
31
+ @mutex.synchronize do
32
+ @contexts.each{|context| remove(context)}
33
+ end
34
+ end
35
+
36
+ def log_context=(context)
37
+ @mutex.synchronize do
38
+ @threads[Thread.current.object_id.to_s] = context
39
+ end
40
+ end
41
+
42
+ private
43
+
44
+ def add(context)
45
+ log_file = File.join(@log_path, context)
46
+ logger = Logger.new(log_file)
47
+ if context == 'all'
48
+ logger.formatter = Logger::Formatter.new
49
+ else
50
+ logger.formatter = formatter(context)
51
+ end
52
+ logger.level = ::Logger.const_get(DopCommon.config.log_level.upcase)
53
+
54
+ @loggers[context] = logger
55
+ DopCommon.add_log_junction(logger)
56
+ end
57
+
58
+ def remove(context)
59
+ logger = @loggers[context]
60
+ DopCommon.remove_log_junction(logger)
61
+ end
62
+
63
+ def formatter(context)
64
+ orig_formatter = Logger::Formatter.new
65
+ Proc.new do |severity, datetime, progname, msg|
66
+ @mutex.synchronize do
67
+ if context == @threads[Thread.current.object_id.to_s]
68
+ orig_formatter.call(severity, datetime, progname, msg)
69
+ else
70
+ nil
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,106 @@
1
+ module DopCommon
2
+ module Utils
3
+ def sanitize_env(additional_env_vars = {})
4
+ {
5
+ 'HOME' => ENV['HOME'],
6
+ 'PATH' => '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin'
7
+ }.merge(additional_env_vars)
8
+ end
9
+ module_function :sanitize_env
10
+
11
+ class DataSize
12
+ include Validator
13
+
14
+ KIBIBYTE = 1024.0
15
+ MEBIBYTE = 1048576.0
16
+ GIBIBYTE = 1073741824.0
17
+ KILOBYTE = 1000.0
18
+ MEGABYTE = 1000000.0
19
+ GIGABYTE = 1000000000.0
20
+
21
+ def initialize(input)
22
+ @input ||= input
23
+ end
24
+
25
+ def validate
26
+ log_validation_method(:input_valid?)
27
+ end
28
+
29
+ def size
30
+ @size ||= input_valid? ? create_size : nil
31
+ end
32
+ alias_method :bytes, :size
33
+ alias_method :b, :size
34
+
35
+ def kibibytes
36
+ size / KIBIBYTE
37
+ end
38
+ alias_method :k, :kibibytes
39
+
40
+ def mebibytes
41
+ size / MEBIBYTE
42
+ end
43
+ alias_method :m, :mebibytes
44
+
45
+ def gibibytes
46
+ size / GIBIBYTE
47
+ end
48
+ alias_method :g, :gibibytes
49
+
50
+ def kilobytes
51
+ size / KILOBYTE
52
+ end
53
+ alias_method :kb, :kilobytes
54
+
55
+ def megabytes
56
+ size / MEGABYTE
57
+ end
58
+ alias_method :mb, :megabytes
59
+
60
+ def gigabytes
61
+ size / GIGABYTE
62
+ end
63
+ alias_method :gb, :gigabytes
64
+
65
+ def to_s
66
+ size.to_s
67
+ end
68
+
69
+ private
70
+
71
+ def input_valid?
72
+ raise PlanParsingError, "DataSize: Invalid input '#{@input}'. It must be an integer or string" unless
73
+ [String, Fixnum].include?(@input.class)
74
+ raise PlanParsingError, "DataSize: Invalid input '#{@input}'. It must be greater than zero" if
75
+ @input.kind_of?(Fixnum) && @input < 1
76
+ raise PlanParsingError, "DataSize: Invalid input '#{@input}'. " \
77
+ "It must be a positive number followed by one of K,KB,M,MB,G,GB literals" if
78
+ @input.kind_of?(String) && @input !~ /^(([1-9]\d*)(\.\d+)?|0\.(0*[1-9]\d*))[KMG]B?$/
79
+ true
80
+ end
81
+
82
+ def create_size
83
+ if @input.kind_of?(String)
84
+ if @input.index(/K$/)
85
+ s = @input.sub(/K$/, '').to_f * KIBIBYTE
86
+ elsif @input.index(/M$/)
87
+ s = @input.sub(/M$/, '').to_f * MEBIBYTE
88
+ elsif @input.index(/G$/)
89
+ s = @input.sub(/G$/, '').to_f * GIBIBYTE
90
+ elsif @input.index(/KB$/)
91
+ s = @input.sub(/KB$/, '').to_f * KILOBYTE
92
+ elsif @input.index(/MB$/)
93
+ s = @input.sub(/MB$/, '').to_f * MEGABYTE
94
+ elsif @input.index(/GB$/)
95
+ s = @input.sub(/GB$/, '').to_f * GIGABYTE
96
+ else
97
+ s = @input
98
+ end
99
+ @size = s.to_i
100
+ else
101
+ @size = @input
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,53 @@
1
+ #
2
+ # DOP Common Validator
3
+ #
4
+ # Some Validation Helper stuff
5
+ #
6
+
7
+ module DopCommon
8
+ module Validator
9
+
10
+ def valid?
11
+ @validity = true
12
+ validate
13
+ @validity
14
+ end
15
+
16
+ def set_not_valid
17
+ @validity = false
18
+ end
19
+
20
+ def log_validation_method(method, error_klass = PlanParsingError)
21
+ begin
22
+ send(method)
23
+ rescue error_klass => e
24
+ set_not_valid
25
+ DopCommon.log.error(e.message)
26
+ end
27
+ end
28
+
29
+ def try_validate_obj(message, error_klass = PlanParsingError)
30
+ begin
31
+ obj = yield
32
+ if obj.kind_of?(Array)
33
+ obj.each do |x|
34
+ x.validate
35
+ set_not_valid unless x.valid?
36
+ end
37
+ elsif obj.kind_of?(Hash)
38
+ obj.each_value do |x|
39
+ x.validate
40
+ set_not_valid unless x.valid?
41
+ end
42
+ else
43
+ obj.validate
44
+ set_not_valid unless obj.valid?
45
+ end
46
+ rescue error_klass => e
47
+ set_not_valid
48
+ DopCommon.log.warn(message)
49
+ end
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,3 @@
1
+ module DopCommon
2
+ VERSION = "0.13.0"
3
+ end
data/lib/dop_common.rb ADDED
@@ -0,0 +1,32 @@
1
+ require "dop_common/version"
2
+ require "dop_common/config"
3
+ require "dop_common/log"
4
+ require "dop_common/thread_context_logger"
5
+ require "dop_common/validator"
6
+ require "dop_common/hash_parser"
7
+ require "dop_common/utils"
8
+ require "dop_common/run_options"
9
+ require "dop_common/plan"
10
+ require 'dop_common/infrastructure'
11
+ require 'dop_common/network'
12
+ require 'dop_common/affinity_group'
13
+ require 'dop_common/hooks'
14
+ require 'dop_common/node'
15
+ require 'dop_common/infrastructure_properties'
16
+ require 'dop_common/interface'
17
+ require 'dop_common/step'
18
+ require 'dop_common/step_set'
19
+ require 'dop_common/configuration'
20
+ require 'dop_common/credential'
21
+ require 'dop_common/command'
22
+ require 'dop_common/pre_processor'
23
+ require 'dop_common/plan_store'
24
+ require 'dop_common/plan_cache'
25
+ require 'dop_common/state_store'
26
+ require 'dop_common/dns'
27
+ require 'dop_common/data_disk'
28
+ require 'dop_common/node_filter'
29
+ require 'dop_common/signal_handler'
30
+
31
+ module DopCommon
32
+ end