dopv 0.11.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 (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