brpm_content_framework 0.1.55

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 (77) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +38 -0
  3. data/.travis.yml +17 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +21 -0
  6. data/README.md +308 -0
  7. data/Rakefile +23 -0
  8. data/TO_BE_MIGRATED.txt +9 -0
  9. data/architecture.png +0 -0
  10. data/automations/direct_execute.meta +10 -0
  11. data/automations/direct_execute.rb +10 -0
  12. data/automations/install_module.meta +10 -0
  13. data/automations/install_module.rb +13 -0
  14. data/bin/brpm_install +30 -0
  15. data/bin/brpm_uninstall +30 -0
  16. data/bin/event_handler +63 -0
  17. data/bin/webhook_receiver +49 -0
  18. data/brpm_content.gemspec +31 -0
  19. data/config.yml +8 -0
  20. data/infrastructure/.bashrc +6 -0
  21. data/infrastructure/.brpm +2 -0
  22. data/infrastructure/config/customer_include.rb +26 -0
  23. data/infrastructure/config/server.yml +3 -0
  24. data/infrastructure/log.html +39 -0
  25. data/infrastructure/scripts/backup_database.sh +19 -0
  26. data/infrastructure/scripts/ddns.sh +10 -0
  27. data/infrastructure/scripts/install_brpm.sh +63 -0
  28. data/infrastructure/scripts/maintenance.sh +4 -0
  29. data/infrastructure/scripts/patch_brpm.sh +90 -0
  30. data/infrastructure/scripts/restore_database.sh +33 -0
  31. data/infrastructure/scripts/run_event_handler.cmd +19 -0
  32. data/infrastructure/scripts/run_event_handler.sh +20 -0
  33. data/infrastructure/scripts/run_webhook_receiver.cmd +15 -0
  34. data/infrastructure/scripts/run_webhook_receiver.sh +15 -0
  35. data/infrastructure/silent_install_options_4.6.txt +93 -0
  36. data/infrastructure/silent_install_options_upgrade_4.6.txt +92 -0
  37. data/infrastructure/smtp_settings.rb +42 -0
  38. data/lib/brpm_auto.rb +358 -0
  39. data/lib/brpm_script_executor.rb +80 -0
  40. data/lib/logging/brpm_logger.rb +39 -0
  41. data/lib/logging/logger_base.rb +36 -0
  42. data/lib/logging/simple_logger.rb +27 -0
  43. data/lib/module_installer.rb +483 -0
  44. data/lib/params/all_params.rb +80 -0
  45. data/lib/params/integration_settings.rb +27 -0
  46. data/lib/params/params.rb +174 -0
  47. data/lib/params/params_base.rb +81 -0
  48. data/lib/params/request_params.rb +38 -0
  49. data/lib/rest_api.rb +155 -0
  50. data/lib/semaphore.rb +79 -0
  51. data/lib/utilities.rb +317 -0
  52. data/lib/version_control/git.rb +192 -0
  53. data/lib/version_control/svn.rb +221 -0
  54. data/lib/write_to.rb +1 -0
  55. data/tests/all_params_spec.rb +116 -0
  56. data/tests/brpm_auto_spec.rb +84 -0
  57. data/tests/customer_include/config/customer_include.rb +10 -0
  58. data/tests/customer_include/config/server.yml +3 -0
  59. data/tests/customer_include_spec.rb +29 -0
  60. data/tests/gemspec_spec.rb +11 -0
  61. data/tests/module_installer_spec.rb +46 -0
  62. data/tests/params_spec.rb +172 -0
  63. data/tests/request_params_spec.rb +86 -0
  64. data/tests/server_yaml_spec.rb +19 -0
  65. data/tests/spec_helper.rb +64 -0
  66. data/to_be_migrated/brpm_framework.rb +88 -0
  67. data/to_be_migrated/customer_include_default.rb +25 -0
  68. data/to_be_migrated/local_jirb.rb +15 -0
  69. data/to_be_migrated/resource_framework.rb +211 -0
  70. data/transport/dispatch_baa.rb +355 -0
  71. data/transport/dispatch_base.rb +345 -0
  72. data/transport/dispatch_nsh.rb +248 -0
  73. data/transport/dispatch_ssh.rb +154 -0
  74. data/transport/transport_baa.rb +1095 -0
  75. data/transport/transport_nsh.rb +359 -0
  76. data/transport/transport_ssh.rb +220 -0
  77. metadata +204 -0
