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
@@ -35,9 +35,11 @@ module HybridPlatformsConductor
35
35
  # [API] - @stderr_io can be used to send stderr output
36
36
  #
37
37
  # Parameters::
38
- # * *bash_cmds* (String): Bash commands to execute
38
+ # * *bash_cmds* (String or SecretString): Bash commands to execute. Use #to_unprotected to access the real content (otherwise secrets are obfuscated).
39
39
  def remote_bash(bash_cmds)
40
- run_cmd "cd #{workspace_for(@node)} ; #{bash_cmds}", force_bash: true
40
+ SecretString.protect("cd #{workspace_for(@node)} ; #{bash_cmds.to_unprotected}", silenced_str: "cd #{workspace_for(@node)} ; #{bash_cmds}") do |cmd|
41
+ run_cmd cmd, force_bash: true
42
+ end
41
43
  end
42
44
 
43
45
  # Execute an interactive shell on the remote node
@@ -104,7 +104,7 @@ module HybridPlatformsConductor
104
104
  # [API] - @stderr_io can be used to send stderr output
105
105
  #
106
106
  # Parameters::
107
- # * *bash_cmds* (String): Bash commands to execute
107
+ # * *bash_cmds* (String or SecretString): Bash commands to execute. Use #to_unprotected to access the real content (otherwise secrets are obfuscated).
108
108
  def remote_bash(bash_cmds)
109
109
  MyConnectLib.connect_to(@nodes_handler.get_host_ip_of(@node)).run_bash(bash_cmds)
110
110
  end
@@ -236,31 +236,40 @@ module HybridPlatformsConductor
236
236
  # [API] - @stderr_io can be used to send stderr output
237
237
  #
238
238
  # Parameters::
239
- # * *bash_cmds* (String): Bash commands to execute
239
+ # * *bash_cmds* (String or SecretString): Bash commands to execute. Use #to_unprotected to access the real content (otherwise secrets are obfuscated).
240
240
  def remote_bash(bash_cmds)
241
- ssh_cmd =
241
+ SecretString.protect(
242
242
  if @nodes_handler.get_ssh_session_exec_of(@node) == false
243
243
  # When ExecSession is disabled we need to use stdin directly
244
- "{ cat | #{ssh_exec} #{ssh_url} -T; } <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
244
+ "{ cat | #{ssh_exec} #{ssh_url} -T; } <<'HPC_EOF'\n#{bash_cmds.to_unprotected}\nHPC_EOF"
245
245
  else
246
- "#{ssh_exec} #{ssh_url} /bin/bash <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
247
- end
248
- # Due to a limitation of Process.spawn, each individual argument is limited to 128KB of size.
249
- # Therefore we need to make sure that if bash_cmds exceeds MAX_CMD_ARG_LENGTH bytes (considering EOF chars) then we use an intermediary shell script to store the commands.
250
- if bash_cmds.size > MAX_CMD_ARG_LENGTH
251
- # Write the commands in a file
252
- temp_file = "#{Dir.tmpdir}/hpc_temp_cmds_#{Digest::MD5.hexdigest(bash_cmds)}.sh"
253
- File.open(temp_file, 'w+') do |file|
254
- file.write ssh_cmd
255
- file.chmod 0o700
256
- end
257
- begin
258
- run_cmd(temp_file)
259
- ensure
260
- File.unlink(temp_file)
246
+ "#{ssh_exec} #{ssh_url} /bin/bash <<'HPC_EOF'\n#{bash_cmds.to_unprotected}\nHPC_EOF"
247
+ end,
248
+ silenced_str:
249
+ if @nodes_handler.get_ssh_session_exec_of(@node) == false
250
+ # When ExecSession is disabled we need to use stdin directly
251
+ "{ cat | #{ssh_exec} #{ssh_url} -T; } <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
252
+ else
253
+ "#{ssh_exec} #{ssh_url} /bin/bash <<'HPC_EOF'\n#{bash_cmds}\nHPC_EOF"
254
+ end
255
+ ) do |ssh_cmd|
256
+ # Due to a limitation of Process.spawn, each individual argument is limited to 128KB of size.
257
+ # Therefore we need to make sure that if bash_cmds exceeds MAX_CMD_ARG_LENGTH bytes (considering EOF chars) then we use an intermediary shell script to store the commands.
258
+ if bash_cmds.to_unprotected.size > MAX_CMD_ARG_LENGTH
259
+ # Write the commands in a file
260
+ temp_file = "#{Dir.tmpdir}/hpc_temp_cmds_#{Digest::MD5.hexdigest(bash_cmds.to_unprotected)}.sh"
261
+ File.open(temp_file, 'w+') do |file|
262
+ file.write ssh_cmd.to_unprotected
263
+ file.chmod 0o700
264
+ end
265
+ begin
266
+ run_cmd(temp_file)
267
+ ensure
268
+ File.unlink(temp_file)
269
+ end
270
+ else
271
+ run_cmd ssh_cmd
261
272
  end
