cem_acpt 0.8.0 → 0.8.2
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/cem_acpt/provision/terraform/terraform_cmd.rb +9 -36
- data/lib/cem_acpt/provision/terraform.rb +13 -1
- data/lib/cem_acpt/test_runner.rb +62 -63
- data/lib/cem_acpt/utils/shell.rb +66 -0
- data/lib/cem_acpt/utils/ssh.rb +8 -21
- data/lib/cem_acpt/utils.rb +23 -5
- data/lib/cem_acpt/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e7eb7faf465af2f2ea5ab7649db1cf7e05c55573b869966c7e99c49aff498bf7
|
|
4
|
+
data.tar.gz: d79aadcc053957630a339b49a5ea456c5d67cc0dab24b036184cfec3e6c67609
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cee1f24c8c38d68b01078f56e41963a02f5c3c5e2df8a35907b86e19b20600fe5ba612d7382be02da41b0a38f662a09019f629cf4decae30f35dad14f878fd38
|
|
7
|
+
data.tar.gz: 968a449a29d6f487e802954ca9af7d1d64bd2dd85c7f95cbaf95cecf7357a261a113293e712b8be8b01a593564de885d25c80ab5b01632215b98e8bd43310012
|
data/Gemfile.lock
CHANGED
|
@@ -4,6 +4,7 @@ require 'json'
|
|
|
4
4
|
require 'open3'
|
|
5
5
|
require 'stringio'
|
|
6
6
|
require_relative '../../logging'
|
|
7
|
+
require_relative '../../utils/shell'
|
|
7
8
|
|
|
8
9
|
module CemAcpt
|
|
9
10
|
module Provision
|
|
@@ -81,34 +82,10 @@ module CemAcpt
|
|
|
81
82
|
end
|
|
82
83
|
|
|
83
84
|
def run_cmd(cmd, opts = {}, env = {}, suffix: '')
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
outerr
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
def execute(cmd, env)
|
|
92
|
-
logger.debug('CemAcpt::Provision::TerraformCmd') { "Executing command: #{cmd}" }
|
|
93
|
-
io_outerr = StringIO.new
|
|
94
|
-
val = Open3.popen2e(env, cmd) do |stdin, outerr, wait_thr|
|
|
95
|
-
stdin.close
|
|
96
|
-
outerr.sync = true
|
|
97
|
-
output_thread = Thread.new do
|
|
98
|
-
while (line = outerr.readline_nonblock)
|
|
99
|
-
logger << line
|
|
100
|
-
io_outerr.write(line) unless line.chomp.empty?
|
|
101
|
-
end
|
|
102
|
-
rescue IO::WaitReadable
|
|
103
|
-
retry
|
|
104
|
-
rescue EOFError
|
|
105
|
-
# Do nothing
|
|
106
|
-
end
|
|
107
|
-
wait_thr.join
|
|
108
|
-
output_thread.exit
|
|
109
|
-
wait_thr.value
|
|
110
|
-
end
|
|
111
|
-
[val, io_outerr.string]
|
|
85
|
+
cmd = format_cmd(cmd, opts, suffix)
|
|
86
|
+
env = environment(env)
|
|
87
|
+
logger.debug('CemAcpt::Provision::TerraformCmd') { "Running command \"#{cmd}\" with environment \"#{env}\"" }
|
|
88
|
+
CemAcpt::Utils::Shell.run_cmd(cmd, env, output: logger)
|
|
112
89
|
end
|
|
113
90
|
|
|
114
91
|
def chdir(opts = {})
|
|
@@ -123,14 +100,10 @@ module CemAcpt
|
|
|
123
100
|
end
|
|
124
101
|
|
|
125
102
|
def which_terraform
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return exe if File.executable?(exe) && !File.directory?(exe)
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
raise 'terraform not found in PATH, make sure it is installed'
|
|
103
|
+
path = CemAcpt::Utils::Shell.which('terraform')
|
|
104
|
+
raise 'terraform not found in PATH, make sure it is installed' if path.nil?
|
|
105
|
+
|
|
106
|
+
path
|
|
134
107
|
end
|
|
135
108
|
|
|
136
109
|
def format_cmd(cmd, opts = {}, suffix = '')
|
|
@@ -25,6 +25,7 @@ module CemAcpt
|
|
|
25
25
|
@module_package_path = nil
|
|
26
26
|
@private_key = nil
|
|
27
27
|
@public_key = nil
|
|
28
|
+
@applied = false
|
|
28
29
|
end
|
|
29
30
|
|
|
30
31
|
# @return [Hash] A hash of instance names and IPs
|
|
@@ -36,7 +37,18 @@ module CemAcpt
|
|
|
36
37
|
terraform_init
|
|
37
38
|
terraform_plan(formatted_vars, DEFAULT_PLAN_NAME)
|
|
38
39
|
terraform_apply(DEFAULT_PLAN_NAME)
|
|
39
|
-
|
|
40
|
+
@applied = true
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def output
|
|
44
|
+
raise 'Terraform has not been applied yet' unless @applied
|
|
45
|
+
|
|
46
|
+
output = terraform_output('instance_name_ip', json: true)
|
|
47
|
+
logger.debug('CemAcpt::Provision::Terraform') { "Terraform output:\n#{output}" }
|
|
48
|
+
JSON.parse(output)
|
|
49
|
+
rescue JSON::ParserError => e
|
|
50
|
+
logger.error('CemAcpt::Provision::Terraform') { "Error parsing Terraform output: #{output}" }
|
|
51
|
+
raise e
|
|
40
52
|
end
|
|
41
53
|
|
|
42
54
|
def destroy
|
data/lib/cem_acpt/test_runner.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require 'fileutils'
|
|
3
4
|
require 'securerandom'
|
|
4
5
|
require_relative 'action_result'
|
|
5
6
|
require_relative 'goss'
|
|
@@ -8,7 +9,6 @@ require_relative 'platform'
|
|
|
8
9
|
require_relative 'provision'
|
|
9
10
|
require_relative 'test_data'
|
|
10
11
|
require_relative 'utils'
|
|
11
|
-
require_relative 'utils/winrm_runner'
|
|
12
12
|
require_relative 'version'
|
|
13
13
|
require_relative 'test_runner/log_formatter'
|
|
14
14
|
|
|
@@ -30,6 +30,7 @@ module CemAcpt
|
|
|
30
30
|
@results = []
|
|
31
31
|
@http_statuses = []
|
|
32
32
|
@provisioned = false
|
|
33
|
+
@destroyed = false
|
|
33
34
|
end
|
|
34
35
|
|
|
35
36
|
def inspect
|
|
@@ -48,7 +49,6 @@ module CemAcpt
|
|
|
48
49
|
Dir.chdir(module_dir)
|
|
49
50
|
logger.start_ci_group("CemAcpt v#{CemAcpt::VERSION} run started at #{@start_time}")
|
|
50
51
|
logger.info('CemAcpt::TestRunner') { "Using module directory: #{module_dir}..." }
|
|
51
|
-
keep_terminal_alive
|
|
52
52
|
@run_data[:private_key], @run_data[:public_key], @run_data[:known_hosts] = new_ephemeral_ssh_keys
|
|
53
53
|
logger.info('CemAcpt::TestRunner') { 'Created ephemeral SSH key pair...' }
|
|
54
54
|
@run_data[:module_package_path] = build_module_package
|
|
@@ -59,7 +59,8 @@ module CemAcpt
|
|
|
59
59
|
@run_data[:nodes] = new_node_data
|
|
60
60
|
logger.info('CemAcpt::TestRunner') { 'Created node data...' }
|
|
61
61
|
logger.verbose('CemAcpt::TestRunner') { "Node data: #{@run_data[:nodes]}" }
|
|
62
|
-
|
|
62
|
+
provision_test_nodes
|
|
63
|
+
@instance_names_ips = provisioner_output
|
|
63
64
|
logger.info('CemAcpt::TestRunner') { "Instance names and IPs class: #{@instance_names_ips.class}" }
|
|
64
65
|
@provisioned = true
|
|
65
66
|
logger.info('CemAcpt::TestRunner') { 'Provisioned test nodes...' }
|
|
@@ -74,7 +75,7 @@ module CemAcpt
|
|
|
74
75
|
# instance_names_ips. It contains the username, password, and ip of the
|
|
75
76
|
# windows node, as well as the test name that will be run on that node.
|
|
76
77
|
login_info = CemAcpt::Utils.get_windows_login_info(k, v)
|
|
77
|
-
win_node = CemAcpt::Utils::WinRMRunner::WinNode.new(login_info, @run_data[:
|
|
78
|
+
win_node = CemAcpt::Utils::WinRMRunner::WinNode.new(login_info, @run_data[:win_remote_module_name])
|
|
78
79
|
win_node.run
|
|
79
80
|
end
|
|
80
81
|
end
|
|
@@ -85,43 +86,37 @@ module CemAcpt
|
|
|
85
86
|
logger.error('CemAcpt::TestRunner') { 'Run failed due to error...' }
|
|
86
87
|
@results << ActionResult.new(e)
|
|
87
88
|
ensure
|
|
89
|
+
logger.end_ci_group
|
|
88
90
|
clean_up
|
|
89
91
|
process_test_results
|
|
90
92
|
Dir.chdir(@old_dir) if @old_dir
|
|
91
93
|
@results
|
|
92
94
|
end
|
|
93
95
|
|
|
94
|
-
def clean_up(
|
|
95
|
-
logger.
|
|
96
|
-
|
|
97
|
-
cleanup_bucket # Clean up bucket if we're testing the cem_windows module
|
|
98
|
-
|
|
99
|
-
return no_destroy if config.get('no_destroy_nodes')
|
|
96
|
+
def clean_up(_trap_context = false)
|
|
97
|
+
logger.start_ci_group("CemAcpt v#{CemAcpt::VERSION} run finished at #{Time.now}")
|
|
98
|
+
logger.debug('CemAcpt::TestRunner') { "Starting clean up, provisioned: #{@provisioned}, destroyed: #{@destroyed}" }
|
|
100
99
|
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
if config.get('no_destroy_nodes')
|
|
101
|
+
logger.warn('CemAcpt::TestRunner') { 'Not destroying test nodes because no-destroy-nodes is set...' }
|
|
102
|
+
@provisioner&.show
|
|
103
|
+
logger.info('CemAcpt') { "Test SSH Keys:\n Private Key: #{@run_data[:private_key]}\n Public Key:#{@run_data[:public_key]}" }
|
|
104
|
+
else
|
|
105
|
+
cleanup_bucket # Clean up bucket if we're testing the cem_windows module
|
|
106
|
+
clean_ephemeral_ssh_keys
|
|
107
|
+
destroy_test_nodes
|
|
108
|
+
end
|
|
103
109
|
rescue StandardError => e
|
|
104
110
|
logger.verbose('CemAcpt::TestRunner') { "Error cleaning up: #{e}" }
|
|
105
111
|
logger.verbose('CemAcpt::TestRunner') { e.backtrace.join("\n") }
|
|
112
|
+
ensure
|
|
113
|
+
logger.end_ci_group
|
|
106
114
|
end
|
|
107
115
|
|
|
108
116
|
private
|
|
109
117
|
|
|
110
118
|
attr_reader :config
|
|
111
119
|
|
|
112
|
-
# @return [Thread] The thread that keeps the terminal alive
|
|
113
|
-
def keep_terminal_alive
|
|
114
|
-
return unless config.ci?
|
|
115
|
-
|
|
116
|
-
@keep_terminal_alive ||= CemAcpt::Utils::Terminal.keep_terminal_alive
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
def kill_keep_terminal_alive
|
|
120
|
-
return if @trap_context
|
|
121
|
-
|
|
122
|
-
keep_terminal_alive&.kill
|
|
123
|
-
end
|
|
124
|
-
|
|
125
120
|
# @return [String] The path to the module package
|
|
126
121
|
def build_module_package
|
|
127
122
|
if config.get('tests').first.include? 'windows'
|
|
@@ -162,24 +157,41 @@ module CemAcpt
|
|
|
162
157
|
@provisioner.provision
|
|
163
158
|
end
|
|
164
159
|
|
|
165
|
-
def
|
|
166
|
-
|
|
160
|
+
def provisioner_output
|
|
161
|
+
logger.info('CemAcpt::TestRunner') { 'Getting provisioner output...' }
|
|
162
|
+
@attempts = 0
|
|
163
|
+
@max_attempts = 3
|
|
164
|
+
output = nil
|
|
165
|
+
while @attempts < @max_attempts
|
|
166
|
+
@attempts += 1
|
|
167
|
+
output = @provisioner.output
|
|
168
|
+
break unless (output.nil? || output.empty?) && @attempts < @max_attempts # Don't sleep if this is last attempt
|
|
169
|
+
|
|
170
|
+
logger.info('CemAcpt::TestRunner') { "Provisioner output is nil or empty, retrying (#{@attempts}/#{@max_attempts})" }
|
|
171
|
+
sleep 3
|
|
172
|
+
end
|
|
173
|
+
raise 'Provisioner output is nil or empty' if output.nil? || output.empty?
|
|
167
174
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
175
|
+
output
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
def destroy_test_nodes
|
|
179
|
+
logger.info('CemAcpt::TestRunner') { 'Destroying test nodes if necessary...' }
|
|
180
|
+
if !@provisioned
|
|
181
|
+
logger.warn('CemAcpt::TestRunner') { 'Test nodes not provisioned, nothing to destroy...' }
|
|
182
|
+
elsif @destroyed
|
|
183
|
+
logger.warn('CemAcpt::TestRunner') { 'Test nodes already destroyed, not destroying...' }
|
|
184
|
+
else
|
|
185
|
+
logger.info('CemAcpt::TestRunner') { 'Test nodes are provisioned and not destroyed, destroying...' }
|
|
186
|
+
@provisioner&.destroy
|
|
187
|
+
@destroyed = true
|
|
188
|
+
end
|
|
174
189
|
end
|
|
175
190
|
|
|
176
191
|
def no_destroy
|
|
177
|
-
logger.warn('CemAcpt::TestRunner') { 'Not destroying test nodes...' }
|
|
178
|
-
logger.start_ci_group("CemAcpt v#{CemAcpt::VERSION} run finished at #{Time.now}")
|
|
192
|
+
logger.warn('CemAcpt::TestRunner') { 'Not destroying test nodes because no-destroy-nodes is set...' }
|
|
179
193
|
@provisioner&.show
|
|
180
194
|
logger.info('CemAcpt') { "Test SSH Keys:\n Private Key: #{@run_data[:private_key]}\n Public Key:#{@run_data[:public_key]}" }
|
|
181
|
-
ensure
|
|
182
|
-
logger.end_ci_group
|
|
183
195
|
end
|
|
184
196
|
|
|
185
197
|
def run_tests(hosts, only_actions, except_actions)
|
|
@@ -248,38 +260,25 @@ module CemAcpt
|
|
|
248
260
|
# This should only be done once per cem_acpt run. It's important to update the module_package_path
|
|
249
261
|
# in the run_data to reflect the new module path if we do end up changing the module name
|
|
250
262
|
def upload_module_to_bucket
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
logger.debug('CemAcpt') { 'Checking if there duplicate cem_windows module in the bucket already...' }
|
|
255
|
-
# Checking if the module already exists in the bucket. Gcloud will return an empty string if the module
|
|
256
|
-
# doesn't exist in the bucket.
|
|
257
|
-
attempts = 0
|
|
258
|
-
until `gcloud storage ls gs://win_cem_acpt/#{curr_module_name}`.empty? do
|
|
259
|
-
raise "Failed to rename duplicate module in GCloud" if attempts >= 3
|
|
260
|
-
|
|
261
|
-
logger.debug('CemAcpt') { 'Duplicate cem_windows module found. Renaming cem_windows module...' }
|
|
262
|
-
# Rename the cem_windows module
|
|
263
|
-
curr_module_name = SecureRandom.uuid << curr_module_name
|
|
264
|
-
`mv #{@run_data[:module_package_path]} #{curr_module_path}/#{curr_module_name}`
|
|
265
|
-
# update the module_package_path in the run_data
|
|
266
|
-
@run_data[:module_package_path] = File.join(curr_module_path, curr_module_name)
|
|
267
|
-
attempts += 1
|
|
268
|
-
end
|
|
263
|
+
@run_data[:win_remote_module_name] = SecureRandom.uuid << File.split(@run_data[:module_package_path]).last
|
|
264
|
+
@run_data[:win_remote_module_path] = File.join('gs://win_cem_acpt', @run_data[:win_remote_module_name])
|
|
269
265
|
# Upload the module from the local host to the bucket
|
|
270
|
-
logger.info('CemAcpt') {
|
|
271
|
-
|
|
272
|
-
logger.debug('CemAcpt') {
|
|
266
|
+
logger.info('CemAcpt') { "Uploading #{@run_data[:module_pakage_path]} to #{@run_data[:win_remote_module_path]}..." }
|
|
267
|
+
CemAcpt::Utils::Shell.run_cmd("gcloud storage cp #{@run_data[:module_package_path]} #{@run_data[:win_remote_module_path]}")
|
|
268
|
+
logger.debug('CemAcpt') { 'Successfully uploaded module' }
|
|
273
269
|
end
|
|
274
270
|
|
|
275
271
|
# We have to clean up our gcp bucket after we're done testing. This will limit the duplicated
|
|
276
272
|
# modules existing in the bucket.
|
|
277
273
|
def cleanup_bucket
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
274
|
+
if @run_data[:win_remote_module_path]
|
|
275
|
+
logger.info('CemAcpt::TestRunner') { "Cleaning up bucket #{@run_data[:win_remote_module_path]}..." }
|
|
276
|
+
# Cleanup the module from the bucket
|
|
277
|
+
cleanup_cmd = CemAcpt::Utils::Shell.run_cmd("gcloud storage rm #{@run_data[:win_remote_module_path]}", raise_on_error: false)
|
|
278
|
+
logger.debug('CemAcpt::TestRunner') { "Removed module from bucket: #{cleanup_cmd}" } unless cleanup_cmd.nil? || cleanup_cmd.empty?
|
|
279
|
+
else
|
|
280
|
+
logger.info('CemAcpt::TestRunner') { 'No module to clean up in bucket...' }
|
|
281
|
+
end
|
|
283
282
|
end
|
|
284
283
|
end
|
|
285
284
|
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'open3'
|
|
4
|
+
require 'stringio'
|
|
5
|
+
|
|
6
|
+
module CemAcpt
|
|
7
|
+
# Error class for shell commands
|
|
8
|
+
class ShellCommandError < StandardError; end
|
|
9
|
+
|
|
10
|
+
module Utils
|
|
11
|
+
# Generic utilities for running local shell commands
|
|
12
|
+
module Shell
|
|
13
|
+
# Runs a command in a subshell and returns the Process::Status
|
|
14
|
+
# and the string output of the command.
|
|
15
|
+
# @param cmd [String] The command to run
|
|
16
|
+
# @param env [Hash] A hash of environment variables to set
|
|
17
|
+
# @param output [IO] An IO object that implements #:<< to write the output of the
|
|
18
|
+
# command to in real time. Typically this is a Logger object. Defaults to $stdout.
|
|
19
|
+
# If the object responds to #:debug, the command will be logged at the debug level.
|
|
20
|
+
# @param raise_on_fail [Boolean] Whether to raise an error if the command fails
|
|
21
|
+
# @return [String] The string output of the command
|
|
22
|
+
def self.run_cmd(cmd, env = {}, output: $stdout, raise_on_fail: true)
|
|
23
|
+
io_outerr = StringIO.new
|
|
24
|
+
if output.respond_to?(:debug)
|
|
25
|
+
output.debug('CemAcpt::Utils::Shell') { "Running command:\n\t#{cmd}\nWith environment:\n\t#{env}" }
|
|
26
|
+
else
|
|
27
|
+
output << "Running command:\n\t#{cmd}\nWith environment:\n\t#{env}\n"
|
|
28
|
+
end
|
|
29
|
+
val = Open3.popen2e(env, cmd) do |stdin, outerr, wait_thr|
|
|
30
|
+
stdin.close
|
|
31
|
+
outerr.sync = true
|
|
32
|
+
output_thread = Thread.new do
|
|
33
|
+
while (line = outerr.gets("\n"))
|
|
34
|
+
output << line if output
|
|
35
|
+
io_outerr.write(line) unless line.chomp.empty?
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
wait_thr.join
|
|
39
|
+
output_thread.exit
|
|
40
|
+
wait_thr.value
|
|
41
|
+
end
|
|
42
|
+
io_string = io_outerr.string
|
|
43
|
+
raise CemAcpt::ShellCommandError, "Error running command: #{cmd}\n#{io_string}" if raise_on_fail && !val.success?
|
|
44
|
+
|
|
45
|
+
io_string
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Mimics the behavior of the `which` command.
|
|
49
|
+
# @param cmd [String] The command to find
|
|
50
|
+
# @return [String] The path to the command
|
|
51
|
+
# @return [nil] If the command is not found
|
|
52
|
+
def self.which(cmd)
|
|
53
|
+
return cmd if File.executable?(cmd) && !File.directory?(cmd)
|
|
54
|
+
|
|
55
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
|
56
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
|
57
|
+
exts.each do |ext|
|
|
58
|
+
exe = File.join(path, "#{cmd}#{ext}")
|
|
59
|
+
return exe if File.executable?(exe) && !File.directory?(exe)
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
nil
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
data/lib/cem_acpt/utils/ssh.rb
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require_relative 'shell'
|
|
4
4
|
require_relative '../logging'
|
|
5
5
|
|
|
6
6
|
module CemAcpt
|
|
@@ -32,9 +32,7 @@ module CemAcpt
|
|
|
32
32
|
delete(key_name) # Delete existing keys with same name
|
|
33
33
|
cmd = new_keygen_cmd(key_name, **options)
|
|
34
34
|
logger.debug('CemAcpt::Utils::SSH::Keygen') { "Creating SSH key with command: #{cmd}" }
|
|
35
|
-
|
|
36
|
-
raise "Failed to create SSH key! #{stderr}" unless status.success?
|
|
37
|
-
|
|
35
|
+
CemAcpt::Utils::Shell.run_cmd(cmd, output: logger)
|
|
38
36
|
key_paths(key_name)
|
|
39
37
|
end
|
|
40
38
|
|
|
@@ -53,20 +51,11 @@ module CemAcpt
|
|
|
53
51
|
|
|
54
52
|
private
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
].freeze
|
|
60
|
-
|
|
61
|
-
def find_bin_path(find_cmd = FIND_BIN_PATH_COMMANDS.first)
|
|
62
|
-
bin_path, stderr, status = Open3.capture3(find_cmd)
|
|
63
|
-
raise "Cannot find ssh-keygen with command #{find_cmd}: #{stderr}" unless status.success?
|
|
64
|
-
|
|
65
|
-
bin_path.chomp
|
|
66
|
-
rescue StandardError => e
|
|
67
|
-
return find_bin_path(FIND_BIN_PATH_COMMANDS.last) unless FIND_BIN_PATH_COMMANDS.last == find_cmd
|
|
54
|
+
def find_bin_path
|
|
55
|
+
bin_path = CemAcpt::Utils::Shell.which('ssh-keygen')
|
|
56
|
+
raise 'Cannot find command ssh-keygen in PATH, make sure it is installed' if bin_path.nil?
|
|
68
57
|
|
|
69
|
-
|
|
58
|
+
bin_path
|
|
70
59
|
end
|
|
71
60
|
|
|
72
61
|
def new_keygen_cmd(key_name, **options)
|
|
@@ -100,12 +89,10 @@ module CemAcpt
|
|
|
100
89
|
end
|
|
101
90
|
|
|
102
91
|
def self.ssh_keygen
|
|
103
|
-
bin_path =
|
|
104
|
-
raise 'Cannot find ssh-keygen
|
|
92
|
+
bin_path = CemAcpt::Utils::Shell.which('ssh-keygen')
|
|
93
|
+
raise 'Cannot find command ssh-keygen in PATH, make sure it is installed' if bin_path.nil?
|
|
105
94
|
|
|
106
95
|
bin_path
|
|
107
|
-
rescue StandardError => e
|
|
108
|
-
raise "Cannot find ssh-keygen! Install it and verify PATH. Orignal error: #{e}"
|
|
109
96
|
end
|
|
110
97
|
|
|
111
98
|
def self.default_keydir
|
data/lib/cem_acpt/utils.rb
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require_relative 'utils/puppet'
|
|
4
|
+
require_relative 'utils/shell'
|
|
4
5
|
require_relative 'utils/ssh'
|
|
5
6
|
require_relative 'utils/terminal'
|
|
7
|
+
require_relative 'utils/winrm_runner'
|
|
6
8
|
require_relative 'logging'
|
|
7
9
|
|
|
8
10
|
module CemAcpt
|
|
@@ -19,17 +21,33 @@ module CemAcpt
|
|
|
19
21
|
FileUtils.rm_f(package_file)
|
|
20
22
|
`cd #{module_dir} && touch puppetlabs-cem_windows.tar.gz && tar -czf puppetlabs-cem_windows.tar.gz --exclude=puppetlabs-cem_windows.tar.gz *`
|
|
21
23
|
logger.info('CemAcpt') { "Windows module packaged at #{package_file}" }
|
|
22
|
-
|
|
24
|
+
package_file
|
|
23
25
|
end
|
|
24
26
|
|
|
25
27
|
def reset_password_readiness_polling(instance_name)
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
attempts = 0
|
|
29
|
+
last_error = nil
|
|
30
|
+
result = nil
|
|
31
|
+
begin
|
|
32
|
+
result = CemAcpt::Utils::Shell.run_cmd("echo Y | gcloud compute reset-windows-password #{instance_name} --zone=us-west1-b")
|
|
33
|
+
rescue StandardError => e
|
|
34
|
+
logger.debug('CemAcpt::Utils') { "Error polling for password readiness: #{e}" }
|
|
35
|
+
last_error = e
|
|
36
|
+
end
|
|
37
|
+
while result.nil? || result.empty?
|
|
38
|
+
raise "Instance not ready for password reset. Last error: #{last_error}" if attempts >= 60 # 10 minutes
|
|
39
|
+
|
|
28
40
|
logger.info('CemAcpt') { "Waiting for instance #{instance_name} to be ready for password reset..." }
|
|
29
41
|
sleep 10
|
|
30
|
-
|
|
42
|
+
begin
|
|
43
|
+
result = CemAcpt::Utils::Shell.run_cmd("echo Y | gcloud compute reset-windows-password #{instance_name} --zone=us-west1-b")
|
|
44
|
+
rescue StandardError => e
|
|
45
|
+
logger.debug('CemAcpt::Utils') { "Error polling for password readiness: #{e}" }
|
|
46
|
+
last_error = e
|
|
47
|
+
end
|
|
48
|
+
attempts += 1
|
|
31
49
|
end
|
|
32
|
-
|
|
50
|
+
result
|
|
33
51
|
end
|
|
34
52
|
|
|
35
53
|
def get_windows_login_info(instance_name, hash_of_instance)
|
data/lib/cem_acpt/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: cem_acpt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.8.
|
|
4
|
+
version: 0.8.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- puppetlabs
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2023-
|
|
11
|
+
date: 2023-09-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: async-http
|
|
@@ -237,6 +237,7 @@ files:
|
|
|
237
237
|
- lib/cem_acpt/test_runner/log_formatter/goss_action_response.rb
|
|
238
238
|
- lib/cem_acpt/utils.rb
|
|
239
239
|
- lib/cem_acpt/utils/puppet.rb
|
|
240
|
+
- lib/cem_acpt/utils/shell.rb
|
|
240
241
|
- lib/cem_acpt/utils/ssh.rb
|
|
241
242
|
- lib/cem_acpt/utils/terminal.rb
|
|
242
243
|
- lib/cem_acpt/utils/winrm_runner.rb
|