dopv 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +23 -0
  3. data/.rspec +2 -0
  4. data/ChangeLog.md +456 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.lock +260 -0
  7. data/Guardfile +22 -0
  8. data/LICENSE.txt +177 -0
  9. data/README.md +214 -0
  10. data/Rakefile +6 -0
  11. data/bin/dopv +4 -0
  12. data/dopv.gemspec +52 -0
  13. data/lib/dopv.rb +166 -0
  14. data/lib/dopv/cli.rb +54 -0
  15. data/lib/dopv/cli/command_add.rb +37 -0
  16. data/lib/dopv/cli/command_export.rb +26 -0
  17. data/lib/dopv/cli/command_import.rb +32 -0
  18. data/lib/dopv/cli/command_list.rb +18 -0
  19. data/lib/dopv/cli/command_remove.rb +29 -0
  20. data/lib/dopv/cli/command_run.rb +38 -0
  21. data/lib/dopv/cli/command_update.rb +35 -0
  22. data/lib/dopv/cli/command_validate.rb +30 -0
  23. data/lib/dopv/infrastructure.rb +40 -0
  24. data/lib/dopv/infrastructure/providers/baremetal.rb +12 -0
  25. data/lib/dopv/infrastructure/providers/base.rb +422 -0
  26. data/lib/dopv/infrastructure/providers/openstack.rb +308 -0
  27. data/lib/dopv/infrastructure/providers/ovirt.rb +228 -0
  28. data/lib/dopv/infrastructure/providers/vsphere.rb +322 -0
  29. data/lib/dopv/log.rb +14 -0
  30. data/lib/dopv/persistent_disk.rb +128 -0
  31. data/lib/dopv/plan.rb +17 -0
  32. data/lib/dopv/state_store.rb +87 -0
  33. data/lib/dopv/version.rb +3 -0
  34. data/spec/data/hooks/test_hook_script_1 +9 -0
  35. data/spec/data/hooks/test_hook_script_2 +10 -0
  36. data/spec/data/plans/test-plan-1.yaml +140 -0
  37. data/spec/spec_helper.rb +112 -0
  38. data/spec/unit/dopv/dopv_spec.rb +7 -0
  39. data/spec/unit/dopv/persistent_disk_spec.rb +38 -0
  40. data/spec/unit/dopv/plan_spec.rb +34 -0
  41. data/spec/unit/dopv/version_spec.rb +17 -0
  42. metadata +401 -0
