hybrid_platforms_conductor 33.2.2 → 33.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -0
  3. data/README.md +29 -2
  4. data/docs/config_dsl.md +45 -0
  5. data/docs/plugins.md +1 -0
  6. data/docs/plugins/secrets_reader/keepass.md +62 -0
  7. data/lib/hybrid_platforms_conductor/bitbucket.rb +134 -90
  8. data/lib/hybrid_platforms_conductor/cmd_runner.rb +4 -4
  9. data/lib/hybrid_platforms_conductor/common_config_dsl/bitbucket.rb +12 -44
  10. data/lib/hybrid_platforms_conductor/common_config_dsl/github.rb +9 -31
  11. data/lib/hybrid_platforms_conductor/config.rb +0 -35
  12. data/lib/hybrid_platforms_conductor/confluence.rb +93 -88
  13. data/lib/hybrid_platforms_conductor/connector.rb +1 -1
  14. data/lib/hybrid_platforms_conductor/core_extensions/bundler/without_bundled_env.rb +18 -1
  15. data/lib/hybrid_platforms_conductor/credentials.rb +122 -97
  16. data/lib/hybrid_platforms_conductor/deployer.rb +37 -30
  17. data/lib/hybrid_platforms_conductor/github.rb +39 -0
  18. data/lib/hybrid_platforms_conductor/hpc_plugins/action/bash.rb +1 -1
  19. data/lib/hybrid_platforms_conductor/hpc_plugins/action/remote_bash.rb +27 -17
  20. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/local.rb +4 -2
  21. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/my_connector.rb.sample +1 -1
  22. data/lib/hybrid_platforms_conductor/hpc_plugins/connector/ssh.rb +29 -20
  23. data/lib/hybrid_platforms_conductor/hpc_plugins/platform_handler/serverless_chef.rb +1 -1
  24. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox.rb +5 -3
  25. data/lib/hybrid_platforms_conductor/hpc_plugins/provisioner/proxmox/reserve_proxmox_container +1 -0
  26. data/lib/hybrid_platforms_conductor/hpc_plugins/report/confluence.rb +3 -1
  27. data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/keepass.rb +174 -0
  28. data/lib/hybrid_platforms_conductor/hpc_plugins/secrets_reader/thycotic.rb +3 -1
  29. data/lib/hybrid_platforms_conductor/hpc_plugins/test/bitbucket_conf.rb +4 -1
  30. data/lib/hybrid_platforms_conductor/hpc_plugins/test/github_ci.rb +4 -1
  31. data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_conf.rb +7 -3
  32. data/lib/hybrid_platforms_conductor/hpc_plugins/test/jenkins_ci_masters_ok.rb +8 -4
  33. data/lib/hybrid_platforms_conductor/hpc_plugins/test_report/confluence.rb +3 -1
  34. data/lib/hybrid_platforms_conductor/logger_helpers.rb +24 -1
  35. data/lib/hybrid_platforms_conductor/plugins.rb +1 -0
  36. data/lib/hybrid_platforms_conductor/safe_merge.rb +37 -0
  37. data/lib/hybrid_platforms_conductor/thycotic.rb +80 -75
  38. data/lib/hybrid_platforms_conductor/topographer/plugins/graphviz.rb +5 -3
  39. data/lib/hybrid_platforms_conductor/version.rb +1 -1
  40. data/spec/hybrid_platforms_conductor_test.rb +10 -0
  41. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/bash_spec.rb +15 -0
  42. data/spec/hybrid_platforms_conductor_test/api/actions_executor/actions/remote_bash_spec.rb +32 -0
  43. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/local/remote_actions_spec.rb +9 -0
  44. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/config_dsl_spec.rb +8 -6
  45. data/spec/hybrid_platforms_conductor_test/api/actions_executor/connectors/ssh/remote_actions_spec.rb +38 -0
  46. data/spec/hybrid_platforms_conductor_test/api/cmd_runner_spec.rb +21 -1
  47. data/spec/hybrid_platforms_conductor_test/api/config_spec.rb +48 -72
  48. data/spec/hybrid_platforms_conductor_test/api/credentials_spec.rb +251 -0
  49. data/spec/hybrid_platforms_conductor_test/api/deployer/config_dsl_spec.rb +36 -0
  50. data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/keepass_spec.rb +680 -0
  51. data/spec/hybrid_platforms_conductor_test/api/deployer/secrets_reader_plugins/thycotic_spec.rb +2 -2
  52. data/spec/hybrid_platforms_conductor_test/api/nodes_handler/cmdbs_plugins_api_spec.rb +2 -2
  53. data/spec/hybrid_platforms_conductor_test/api/platform_handlers/serverless_chef/services_deployment_spec.rb +1 -1
  54. data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/bitbucket_conf_spec.rb +49 -69
  55. data/spec/hybrid_platforms_conductor_test/api/tests_runner/test_plugins/github_ci_spec.rb +29 -39
  56. data/spec/hybrid_platforms_conductor_test/executables/nodes_to_deploy_spec.rb +21 -15
  57. data/spec/hybrid_platforms_conductor_test/test_connector.rb +2 -2
  58. metadata +188 -139
