dopi 0.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (149) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/CHANGELOG.md +322 -0
  6. data/Gemfile +7 -0
  7. data/Gemfile.lock +102 -0
  8. data/LICENSE.txt +177 -0
  9. data/README.md +309 -0
  10. data/Rakefile +44 -0
  11. data/Vagrantfile +64 -0
  12. data/bin/dopi +4 -0
  13. data/doc/getting_started.md +247 -0
  14. data/doc/getting_started_examples/001_hello_world.yaml +17 -0
  15. data/doc/getting_started_examples/002_connecting_over_ssh.yaml +35 -0
  16. data/doc/plugins/custom.md +88 -0
  17. data/doc/plugins/mco/rpc.md +82 -0
  18. data/doc/plugins/ssh/custom.md +141 -0
  19. data/doc/plugins/ssh/file_contains.md +37 -0
  20. data/doc/plugins/ssh/file_deploy.md +52 -0
  21. data/doc/plugins/ssh/file_exists.md +31 -0
  22. data/doc/plugins/ssh/file_replace.md +37 -0
  23. data/doc/plugins/ssh/puppet_agent_run.md +50 -0
  24. data/doc/plugins/ssh/reboot.md +22 -0
  25. data/doc/plugins/ssh/wait_for_login.md +53 -0
  26. data/doc/plugins/winrm/cmd.md +161 -0
  27. data/doc/plugins/winrm/file_contains.md +39 -0
  28. data/doc/plugins/winrm/file_exists.md +31 -0
  29. data/doc/plugins/winrm/powershell.md +27 -0
  30. data/doc/plugins/winrm/puppet_agent_run.md +49 -0
  31. data/doc/plugins/winrm/reboot.md +17 -0
  32. data/doc/plugins/winrm/wait_for_login.md +55 -0
  33. data/dopi.gemspec +42 -0
  34. data/lib/dopi/cli/command_add.rb +35 -0
  35. data/lib/dopi/cli/command_list.rb +19 -0
  36. data/lib/dopi/cli/command_remove.rb +31 -0
  37. data/lib/dopi/cli/command_reset.rb +27 -0
  38. data/lib/dopi/cli/command_run.rb +68 -0
  39. data/lib/dopi/cli/command_show.rb +109 -0
  40. data/lib/dopi/cli/command_update.rb +37 -0
  41. data/lib/dopi/cli/command_validate.rb +27 -0
  42. data/lib/dopi/cli/global_options.rb +55 -0
  43. data/lib/dopi/cli/log.rb +33 -0
  44. data/lib/dopi/cli.rb +57 -0
  45. data/lib/dopi/command/custom.rb +52 -0
  46. data/lib/dopi/command/dummy.rb +27 -0
  47. data/lib/dopi/command/mco/rpc.rb +158 -0
  48. data/lib/dopi/command/ssh/custom.rb +48 -0
  49. data/lib/dopi/command/ssh/file_contains.rb +70 -0
  50. data/lib/dopi/command/ssh/file_deploy.rb +71 -0
  51. data/lib/dopi/command/ssh/file_exists.rb +54 -0
  52. data/lib/dopi/command/ssh/file_replace.rb +96 -0
  53. data/lib/dopi/command/ssh/puppet_agent_run.rb +63 -0
  54. data/lib/dopi/command/ssh/reboot.rb +50 -0
  55. data/lib/dopi/command/ssh/wait_for_login.rb +68 -0
  56. data/lib/dopi/command/winrm/cmd.rb +44 -0
  57. data/lib/dopi/command/winrm/file_contains.rb +66 -0
  58. data/lib/dopi/command/winrm/file_exists.rb +51 -0
  59. data/lib/dopi/command/winrm/powershell.rb +16 -0
  60. data/lib/dopi/command/winrm/puppet_agent_run.rb +61 -0
  61. data/lib/dopi/command/winrm/reboot.rb +33 -0
  62. data/lib/dopi/command/winrm/wait_for_login.rb +49 -0
  63. data/lib/dopi/command.rb +239 -0
  64. data/lib/dopi/command_parser/arguments.rb +38 -0
  65. data/lib/dopi/command_parser/credentials.rb +59 -0
  66. data/lib/dopi/command_parser/env.rb +37 -0
  67. data/lib/dopi/command_parser/exec.rb +27 -0
  68. data/lib/dopi/command_parser/exit_code.rb +73 -0
  69. data/lib/dopi/command_parser/output.rb +126 -0
  70. data/lib/dopi/command_set.rb +66 -0
  71. data/lib/dopi/connector/local.rb +77 -0
  72. data/lib/dopi/connector/ssh.rb +170 -0
  73. data/lib/dopi/connector/winrm.rb +167 -0
  74. data/lib/dopi/error.rb +43 -0
  75. data/lib/dopi/log.rb +18 -0
  76. data/lib/dopi/node.rb +70 -0
  77. data/lib/dopi/plan.rb +99 -0
  78. data/lib/dopi/pluginmanager.rb +62 -0
  79. data/lib/dopi/state.rb +226 -0
  80. data/lib/dopi/state_store.rb +155 -0
  81. data/lib/dopi/step.rb +227 -0
  82. data/lib/dopi/step_set.rb +70 -0
  83. data/lib/dopi/version.rb +3 -0
  84. data/lib/dopi.rb +165 -0
  85. data/spec/command_helper.rb +11 -0
  86. data/spec/fixtures/mco_client.cfg +26 -0
  87. data/spec/fixtures/plans/fail_on_timeout.yaml +20 -0
  88. data/spec/fixtures/plans/hello_world.yaml +34 -0
  89. data/spec/fixtures/plans/non_existing_node.yaml +26 -0
  90. data/spec/fixtures/plans/test_role_variable.yaml +29 -0
  91. data/spec/fixtures/puppet/Puppetfile +8 -0
  92. data/spec/fixtures/puppet/Puppetfile.lock +57 -0
  93. data/spec/fixtures/puppet/hiera.yaml +6 -0
  94. data/spec/fixtures/puppet/manifests/site.pp +52 -0
  95. data/spec/fixtures/test_configuration.yaml +54 -0
  96. data/spec/fixtures/test_credentials.yaml +11 -0
  97. data/spec/fixtures/test_deloyed_file.txt +5 -0
  98. data/spec/fixtures/test_infrastructure.yaml +12 -0
  99. data/spec/fixtures/test_nodes.yaml +45 -0
  100. data/spec/fixtures/testenv_plan.yaml +159 -0
  101. data/spec/integration/dopi/addrun_spec.rb +31 -0
  102. data/spec/integration/dopi/cli/command_run_spec.rb +38 -0
  103. data/spec/integration/dopi/cli/global_options_spec.rb +128 -0
  104. data/spec/integration/dopi/command_spec.rb +66 -0
  105. data/spec/integration/dopi/fail_check_plans/file_exists_fails.yaml +38 -0
  106. data/spec/integration/dopi/fail_check_plans/output_parser.yaml +39 -0
  107. data/spec/integration/dopi/fail_check_plans/powershell_fail.yaml +25 -0
  108. data/spec/integration/dopi/fail_check_plans/timeout.yaml +29 -0
  109. data/spec/integration/dopi/fail_check_plans/verify_commands.yaml +33 -0
  110. data/spec/integration/dopi/failplan.rb +27 -0
  111. data/spec/integration/dopi/plan.rb +27 -0
  112. data/spec/integration/dopi/plans/dummy.yaml +29 -0
  113. data/spec/integration/dopi/plans/max_per_role.yaml +55 -0
  114. data/spec/integration/dopi/plans/no_timeout.yaml +29 -0
  115. data/spec/integration/dopi/plans/node_and_role_patterns.yaml +58 -0
  116. data/spec/integration/dopi/plans/node_by_config.yaml +116 -0
  117. data/spec/integration/dopi/plans/plugin_defaults.yaml +86 -0
  118. data/spec/integration/dopi/plans/plugins/mco/rpc.yaml +33 -0
  119. data/spec/integration/dopi/plans/plugins/ssh/custom.yaml +97 -0
  120. data/spec/integration/dopi/plans/plugins/ssh/file_contains.yaml +51 -0
  121. data/spec/integration/dopi/plans/plugins/ssh/file_deploy.yaml +82 -0
  122. data/spec/integration/dopi/plans/plugins/ssh/file_exists.yaml +69 -0
  123. data/spec/integration/dopi/plans/plugins/ssh/file_replace.yaml +55 -0
  124. data/spec/integration/dopi/plans/plugins/ssh/puppet_agent_run.yaml +45 -0
  125. data/spec/integration/dopi/plans/plugins/ssh/reboot.yaml +43 -0
  126. data/spec/integration/dopi/plans/plugins/ssh/wait_for_login.yaml +45 -0
  127. data/spec/integration/dopi/plans/plugins/winrm/cmd.yaml +39 -0
  128. data/spec/integration/dopi/plans/plugins/winrm/file_contains.yaml +51 -0
  129. data/spec/integration/dopi/plans/plugins/winrm/file_exists.yaml +69 -0
  130. data/spec/integration/dopi/plans/plugins/winrm/reboot.yaml +31 -0
  131. data/spec/integration/dopi/plans/resolve_roles_on_validate.yaml +23 -0
  132. data/spec/integration/dopi/plans/ssh_parallel.yaml +37 -0
  133. data/spec/integration/dopi/plans/verify_commands.yaml +49 -0
  134. data/spec/spec_helper.rb +104 -0
  135. data/spec/unit/dopi/command/custom_spec.rb +58 -0
  136. data/spec/unit/dopi/command/mco/rpc_spec.rb +157 -0
  137. data/spec/unit/dopi/command/ssh/custom_spec.rb +30 -0
  138. data/spec/unit/dopi/command/ssh/file_deploy_spec.rb +42 -0
  139. data/spec/unit/dopi/command/ssh/file_replace_spec.rb +35 -0
  140. data/spec/unit/dopi/command_parser/credentials_spec.rb +53 -0
  141. data/spec/unit/dopi/command_parser/exit_code_spec.rb +63 -0
  142. data/spec/unit/dopi/command_parser/output_spec.rb +129 -0
  143. data/spec/unit/dopi/command_spec.rb +14 -0
  144. data/spec/unit/dopi/connector/winrm_spec.rb +111 -0
  145. data/spec/unit/dopi/node_spec.rb +24 -0
  146. data/spec/unit/dopi/plan_spec.rb +31 -0
  147. data/spec/unit/dopi/state_spec.rb +109 -0
  148. data/spec/unit/dopi/step_spec.rb +13 -0
  149. metadata +448 -0