@@ -0,0 +1,214 @@
1
+ # Dopv
2
+
3
+ Dopv orchestrates deployments of nodes. A node can be a virtual machine or a bare-metal compute node.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'dopv'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install dopv
18
+
19
+ ## Usage
20
+
21
+ ### Library
22
+ Deploy a plan
23
+ ```ruby
24
+ require 'dopv'
25
+ plan = ::Dopv::load_plan(plan_file)
26
+ data_volumes_db = ::Dopv::load_data_volumes_db(db_file)
27
+ ::Dopv::run_plan(plan, data_volumes_db)
28
+ ```
29
+ Undeploy a plan while keeping data volumes
30
+ ```ruby
31
+ require 'dopv'
32
+ plan = ::Dopv::load_plan(plan_file)
33
+ data_volumes_db = ::Dopv::load_data_volumes_db(db_file)
34
+ ::Dopv::run_plan(plan, data_volumes_db, :undeploy)
35
+ ```
36
+ Undeploy a plan and remove data volumes from infrastructure provider (stack) as
37
+ well as from persistent data volumes DB:
38
+ ```ruby
39
+ require 'dopv'
40
+ plan = ::Dopv::load_plan(plan_file)
41
+ data_volumes_db = ::Dopv::load_data_volumes_db(db_file)
42
+ ::Dopv::run_plan(plan, data_volumes_db, :undeploy, true)
43
+ ```
44
+
45
+ ### CLI
46
+ A command line interface utility `dopv` is provided.
47
+
48
+ #### Getting help
49
+ A help can be obtained by calling `dopv --help`:
50
+ ```
51
+ $ dopv --help
52
+ NAME
53
+ dopv - DOPv command line tool
54
+
55
+ SYNOPSIS
56
+ dopv [global options] command [command options] [arguments...]
57
+
58
+ VERSION
59
+ 0.7.0
60
+
61
+ GLOBAL OPTIONS
62
+ --help - Show this message
63
+ --logfile, -l path_to_log_file - Log file (default: none)
64
+ --[no-]trace, -t - Show stacktrace on crash
65
+ --verbosity, -v level - Verbosity of the command line tool (default: info)
66
+ --version - Display the program version
67
+
68
+ COMMANDS
69
+ add - Add a new plan file to the plan cache
70
+ deploy - Deploy a plan
71
+ export - Export the internal disk state into a local diskdb file
72
+ help - Shows a list of commands or help for one command
73
+ import - Import a diskdb file into the internal state store
74
+ list - Show the list of plans in the plan store
75
+ remove - Remove an existing plan from the plan cache
76
+ undeploy - Undeploy a plan
77
+ update - Update the plan and/or the plan state for a given plan yaml or plan name.
78
+ validate - Validate plan file
79
+ ```
80
+
81
+ #### Validating a plan
82
+ The deployment plan `/tmp/foo_plan.yml` could be validated by issuing:
83
+ ```
84
+ $ dopv validate -p /tmp/foo_plan.yml
85
+ Plan valid.
86
+ ```
87
+
88
+ Please note that the plan is always validated before any action takes place.
89
+
90
+ #### Adding a plan
91
+ In order to add a plan to plan cache, use `dopv` `add` command:
92
+ ```
93
+ $ dopv add /tmp/bar_plan.yml
94
+ ```
95
+
96
+ Please note that this feature is considered experimental and should be used with extreme care.
97
+
98
+ #### Updating a plan
99
+ In order to update a plan in the cache after some local changes have been introduced, use `dopv`
100
+ `update` command:
101
+ ```
102
+ $ dopv update /tmp/bar_plan.yml
103
+ ```
104
+
105
+ One may use `-c` or `-i` in order to remove the existing disk information and start with a clean
106
+ state or to ignore the update and to merely set it to the latest version.
107
+
108
+ Please note that this feature is considered experimental and should be used with extreme care.
109
+
110
+ #### Listing plans in cache
111
+ One may use the `list` command to check which plans are stored in the plan cache.
112
+
113
+ #### Deploying a plan
114
+ To get a help on deploy CLI options launch `dopv help deploy` argument:
115
+ ```
116
+ $ dopv help deploy
117
+ NAME
118
+ deploy - Deploy a plan
119
+
120
+ SYNOPSIS
121
+ dopv [global options] deploy [command options]
122
+
123
+ COMMAND OPTIONS
124
+ --diskdb, -d path_to_db_file - Use a local diskdb file and import/export it automatically (default: none)
125
+ --exclude_nodes=node01.example.com,node02.example.com,/example\.com$/ - Exclude this nodes from the run (default: )
126
+ --exclude_nodes_by_config='{"var1": ["val1", "/val2/"], "var2": "val2"}' - Exclude nodes with this config from the run (You have to specify a JSON hash here) (default: {})
127
+ --exclude_roles=role01,role01,/^rolepattern/ - Exclude this roles from the run (default: )
128
+ --nodes=node01.example.com,node02.example.com,/example\.com$/ - Run plans for this nodes only (default: )
129
+ --nodes_by_config='{"var1": ["val1", "/val2/"], "var2": "val2"}' - Run plans for this nodes with this config only (You have to specify a JSON hash here) (default: {})
130
+ --plan, -p path_to_plan_file - plan name from the store or plan file to deploy. If a plan file is given DOPv will run in oneshot mode and add/remove
131
+ the plan automatically to the plan store (required, default: none)
132
+ --roles=role01,role01,/^rolepattern/ - Run plans for this roles only (default: )
133
+ ```
134
+ To deploy a plan located at `/tmp/plan.yaml` and store and/or load persistent disks database located at `/tmp/pdisks.yaml` one can launch `dopv` with following options:
135
+ ```
136
+ $ dopv deploy -p /tmp/pdisks.yaml -d /tmp/pdisks.yaml
137
+ ```
138
+
139
+ To deploy only nodes matching a regular expression `^foo-[1-9]+\.bar\.baz$` that are defined in a plan called `/tmp/plan.yaml` and store and/or load persistent disks database located at `/tmp/pdisks.yaml` one can launch `dopv` with following options:
140
+ ```
141
+ $ dopv deploy -p /tmp/pdisks.yaml -d /tmp/pdisks.yaml --nodes=/^foo-[1-9]+\.bar\.baz$/
142
+ ```
143
+
144
+ Please note that disk database file is created if it does not exist.
145
+
146
+ #### Undeploying a plan
147
+ To get a help on undeploy CLI options launch `dopv` `help undeploy` argument:
148
+ ```
149
+ $ dopv help undeploy
150
+ NAME
151
+ undeploy - Undeploy a plan
152
+
153
+ SYNOPSIS
154
+ dopv [global options] undeploy [command options]
155
+
156
+ COMMAND OPTIONS
157
+ --diskdb, -d path_to_db_file - (default: none)
158
+ --plan, -p path_to_plan_file - (required, default: none)
159
+ ME
160
+ undeploy - Undeploy a plan
161
+
162
+ SYNOPSIS
163
+ dopv [global options] undeploy [command options]
164
+
165
+ COMMAND OPTIONS
166
+ --diskdb, -d path_to_db_file - Use a local diskdb file and import/export it automatically (default: none)
167
+ --exclude_nodes=node01.example.com,node02.example.com,/example\.com$/ - Exclude this nodes from the run (default: )
168
+ --exclude_nodes_by_config='{"var1": ["val1", "/val2/"], "var2": "val2"}' - Exclude nodes with this config from the run (You have to specify a JSON hash here) (default: {})
169
+ --exclude_roles=role01,role01,/^rolepattern/ - Exclude this roles from the run (default: )
170
+ --nodes=node01.example.com,node02.example.com,/example\.com$/ - Run plans for this nodes only (default: )
171
+ --nodes_by_config='{"var1": ["val1", "/val2/"], "var2": "val2"}' - Run plans for this nodes with this config only (You have to specify a JSON hash here) (default: {})
172
+ --plan, -p path_to_plan_file - plan name from the store or plan file to undeploy. If a plan file is given DOPv will run in oneshot mode and
173
+ add/remove the plan automatically to the plan store (required, default: none)
174
+ --[no-]rmdisk, -r - Remove the disks
175
+ --roles=role01,role01,/^rolepattern/ - Run plans for this roles only (default: ) --[no-]rmdisk, -r -
176
+ ```
177
+
178
+ In order to destroy a deployment specified by a plan located at `/tmp/plan.yaml` and persistent disks database located at `/tmp/pdisks.yaml` one can launch `dopv` with following options:
179
+ ```
180
+ $ dopv undeploy -p /tmp/pdisks.yaml -d /tmp/pdisks.yaml
181
+ ```
182
+ If you also want to remove the data volumes of each node and remove their records from persistent data volumes DB, please specify `-r` or `--rmdisk` option as shown bellow:
183
+ ```
184
+ $ dopv undeploy -p /tmp/pdisks.yaml -d /tmp/pdisks.yaml -r
185
+ ```
186
+ If you'd like to selectively remove a node called `foo.bar.baz` as well as nodes that match regular expression `^foo[1-5]\.bar\.baz$` and their data disks, you would use `--nodes` filter:
187
+ ```
188
+ $ dopv undeploy -p /tmp/pdisks.yaml -d /tmp/pdisks.yaml -r --nodes=foo.bar.baz,/^foo[1-5]\.bar\.baz$/
189
+ ```
190
+ If you'd like to remove all nodes but those matching `foo.bar.baz` as well as nodes that match regular expression `^foo[1-5]\.bar\.baz$` and their data disks, you would use `--exclude_nodes` filter:
191
+ ```
192
+ $ dopv undeploy -p /tmp/pdisks.yaml -d /tmp/pdisks.yaml -r --exclude_nodes=foo.bar.baz,/^foo[1-5]\.bar\.baz$/
193
+ ```
194
+
195
+ #### Logging
196
+ By default `dopv` logs messages with `INFO` level and higher to standard output. In order to log to a file `-l` can be specified. The `-v` option is used to set a different log threshold. Following is an example of logging everything (`DEBUG` and above) into `/tmp/dopv.log` during plan deployment:
197
+ ```
198
+ $ dopv -l /tmp/dopv.log -v debug deploy -p /tmp/plan.yaml -d /tmp/disks.yaml
199
+ ```
200
+
201
+ ## Node Filtering Notes
202
+ Please note that `dopv` filtering by configuration and roles is not yet supported.
203
+
204
+ ## Plan
205
+ A plan format and description can be found [here](https://github.com/swisscom/dop_common/blob/master/doc/plan_format_v0.0.1.md). A plan example can be found [here](https://github.com/swisscom/dop_common/blob/master/doc/plan_format_v0.0.1.md)
206
+
207
+
208
+ ## Contributing
209
+
210
+ 1. Fork it
211
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
212
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
213
+ 4. Push to the branch (`git push origin my-new-feature`)
214
+ 5. Create new Pull Request
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'dopv/cli'
4
+ exit Dopv::Cli.run(ARGV)
@@ -0,0 +1,52 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'dopv/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "dopv"
8
+ spec.version = Dopv::VERSION
9
+ spec.authors = ["Pavol Dilung", "Andreas Zuber"]
10
+ spec.email = ["pavol.dilung@swisscom.com", "azuber@puzzle.ch"]
11
+ spec.description = %q{Deployment orchestrator for VMs}
12
+ spec.summary = %q{Deployment orchestrator for VMs}
13
+ spec.homepage = "https://github.com/swisscom/dopv"
14
+ spec.license = "Apache-2.0"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "rspec-mocks"
25
+ spec.add_development_dependency "rspec-command"
26
+ spec.add_development_dependency "simplecov"
27
+ spec.add_development_dependency "pry"
28
+ if RUBY_VERSION < "2"
29
+ spec.add_development_dependency "pry-debugger"
30
+ else
31
+ spec.add_development_dependency "pry-byebug"
32
+ end
33
+ # Newer guard listen versions do not work properly with RB <= 2.2.2
34
+ spec.add_development_dependency "listen", "~> 3.0.8"
35
+ spec.add_development_dependency "guard-ctags-bundler"
36
+
37
+ spec.add_dependency "json", "~> 1.8"
38
+ spec.add_dependency 'logger-colors', '~> 1'
39
+ #spec.add_dependency "rest-client", "~> 1.7"
40
+ spec.add_dependency "rbovirt", "~> 0.1", '>= 0.1.3'
41
+ spec.add_dependency "rbvmomi", "~> 1.8.2"
42
+ spec.add_dependency "net-ssh", "< 3.0" # fog dependcy but net-ssh >= 3.x require ruby 2.x
43
+ spec.add_dependency "fog-google", "< 0.1.1" # fog dependcy but net-ssh >= 3.x require ruby 2.x
44
+ spec.add_dependency "fog-profitbricks", "~> 0.0.5" # fog dependency but fog-profitbricks > 0.5 requires ruby 2.x
45
+ spec.add_dependency "fog", "~> 1.36.0"
46
+ spec.add_dependency "gli", "~> 2.13.1"
47
+ spec.add_dependency "dop_common", "~> 0.13", '>= 0.13.0'
48
+ spec.add_dependency 'parallel', '~> 1'
49
+ if RUBY_VERSION < "2"
50
+ spec.add_dependency "rest-client", "< 2.0"
51
+ end
52
+ end
@@ -0,0 +1,166 @@
1
+ require 'dopv/version'
2
+ require 'dopv/log'
3
+ require 'dopv/persistent_disk'
4
+ require 'dopv/plan'
5
+ require 'dopv/infrastructure'
6
+ require 'dopv/state_store'
7
+ require 'dop_common'
8
+ require 'etc'
9
+ require 'parallel'
10
+
11
+ module Dopv
12
+ extend DopCommon::NodeFilter
13
+
14
+ DEFAULT_MAX_IN_FLIGHT = 5
15
+
16
+ def self.valid?(plan_file)
17
+ hash, _ = plan_store.read_plan_file(plan_file)
18
+ plan = DopCommon::Plan.new(hash)
19
+ plan.valid?
20
+ end
21
+
22
+ def self.add(plan_file)
23
+ raise StandardError, 'Plan not valid; did not add' unless valid?(plan_file)
24
+ plan_name = plan_store.add(plan_file)
25
+ Dopv.update_state(plan_name)
26
+ plan_name
27
+ end
28
+
29
+ def self.update_plan(plan_file, options = {})
30
+ raise StandardError, 'Plan not valid; did not add' unless valid?(plan_file)
31
+ plan_name = plan_store.update(plan_file)
32
+ update_state(plan_name, options)
33
+ plan_name
34
+ end
35
+
36
+ def self.update_state(plan_name, options = {})
37
+ plan_store.run_lock(plan_name) do
38
+ state_store = Dopv::StateStore.new(plan_name, plan_store)
39
+ state_store.update(options)
40
+ end
41
+ end
42
+
43
+ def self.remove(plan_name, remove_dopi_state = true, remove_dopv_state = false)
44
+ plan_store.remove(plan_name, remove_dopi_state, remove_dopv_state)
45
+ end
46
+
47
+ def self.list
48
+ plan_store.list
49
+ end
50
+
51
+ def self.deploy(plan_name, options = {})
52
+ run(:deploy, plan_name, options)
53
+ end
54
+
55
+ def self.undeploy(plan_name, options = {})
56
+ run(:undeploy, plan_name, options)
57
+ end
58
+
59
+ def self.refresh(plan_name, options = {})
60
+ run(:refresh, plan_name, options)
61
+ end
62
+
63
+ def self.export_state(plan_name)
64
+ ensure_plan_exists(plan_name)
65
+ state_store = Dopv::StateStore.new(plan_name, plan_store)
66
+ state_store.export
67
+ end
68
+
69
+ def self.export_state_file(plan_name, state_file)
70
+ ensure_plan_exists(plan_name)
71
+ File.open(state_file, 'w+') do |diskdb|
72
+ diskdb << YAML.dump(Dopv.export_state(plan_name))
73
+ end
74
+ end
75
+
76
+ def self.import_state(plan_name, data_volumes_db)
77
+ ensure_plan_exists(plan_name)
78
+ plan_store.run_lock(plan_name) do
79
+ state_store = Dopv::StateStore.new(plan_name, plan_store)
80
+ state_store.import(data_volumes_db)
81
+ end
82
+ end
83
+
84
+ def self.import_state_file(plan_name, state_file)
85
+ ensure_plan_exists(plan_name)
86
+ Dopv.import_state(plan_name, YAML.load_file(state_file))
87
+ end
88
+
89
+ private
90
+
91
+ def self.plan_store
92
+ @plan_store ||= DopCommon::PlanStore.new(DopCommon.config.plan_store_dir)
93
+ end
94
+
95
+ def self.ensure_plan_exists(plan_name)
96
+ unless plan_store.list.include?(plan_name)
97
+ raise StandardError, "The plan #{plan_name} does not exist in the plan store"
98
+ end
99
+ end
100
+
101
+ def self.get_plan(plan_name)
102
+ raise StandardError, 'Please update the plan state, there are pending updates' if pending_updates?(plan_name)
103
+ plan_parser = plan_store.get_plan(plan_name)
104
+ Dopv::Plan.new(plan_parser)
105
+ end
106
+
107
+ def self.pending_updates?(plan_name)
108
+ state_store = Dopv::StateStore.new(plan_name, plan_store)
109
+ state_store.pending_updates?
110
+ end
111
+
112
+ def self.run(operation, plan_name, options)
113
+ ensure_plan_exists(plan_name)
114
+ update_state(plan_name)
115
+ plan = get_plan(plan_name)
116
+ run_options = merge_default_options(options)
117
+ nodes = filter_nodes(plan.nodes, run_options[:run_for_nodes])
118
+
119
+ context_log_path = File.join(DopCommon.config.log_dir, "#{run_options[:run_id]}-#{plan_name}")
120
+ node_names = nodes.map{|n| n.name}
121
+ context_logger = DopCommon::ThreadContextLogger.new(context_log_path, node_names)
122
+
123
+ plan_store.run_lock(plan_name) do
124
+ state_store = Dopv::StateStore.new(plan_name, plan_store)
125
+ in_parallel(plan, nodes) do |node|
126
+ context_logger.log_context = node.name
127
+ case operation
128
+ when :deploy then Dopv::Infrastructure::bootstrap_node(node, state_store)
129
+ when :undeploy then Dopv::Infrastructure::destroy_node(node, state_store, run_options[:rmdisk])
130
+ when :refresh then Dopv::Infrastructure::refresh_node(node, state_store)
131
+ end
132
+ end
133
+ end
134
+ end
135
+
136
+ def self.merge_default_options(options)
137
+ {
138
+ :run_for_nodes => :all,
139
+ :rmdisk => false,
140
+ :run_id => Time.now.strftime('%Y%m%d-%H%M%S'),
141
+ }.merge(options)
142
+ end
143
+
144
+ def self.in_parallel(plan, nodes)
145
+ errors = false
146
+ infras = nodes.group_by {|node| node.infrastructure}
147
+ Parallel.each(infras.keys, :in_threads => infras.keys.length) do |infra|
148
+ Dopv.log.debug("Spawning control thread for infra #{infra.name}")
149
+ max_in_flight = infra.max_in_flight || plan.max_in_flight || DEFAULT_MAX_IN_FLIGHT
150
+ Dopv.log.debug("Threads for infra #{infra.name}: #{max_in_flight}")
151
+ Parallel.each(infras[infra], :in_threads => max_in_flight) do |node|
152
+ Dopv.log.debug("Spawning thread for node #{node.name}.")
153
+ begin
154
+ Dopv.log.debug("Yielding node #{node.name}.")
155
+ yield(node)
156
+ rescue => e
157
+ errors = true
158
+ Dopv.log.error("There was an error while processing node #{node.name}: #{e}")
159
+ raise Parallel::Break
160
+ end
161
+ end
162
+ end
163
+ raise "Errors detected during plan run" if errors
164
+ end
165
+
166
+ end
@@ -0,0 +1,54 @@
1
+ #
2
+ # DOPv command line main module
3
+ #
4
+
5
+ require 'gli'
6
+ require 'dop_common/cli/node_selection'
7
+ require 'dop_common/cli/log'
8
+ require 'dop_common/cli/global_options'
9
+ require 'dopv'
10
+ require 'dopv/cli/command_validate'
11
+ require 'dopv/cli/command_add'
12
+ require 'dopv/cli/command_remove'
13
+ require 'dopv/cli/command_list'
14
+ require 'dopv/cli/command_update'
15
+ require 'dopv/cli/command_import'
16
+ require 'dopv/cli/command_export'
17
+ require 'dopv/cli/command_run'
18
+ require 'logger/colors'
19
+
20
+ module Dopv
21
+ module Cli
22
+ include GLI::App
23
+ extend self
24
+
25
+ trace = false
26
+
27
+ program_desc 'DOPv command line tool'
28
+ version Dopv::VERSION
29
+
30
+ subcommand_option_handling :normal
31
+ arguments :strict
32
+
33
+ DopCommon::Cli.global_options(self)
34
+
35
+ pre do |global,command,options,args|
36
+ DopCommon.configure = global
37
+ ENV['GLI_DEBUG'] = 'true' if global[:trace] == true
38
+ DopCommon::Cli.initialize_logger('dopv.log', global[:log_level], global[:verbosity], global[:trace])
39
+ true
40
+ end
41
+
42
+ command_validate(self)
43
+ command_add(self)
44
+ command_remove(self)
45
+ command_list(self)
46
+ command_update(self)
47
+ command_import(self)
48
+ command_export(self)
49
+ command_run(self, :deploy)
50
+ command_run(self, :undeploy)
51
+ command_run(self, :refresh)
52
+
53
+ end
54
+ end