@@ -0,0 +1,174 @@
1
+ class Params < ParamsBase
2
+ attr_reader :application
3
+ attr_reader :component
4
+ attr_reader :component_version
5
+
6
+ attr_reader :request_id
7
+ attr_reader :request_name
8
+ attr_reader :request_number
9
+ attr_reader :request_environment
10
+ attr_reader :request_scheduled_at
11
+ attr_reader :request_started_at
12
+ attr_reader :request_status
13
+
14
+ attr_reader :request_plan
15
+ attr_reader :request_plan_id
16
+ attr_reader :request_plan_member_id
17
+ attr_reader :request_plan_stage
18
+
19
+ attr_reader :request_run_id
20
+ attr_reader :request_run_name
21
+
22
+ attr_reader :step_id
23
+ attr_reader :step_number
24
+ attr_reader :step_name
25
+ attr_reader :step_description
26
+ attr_reader :step_estimate
27
+
28
+ attr_reader :step_version
29
+ attr_reader :step_version_artifact_url
30
+
31
+ attr_reader :servers
32
+
33
+ attr_reader :ticket_ids
34
+ attr_reader :tickets_foreign_ids
35
+
36
+ attr_reader :run_key
37
+
38
+ attr_reader :home_dir
39
+ attr_reader :automation_results_dir
40
+ attr_reader :output_dir
41
+ attr_reader :output_file
42
+ attr_reader :config_dir
43
+
44
+ attr_reader :log_file
45
+
46
+ attr_reader :brpm_url
47
+ attr_reader :brpm_api_token
48
+
49
+ attr_reader :run_from_brpm
50
+ attr_reader :unit_test
51
+ attr_reader :also_log_to_console
52
+
53
+ attr_reader :private_params
54
+
55
+ def initialize(params)
56
+ self.merge!(params)
57
+
58
+ @application = params["application"]
59
+ @component = params["component"]
60
+ @component_version = params["component_version"]
61
+
62
+ @request_id = params["request_id"]
63
+ @request_name = params["request_name"]
64
+ @request_number = params["request_number"]
65
+ @request_environment = params["request_environment"]
66
+ @request_scheduled_at = params["request_scheduled_at"]
67
+ @request_started_at = params["request_started_at"]
68
+ @request_status = params["request_status"]
69
+
70
+ @request_plan = params["request_plan"]
71
+ @request_plan_id = params["request_plan_id"]
72
+ @request_plan_member_id = params["request_plan_member_id"]
73
+ @request_plan_stage = params["request_plan_stage"]
74
+
75
+ @request_run_id = params["request_run_id"]
76
+ @request_run_name = params["request_run_name"]
77
+
78
+ @step_id = params["step_id"]
79
+ @step_number = params["step_number"]
80
+ @step_name = params["step_name"]
81
+ @step_description = params["step_description"]
82
+ @step_estimate = params["step_estimate"]
83
+
84
+ @step_version = params["step_version"]
85
+ @step_version_artifact_url = params["step_version_artifact_url"]
86
+
87
+ @servers = get_server_list
88
+
89
+ @ticket_ids = params["ticket_ids"]
90
+ @tickets_foreign_ids = params["tickets_foreign_ids"]
91
+
92
+ @run_key = params["SS_run_key"] || params["run_key"]
93
+
94
+ if params["SS_automation_results_dir"]
95
+ @home_dir = params["SS_automation_results_dir"].sub("automation_results", "")
96
+ else
97
+ @home_dir = params["home_dir"] || Dir.pwd
98
+ end
99
+ @automation_results_dir = params["SS_automation_results_dir"]
100
+ @output_dir = params["SS_output_dir"] || params["output_dir"] || Dir.pwd
101
+ @output_file = params["SS_output_file"]
102
+ @config_dir = "#{@home_dir}/config"
103
+
104
+ @log_file = params["log_file"] || "#{@output_dir}/brpm_auto.log"
105
+
106
+ @brpm_url = params["SS_base_url"] || params["brpm_url"]
107
+ @brpm_api_token = params["SS_api_token"] || params["brpm_api_token"]
108
+
109
+ @run_from_brpm = (@run_key != nil)
110
+ @unit_test = (params["unit_test"] == "true" || params["unit_test"] == 'true')
111
+ @also_log_to_console = (params["also_log_to_console"] == "true" || params["also_log_to_console"] == 'true')
112
+
113
+ @private_params = {}
114
+ if self.run_from_brpm
115
+ params.each do |k,v|
116
+ if k.end_with?("_encrypt") || k.end_with?("_enc")
117
+ if k.end_with?("_encrypt")
118
+ key_decrypted = k.gsub("_encrypt","")
119
+ elsif k.end_with?("_enc")
120
+ key_decrypted = k.gsub("_enc","")
121
+ end
122
+ value_decrypted = decrypt_string_with_prefix(v)
123
+ @private_params[key_decrypted] = value_decrypted
124
+ end
125
+ end
126
+ end
127
+ self.merge!(@private_params)
128
+ end
129
+
130
+ # Servers in params need to be filtered by OS
131
+ def get_servers_by_os_platform(os_platform, alt_servers = nil)
132
+ servers = alt_servers || @servers
133
+ result = servers.select{|k,v| v["os_platform"].downcase =~ /#{os_platform}/ }
134
+ end
135
+
136
+ # Fetches the property value for a server
137
+ #
138
+ # ==== Returns
139
+ #
140
+ # * property value
141
+ def get_server_property(server, property)
142
+ ans = ""
143
+ ans = @servers[server][property] if @servers.has_key?(server) && @servers[server].has_key?(property)
144
+ ans
145
+ end
146
+
147
+ # Returns the request id for use in rest calls
148
+ #
149
+ def rest_request_id
150
+ (self["request_id"].to_i - 1000).to_s
151
+ end
152
+
153
+ private
154
+
155
+ def get_server_list()
156
+ rxp = /server\d+_/
157
+ slist = {}
158
+ lastcur = -1
159
+ curname = ""
160
+
161
+ self.sort.reject{ |k| k[0].scan(rxp).empty? }.each_with_index do |server, idx|
162
+ cur = (server[0].scan(rxp)[0].gsub("server","").to_i * 0.001).round * 1000
163
+ if cur == lastcur
164
+ prop = server[0].gsub(rxp, "")
165
+ slist[curname][prop] = server[1]
166
+ else # new server
167
+ lastcur = cur
168
+ curname = server[1].chomp("0")
169
+ slist[curname] = {}
170
+ end
171
+ end
172
+ return slist
173
+ end
174
+ end
@@ -0,0 +1,81 @@
1
+ class ParamsBase < Hash
2
+ def [] key
3
+ BrpmAuto.substitute_tokens(super(key))
4
+ end
5
+
6
+ # Gets a params
7
+ #
8
+ # ==== Attributes
9
+ #
10
+ # * +key+ - key to find
11
+ def get(key, default_value = "")
12
+ self[key] || default_value
13
+ end
14
+
15
+ # Adds a key/value to the params
16
+ #
17
+ # ==== Attributes
18
+ #
19
+ # * +key_name+ - key name
20
+ # * +value+ - value to assign
21
+ #
22
+ # ==== Returns
23
+ #
24
+ # * value added
25
+ def add(key, value)
26
+ self[key] = value
27
+ end
28
+
29
+ # Adds a key/value to the params if not found
30
+ #
31
+ # ==== Attributes
32
+ #
33
+ # * +key_name+ - key name
34
+ # * +value+ - value to assign
35
+ #
36
+ # ==== Returns
37
+ #
38
+ # * value of key
39
+ def find_or_add(key, value)
40
+ ans = get(key)
41
+ add(key, value) if ans == ""
42
+ ans == "" ? value : ans
43
+ end
44
+
45
+ # Allows you to specify a key like a method call
46
+ #
47
+ # ==== Attributes
48
+ #
49
+ # * +key_name+ - key name note: you must use get if keyname has spaces
50
+ # * +*args+ - allows you to send a default value
51
+ #
52
+ # ==== Returns
53
+ #
54
+ # * value of key - including resolved properties that may be embedded
55
+ #
56
+ # ==== Examples
57
+ #
58
+ # @p = Params.new(params)
59
+ # @p.SS_application
60
+ # => "Sales"
61
+ def method_missing(key, *args)
62
+ ans = get(key.to_s)
63
+ ans = args[0] if ans == "" && args[0]
64
+ ans
65
+ end
66
+
67
+ # Raises an error if a key is not found
68
+ #
69
+ # ==== Attributes
70
+ #
71
+ # * +key_name+ - key name
72
+ #
73
+ # ==== Returns
74
+ #
75
+ # * value of key
76
+ def required(key)
77
+ raise "ParamsError: param #{key} must be present" unless self.has_key?(key)
78
+ get(key)
79
+ end
80
+
81
+ end
@@ -0,0 +1,38 @@
1
+ class RequestParams < ParamsBase
2
+ attr_reader :file_path
3
+
4
+ def initialize(path)
5
+ @file_path = "#{path}/request_data.json"
6
+
7
+ self.merge!(get_request_params)
8
+ end
9
+
10
+ def self.new_for_request(automation_results_dir, app_name, request_id)
11
+ self.new("#{automation_results_dir}/request/#{app_name}/#{request_id}")
12
+ end
13
+
14
+ def []=(key,val)
15
+ super(key, val)
16
+
17
+ set_request_params
18
+ end
19
+
20
+ #TODO: support parallel steps modifying the same request params file
21
+
22
+ private
23
+
24
+ def set_request_params
25
+ File.open(@file_path, "w") do |file|
26
+ file.puts(self.to_json)
27
+ end
28
+ end
29
+
30
+ def get_request_params
31
+ if File.exist?(@file_path)
32
+ json = File.read(@file_path)
33
+ JSON.parse(json)
34
+ else
35
+ {}
36
+ end
37
+ end
38
+ end
data/lib/rest_api.rb ADDED
@@ -0,0 +1,155 @@
1
+ require 'rest-client'
2
+ require 'uri'
3
+ require 'json'
4
+ require 'cgi'
5
+
6
+ class Rest
7
+ class << self
8
+ def get(url, options = {})
9
+ rest_call(url, "get", options)
10
+ end
11
+
12
+ def post(url, data, options = {})
13
+ options[:data] = data
14
+ rest_call(url, "post", options)
15
+ end
16
+
17
+ def put(url, data, options = {})
18
+ options[:data] = data
19
+ rest_call(url, "put", options)
20
+ end
21
+
22
+ def delete(url, options = {})
23
+ rest_call(url, "delete", options)
24
+ end
25
+
26
+ # Makes an http method call and returns data in JSON
27
+ #
28
+ # ==== Attributes
29
+ #
30
+ # * +url+ - the url for the request
31
+ # * +method+ - the http method [get, put, post]
32
+ # * +options+ - a hash of options
33
+ # +verbose+: gives verbose output (yes/no)
34
+ # +data+: required for put and post methods a hash of post data
35
+ # +username+: username for basic http authentication
36
+ # +password+: password for basic http authentication
37
+ # +suppress_errors+: continues after errors if true
38
+ #
39
+ # ==== Returns
40
+ #
41
+ # * returns a hash of the http response with these keys
42
+ # * +status+ - success or ERROR
43
+ # * +message+ - if status is ERROR this will hold an error message
44
+ # * +code+ - the http status code 200=ok, 404=not found, 500=error, 504=not authorized
45
+ # * +data+ - the body of the http response
46
+ def rest_call(url, method, options = {})
47
+ methods = %w{get post put delete}
48
+ result = rest_params = {}
49
+ rest_params[:url] = URI.escape(url)
50
+
51
+ unless methods.include?(method.downcase)
52
+ BrpmAuto.log "No method named: #{method}"
53
+ result["code"] = -1
54
+ result["status"] = "failure"
55
+ result["message"] = "No method named: #{method}"
56
+ return result
57
+ end
58
+
59
+ rest_params[:method] = method.downcase
60
+
61
+ begin
62
+ BrpmAuto.log("REST #{method.upcase} #{BrpmAuto.privatize(url, get_token(url))}") unless options.has_key?("quiet")
63
+
64
+ if options.has_key?(:username) && options.has_key?(:password)
65
+ rest_params[:user] = options[:username]
66
+ rest_params[:password] = options[:password]
67
+ end
68
+
69
+ if %{put post}.include?(method.downcase)
70
+ options[:data] = options["data"] if options.has_key?("data")
71
+ rest_params[:payload] = options[:data].to_json if options.has_key?(:data)
72
+ if !options.has_key?(:data) || rest_params[:payload].length < 4
73
+ result["code"] = -1
74
+ result["status"] = "failure"
75
+ result["message"] = "No Post data"
76
+ return result
77
+ end
78
+ BrpmAuto.log "\tPost Data: #{rest_params[:payload].inspect}" unless options.has_key?("quiet")
79
+ end
80
+
81
+ rest_params.merge!({:headers => { :accept => :json, :content_type => :json }})
82
+ rest_params.merge!({:verify_ssl => OpenSSL::SSL::VERIFY_NONE})
83
+ rest_params.merge!({:cookies => options["cookies"] }) if options.has_key?("cookies")
84
+
85
+ BrpmAuto.log rest_params.inspect if options.has_key?("verbose")
86
+
87
+ response = RestClient::Request.new(rest_params).execute
88
+
89
+ BrpmAuto.log "\tParsing response to JSON format ..." if options.has_key?("verbose")
90
+ begin
91
+ parsed_response = JSON.parse(response)
92
+ rescue
93
+ parsed_response = response
94
+ end
95
+ BrpmAuto.log "Parsed response: #{parsed_response.inspect}" if options.has_key?("verbose")
96
+
97
+ if response.code < 300
98
+ BrpmAuto.log "\treturn code: #{response.code}" unless options.has_key?("quiet")
99
+ result["status"] = "success"
100
+ result["code"] = response.code
101
+ result["response"] = parsed_response
102
+ result["cookies"] = response.cookies if options.has_key?("cookies")
103
+ else
104
+ result["status"] = "error"
105
+ result["code"] = response.code
106
+ result["response"] = parsed_response
107
+ result["error_message"] = "REST call returned HTTP code:\n#{response.code}\n#{response}"
108
+ BrpmAuto.log "\tREST call returned HTTP code #{response.code}" unless options.has_key?("quiet")
109
+ end
110
+
111
+ rescue RestClient::Exception => e
112
+ BrpmAuto.log "\tREST call generated an error: #{e.message}" unless options.has_key?("quiet")
113
+
114
+ if e.response.nil?
115
+ result["status"] = "error"
116
+ result["code"] = 1000
117
+ result["response"] = "No response received."
118
+ result["error_message"] = "REST call generated a RestClient error:\n#{e.message}\n#{e.backtrace}"
119
+ return
120
+ end
121
+
122
+ BrpmAuto.log "\tParsing response to JSON format ..." unless options.has_key?("quiet")
123
+ begin
124
+ parsed_response = JSON.parse(e.response)
125
+ rescue
126
+ parsed_response = e.response
127
+ end
128
+ BrpmAuto.log "\tParsed response: #{parsed_response.inspect}"
129
+
130
+ result["status"] = "error"
131
+ result["code"] = e.response.code
132
+ result["response"] = parsed_response
133
+ result["error_message"] = "REST call generated a RestClient error:\n#{e.response.code}\n#{e.response}\n#{e.message}\n#{e.backtrace}"
134
+
135
+ BrpmAuto.log "Back trace:\n#{e.backtrace}" unless already_exists_error(result) or not_found_error(result)
136
+ end
137
+ result
138
+ end
139
+
140
+ def already_exists_error(result)
141
+ result["code"] == 422 && result["response"].keys.count >= 1 && (result["response"][result["response"].keys[0]][0] == "has already been taken" || result["response"][result["response"].keys[0]][0] =~ /Version Tag is not unique/)
142
+ end
143
+
144
+ def not_found_error(result)
145
+ result["code"] == 404
146
+ end
147
+
148
+ private
149
+
150
+ def get_token(url)
151
+ params = CGI::parse(url.split("?").last)
152
+ params.has_key?("token") ? params["token"] : ""
153
+ end
154
+ end
155
+ end
data/lib/semaphore.rb ADDED
@@ -0,0 +1,79 @@
1
+ # Creates a pid-file semaphore to govern global execution
2
+ #
3
+ # ==== Attributes
4
+ #
5
+ # * +semaphore_key+ - string to name semaphore
6
+ # ==== Returns
7
+ #
8
+ # true if semaphore created, false if already exists
9
+ #
10
+ def semaphore(semaphore_key)
11
+ semaphore_dir = "#{BrpmAuto.params.automation_results_dir}/semaphores"
12
+ semaphore_name = "#{semaphore_key}.pid"
13
+ FileUtils.mkdir(semaphore_dir) unless File.exist?(semaphore_dir)
14
+ return false if File.exist?(File.join(semaphore_dir, semaphore_name))
15
+ fil = File.open(File.join(semaphore_dir, semaphore_name), "w+")
16
+ fil.puts BrpmAuto.precision_timestamp
17
+ fil.flush
18
+ fil.close
19
+ return true
20
+ end
21
+
22
+ # Clears a pid-file semaphore to govern global execution
23
+ #
24
+ # ==== Attributes
25
+ #
26
+ # * +semaphore_key+ - string to name semaphore
27
+ # ==== Returns
28
+ #
29
+ # true if semaphore deleted, false if it doesn't exist
30
+ #
31
+ def semaphore_clear(semaphore_key)
32
+ semaphore_dir = "#{BrpmAuto.params.automation_results_dir}/semaphores"
33
+ semaphore_name = "#{semaphore_key}.pid"
34
+ return false unless File.exist?(File.join(semaphore_dir, semaphore_name))
35
+ File.delete(File.join(semaphore_dir, semaphore_name))
36
+ return true
37
+ end
38
+
39
+ # Checks if a semaphore exists
40
+ #
41
+ # ==== Attributes
42
+ #
43
+ # * +semaphore_key+ - string to name semaphore
44
+ # ==== Returns
45
+ #
46
+ # true if semaphore exists, false if it doesn't exist
47
+ #
48
+ def semaphore_exists(semaphore_key)
49
+ semaphore_dir = "#{BrpmAuto.params.automation_results_dir}/semaphores"
50
+ semaphore_name = "#{semaphore_key}.pid"
51
+ return true if File.exist?(File.join(semaphore_dir, semaphore_name))
52
+ return false
53
+ end
54
+
55
+ # Waits a specified period for a semaphore to clear
56
+ # throws error after wait time if semaphore does not clear
57
+ # ==== Attributes
58
+ #
59
+ # * +semaphore_key+ - string to name semaphore
60
+ # * +wait_time+ - time in minutes before failure (default = 15mins)
61
+ # ==== Returns
62
+ #
63
+ # true if semaphore is cleared
64
+ #
65
+ def semaphore_wait(semaphore_key, wait_time = 15)
66
+ interval = 20; elapsed = 0
67
+ semaphore_dir = "#{BrpmAuto.params.automation_results_dir}/semaphores"
68
+ semaphore_name = "#{semaphore_key}.pid"
69
+ semaphore = File.join(semaphore_dir, semaphore_name)
70
+ return true if !File.exist?(semaphore)
71
+ until !File.exist?(semaphore) || (elapsed/60 > wait_time) do
72
+ sleep interval
73
+ elapsed += interval
74
+ end
75
+ if File.exist?(semaphore)
76
+ raise "ERROR: Semaphore (#{semaphore}) still exists after #{wait_time} minutes"
77
+ end
78
+ return true
79
+ end