dopi 0.17.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 (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"'