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
@@ -0,0 +1,71 @@
1
+ #
2
+ # DOPi Plugin: Deploy File
3
+ #
4
+ require 'pathname'
5
+ require "base64"
6
+
7
+ module Dopi
8
+ class Command
9
+ class Ssh
10
+ class FileDeploy < Dopi::Command
11
+ include DopCommon::HashParser
12
+ include Dopi::Connector::Ssh
13
+ include Dopi::CommandParser::ExitCode
14
+
15
+ public
16
+
17
+ def validate
18
+ validate_ssh
19
+ validate_exit_code
20
+ log_validation_method('file_valid?', CommandParsingError)
21
+ log_validation_method('content_valid?', CommandParsingError)
22
+ end
23
+
24
+ def run
25
+ cmd_stdout, cmd_stderr, cmd_exit_code = ssh_command({}, command_string)
26
+ check_exit_code(cmd_exit_code)
27
+ end
28
+
29
+ def run_noop
30
+ log(:info, "(NOOP) Executing '#{command_string}' for command #{name}")
31
+ end
32
+
33
+ def file
34
+ file_valid? ? hash[:file] : nil
35
+ end
36
+
37
+ def content
38
+ content_valid? ? load_content(hash[:content]) : nil
39
+ end
40
+
41
+ private
42
+
43
+ def command_string
44
+ "echo -n #{Base64.strict_encode64(content)} | base64 -d > #{file}"
45
+ end
46
+
47
+ def file_valid?
48
+ hash[:file] or
49
+ raise CommandParsingError, "Plugin #{name}: The key 'file' needs to be specified"
50
+ hash[:file].kind_of?(String) or
51
+ raise CommandParsingError, "Plugin #{name}: The value for key 'file' has to be a String"
52
+ begin
53
+ Pathname.new(hash[:file]).absolute? or
54
+ raise CommandParsingError, "Plugin #{name}: The path for 'file' has to be absolute"
55
+ rescue ArgumentError => e
56
+ raise CommandParsingError, "Plugin #{name}: The value in 'file' is not a valid file path: #{e.message}"
57
+ end
58
+ end
59
+
60
+ def content_valid?
61
+ hash[:content] or
62
+ raise CommandParsingError, "Plugin #{name}: The key 'content' needs to be specified"
63
+ load_content_valid?(hash[:content])
64
+ rescue DopCommon::PlanParsingError => e
65
+ raise CommandParsingError, "Plugin #{name}: value content not valid: #{e.message}"
66
+ end
67
+
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,54 @@
1
+ #
2
+ # DOPi Plugin: File Exists
3
+ #
4
+ require 'pathname'
5
+
6
+ module Dopi
7
+ class Command
8
+ class Ssh
9
+ class FileExists < Dopi::Command
10
+ include Dopi::Connector::Ssh
11
+ include Dopi::CommandParser::ExitCode
12
+
13
+ public
14
+
15
+ def validate
16
+ validate_ssh
17
+ validate_exit_code
18
+ log_validation_method('file_valid?', CommandParsingError)
19
+ end
20
+
21
+ def run
22
+ cmd_stdout, cmd_stderr, cmd_exit_code = ssh_command({}, command_string)
23
+ check_exit_code(cmd_exit_code)
24
+ end
25
+
26
+ def run_noop
27
+ log(:info, "(NOOP) Executing '#{command_string}' for command #{name}")
28
+ end
29
+
30
+ def file
31
+ @file ||= file_valid? ? hash[:file] : nil
32
+ end
33
+
34
+ private
35
+
36
+ def command_string
37
+ "[ -e #{file} ]"
38
+ end
39
+
40
+ def file_valid?
41
+ hash[:file] or
42
+ raise CommandParsingError, "Plugin #{name}: The key 'file' needs to be specified"
43
+ begin
44
+ Pathname.new(hash[:file]).absolute? or
45
+ raise CommandParsingError, "Plugin #{name}: The path for 'file' has to be absolute"
46
+ rescue ArgumentError => e
47
+ raise CommandParsingError, "Plugin #{name}: The value in 'file' is not a valid file path: #{e.message}"
48
+ end
49
+ end
50
+
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,96 @@
1
+ #
2
+ # DOPi Plugin: File Replace
3
+ #
4
+
5
+ module Dopi
6
+ class Command
7
+ class Ssh
8
+ class FileReplace < Dopi::Command
9
+ include Dopi::Connector::Ssh
10
+ include Dopi::CommandParser::ExitCode
11
+
12
+ public
13
+
14
+ def validate
15
+ validate_ssh
16
+ validate_exit_code
17
+ log_validation_method(:replacement_valid?, CommandParsingError)
18
+ log_validation_method(:global_valid?, CommandParsingError)
19
+ end
20
+
21
+ def run
22
+ cmd_stdout, cmd_stderr, cmd_exit_code = ssh_command({}, command_string)
23
+ check_exit_code(cmd_exit_code)
24
+ end
25
+
26
+ def run_noop
27
+ log(:info, "(NOOP) Executing '#{command_string}' for command #{name}")
28
+ end
29
+
30
+ def replacement
31
+ @replacement ||= replacement_valid? ?
32
+ hash[:replacement] : nil
33
+ end
34
+
35
+ def global
36
+ @global ||= global_valid? ?
37
+ hash[:global] : true
38
+ end
39
+
40
+ def file
41
+ @file ||= file_valid? ? hash[:file] : nil
42
+ end
43
+
44
+ def pattern
45
+ @pattern ||= pattern_valid? ?
46
+ hash[:pattern] : nil
47
+ end
48
+
49
+ private
50
+
51
+ def command_string
52
+ "sed -i \"s/#{pattern}/#{replacement}/#{global_string}\" #{file}"
53
+ end
54
+
55
+ def global_string
56
+ global ? 'g' : ''
57
+ end
58
+
59
+ def replacement_valid?
60
+ hash[:replacement] or
61
+ raise CommandParsingError, "Plugin #{name}: The key 'replacement' needs to be specified"
62
+ hash[:replacement].kind_of?(String) or
63
+ raise CommandParsingError, "Plugin #{name}: The value in 'replacement' has to be a String"
64
+ end
65
+
66
+ def global_valid?
67
+ return false if hash[:global].nil? # is optional
68
+ hash[:global].kind_of?(TrueClass) or hash[:global].kind_of?(FalseClass) or
69
+ raise CommandParsingError, "Plugin #{name}: The value for 'global' must be boolean"
70
+ end
71
+
72
+ def file_valid?
73
+ hash[:file] or
74
+ raise CommandParsingError, "Plugin #{name}: The key 'file' needs to be specified"
75
+ begin
76
+ Pathname.new(hash[:file]).absolute? or
77
+ raise CommandParsingError, "Plugin #{name}: The path for 'file' has to be absolute"
78
+ rescue ArgumentError => e
79
+ raise CommandParsingError, "Plugin #{name}: The value in 'file' is not a valid file path: #{e.message}"
80
+ end
81
+ end
82
+
83
+ def pattern_valid?
84
+ hash[:pattern] or
85
+ raise CommandParsingError, "Plugin #{name}: The key 'pattern' needs to be specified"
86
+ begin
87
+ Regexp.new(hash[:pattern])
88
+ rescue
89
+ raise CommandParsingError, "Plugin #{name}: The value in 'pattern' is not a valid regexp: #{e.message}"
90
+ end
91
+ end
92
+
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,63 @@
1
+ #
2
+ # SSH custom command
3
+ #
4
+ module Dopi
5
+ class Command
6
+ class Ssh
7
+ class PuppetAgentRun < Dopi::Command
8
+ include Dopi::Connector::Ssh
9
+ include Dopi::CommandParser::Env
10
+ include Dopi::CommandParser::Arguments
11
+ include Dopi::CommandParser::ExitCode
12
+ include Dopi::CommandParser::Output
13
+
14
+ public
15
+
16
+ def initialize(command_parser, step, node, is_verify_command)
17
+ command_parser.overwrite_defaults = { :plugin_timeout => 1800 }
18
+ super(command_parser, step, node, is_verify_command)
19
+ end
20
+
21
+ def validate
22
+ validate_ssh
23
+ validate_env
24
+ validate_arguments
25
+ validate_exit_code
26
+ validate_output
27
+ end
28
+
29
+ def run
30
+ cmd_stdout, cmd_stderr, cmd_exit_code = ssh_command(env, command_string)
31
+ check_output(cmd_stdout) &&
32
+ check_output(cmd_stderr) &&
33
+ check_exit_code(cmd_exit_code)
34
+ end
35
+
36
+ def run_noop
37
+ log(:info, "(NOOP) Executing '#{command_string}' for command #{name}")
38
+ end
39
+
40
+ def expect_exit_codes_defaults
41
+ [ 0, 2 ]
42
+ end
43
+
44
+ def parse_output_defaults
45
+ { :error => [
46
+ '^Error:'
47
+ ],
48
+ :warning => [
49
+ '^Warning:'
50
+ ]
51
+ }
52
+ end
53
+
54
+ private
55
+
56
+ def command_string
57
+ "puppet agent --test --color false #{arguments}"
58
+ end
59
+
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,50 @@
1
+ #
2
+ # DOPi Plugin: Reboot a node
3
+ #
4
+
5
+ module Dopi
6
+ class Command
7
+ class Ssh
8
+ class Reboot < Dopi::Command::Ssh::WaitForLogin
9
+
10
+ def validate
11
+ super
12
+ log_validation_method(:reboot_cmd_valid?, CommandParsingError)
13
+ end
14
+
15
+ def run
16
+ ssh_command({}, reboot_cmd)
17
+ connected = true
18
+ @connection_timeout = 1
19
+ while connected
20
+ begin connected = check_exit_code(ssh_command({}, 'exit')[2])
21
+ rescue Dopi::NodeConnectionError, Dopi::CommandConnectionError
22
+ connected = false
23
+ end
24
+ if connected
25
+ sleep 1
26
+ raise GracefulExit if signals[:stop]
27
+ log(:info, "Still able to login, waiting for shutdown")
28
+ end
29
+ end
30
+ log(:info, "Node is down, starting to check for login")
31
+ @connection_timeout = nil
32
+ super
33
+ end
34
+
35
+ def reboot_cmd
36
+ @reboot_cmd ||= reboot_cmd_valid? ? hash[:reboot_cmd] : 'shutdown -r now'
37
+ end
38
+
39
+ private
40
+
41
+ def reboot_cmd_valid?
42
+ return false if hash[:reboot_cmd].nil? # is optional
43
+ hash[:reboot_cmd].class == String or
44
+ raise CommandParsingError, "Plugin #{name}: the value of 'reboot_cmd' has to be a string"
45
+ end
46
+
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,68 @@
1
+ #
2
+ # DOPi Plugin: Wait For Login
3
+ #
4
+
5
+ module Dopi
6
+ class Command
7
+ class Ssh
8
+ class WaitForLogin < Dopi::Command
9
+ include Dopi::Connector::Ssh
10
+ include Dopi::CommandParser::ExitCode
11
+
12
+ DEFAULT_CONNECTION_TIMEOUT = 0
13
+ DEFAULT_INTERVAL = 10
14
+
15
+ def validate
16
+ validate_ssh
17
+ validate_exit_code
18
+ log_validation_method(:connection_timeout_valid?, CommandParsingError)
19
+ log_validation_method(:interval_valid?, CommandParsingError)
20
+ end
21
+
22
+ def run
23
+ connected = false
24
+ until connected
25
+ begin connected = check_exit_code(ssh_command({}, 'exit')[2])
26
+ rescue Dopi::NodeConnectionError, Dopi::CommandConnectionError
27
+ end
28
+ unless connected
29
+ sleep interval
30
+ raise GracefulExit if signals[:stop]
31
+ log(:info, "Retrying connect to node")
32
+ end
33
+ end
34
+ true
35
+ end
36
+
37
+ def connection_timeout
38
+ @connection_timeout ||= connection_timeout_valid? ?
39
+ hash[:connection_timeout] : DEFAULT_CONNECTION_TIMEOUT
40
+ end
41
+
42
+ def interval
43
+ @interval ||= interval_valid? ?
44
+ hash[:interval] : DEFAULT_INTERVAL
45
+ end
46
+
47
+ def ssh_options_defaults
48
+ [" -o ConnectTimeout=#{connection_timeout} -q "]
49
+ end
50
+
51
+ private
52
+
53
+ def connection_timeout_valid?
54
+ return false if hash[:connection_timeout].nil? # is optional
55
+ hash[:connection_timeout].class == Fixnum or
56
+ raise CommandParsingError, "Plugin #{name}: the value of 'connection_timeout' has to be a number"
57
+ end
58
+
59
+ def interval_valid?
60
+ return false if hash[:interval].nil? # is optional
61
+ hash[:interval].class == Fixnum or
62
+ raise CommandParsingError, "Plugin #{name}: the value of 'interval' has to be a number"
63
+ end
64
+
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,44 @@
1
+ #
2
+ # DOPi Plugin: WinRM Command
3
+ #
4
+ require 'winrm'
5
+
6
+ module Dopi
7
+ class Command
8
+ class Winrm
9
+ class Cmd < Dopi::Command
10
+ include Dopi::Connector::Winrm
11
+ include Dopi::CommandParser::Exec
12
+ include Dopi::CommandParser::Env
13
+ include Dopi::CommandParser::Arguments
14
+ include Dopi::CommandParser::ExitCode
15
+ include Dopi::CommandParser::Output
16
+
17
+ def validate
18
+ validate_winrm
19
+ validate_exec
20
+ validate_env
21
+ validate_arguments
22
+ validate_exit_code
23
+ validate_output
24
+ end
25
+
26
+ def run
27
+ cmd_stdout, cmd_stderr, cmd_exit_code = winrm_command(command_string)
28
+ check_output(cmd_stdout) &&
29
+ check_output(cmd_stderr) &&
30
+ check_exit_code(cmd_exit_code)
31
+ end
32
+
33
+ def run_noop
34
+ log(:info, "(NOOP) Executing '#{command_string}' for command #{name}")
35
+ end
36
+
37
+ def command_string
38
+ exec + ' ' + arguments
39
+ end
40
+
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,66 @@
1
+ #
2
+ # DOPi Plugin: File Contains
3
+ #
4
+
5
+ module Dopi
6
+ class Command
7
+ class Winrm
8
+ class FileContains < Dopi::Command
9
+ include Dopi::Connector::Winrm
10
+ include Dopi::CommandParser::ExitCode
11
+
12
+ def validate
13
+ validate_winrm
14
+ validate_exit_code
15
+ log_validation_method('file_valid?', CommandParsingError)
16
+ log_validation_method('pattern_valid?', CommandParsingError)
17
+ end
18
+
19
+ def run
20
+ cmd_stdout, cmd_stderr, cmd_exit_code = winrm_powershell_command(command_string)
21
+ check_exit_code(cmd_exit_code)
22
+ end
23
+
24
+ def run_noop
25
+ log(:info, "(NOOP) Executing '#{command_string}' for command #{name}")
26
+ end
27
+
28
+ def command_string
29
+ "if(-not(Select-String -Pattern #{pattern} -Path '#{file}' -Quiet)) { exit 1 }"
30
+ end
31
+
32
+ def file
33
+ @file ||= file_valid? ?
34
+ hash[:file] : nil
35
+ end
36
+
37
+ def pattern
38
+ @pattern ||= pattern_valid? ?
39
+ hash[:pattern] : nil
40
+ end
41
+
42
+ def file_valid?
43
+ hash[:file] or
44
+ raise CommandParsingError, "Plugin #{name}: The key 'file' needs to be specified"
45
+ begin
46
+ hash[:file][/[a-zA-Z]+:\\/] or hash[:file][/\\\\\w+/] or
47
+ raise CommandParsingError, "Plugin #{name}: The path for 'file' has to be absolute"
48
+ rescue ArgumentError => e
49
+ raise CommandParsingError, "Plugin #{name}: The value in 'file' is not a valid file path: #{e.message}"
50
+ end
51
+ end
52
+
53
+ def pattern_valid?
54
+ hash[:pattern] or
55
+ raise CommandParsingError, "Plugin #{name}: The key 'pattern' needs to be specified"
56
+ begin
57
+ Regexp.new(hash[:pattern])
58
+ rescue
59
+ raise CommandParsingError, "Plugin #{name}: The value in 'pattern' is not a valid regexp: #{e.message}"
60
+ end
61
+ end
62
+
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,51 @@
1
+ #
2
+ # DOPi Plugin: File Exists
3
+ #
4
+ require 'pathname'
5
+
6
+ module Dopi
7
+ class Command
8
+ class Winrm
9
+ class FileExists < Dopi::Command
10
+ include Dopi::Connector::Winrm
11
+ include Dopi::CommandParser::ExitCode
12
+
13
+ def validate
14
+ validate_winrm
15
+ validate_exit_code
16
+ log_validation_method(:file_valid?, CommandParsingError)
17
+ end
18
+
19
+ def run
20
+ cmd_stdout, cmd_stderr, cmd_exit_code = winrm_powershell_command(command_string)
21
+ check_exit_code(cmd_exit_code)
22
+ end
23
+
24
+ def run_noop
25
+ log(:info, "(NOOP) Executing '#{command_string}' for command #{name}")
26
+ end
27
+
28
+ def command_string
29
+ "if(-not(Test-Path '#{file}')) { exit 1 }"
30
+ end
31
+
32
+ def file
33
+ @file ||= file_valid? ?
34
+ hash[:file] : nil
35
+ end
36
+
37
+ def file_valid?
38
+ hash[:file] or
39
+ raise CommandParsingError, "Plugin #{name}: The key 'file' needs to be specified"
40
+ begin
41
+ hash[:file][/[a-zA-Z]+:\\/] or hash[:file][/\\\\\w+/] or
42
+ raise CommandParsingError, "Plugin #{name}: The path for 'file' has to be absolute"
43
+ rescue ArgumentError => e
44
+ raise CommandParsingError, "Plugin #{name}: The value in 'file' is not a valid file path: #{e.message}"
45
+ end
46
+ end
47
+
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,16 @@
1
+ module Dopi
2
+ class Command
3
+ class Winrm
4
+ class Powershell < Dopi::Command::Winrm::Cmd
5
+
6
+ def run
7
+ cmd_stdout, cmd_stderr, cmd_exit_code = winrm_powershell_command(command_string)
8
+ check_output(cmd_stdout) &&
9
+ check_output(cmd_stderr) &&
10
+ check_exit_code(cmd_exit_code)
11
+ end
12
+
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,61 @@
1
+ #
2
+ # WinRM Puppet Agent Plugin
3
+ #
4
+ module Dopi
5
+ class Command
6
+ class Winrm
7
+ class PuppetAgentRun < Dopi::Command
8
+ include Dopi::Connector::Winrm
9
+ include Dopi::CommandParser::Arguments
10
+ include Dopi::CommandParser::ExitCode
11
+ include Dopi::CommandParser::Output
12
+
13
+ public
14
+
15
+ def initialize(command_parser, step, node, is_verify_command)
16
+ command_parser.overwrite_defaults = { :plugin_timeout => 1800 }
17
+ super(command_parser, step, node, is_verify_command)
18
+ end
19
+
20
+ def validate
21
+ validate_winrm
22
+ validate_arguments
23
+ validate_exit_code
24
+ validate_output
25
+ end
26
+
27
+ def run
28
+ cmd_stdout, cmd_stderr, cmd_exit_code = winrm_powershell_command(command_string)
29
+ check_output(cmd_stdout) &&
30
+ check_output(cmd_stderr) &&
31
+ check_exit_code(cmd_exit_code)
32
+ end
33
+
34
+ def run_noop
35
+ log(:info, "(NOOP) Executing '#{command_string}' for command #{name}")
36
+ end
37
+
38
+ def expect_exit_codes_defaults
39
+ [ 0, 2 ]
40
+ end
41
+
42
+ def parse_output_defaults
43
+ { :error => [
44
+ '^Error:'
45
+ ],
46
+ :warning => [
47
+ '^Warning:'
48
+ ]
49
+ }
50
+ end
51
+
52
+ private
53
+
54
+ def command_string
55
+ "puppet agent --test --color false #{arguments}"
56
+ end
57
+
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,33 @@
1
+ #
2
+ # DOPi Plugin: Wait For Login
3
+ #
4
+
5
+ module Dopi
6
+ class Command
7
+ class Winrm
8
+ class Reboot < Dopi::Command::Winrm::WaitForLogin
9
+
10
+ def run
11
+ winrm_powershell_command('shutdown /r /f /t 0')
12
+ connected = true
13
+ while connected
14
+ begin
15
+ @node.reset_address(port)
16
+ @node.address(port)
17
+ rescue Dopi::NodeConnectionError
18
+ connected = false
19
+ end
20
+ if connected
21
+ sleep 1
22
+ raise GracefulExit if signals[:stop]
23
+ log(:info, "Still able to login, waiting for shutdown")
24
+ end
25
+ end
26
+ log(:info, "Node is down, starting to check for login")
27
+ super
28
+ end
29
+
30
+ end
31
+ end
32
+ end
33
+ end