262
- else
263
- run_cmd ssh_cmd
264
273
  end
265
274
  end
266
275
 
@@ -263,7 +263,7 @@ module HybridPlatformsConductor
263
263
  raise "Missing file #{chef_versions_file} specifying the Chef Infra Client version to be deployed" unless File.exist?(chef_versions_file)
264
264
 
265
265
  required_chef_client_version = YAML.load_file(chef_versions_file)['client']
266
- sudo = (@actions_executor.connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} ")
266
+ sudo = (@actions_executor.connector(:ssh).ssh_user == 'root' ? '' : "#{@nodes_handler.sudo_on(node)} -E ")
267
267
  [
268
268
  {
269
269
  # Install dependencies
@@ -263,6 +263,8 @@ module HybridPlatformsConductor
263
263
 
264
264
  private
265
265
 
266
+ include Credentials
267
+
266
268
  # Connect to the Proxmox API
267
269
  #
268
270
  # Parameters::
@@ -273,7 +275,7 @@ module HybridPlatformsConductor
273
275
  url = proxmox_test_info[:api_url]
274
276
  raise 'No Proxmox server defined' if url.nil?
275
277
 
276
- Credentials.with_credentials_for(:proxmox, @logger, @logger_stderr, url: url) do |user, password|
278
+ with_credentials_for(:proxmox, resource: url) do |user, password|
277
279
  log_debug "[ #{@node}/#{@environment} ] - Connect to Proxmox #{url}"
278
280
  proxmox_logs = StringIO.new
279
281
  proxmox = ::Proxmox::Proxmox.new(
@@ -282,7 +284,7 @@ module HybridPlatformsConductor
282
284
  # cf https://pve.proxmox.com/wiki/Renaming_a_PVE_node
283
285
  URI.parse(url).host.downcase.split('.').first,
284
286
  user,
285
- password,
287
+ password&.to_unprotected,
286
288
  ENV['hpc_realm_for_proxmox'] || 'pam',
287
289
  {
288
290
  verify_ssl: false,
@@ -415,7 +417,7 @@ module HybridPlatformsConductor
415
417
  extra_files[config_file] = './proxmox/config'
416
418
  cmd << " --config ./proxmox/config/#{File.basename(config_file)}"
417
419
  stdout = nil
418
- Credentials.with_credentials_for(:proxmox, @logger, @logger_stderr, url: proxmox_test_info[:api_url]) do |user, password|
420
+ with_credentials_for(:proxmox, resource: proxmox_test_info[:api_url]) do |user, password|
419
421
  # To avoid too fine concurrent accesses on the sync node file system, make sure all threads of our process wait for their turn to upload their files.
420
422
  # Otherwise there is a small probability that a directory scp makes previously copied files inaccessible for a short period of time.
421
423
  self.class.proxmox_waiter_files_mutex.synchronize do
@@ -34,6 +34,7 @@
34
34
  # * *hpc_password_for_proxmox*: Password to be used to query Proxmox API
35
35
  # * *hpc_realm_for_proxmox*: Realm used to connect to the Proxmox API [default = 'pam']
36
36
 
37
+ require 'English'
37
38
  require 'json'
38
39
 
39
40
  reserved_resource = nil
@@ -14,6 +14,8 @@ module HybridPlatformsConductor
14
14
 
15
15
  extend_config_dsl_with CommonConfigDsl::Confluence, :init_confluence
16
16
 
17
+ include HybridPlatformsConductor::Confluence
18
+
17
19
  # Give the list of supported locales by this report generator
18
20
  # [API] - This method is mandatory.
19
21
  #
@@ -34,7 +36,7 @@ module HybridPlatformsConductor
34
36
  if confluence_info
35
37
  if confluence_info[:inventory_report_page_id]
36
38
  @nodes = nodes
37
- HybridPlatformsConductor::Confluence.with_confluence(confluence_info[:url], @logger, @logger_stderr) do |confluence|
39
+ with_confluence(confluence_info[:url]) do |confluence|
38
40
  confluence.update_page(confluence_info[:inventory_report_page_id], render('confluence_inventory'))
39
41
  end
40
42
  out "Inventory report Confluence page updated. Please visit #{confluence_info[:url]}/pages/viewpage.action?pageId=#{confluence_info[:inventory_report_page_id]}"
@@ -0,0 +1,174 @@
1
+ require 'base64'
2
+ require 'nokogiri'
3
+ require 'tempfile'
4
+ require 'keepass_kpscript'
5
+ require 'zlib'
6
+ require 'hybrid_platforms_conductor/credentials'
7
+ require 'hybrid_platforms_conductor/safe_merge'
8
+ require 'hybrid_platforms_conductor/secrets_reader'
9
+
10
+ module HybridPlatformsConductor
11
+
12
+ module HpcPlugins
13
+
14
+ module SecretsReader
15
+
16
+ # Get secrets from a KeePass database
17
+ class Keepass < HybridPlatformsConductor::SecretsReader
18
+
19
+ include SafeMerge
20
+ include Credentials
21
+
22
+ # Extend the Config DSL
23
+ module ConfigDSLExtension
24
+
25
+ # List of defined KeePass secrets. Each info has the following properties:
26
+ # * *nodes_selectors_stack* (Array<Object>): Stack of nodes selectors impacted by this rule.
27
+ # * *database* (String): Database file path.
28
+ # * *group_path* (Array<String>): Group path to extract from.
29
+ # Array< Hash<Symbol, Object> >
30
+ attr_reader :keepass_secrets
31
+
32
+ # String: The KPScript command line
33
+ attr_reader :kpscript
34
+
35
+ # Mixin initializer
36
+ def init_keepass_config
37
+ @keepass_secrets = []
38
+ @kpscript = nil
39
+ end
40
+
41
+ # Set the KPScript command line
42
+ #
43
+ # Parameters::
44
+ # * *cmd* (String): KPScript command line
45
+ def use_kpscript_from(cmd)
46
+ @kpscript = cmd
47
+ end
48
+
49
+ # Set a KeePass database configuration
50
+ #
51
+ # Parameters::
52
+ # * *database* (String): Database file path.
53
+ # * *group_path* (Array<String>): Group path to extract from [default: []].
54
+ def secrets_from_keepass(database:, group_path: [])
55
+ @keepass_secrets << {
56
+ nodes_selectors_stack: current_nodes_selectors_stack,
57
+ database: database,
58
+ group_path: group_path
59
+ }
60
+ end
61
+
62
+ end
63
+
64
+ Config.extend_config_dsl_with ConfigDSLExtension, :init_keepass_config
65
+
66
+ # Return secrets for a given service to be deployed on a node.
67
+ # [API] - This method is mandatory
68
+ # [API] - The following API components are accessible:
69
+ # * *@config* (Config): Main configuration API.
70
+ # * *@cmd_runner* (CmdRunner): Command Runner API.
71
+ # * *@nodes_handler* (NodesHandler): Nodes handler API.
72
+ #
73
+ # Parameters::
74
+ # * *node* (String): Node to be deployed
75
+ # * *service* (String): Service to be deployed
76
+ # Result::
77
+ # * Hash: The secrets
78
+ def secrets_for(node, service)
79
+ secrets = {}
80
+ # As we are dealing with global secrets, cache the reading for performance between nodes and services.
81
+ # Keep secrets cache grouped by URL/ID
82
+ @secrets = {} unless defined?(@secrets)
83
+ @nodes_handler.select_confs_for_node(node, @config.keepass_secrets).each do |keepass_secrets_info|
84
+ secret_id = "#{keepass_secrets_info[:database]}:#{keepass_secrets_info[:group_path].join('/')}"
85
+ unless @secrets.key?(secret_id)
86
+ raise 'Missing KPScript configuration. Please use use_kpscript_from to set it.' if @config.kpscript.nil?
87
+
88
+ with_credentials_for(:keepass, resource: keepass_secrets_info[:database]) do |_user, password|
89
+ Tempfile.create('hpc_keepass') do |xml_file|
90
+ key_file = ENV['hpc_key_file_for_keepass']
91
+ password_enc = ENV['hpc_password_enc_for_keepass']
92
+ keepass_credentials = {}
93
+ keepass_credentials[:password] = password.to_unprotected if password
94
+ keepass_credentials[:password_enc] = password_enc if password_enc
95
+ keepass_credentials[:key_file] = key_file if key_file
96
+ KeepassKpscript.
97
+ use(@config.kpscript, debug: log_debug?).
98
+ open(keepass_secrets_info[:database], **keepass_credentials).
99
+ export('KeePass XML (2.x)', xml_file.path, group_path: keepass_secrets_info[:group_path].empty? ? nil : keepass_secrets_info[:group_path])
100
+ @secrets[secret_id] = parse_xml_secrets(Nokogiri::XML(xml_file).at_xpath('KeePassFile/Root/Group'))
101
+ end
102
+ end
103
+ end
104
+ conflicting_path = safe_merge(secrets, @secrets[secret_id])
105
+ raise "Secret set at path #{conflicting_path.join('->')} by #{keepass_secrets_info[:database]}#{keepass_secrets_info[:group_path].empty? ? '' : " from group #{keepass_secrets_info[:group_path].join('/')}"} for service #{service} on node #{node} has conflicting values (#{log_debug? ? "#{@secrets[secret_id].dig(*conflicting_path)} != #{secrets.dig(*conflicting_path)}" : 'set debug for value details'})." unless conflicting_path.nil?
106
+ end
107
+ secrets
108
+ end
109
+
110
+ private
111
+
112
+ # List of fields to include in the secrets and their corresponding XML name
113
+ FIELDS = {
114
+ notes: 'Notes',
115
+ password: 'Password',
116
+ url: 'URL',
117
+ user_name: 'UserName'
118
+ }
119
+
120
+ # Parse XML secrets from a Nokogiri XML group node
121
+ #
122
+ # Parameters::
123
+ # * *group* (Nokogiri::XML::Element): The group to parse
124
+ # Result::
125
+ # * Hash: The JSON secrets parsed from this group
126
+ def parse_xml_secrets(group)
127
+ # Parse all entries
128
+ group.xpath('Entry').map do |entry|
129
+ [
130
+ entry.at_xpath('String/Key[contains(.,"Title")]/../Value').text,
131
+ FIELDS.map do |property, field|
132
+ value = entry.at_xpath("String/Key[contains(.,\"#{field}\")]/../Value")&.text
133
+ if value.nil? || value.empty?
134
+ nil
135
+ else
136
+ [
137
+ property.to_s,
138
+ value
139
+ ]
140
+ end
141
+ end.compact.to_h.merge(
142
+ entry.xpath('Binary').map do |binary|
143
+ binary_meta = group.document.at_xpath("KeePassFile/Meta/Binaries/Binary[@ID=#{Integer(binary.xpath('Value').attr('Ref').value)}]")
144
+ binary_content = Base64.decode64(binary_meta.text)
145
+ if binary_meta.attr('Compressed') == 'True'
146
+ gz = Zlib::GzipReader.new(StringIO.new(binary_content))
147
+ binary_content = gz.read
148
+ gz.close
149
+ end
150
+ [
151
+ binary.xpath('Key').text,
152
+ binary_content
153
+ ]
154
+ end.to_h
155
+ )
156
+ ]
157
+ end.to_h.merge(
158
+ # Add children groups
159
+ group.xpath('Group').map do |sub_group|
160
+ [
161
+ sub_group.at_xpath('Name').text,
162
+ parse_xml_secrets(sub_group)
163
+ ]
164
+ end.to_h
165
+ )
166
+ end
167
+
168
+ end
169
+
170
+ end
171
+
172
+ end
173
+
174
+ end
@@ -42,6 +42,8 @@ module HybridPlatformsConductor
42
42
 
43
43
  Config.extend_config_dsl_with ConfigDSLExtension, :init_thycotic_config
44
44
 
45
+ include HybridPlatformsConductor::Thycotic
46
+
45
47
  # Return secrets for a given service to be deployed on a node.
46
48
  # [API] - This method is mandatory
47
49
  # [API] - The following API components are accessible:
@@ -62,7 +64,7 @@ module HybridPlatformsConductor
62
64
  @nodes_handler.select_confs_for_node(node, @config.thycotic_secrets).each do |thycotic_secrets_info|
63
65
  server_id = "#{thycotic_secrets_info[:thycotic_url]}:#{thycotic_secrets_info[:secret_id]}"
64
66
  unless @secrets.key?(server_id)
65
- HybridPlatformsConductor::Thycotic.with_thycotic(thycotic_secrets_info[:thycotic_url], @logger, @logger_stderr) do |thycotic|
67
+ with_thycotic(thycotic_secrets_info[:thycotic_url]) do |thycotic|
66
68
  secret_file_item_id = thycotic.get_secret(thycotic_secrets_info[:secret_id]).dig(:secret, :items, :secret_item, :id)
67
69
  raise "Unable to fetch secret file ID #{thycotic_secrets_info[:secret_id]} from #{thycotic_secrets_info[:thycotic_url]}" if secret_file_item_id.nil?
68
70
 
@@ -1,4 +1,5 @@
1
1
  require 'git'
2
+ require 'hybrid_platforms_conductor/bitbucket'
2
3
  require 'hybrid_platforms_conductor/common_config_dsl/bitbucket'
3
4
 
4
5
  module HybridPlatformsConductor
@@ -12,9 +13,11 @@ module HybridPlatformsConductor
12
13
 
13
14
  extend_config_dsl_with CommonConfigDsl::Bitbucket, :init_bitbucket
14
15
 
16
+ include HybridPlatformsConductor::Bitbucket
17
+
15
18
  # Check my_test_plugin.rb.sample documentation for signature details.
16
19
  def test
17
- @config.for_each_bitbucket_repo do |bitbucket, repo_info|
20
+ for_each_bitbucket_repo do |bitbucket, repo_info|
18
21
  # Test repo_info
19
22
  repo_id = "#{repo_info[:project]}/#{repo_info[:name]}"
20
23
  settings_pr = bitbucket.settings_pr(repo_info[:project], repo_info[:name])
@@ -1,3 +1,4 @@
1
+ require 'hybrid_platforms_conductor/github'
1
2
  require 'hybrid_platforms_conductor/common_config_dsl/github'
2
3
 
3
4
  module HybridPlatformsConductor
@@ -11,9 +12,11 @@ module HybridPlatformsConductor
11
12
 
12
13
  extend_config_dsl_with CommonConfigDsl::Github, :init_github
13
14
 
15
+ include HybridPlatformsConductor::Github
16
+
14
17
  # Check my_test_plugin.rb.sample documentation for signature details.
15
18
  def test
16
- @config.for_each_github_repo do |client, repo_info|
19
+ for_each_github_repo do |client, repo_info|
17
20
  log_debug "Checking CI for Github repository #{repo_info[:slug]}"
18
21
  last_status = client.repository_workflow_runs(repo_info[:slug])[:workflow_runs].
19
22
  select { |run| run[:head_branch] == 'master' }.
@@ -1,6 +1,7 @@
1
1
  require 'open-uri'
2
2
  require 'nokogiri'
3
3
  require 'hybrid_platforms_conductor/credentials'
4
+ require 'hybrid_platforms_conductor/bitbucket'
4
5
  require 'hybrid_platforms_conductor/common_config_dsl/bitbucket'
5
6
 
6
7
  module HybridPlatformsConductor
@@ -14,15 +15,18 @@ module HybridPlatformsConductor
14
15
 
15
16
  extend_config_dsl_with CommonConfigDsl::Bitbucket, :init_bitbucket
16
17
 
18
+ include Credentials
19
+ include HybridPlatformsConductor::Bitbucket
20
+
17
21
  # Check my_test_plugin.rb.sample documentation for signature details.
18
22
  def test
19
- @config.for_each_bitbucket_repo do |bitbucket, repo_info|
23
+ for_each_bitbucket_repo do |bitbucket, repo_info|
20
24
  if repo_info[:jenkins_ci_url].nil?
21
25
  error "Repository #{repo_info[:name]} does not have any Jenkins CI URL configured."
22
26
  else
23
- Credentials.with_credentials_for(:jenkins_ci, @logger, @logger_stderr, url: repo_info[:jenkins_ci_url]) do |jenkins_user, jenkins_password|
27
+ with_credentials_for(:jenkins_ci, resource: repo_info[:jenkins_ci_url]) do |jenkins_user, jenkins_password|
24
28
  # Get its config
25
- doc = Nokogiri::XML(URI.parse("#{repo_info[:jenkins_ci_url]}/config.xml").open(http_basic_authentication: [jenkins_user, jenkins_password]).read)
29
+ doc = Nokogiri::XML(URI.parse("#{repo_info[:jenkins_ci_url]}/config.xml").open(http_basic_authentication: [jenkins_user, jenkins_password&.to_unprotected]).read)
26
30
  # Check that this job builds the correct Bitbucket repository
27
31
  assert_equal(
28
32
  doc.xpath('/org.jenkinsci.plugins.workflow.multibranch.WorkflowMultiBranchProject/sources/data/jenkins.branch.BranchSource/source/serverUrl').text,
@@ -1,5 +1,6 @@
1
1
  require 'json'
2
2
  require 'hybrid_platforms_conductor/credentials'
3
+ require 'hybrid_platforms_conductor/bitbucket'
3
4
  require 'hybrid_platforms_conductor/common_config_dsl/bitbucket'
4
5
 
5
6
  module HybridPlatformsConductor
@@ -13,6 +14,9 @@ module HybridPlatformsConductor
13
14
 
14
15
  extend_config_dsl_with CommonConfigDsl::Bitbucket, :init_bitbucket
15
16
 
17
+ include Credentials
18
+ include HybridPlatformsConductor::Bitbucket
19
+
16
20
  SUCCESS_STATUSES = [
17
21
  # Add nil as the status of a currently running job (which is always the case for hybrid-platforms) is null
18
22
  nil,
@@ -23,17 +27,17 @@ module HybridPlatformsConductor
23
27
 
24
28
  # Check my_test_plugin.rb.sample documentation for signature details.
25
29
  def test
26
- @config.for_each_bitbucket_repo do |_bitbucket, repo_info|
30
+ for_each_bitbucket_repo do |_bitbucket, repo_info|
27
31
  if repo_info[:jenkins_ci_url].nil?
28
32
  error "Repository #{repo_info[:name]} does not have any Jenkins CI URL configured."
29
33
  else
30
34
  master_info_url = "#{repo_info[:jenkins_ci_url]}/job/master/api/json"
31
- Credentials.with_credentials_for(:jenkins_ci, @logger, @logger_stderr, url: master_info_url) do |jenkins_user, jenkins_password|
35
+ with_credentials_for(:jenkins_ci, resource: master_info_url) do |jenkins_user, jenkins_password|
32
36
  # Get the master branch info from the API
33
- master_info = JSON.parse(URI.parse(master_info_url).open(http_basic_authentication: [jenkins_user, jenkins_password]).read)
37
+ master_info = JSON.parse(URI.parse(master_info_url).open(http_basic_authentication: [jenkins_user, jenkins_password&.to_unprotected]).read)
34
38
  # Get the last build's URL
35
39
  last_build_info_url = "#{master_info['lastBuild']['url']}/api/json"
36
- last_build_info = JSON.parse(URI.parse(last_build_info_url).open(http_basic_authentication: [jenkins_user, jenkins_password]).read)
40
+ last_build_info = JSON.parse(URI.parse(last_build_info_url).open(http_basic_authentication: [jenkins_user, jenkins_password&.to_unprotected]).read)
37
41
  log_debug "Build info for #{master_info_url}:\n#{JSON.pretty_generate(last_build_info)}"
38
42
  error "Last build for job #{repo_info[:project]}/#{repo_info[:name]} is in status #{last_build_info['result']}: #{master_info['lastBuild']['url']}" unless SUCCESS_STATUSES.include?(last_build_info['result'])
39
43
  rescue