@@ -13,6 +13,15 @@ describe HybridPlatformsConductor::ActionsExecutor do
13
13
  end
14
14
  end
15
15
 
16
+ it 'executes bash commands remotely from a SecretString' do
17
+ with_test_platform_for_remote_testing(
18
+ expected_cmds: [[%r{.+/ssh hpc\.node /bin/bash <<'HPC_EOF'\nbash_cmd.bash\nHPC_EOF}, proc { [0, 'Bash commands executed on node', ''] }]],
19
+ expected_stdout: 'Bash commands executed on node'
20
+ ) do
21
+ test_connector.remote_bash(SecretString.new('bash_cmd.bash', silenced_str: '__INVALID_BASH__'))
22
+ end
23
+ end
24
+
16
25
  it 'executes bash commands remotely with timeout' do
17
26
  with_test_platform_for_remote_testing(
18
27
  expected_cmds: [
@@ -88,6 +97,25 @@ describe HybridPlatformsConductor::ActionsExecutor do
88
97
  end
89
98
  end
90
99
 
100
+ it 'executes really big bash commands remotely using a SecretString' do
101
+ cmd = "echo #{'1' * 131_060}"
102
+ with_test_platform_for_remote_testing(
103
+ expected_cmds: [
104
+ [
105
+ %r{.+/hpc_temp_cmds_.+\.sh$},
106
+ proc do |received_cmd|
107
+ expect(File.read(received_cmd)).to match(%r{.+/ssh hpc\.node /bin/bash <<'HPC_EOF'\n#{Regexp.escape(cmd)}\nHPC_EOF})
108
+ [0, 'Bash commands executed on node', '']
109
+ end
110
+ ]
111
+ ],
112
+ expected_stdout: 'Bash commands executed on node'
113
+ ) do
114
+ # Use an argument that exceeds the max arg length limit
115
+ test_connector.remote_bash(SecretString.new(cmd, silenced_str: '__INVALID_BASH__'))
116
+ end
117
+ end
118
+
91
119
  it 'copies files remotely with sudo' do
92
120
  with_test_platform_for_remote_testing(
93
121
  expected_cmds: [
@@ -153,6 +181,16 @@ describe HybridPlatformsConductor::ActionsExecutor do
153
181
  end
154
182
  end
155
183
 
184
+ it 'executes bash commands remotely without Session Exec capabilities using a SecretString' do
185
+ with_test_platform_for_remote_testing(
186
+ expected_cmds: [[%r{^\{ cat \| .+/ssh hpc\.node -T; \} <<'HPC_EOF'\nbash_cmd.bash\nHPC_EOF$}, proc { [0, 'Bash commands executed on node', ''] }]],
187
+ expected_stdout: 'Bash commands executed on node',
188
+ session_exec: false
189
+ ) do
190
+ test_connector.remote_bash(SecretString.new('bash_cmd.bash', silenced_str: '__INVALID_BASH__'))
191
+ end
192
+ end
193
+
156
194
  it 'copies files remotely without Session Exec capabilities' do
157
195
  with_test_platform_for_remote_testing(
158
196
  expected_cmds: [
@@ -7,6 +7,13 @@ describe HybridPlatformsConductor::CmdRunner do
7
7
  end
8
8
  end
9
9
 
10
+ it 'runs a simple bash command in a SecretString' do
11
+ with_repository do |repository|
12
+ test_cmd_runner.run_cmd SecretString.new("echo TestContent >#{repository}/test_file", silenced_str: '__INVALID_BASH__')
13
+ expect(File.read("#{repository}/test_file")).to eq "TestContent\n"
14
+ end
15
+ end
16
+
10
17
  it 'runs a simple bash command and returns exit code, stdout and stderr correctly' do
11
18
  with_repository do
12
19
  expect(test_cmd_runner.run_cmd('echo TestStderr 1>&2 ; echo TestStdout')).to eq [0, "TestStdout\n", "TestStderr\n"]
@@ -20,6 +27,13 @@ describe HybridPlatformsConductor::CmdRunner do
20
27
  end
21
28
  end
22
29
 
30
+ it 'runs a simple bash command and forces usage of bash in a SecretString' do
31
+ with_repository do
32
+ # Use set -o pipefail that does not work in /bin/sh
33
+ expect(test_cmd_runner.run_cmd(SecretString.new('set -o pipefail ; echo TestStderr 1>&2 ; echo TestStdout', silenced_str: '__INVALID_BASH__'), force_bash: true)).to eq [0, "TestStdout\n", "TestStderr\n"]
34
+ end
35
+ end
36
+
23
37
  it 'runs a simple bash command and logs stdout and stderr to a file' do
24
38
  with_repository do |repository|
25
39
  test_cmd_runner.run_cmd 'echo TestStderr 1>&2 ; sleep 1 ; echo TestStdout', log_to_file: "#{repository}/test_file"
@@ -47,7 +61,13 @@ describe HybridPlatformsConductor::CmdRunner do
47
61
 
48
62
  it 'runs a command in an un-bundled environment' do
49
63
  with_repository do
50
- expect(test_cmd_runner.run_cmd('echo "${BUNDLE_GEMFILE}"')).to eq [0, "\n", '']
64
+ %w[
65
+ BUNDLE_GEMFILE
66
+ GEM_HOME
67
+ RUBYOPT
68
+ ].each do |var_to_check|
69
+ expect(test_cmd_runner.run_cmd("echo \"${#{var_to_check}}\"")).to eq [0, "\n", '']
70
+ end
51
71
  end
52
72
  end
53
73
 
@@ -19,10 +19,12 @@ describe HybridPlatformsConductor::Config do
19
19
  end
20
20
 
21
21
  it 'returns several defined OS images' do
22
- with_platforms '
23
- os_image :image_1, \'/path/to/image_1\'
24
- os_image :image_2, \'/path/to/image_2\'
25
- ' do
22
+ with_platforms(
23
+ <<~EO_CONFIG
24
+ os_image :image_1, '/path/to/image_1'
25
+ os_image :image_2, '/path/to/image_2'
26
+ EO_CONFIG
27
+ ) do
26
28
  expect(test_config.known_os_images.sort).to eq %i[image_1 image_2].sort
27
29
  end
28
30
  end
@@ -49,11 +51,13 @@ describe HybridPlatformsConductor::Config do
49
51
  end
50
52
 
51
53
  it 'includes several configuration files' do
52
- with_platforms '
53
- os_image :image_1, \'/path/to/image_1\'
54
- include_config_from "#{__dir__}/my_conf_1.rb"
55
- include_config_from "#{__dir__}/my_conf_2.rb"
56
- ' do |hybrid_platforms_dir|
54
+ with_platforms(
55
+ <<~'EO_CONFIG'
56
+ os_image :image_1, '/path/to/image_1'
57
+ include_config_from "#{__dir__}/my_conf_1.rb"
58
+ include_config_from "#{__dir__}/my_conf_2.rb"
59
+ EO_CONFIG
60
+ ) do |hybrid_platforms_dir|
57
61
  File.write("#{hybrid_platforms_dir}/my_conf_1.rb", <<~'EO_CONFIG')
58
62
  os_image :image_4, '/path/to/image_4'
59
63
  include_config_from "#{__dir__}/my_conf_3.rb"
@@ -65,9 +69,7 @@ describe HybridPlatformsConductor::Config do
65
69
  end
66
70
 
67
71
  it 'applies nodes specific configuration to all nodes by default' do
68
- with_platforms '
69
- expect_tests_to_fail :my_test, \'Failure reason\'
70
- ' do
72
+ with_platforms 'expect_tests_to_fail :my_test, \'Failure reason\'' do
71
73
  expect(test_config.expected_failures).to eq [
72
74
  {
73
75
  nodes_selectors_stack: [],
@@ -79,12 +81,14 @@ describe HybridPlatformsConductor::Config do
79
81
  end
80
82
 
81
83
  it 'filters nodes specific configuration to nodes sets in a scope' do
82
- with_platforms '
83
- for_nodes(%w[node1 node2 node3]) do
84
- expect_tests_to_fail :my_test_1, \'Failure reason 1\'
85
- end
86
- expect_tests_to_fail :my_test_2, \'Failure reason 2\'
87
- ' do
84
+ with_platforms(
85
+ <<~EO_CONFIG
86
+ for_nodes(%w[node1 node2 node3]) do
87
+ expect_tests_to_fail :my_test_1, 'Failure reason 1'
88
+ end
89
+ expect_tests_to_fail :my_test_2, 'Failure reason 2'
90
+ EO_CONFIG
91
+ ) do
88
92
  sort_proc = proc { |expected_failure_info| expected_failure_info[:reason] }
89
93
  expect(test_config.expected_failures.sort_by(&sort_proc)).to eq [
90
94
  {
@@ -102,14 +106,16 @@ describe HybridPlatformsConductor::Config do
102
106
  end
103
107
 
104
108
  it 'filters nodes specific configuration in a scoped stack' do
105
- with_platforms '
106
- for_nodes(%w[node1 node2 node3]) do
107
- expect_tests_to_fail :my_test_1, \'Failure reason 1\'
108
- for_nodes(%w[node2 node3 node4]) do
109
- expect_tests_to_fail :my_test_2, \'Failure reason 2\'
109
+ with_platforms(
110
+ <<~EO_CONFIG
111
+ for_nodes(%w[node1 node2 node3]) do
112
+ expect_tests_to_fail :my_test_1, 'Failure reason 1'
113
+ for_nodes(%w[node2 node3 node4]) do
114
+ expect_tests_to_fail :my_test_2, 'Failure reason 2'
115
+ end
110
116
  end
111
- end
112
- ' do
117
+ EO_CONFIG
118
+ ) do
113
119
  sort_proc = proc { |expected_failure_info| expected_failure_info[:reason] }
114
120
  expect(test_config.expected_failures.sort_by(&sort_proc)).to eq [
115
121
  {
@@ -127,13 +133,15 @@ describe HybridPlatformsConductor::Config do
127
133
  end
128
134
 
129
135
  it 'returns the expected failures correctly' do
130
- with_platforms '
131
- expect_tests_to_fail :my_test_1, \'Failure reason 1\'
132
- expect_tests_to_fail %i[my_test_2 my_test_3], \'Failure reason 23\'
133
- for_nodes(%w[node1 node2 node3]) do
134
- expect_tests_to_fail :my_test_4, \'Failure reason 4\'
135
- end
136
- ' do
136
+ with_platforms(
137
+ <<~EO_CONFIG
138
+ expect_tests_to_fail :my_test_1, 'Failure reason 1'
139
+ expect_tests_to_fail %i[my_test_2 my_test_3], 'Failure reason 23'
140
+ for_nodes(%w[node1 node2 node3]) do
141
+ expect_tests_to_fail :my_test_4, 'Failure reason 4'
142
+ end
143
+ EO_CONFIG
144
+ ) do
137
145
  sort_proc = proc { |expected_failure_info| expected_failure_info[:reason] }
138
146
  expect(test_config.expected_failures.sort_by(&sort_proc)).to eq [
139
147
  {
@@ -155,47 +163,15 @@ describe HybridPlatformsConductor::Config do
155
163
  end
156
164
  end
157
165
 
158
- it 'returns the retriable errors correctly' do
159
- with_platforms '
160
- retry_deploy_for_errors_on_stdout \'Retry stdout global\'
161
- retry_deploy_for_errors_on_stderr [
162
- \'Retry stderr global\',
163
- /.+Retry stderr regexp global/
164
- ]
165
- for_nodes(%w[node1 node2 node3]) do
166
- retry_deploy_for_errors_on_stdout \'Retry stdout nodes\'
167
- retry_deploy_for_errors_on_stderr \'Retry stderr nodes\'
168
- end
169
- ' do
170
- sort_proc = proc { |retriable_error_info| ((retriable_error_info[:errors_on_stdout] || []) + (retriable_error_info[:errors_on_stderr] || [])).first.to_s }
171
- expect(test_config.retriable_errors.sort_by(&sort_proc)).to eq [
172
- {
173
- nodes_selectors_stack: [],
174
- errors_on_stdout: ['Retry stdout global']
175
- },
176
- {
177
- nodes_selectors_stack: [],
178
- errors_on_stderr: ['Retry stderr global', /.+Retry stderr regexp global/]
179
- },
180
- {
181
- nodes_selectors_stack: [%w[node1 node2 node3]],
182
- errors_on_stdout: ['Retry stdout nodes']
183
- },
184
- {
185
- nodes_selectors_stack: [%w[node1 node2 node3]],
186
- errors_on_stderr: ['Retry stderr nodes']
187
- }
188
- ].sort_by(&sort_proc)
189
- end
190
- end
191
-
192
166
  it 'returns the deployment schedules correctly' do
193
- with_platforms '
194
- deployment_schedule(IceCube::Schedule.new(Time.parse(\'2020-05-01 11:22:33 UTC\')))
195
- for_nodes(%w[node1 node2 node3]) do
196
- deployment_schedule(IceCube::Schedule.new(Time.parse(\'2020-05-02 22:33:44 UTC\')))
197
- end
198
- ' do
167
+ with_platforms(
168
+ <<~EO_CONFIG
169
+ deployment_schedule(IceCube::Schedule.new(Time.parse('2020-05-01 11:22:33 UTC')))
170
+ for_nodes(%w[node1 node2 node3]) do
171
+ deployment_schedule(IceCube::Schedule.new(Time.parse('2020-05-02 22:33:44 UTC')))
172
+ end
173
+ EO_CONFIG
174
+ ) do
199
175
  sort_proc = proc { |deployment_schedule_info| deployment_schedule_info[:schedule].to_ical }
200
176
  expect(test_config.deployment_schedules.sort_by(&sort_proc)).to eq [
201
177
  {
@@ -0,0 +1,251 @@
1
+ describe HybridPlatformsConductor::Credentials do
2
+
3
+ # Create a container class for the credential Mixin to be tested, as a plugin as credentials can be used in any plugin.
4
+ let(:credential_tester_class) do
5
+ Class.new(HybridPlatformsConductor::Plugin) do
6
+ include HybridPlatformsConductor::Credentials
7
+ end
8
+ end
9
+
10
+ # Expect credentials to be as a given user and password
11
+ #
12
+ # Parameters::
13
+ # * *expected_user* (String or nil): The expected user
14
+ # * *expected_password* (String or nil): The expected password
15
+ # * *resource* (String or nil): The resource for which we query the credentials, or nil if none [default: nil]
16
+ def expect_credentials_to_be(expected_user, expected_password, resource: nil)
17
+ creds = {}
18
+ password_class = nil
19
+ credential_tester_class.new(logger: logger, logger_stderr: logger, config: test_config).instance_exec do
20
+ with_credentials_for(:test_credential, resource: resource) do |user, password|
21
+ password_class = password.class
22
+ creds = {
23
+ user: user,
24
+ # We clone the value as for security reasons it is removed when exiting the block
25
+ password: password&.to_unprotected.clone
26
+ }
27
+ end
28
+ end
29
+ # Make sure we always return a SecretString for the password
30
+ expect(password_class).to be SecretString unless password_class == NilClass
31
+ expect(creds).to eq(
32
+ user: expected_user,
33
+ password: expected_password
34
+ )
35
+ end
36
+
37
+ it 'returns no credentials when they are not set' do
38
+ with_platforms '' do
39
+ # Check that .netrc won't be read
40
+ expect(::Netrc).not_to receive(:read)
41
+ expect_credentials_to_be nil, nil
42
+ end
43
+ end
44
+
45
+ it 'returns credentials taken from environment variables' do
46
+ with_platforms '' do
47
+ ENV['hpc_user_for_test_credential'] = 'env_test_user'
48
+ ENV['hpc_password_for_test_credential'] = 'env_test_password'
49
+ begin
50
+ # Check that .netrc won't be read
51
+ expect(::Netrc).not_to receive(:read)
52
+ expect_credentials_to_be 'env_test_user', 'env_test_password'
53
+ ensure
54
+ ENV.delete('hpc_user_for_test_credential')
55
+ ENV.delete('hpc_password_for_test_credential')
56
+ end
57
+ end
58
+ end
59
+
60
+ it 'erases the value of the password taken from environment variable after usage' do
61
+ with_platforms '' do
62
+ ENV['hpc_user_for_test_credential'] = 'env_test_user'
63
+ ENV['hpc_password_for_test_credential'] = 'env_test_password'
64
+ begin
65
+ leaked_password = nil
66
+ credential_tester_class.new(logger: logger, logger_stderr: logger, config: test_config).instance_exec do
67
+ with_credentials_for(:test_credential) do |_user, password|
68
+ leaked_password = password
69
+ end
70
+ end
71
+ expect(leaked_password.to_unprotected).to eq "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
72
+ ensure
73
+ ENV.delete('hpc_user_for_test_credential')
74
+ ENV.delete('hpc_password_for_test_credential')
75
+ end
76
+ end
77
+ end
78
+
79
+ it 'returns credentials taken from .netrc when a resource is specified' do
80
+ with_platforms '' do
81
+ expect(::Netrc).to receive(:read) do
82
+ mocked_netrc = instance_double(::Netrc)
83
+ expect(mocked_netrc).to receive(:[]).with('my_domain.com').and_return %w[test_user test_password]
84
+ expect(mocked_netrc).to receive(:instance_variable_get).with(:@data).and_return []
85
+ mocked_netrc
86
+ end
87
+ expect_credentials_to_be 'test_user', 'test_password', resource: 'http://My_Domain.com/path/to/resource'
88
+ end
89
+ end
90
+
91
+ it 'returns credentials taken from .netrc when a non-URL resource is specified' do
92
+ with_platforms '' do
93
+ expect(::Netrc).to receive(:read) do
94
+ mocked_netrc = instance_double(::Netrc)
95
+ expect(mocked_netrc).to receive(:[]).with('This is:not/ a URL!').and_return %w[test_user test_password]
96
+ expect(mocked_netrc).to receive(:instance_variable_get).with(:@data).and_return []
97
+ mocked_netrc
98
+ end
99
+ expect_credentials_to_be 'test_user', 'test_password', resource: 'This is:not/ a URL!'
100
+ end
101
+ end
102
+
103
+ it 'erases the value of the password taken from netrc after usage' do
104
+ with_platforms '' do
105
+ netrc_data = [['mocked_data']]
106
+ expect(::Netrc).to receive(:read) do
107
+ mocked_netrc = instance_double(::Netrc)
108
+ expect(mocked_netrc).to receive(:[]).with('my_domain.com').and_return %w[test_user test_password]
109
+ expect(mocked_netrc).to receive(:instance_variable_get).with(:@data).and_return netrc_data
110
+ mocked_netrc
111
+ end
112
+ leaked_password = nil
113
+ credential_tester_class.new(logger: logger, logger_stderr: logger, config: test_config).instance_exec do
114
+ with_credentials_for(:test_credential, resource: 'http://My_Domain.com/path/to/resource') do |_user, password|
115
+ leaked_password = password
116
+ end
117
+ end
118
+ expect(leaked_password).to eq "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
119
+ expect(netrc_data).to eq [['GotYou!!!' * 100]]
120
+ end
121
+ end
122
+
123
+ it 'returns credentials taken from config' do
124
+ with_platforms(
125
+ <<~'EO_CONFIG'
126
+ credentials_for(:test_credential) do |resource, requester|
127
+ requester.call "user_for_#{resource}", "password_for_#{resource}"
128
+ end
129
+ EO_CONFIG
130
+ ) do
131
+ # Check that netrc is not called when config is used, and that env vars are ignored
132
+ ENV['hpc_user_for_test_credential'] = 'env_test_user'
133
+ ENV['hpc_password_for_test_credential'] = 'env_test_password'
134
+ begin
135
+ # Check that .netrc won't be read
136
+ expect(::Netrc).not_to receive(:read)
137
+ expect_credentials_to_be 'user_for_', 'password_for_'
138
+ ensure
139
+ ENV.delete('hpc_user_for_test_credential')
140
+ ENV.delete('hpc_password_for_test_credential')
141
+ end
142
+ end
143
+ end
144
+
145
+ it 'returns credentials taken from config for a given resource' do
146
+ with_platforms(
147
+ <<~'EO_CONFIG'
148
+ credentials_for(:test_credential) do |resource, requester|
149
+ requester.call "user_for_#{resource}", "password_for_#{resource}"
150
+ end
151
+ EO_CONFIG
152
+ ) do
153
+ # Check that netrc is not called when config is used, and that env vars are ignored
154
+ ENV['hpc_user_for_test_credential'] = 'env_test_user'
155
+ ENV['hpc_password_for_test_credential'] = 'env_test_password'
156
+ begin
157
+ # Check that .netrc won't be read
158
+ expect(::Netrc).not_to receive(:read)
159
+ expect_credentials_to_be 'user_for_test_resource', 'password_for_test_resource', resource: 'test_resource'
160
+ ensure
161
+ ENV.delete('hpc_user_for_test_credential')
162
+ ENV.delete('hpc_password_for_test_credential')
163
+ end
164
+ end
165
+ end
166
+
167
+ it 'returns credentials taken from config for a given resource even when they are nil' do
168
+ with_platforms(
169
+ <<~'EO_CONFIG'
170
+ credentials_for(:test_credential) do |resource, requester|
171
+ requester.call nil, nil
172
+ end
173
+ EO_CONFIG
174
+ ) do
175
+ # Check that netrc is not called when config is used, and that env vars are ignored
176
+ ENV['hpc_user_for_test_credential'] = 'env_test_user'
177
+ ENV['hpc_password_for_test_credential'] = 'env_test_password'
178
+ begin
179
+ # Check that .netrc won't be read
180
+ expect(::Netrc).not_to receive(:read)
181
+ expect_credentials_to_be nil, nil, resource: 'test_resource'
182
+ ensure
183
+ ENV.delete('hpc_user_for_test_credential')
184
+ ENV.delete('hpc_password_for_test_credential')
185
+ end
186
+ end
187
+ end
188
+
189
+ it 'returns credentials taken from config after filtering the resource name' do
190
+ with_platforms(
191
+ <<~'EO_CONFIG'
192
+ credentials_for(:test_credential, resource: 'another_resource') do |resource, requester|
193
+ requester.call "wrong_user_for_#{resource}", "wrong_password_for_#{resource}"
194
+ end
195
+ credentials_for(:test_credential, resource: /test_.*/) do |resource, requester|
196
+ requester.call "wrong_user_for_#{resource}", "wrong_password_for_#{resource}"
197
+ end
198
+ credentials_for(:test_credential, resource: /_resource/) do |resource, requester|
199
+ requester.call "correct_user_for_#{resource}", "correct_password_for_#{resource}"
200
+ end
201
+ credentials_for(:test_credential, resource: 'test_resource2') do |resource, requester|
202
+ requester.call "wrong_user_for_#{resource}", "wrong_password_for_#{resource}"
203
+ end
204
+ EO_CONFIG
205
+ ) do
206
+ expect_credentials_to_be 'correct_user_for_test_resource', 'correct_password_for_test_resource', resource: 'test_resource'
207
+ end
208
+ end
209
+
210
+ it 'returns credentials taken from config after filtering the resource name when no resource is given' do
211
+ with_platforms(
212
+ <<~'EO_CONFIG'
213
+ credentials_for(:test_credential, resource: 'another_resource') do |resource, requester|
214
+ requester.call "wrong_user_for_#{resource}", "wrong_password_for_#{resource}"
215
+ end
216
+ credentials_for(:test_credential, resource: /test_.*/) do |resource, requester|
217
+ requester.call "wrong_user_for_#{resource}", "wrong_password_for_#{resource}"
218
+ end
219
+ credentials_for(:test_credential) do |resource, requester|
220
+ requester.call "correct_user_for_#{resource}", "correct_password_for_#{resource}"
221
+ end
222
+ credentials_for(:test_credential, resource: /_resource/) do |resource, requester|
223
+ requester.call "wrong_user_for_#{resource}", "wrong_password_for_#{resource}"
224
+ end
225
+ credentials_for(:test_credential, resource: 'test_resource2') do |resource, requester|
226
+ requester.call "wrong_user_for_#{resource}", "wrong_password_for_#{resource}"
227
+ end
228
+ EO_CONFIG
229
+ ) do
230
+ expect_credentials_to_be 'correct_user_for_', 'correct_password_for_'
231
+ end
232
+ end
233
+
234
+ it 'fails if the requester is not called from config' do
235
+ with_platforms(
236
+ <<~'EO_CONFIG'
237
+ credentials_for(:test_credential) do |resource, requester|
238
+ end
239
+ EO_CONFIG
240
+ ) do
241
+ expect do
242
+ credential_tester_class.new(logger: logger, logger_stderr: logger, config: test_config).instance_exec do
243
+ with_credentials_for(:test_credential) do |_user, _password|
244
+ nil
245
+ end
246
+ end
247
+ end.to raise_error 'Requester not called by the credentials provider for test_credential (resource: ) - Please check the credentials_for code in your configuration.'
248
+ end
249
+ end
250
+
251
+ end