data/README.md ADDED
@@ -0,0 +1,309 @@
1
+ # Dopi
2
+
3
+ DOPi is the "inner" part of the Deployment Orchestrater for Puppet (DOP).
4
+ It is the part that connects into your nodes and runs commands in a defined
5
+ order.
6
+
7
+ The main purpose of DOPi is to get your nodes into a state where they can
8
+ run Puppet or any other config management. It will also allows you to
9
+ orchestrate this Puppet runs so you can setup your nodes in the desired order.
10
+
11
+ DOPi orchestrates puppet runs, mco calls and custom commands over different nodes
12
+
13
+ DOPi uses a DOP plan file to find out what it has to run in what order on
14
+ which nodes. To learn more about the syntax of this DOP plan file make sure
15
+ you checkout the Documentation in [dop_common](https://github.com/swisscom/dop_common).
16
+
17
+ If you are new to DOPi make sure you check out the [getting started guide](doc/getting_started.md).
18
+
19
+ ## Change Log
20
+
21
+ Dopi is currently under heavy development and should not be considered stable. If you are
22
+ upgrading make sure you carefully ready the [Change Log](CHANGELOG.md)
23
+
24
+ ## DOPi as a library
25
+
26
+ ### Install
27
+
28
+ Add this line to your application's Gemfile:
29
+
30
+ gem 'dopi'
31
+
32
+ And then execute:
33
+
34
+ $ bundle
35
+
36
+ ### Usage Example
37
+
38
+ require 'dopi'
39
+
40
+ Dopi.configure do |config|
41
+ config.role_variable = 'my_role'
42
+ config.role_default = 'base'
43
+ end
44
+
45
+ plan_parser = DopCommon::Plan.new(YAML.load_file(plan_file))
46
+ plan = Dopi::Plan.new(plan_parser)
47
+ plan.run
48
+
49
+ puts "Plan status: #{plan.state.to_s}"
50
+ plan.steps.each do |step|
51
+ puts "[#{step.state.to_s}] #{step.name}"
52
+ step.commands.each do |command|
53
+ puts " [#{command.state.to_s}] #{command.node.fqdn}"
54
+ end
55
+ end
56
+
57
+ #### With DOP plan cache
58
+
59
+ This will persist the plan in the DOP plan cache.
60
+
61
+ require 'dopi'
62
+
63
+ Dopi.configure do |config|
64
+ config.role_variable = 'my_role'
65
+ config.role_default = 'base'
66
+ end
67
+
68
+ plan = Dopi.add_plan(plan_file)
69
+ Dopi.run_plan(plan)
70
+
71
+ puts "Plan status: #{plan.state.to_s}"
72
+ plan.steps.each do |step|
73
+ puts "[#{step.state.to_s}] #{step.name}"
74
+ step.commands.each do |command|
75
+ puts " [#{command.state.to_s}] #{command.node.fqdn}"
76
+ end
77
+ end
78
+
79
+ ### DOPi as a CLI
80
+
81
+ ### Install
82
+
83
+ Install the gem
84
+
85
+ $ gem install dopi
86
+
87
+ Help on all available options
88
+
89
+ $ dopi help
90
+
91
+ ### Usage Example
92
+
93
+ First you have to add a plan to the plan cache:
94
+
95
+ $ dopi add spec/data/plan/example_deploment_plan_test.yaml
96
+ example_deploment_plan_test
97
+
98
+ This will return the plan name which can be used to run other
99
+ commands on that plan. You can get a list of all the plans in the
100
+ cache by running:
101
+
102
+ $ dopi list
103
+ example_deploment_plan_test
104
+
105
+ You can get information about the state of a plan with the show command
106
+ and the name of the plan:
107
+
108
+ $ dopi show example_deploment_plan_test
109
+ [ready] test_run
110
+ [ready] mysql01.example.com
111
+ [ready] web01.example.com
112
+ [ready] web02.example.com
113
+ [ready] haproxy01.example.com
114
+ [ready] haproxy02.example.com
115
+ [ready] Make sure we can login to all nodes
116
+ [ready] mysql01.example.com
117
+ [ready] web01.example.com
118
+ [ready] web02.example.com
119
+ [ready] haproxy01.example.com
120
+ [ready] haproxy02.example.com
121
+ [ready] ssh_test_run
122
+ [ready] mysql01.example.com
123
+ [ready] run_puppet
124
+ [ready] mysql01.example.com
125
+ [ready] web01.example.com
126
+ [ready] web02.example.com
127
+ [ready] haproxy01.example.com
128
+ [ready] haproxy02.example.com
129
+ [ready] run_puppet2
130
+ [ready] mysql01.example.com
131
+ [ready] web01.example.com
132
+ [ready] web02.example.com
133
+ [ready] haproxy01.example.com
134
+ [ready] haproxy02.example.com
135
+
136
+ You can run the plan with the run command and the name:
137
+
138
+ $ dopi run example_deploment_plan_test
139
+
140
+
141
+ ## Plan File Format
142
+
143
+ For a general description of the DOP plan file format, please see the
144
+ [dop_common](https://github.com/swisscom/dop_common/blob/master/README.md)
145
+ documentation. The documentation in this gem will focus on the command hashes for all
146
+ the basic plugins which are shipped with DOPi and on how to create your own custom plugins.
147
+
148
+ ### How to use Plugins
149
+
150
+ DOPi uses plugins to run commands on the nodes. Each step in the plan has one
151
+ command and as many verify_commands as needed. DOPi will run all the verify_commands
152
+ before the command and will run the command only if one of them fails.
153
+
154
+ In general a plugin is specified like this:
155
+
156
+ ```YAML
157
+ - name "My new Step"
158
+ nodes: 'all'
159
+ command:
160
+ plugin: 'my_plugin_name'
161
+ parameter1: 'foo'
162
+ parameter2: 'bar'
163
+ ```
164
+
165
+ Some of the Plugins don't actually need parameters, so they can be called with the short form:
166
+
167
+ ```YAML
168
+ - name "My new Step"
169
+ nodes: 'all'
170
+ command: 'my_simple_plugin'
171
+ ```
172
+
173
+ ### Verify Commands
174
+
175
+ It is usually a good idea to check if a step is required to run. This way you can make your
176
+ plans idempotent. You can define any number of verify commands. If they all are successful
177
+ DOPi will skip the run. There are a hand full of plugins who are written exactly for this
178
+ purpose.
179
+
180
+ ```YAML
181
+ - name "Create file if it does not exist"
182
+ command:
183
+ verify_commands:
184
+ - plugin; 'ssh/file_exists'
185
+ file: '/tmp/somefile'
186
+ plugin: 'ssh/custom'
187
+ exec: 'echo'
188
+ arguments: "'Hello World' > /tmp/somefile"
189
+ ```
190
+
191
+ ### Generic Plugin Parameters
192
+
193
+ There are some generic parameters every plugin supports:
194
+
195
+ #### plugin_timeout (optional)
196
+
197
+ `default: 300`
198
+
199
+ The time in seconds after which DOPi will kill the thread and mark the step as failed.
200
+
201
+ #### verify_after_run (optional)
202
+
203
+ `default: false`
204
+
205
+ The verify commands will be executed again after the command run and the step will
206
+ only succeed if the verify commands all successful.
207
+
208
+ ### Command Execution Plugins
209
+
210
+ This are the plugins generally used in steps as commands
211
+
212
+ [custom](doc/plugins/custom.md)
213
+
214
+ [ssh/custom](doc/plugins/ssh/custom.md)
215
+
216
+ [ssh/wait_for_login](doc/plugins/ssh/wait_for_login.md)
217
+
218
+ [ssh/reboot](doc/plugins/ssh/reboot.md)
219
+
220
+ [ssh/puppet_agent_run](doc/plugins/ssh/puppet_agent_run.md)
221
+
222
+ [ssh/file_replace](doc/plugins/ssh/file_replace.md)
223
+
224
+ [ssh/file_deploy](doc/plugins/ssh/file_deploy.md)
225
+
226
+ [mco/rpc](doc/plugins/mco/rpc.md)
227
+
228
+ [winrm/cmd](doc/plugins/winrm/cmd.md)
229
+
230
+ [winrm/powershell](doc/plugins/winrm/powershell.md)
231
+
232
+ [winrm/wait_for_login](doc/plugins/winrm/wait_for_login.md)
233
+
234
+ [winrm/reboot](doc/plugins/winrm/reboot.md)
235
+
236
+ [winrm/puppet_agent_run](doc/plugins/winrm/puppet_agent_run.md)
237
+
238
+ ### Verification Plugins
239
+
240
+ This are some helper plugins that check stuff on the nodes. They are
241
+ usefull for verify_commands. However, every normal plugin can be used
242
+ as a verify_command and vice versa.
243
+
244
+ [ssh/file_contains](doc/plugins/ssh/file_contains.md)
245
+
246
+ [ssh/file_exists](doc/plugins/ssh/file_exists.md)
247
+
248
+ [winrm/file_contains](doc/plugins/winrm/file_contains.md)
249
+
250
+ [winrm/file_exists](doc/plugins/winrm/file_exists.md)
251
+
252
+ ## Example Plans
253
+
254
+ There are some examples for DOPi in the sources which are also used for tests
255
+
256
+ [DOPi test environment setup](spec/integration/dopi/build_dop_test_environment.yaml)
257
+
258
+ More can be found in the plans directory.
259
+
260
+ ## Contributing
261
+
262
+ 1. Fork it
263
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
264
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
265
+ 4. Push to the branch (`git push origin my-new-feature`)
266
+ 5. Create new Pull Request
267
+
268
+ ### Run the test suit
269
+
270
+ Most of the tests depend on Vagrant to create an actual test environment where the DOPi
271
+ plugins can be tested under real conditions.
272
+
273
+ To setup the test suit you need a working vagrant (https://www.vagrantup.com/) installation
274
+ with the dop_common gem added as a plugin:
275
+
276
+ cd /tmp
277
+ git clone https://github.com/swisscom/dop_common.git
278
+ cd dop_common
279
+ gem build dop_common.gemspec
280
+ vagrant plugin install ./dop_common-*.gem
281
+
282
+ After you install the plugin you have to setup the test machines with the rake task:
283
+
284
+ cd /path/to/dopi/
285
+ bundle install --path .bundle
286
+ bundle exec rake spec:prep
287
+
288
+ You should always rerun 'spec:prep' to make sure your test environment is started
289
+ and setup correctly.
290
+
291
+ The tests will connect to the machines and for now you require some hosts file entries
292
+ to work correctly. Add the following lines to your /etc/hosts:
293
+
294
+ # Host entries for DOPi test environment
295
+ 192.168.56.101 puppetmaster.example.com
296
+ 192.168.56.102 broker.example.com
297
+ 192.168.56.103 linux01.example.com
298
+ 192.168.56.104 linux02.example.com
299
+ 192.168.56.105 linux03.example.com
300
+ 192.168.56.106 windows01.example.com
301
+
302
+ Now you are ready to run the test suit:
303
+
304
+ bundle exec rake
305
+
306
+ If you reboot your machine or stop the test machines you can make sure the test
307
+ environment is ready and built by simply running the setup again:
308
+
309
+ bundle exec rake testenv:setup
data/Rakefile ADDED
@@ -0,0 +1,44 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ namespace :spec do
4
+ desc 'setup the test environment (this builds multiple virtual machines with vagrant and virtualbox)'
5
+ task :prep do
6
+ Bundler.with_clean_env do
7
+ sh('vagrant up')
8
+ hiera = 'spec/fixtures/puppet/hiera.yaml'
9
+ plan = 'spec/fixtures/testenv_plan.yaml'
10
+ sh('bundle package --all')
11
+ sh("bundle exec bin/dopi --verbosity debug --trace --hiera_yaml #{hiera} oneshot #{plan}")
12
+ end
13
+ end
14
+
15
+ desc 'destory the test environment'
16
+ task :clean do
17
+ Bundler.with_clean_env do
18
+ sh('vagrant destroy')
19
+ end
20
+ end
21
+
22
+ RSpec::Core::RakeTask.new(:unit) do |t|
23
+ t.pattern = 'spec/unit/**/*_spec.rb'
24
+ end
25
+
26
+ RSpec::Core::RakeTask.new(:integration) do |t|
27
+ t.pattern = 'spec/integration/**/*_spec.rb'
28
+ end
29
+
30
+ desc 'Run single plan file from spec/integration/dopi/plans/<name>.yaml, <name> is taken from env DOPI_TEST_PLAN'
31
+ RSpec::Core::RakeTask.new(:plan) do |t|
32
+ t.pattern = 'spec/integration/dopi/plan.rb'
33
+ end
34
+
35
+ desc 'Run single plan file from spec/integration/dopi/fail_check_plans/<name>.yaml and expect it to fail, <name> is taken from env DOPI_TEST_PLAN'
36
+ RSpec::Core::RakeTask.new(:failplan) do |t|
37
+ t.pattern = 'spec/integration/dopi/failplan.rb'
38
+ end
39
+ end
40
+
41
+ RSpec::Core::RakeTask.new(:spec)
42
+
43
+ task :default => :spec
44
+
data/Vagrantfile ADDED
@@ -0,0 +1,64 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ # This will create the dop test machines with from a dop plan
5
+ # Please make sure you have installed dop_common as a Vagrant plugin
6
+ #
7
+ # $ vagrant plugin install path/to/dop_common-x.x.x.gem
8
+ #
9
+ require 'dop_common'
10
+
11
+ DOP_PLAN = 'spec/fixtures/testenv_plan.yaml'
12
+
13
+ hash = YAML.load(DopCommon::PreProcessor.load_plan(DOP_PLAN))
14
+ plan = DopCommon::Plan.new(hash)
15
+
16
+ Vagrant.configure(2) do |config|
17
+
18
+ # Create vagrant boxes from the plan file
19
+ plan.nodes.each do |node|
20
+
21
+ config.vm.define node.name do |machine|
22
+ machine.vm.box = node.image
23
+
24
+ interface = node.interfaces.first
25
+ machine.vm.network "private_network", ip: interface.ip
26
+
27
+ # windows/linux specific settings
28
+ if node.name[/^windows/, 0]
29
+ machine.vm.guest = :windows
30
+ machine.vm.hostname = node.name.split('.', 2)[0]
31
+ else
32
+ machine.vm.hostname = node.name
33
+ end
34
+
35
+ # disable the default folder sync on the nodes
36
+ # and rsync all the stuff to the puppetmaster
37
+ if node.name == 'puppetmaster.example.com'
38
+ config.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: ".bundle/"
39
+ else
40
+ config.vm.synced_folder ".", "/vagrant", disabled: true
41
+ end
42
+ end
43
+ end
44
+
45
+
46
+ # Test run nodes
47
+ config.vm.define 'rhel6.example.com' do |machine|
48
+ machine.vm.box = 'puppetlabs/centos-6.6-64-nocm'
49
+ machine.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: ".bundle/"
50
+ machine.vm.provision 'shell', inline: 'yum install -y gcc git epel-release centos-release-scl'
51
+ machine.vm.provision 'shell', inline: 'yum install -y ncurses-devel sshpass'
52
+ machine.vm.provision 'shell', inline: 'yum install -y rh-ruby22 rh-ruby22-ruby-devel rh-ruby22-rubygem-bundler'
53
+ end
54
+
55
+ config.vm.define 'rhel7.example.com' do |machine|
56
+ machine.vm.box = 'puppetlabs/centos-7.0-64-nocm'
57
+ machine.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: ".bundle/"
58
+ machine.vm.provision 'shell', inline: 'yum install -y gcc git centos-release-scl'
59
+ machine.vm.provision 'shell', inline: 'yum install -y ncurses-devel sshpass'
60
+ machine.vm.provision 'shell', inline: 'yum install -y rh-ruby22 rh-ruby22-ruby-devel rh-ruby22-rubygem-bundler'
61
+ end
62
+
63
+ end
64
+
data/bin/dopi ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'dopi/cli'
4
+ exit Dopi::Cli.run(ARGV)
@@ -0,0 +1,247 @@
1
+ # Getting started with DOPi
2
+
3
+ This guide is a good starting point if you are new to DOPi and want to
4
+ learn how to use it to automate your node provisioning.
5
+
6
+ To start make sure you installed DOPi according to the instructions in
7
+ the [README](README.md).
8
+
9
+ You will find all the examples written in this tutorial in the example
10
+ directory next to this file.
11
+
12
+ ## Hello World
13
+
14
+ Let's start with a typical hello world plan file and analyze what
15
+ parts are required to actually use DOPi. Use your favored editor to
16
+ create a file called 'hello_world.yaml' with the following content:
17
+
18
+ name: 'hello_world'
19
+
20
+ infrastructures:
21
+ 'test':
22
+ type: 'baremetal'
23
+
24
+ nodes:
25
+ 'testlinux.example.com':
26
+ infrastructure: 'test'
27
+
28
+ steps:
29
+ - name: 'write hello world'
30
+ nodes: 'all'
31
+ command:
32
+ plugin: 'custom'
33
+ exec: 'echo'
34
+ arguments: '"hello world"'
35
+
36
+ Now let's try to use DOPi to run that plan. There are usually a
37
+ few steps required to run a plan. Here is what you have to do:
38
+
39
+ $ dopi add hello_world.yaml
40
+ New plan hello_world was added
41
+ hello_world
42
+
43
+ We just added the 'hello_world' plan to our plan cache. DOPi tells
44
+ us that this was successful and returns the handle 'hello_world'.
45
+ We will require this handle to do other stuff with the plan we
46
+ just added. The handle is in fact the same as the 'name' attribute
47
+ at the very top of the plan file. It is always good to chose a name
48
+ which describes best what the content is. You can use letters,
49
+ numbers, '-' and '_' but no spaces or any other kind of character in
50
+ the name.
51
+
52
+ The plan cache is just a directory which holds all your added plans
53
+ and some files for the state of the plans. This cache will also be
54
+ used by the dop-hiera plugin if you have any configuration data in
55
+ your plans (more on this later).
56
+
57
+ The standard directory for the plan cache is ~/.dop/cache if you run
58
+ DOPi as user or /var/lib/dop/plans if you run it as root. You can also
59
+ overwrite this with the global '--plan_cache_dir' option.
60
+
61
+ To list what plans are already added in your plan cache you can simply
62
+ list them with DOPi:
63
+
64
+ $ dopi list
65
+ hello_world
66
+
67
+ We can see that it contains our 'hello_world' plan file. To see what
68
+ the state of the plan is and what steps are defined we can show
69
+ the content of the plan with DOPi:
70
+
71
+ $ dopi show hello_world
72
+ [ready] hello_world
73
+ [ready] default
74
+ [ready] write hello world
75
+ [ready] testlinux.example.com
76
+
77
+ Now we see a whole hierarchy with every part in the state 'ready'.
78
+ The first line represents the state of the whole plan. You can only
79
+ run a plan which is in the state ready. If part of the plan is in
80
+ the state 'failed' it will reflect that in the plan state.
81
+
82
+ The second line represents the step set. You can separate your steps
83
+ in your plan into different sets, so they can be executed independendly
84
+ of eachother (more on that later). We did not specify a step set in our
85
+ hello_world.yaml, so DOPi will create a default step set for us.
86
+
87
+ The third line represents the step and it is named after the name
88
+ attribute we specified in the first step in the hello_world.yaml file.
89
+ A step is executed on a number of nodes and they are listed under each
90
+ step with their state, which represents the last line in the output.
91
+
92
+ So now that we know that our plan is ready we can execute it for the
93
+ first time. But maybe we want to check first what it actually does.
94
+ To accomplish this we run the plan in 'noop' mode first to see
95
+ exactly what commands get executed:
96
+
97
+ $ dopi run --noop hello_world
98
+ Starting signal handling
99
+ Starting to run step 'write hello world'
100
+ [Command] testlinux.example.com : Running command custom
101
+ [Command] testlinux.example.com : (NOOP) Executing 'echo "hello world"' for command custom
102
+ [Command] testlinux.example.com : (NOOP) Environment: {"DOP_NODE_FQDN"=>"testlinux.example.com"}
103
+ [ready] hello_world
104
+ [ready] default
105
+ [ready] write hello world
106
+ [ready] testlinux.example.com
107
+
108
+ Now you can see that DOPi will run the command 'echo "hello world"' as
109
+ we have specified in the plan file. Now let's remove the 'noop' option
110
+ and actually run it:
111
+
112
+ $ dopi run hello_world
113
+ Starting signal handling
114
+ Starting to run step 'write hello world'
115
+ [Command] testlinux.example.com : Running command custom
116
+ [Command] testlinux.example.com : custom [OK]
117
+ Step 'write hello world' successfully finished.
118
+ [done] hello_world
119
+ [done] default
120
+ [done] write hello world
121
+ [done] testlinux.example.com
122
+
123
+ DOPi successfully executed the plan and the state changed from 'ready'
124
+ to 'done'.
125
+
126
+ ## Connecting over SSH
127
+
128
+ Until now we only executed commands on the local machine. But the main
129
+ purpose of DOPi is to connect to a machine and execute some commands
130
+ to make it ready or execute a configuration management tool like Puppet.
131
+
132
+ To make it easy to demonstrate this we will use the ssh plugin like you
133
+ normaly would to connect to a remote machine, but we will configure DOPi
134
+ so it actually connect to localhost.
135
+
136
+ First we add a network to the infrastructures hash:
137
+
138
+ infrastructures:
139
+ 'test':
140
+ type: 'baremetal'
141
+ networks:
142
+ 'localhost':
143
+ ip_pool:
144
+ from: '127.0.0.2'
145
+ to: '127.0.0.250'
146
+ ip_netmask: '255.255.255.0'
147
+ ip_defgw: '127.0.0.1'
148
+
149
+ We defined the network 'localhost' and a range of IPs. Now we have to
150
+ add our existing machine into this network by adding a network interface:
151
+
152
+ nodes:
153
+ 'testlinux.example.com':
154
+ infrastructure: 'test'
155
+ interfaces:
156
+ 'eth0':
157
+ network: 'localhost'
158
+ ip: '127.0.0.2'
159
+
160
+ Then we need to make sure we can access the local machine with SSH. We
161
+ have to provide some credentials to login to the machine. This is done
162
+ in the credentials hash:
163
+
164
+ credentials:
165
+ 'test-credentials':
166
+ type: 'ssh_key'
167
+ username: 'myuser'
168
+ private_key: '/home/myuser/.ssh/id_rsa'
169
+
170
+ In this case we will use an SSH private key to connect to local host.
171
+ Make sure your public key is in your '~/.ssh/authorized_keys' file.
172
+ You can also define a username/password pair if you don't want to use
173
+ a private key, make sure you check the syntax in the documentation.
174
+
175
+ Now we change the plugin in the step and use the 'ssh/custom' plugin
176
+ instead of 'custom'. DOPi will now connect to the node and execute
177
+ the command via SSH. We also need to tell the plugin what credentials
178
+ it should use. Make sure the step looks like this now:
179
+
180
+ steps:
181
+ - name: 'write hello world'
182
+ nodes: 'all'
183
+ command:
184
+ plugin: 'ssh/custom'
185
+ credentials: 'test-credentials'
186
+ exec: 'echo'
187
+ arguments: '"hello world"'
188
+
189
+ This tells DOPi to use the previously defined credentials to login to
190
+ the machine. Let's update the plan:
191
+
192
+ $ bundle exec dopi update --plan hello_world.yaml hello_world
193
+ Updating plan hello_world
194
+ Plan hello_world was removed
195
+ New plan hello_world was added
196
+ hello_world
197
+
198
+ Updating the plan will always reset the state of the the steps since
199
+ we may completely change them and there is no way for DOPi to know
200
+ what states should be preserves (This may change in the future).
201
+
202
+ Let's run in noop mode:
203
+
204
+ $ bundle exec dopi run --noop hello_world
205
+ Starting signal handling
206
+ Starting to run step 'write hello world'
207
+ [Command] testlinux.example.com : Running command ssh/custom
208
+ [Command] testlinux.example.com : (NOOP) Executing 'ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -q -o ChallengeResponseAuthentication=no -o PasswordAuthentication=no -i /home/myuser/.ssh/id_rsa myuser@127.0.0.2 "DOP_NODE_FQDN=testlinux.example.com echo \"hello world\""' for command ssh/custom
209
+ [Command] testlinux.example.com : (NOOP) Environment: {"DOP_NODE_FQDN"=>"testlinux.example.com"}
210
+ [ready] hello_world
211
+ [ready] default
212
+ [ready] write hello world
213
+ [ready] testlinux.example.com
214
+
215
+ We see that DOPi will actually use ssh to connect to the node and
216
+ execute the step.
217
+
218
+ $ bundle exec dopi run hello_world
219
+ Starting signal handling
220
+ Starting to run step 'write hello world'
221
+ [Command] testlinux.example.com : Running command ssh/custom
222
+ [Command] testlinux.example.com : ssh/custom [OK]
223
+ Step 'write hello world' successfully finished.
224
+ [done] hello_world
225
+ [done] default
226
+ [done] write hello world
227
+ [done] testlinux.example.com
228
+
229
+ We can successfully run the step.
230
+
231
+ ## Idempotency
232
+
233
+ As we have seen before if we update a plan we lose the state and
234
+ have to rerun all the steps. Sometimes this may not be what we want.
235
+ In any case, it is always good practice to write your steps in a way
236
+ so you can rerun them as many times as you want.
237
+
238
+ In DOPi this is made easy with verification commands which run prior
239
+ to the actual command and check if we can skip the step or not.
240
+
241
+
242
+
243
+ DOPi oneshot adds the plan to the plan cache, runs it and at the
244
+ end removes it from the cache again. We will learn more about the
245
+ different methods to run a plan later, for now we will use the
246
+ oneshot command because it is useful to test or if you don't care
247
+ about the state of a plan.
@@ -0,0 +1,17 @@
1
+ name: 'hello_world'
2
+
3
+ infrastructures:
4
+ 'test':
5
+ type: 'baremetal'
6
+
7
+ nodes:
8
+ 'testlinux.example.com':
9
+ infrastructure: 'test'
10
+
11
+ steps:
12
+ - name: 'write hello world'
13
+ nodes: 'all'
14
+ command:
15
+ plugin: 'custom'
16
+ exec: 'echo'
17
+ arguments: '"hello world"'