Top Level Namespace
Class Method Summary collapse
- .execute_cmd(cmd, timeout, log_out, log_err) ⇒ Object
- .generate_aws_keys(key, log_identifier) ⇒ Object
- .get_sanitized_cmd(cmd) ⇒ Object
- .get_secret(key, subkey, log_identifier) ⇒ Object
- .get_url(url) ⇒ Object
- .install_socotra_py_modules(pymodule, environment) ⇒ Object
- .kill_pid(pid, timeout) ⇒ Object
- .load_assets_from_branch(tenant_name, domain, admin_username, admin_password, api_url, apidoc_url) ⇒ Object
- .load_production_assets(version, github_username, github_password, tenant_name, domain, socotra_username, socotra_password, api_url, apidoc_url) ⇒ Object
- .load_tabular_datasources(jwtsecret, api_url, apidoc_url, admin_username, admin_password, tenant_name) ⇒ Object
- .load_tasks(version, environment, tenant_name) ⇒ Object
- .log(level, message) ⇒ Object
- .logger(log, success, retry_exec, raise_on_fail, log_out, log_err, error_message, last_try) ⇒ Object
- .pid_exists(pid) ⇒ Object
- .put_secret(key, subkey_value_map, log_identifier) ⇒ Object
- .revoke_lease(lease_id, log_identifier) ⇒ Object
- .safe_retry(cmd, description, error_message = "command failed", raise_on_fail = true, log = true, tries = 3, timeout = 0) ⇒ Object
- .sync_logs(repo, build_id) ⇒ Object
- .system_safe(cmd = cmd, cmd_description = cmd_description, error_message = error_message, raise_on_fail = true, log = true, print_command = true, retry_exec = false, timeout = 0, log_file_number = 1, last_try = true) ⇒ Object
- .system_unsafe(cmd) ⇒ Object
Instance Method Summary collapse
- #copy_directory(s3_source, s3_destination) ⇒ Object
- #get_path_inject ⇒ Object
- #sanitize_for_filename(path) ⇒ Object
- #upload_to_s3(source_dir, s3_destination) ⇒ Object
Class Method Details
.execute_cmd(cmd, timeout, log_out, log_err) ⇒ Object
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
# File 'lib/socotra-build.rb', line 81 def self.execute_cmd(cmd, timeout, log_out, log_err) pid = spawn(cmd, :out=>log_out, :err=>log_err) begin return Timeout::timeout(timeout) do _, status = Process.wait2(pid) return status.success? end rescue Timeout::Error while pid_exists(pid) if kill_pid(pid, timeout) return false end end end end |
.generate_aws_keys(key, log_identifier) ⇒ Object
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# File 'lib/socotra-build.rb', line 183 def self.generate_aws_keys(key, log_identifier) cmd = "vault read #{key}" status, output = system_safe(cmd, log_identifier, "AWS key generation failed", true, false) cmd = "echo '#{output}' |grep access_key|awk '{print $2'}" status, account_access_key = system_safe(cmd, "get_generated_access_key", "Getting account access key failed", true, false, false) account_access_key = account_access_key.strip cmd = "echo '#{output}' |grep secret_key|awk '{print $2'}" status, account_secret_key = system_safe(cmd, "get_generated_access_key", "Getting account access key failed", true, false, false) account_secret_key = account_secret_key.strip cmd = "echo '#{output}' |grep lease_id|awk '{print $2'}" status, lease_id = system_safe(cmd, "get_generated_access_key", "Getting account access key failed", true, false, false) lease_id = lease_id.strip return account_access_key, account_secret_key, lease_id end |
.get_sanitized_cmd(cmd) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/socotra-build.rb', line 28 def self.get_sanitized_cmd(cmd) secret_fields = ["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "password", "aws_access_key_id", "aws_secret_access_key", "aws_access_key", "aws_secret_key", "access_key", "secret_key", "account_access_key", "account_secret_key", "aws.accessKeyId", "aws.secretKey", "jwtsecret", "master_access_key", "master_secret_key", "github_password"] cmd = cmd.gsub(/\s+/m, ' ').strip.split(" ") replace = cmd.grep(Regexp.union(secret_fields)) unless replace.empty? replace = Set.new replace cmd.collect! {|e| (replace.include? e) ? '<secret>': e} end cmd = cmd.join(' ') end |
.get_secret(key, subkey, log_identifier) ⇒ Object
171 172 173 174 175 176 |
# File 'lib/socotra-build.rb', line 171 def self.get_secret(key, subkey, log_identifier) secret = `vault read -field=#{subkey} #{key}` secret = secret.strip return secret end |
.get_url(url) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/tenant.rb', line 9 def self.get_url(url) timeout = 1200 c = HTTPClient.new c.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE c.ssl_config.timeout = timeout connection_exceptions = [HTTPClient::BadResponseError, HTTPClient::ConnectTimeoutError] begin ssl_tries ||= timeout dns_tries ||= timeout http_tries ||= timeout content = c.get_content(url) rescue OpenSSL::SSL::SSLError if (ssl_tries -= 1) > 0 sleep 1 retry else puts "ERROR: ELB is up, but instances are not (SSL)" $build_failure = true end rescue *connection_exceptions if (http_tries -= 1) > 0 sleep 1 retry else puts "ERROR: ELB is up, but instances are not (HTTP)" $build_failure = true end rescue SocketError if (dns_tries -= 1) > 0 sleep 1 retry else puts "ERROR: DNS record not created" $build_failure = true end else return content end end |
.install_socotra_py_modules(pymodule, environment) ⇒ Object
209 210 211 212 213 214 215 |
# File 'lib/socotra-build.rb', line 209 def self.install_socotra_py_modules(pymodule, environment) cmd = "sudo pip list |grep #{pymodule}; if [ $? -eq 0 ];then /usr/bin/yes|sudo pip uninstall #{pymodule};fi" system_safe(cmd, "uninstall_#{pymodule}_py_module", "Failed to uninstall #{pymodule}") cmd = "/usr/bin/yes|sudo pip install --egg --process-dependency-links --allow-external mysql-connector-python --trusted-host socotra-pypi-euw1.s3-website-eu-west-1.amazonaws.com --extra-index-url=http://socotra-pypi-euw1.s3-website-eu-west-1.amazonaws.com/#{pymodule}/#{environment} #{pymodule}" system_safe(cmd, "install_#{pymodule}_py_module", "Failed to install #{pymodule}") end |
.kill_pid(pid, timeout) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 |
# File 'lib/socotra-build.rb', line 67 def self.kill_pid(pid, timeout) puts "INFO: #{pid} timed out after #{timeout}, killing it" killpid = fork { Process.kill('INT', pid) } Process.detach(killpid) begin Process.waitpid(killpid) rescue Errno::ECHILD return true end return false end |
.load_assets_from_branch(tenant_name, domain, admin_username, admin_password, api_url, apidoc_url) ⇒ Object
86 87 88 89 90 91 92 93 94 |
# File 'lib/tenant.rb', line 86 def self.load_assets_from_branch(tenant_name, domain, admin_username, admin_password, api_url, apidoc_url) if api_url == "https://api.staging.socotra.com" cmd = "socotraadmin tenant add_tenant #{tenant_name} --overwrite_ontology --tenant_hostname=#{tenant_name}.co.#{domain} --tenant_path=. --admin_username=#{admin_username} --admin_password=#{admin_password} --apidoc_url=#{apidoc_url} --api_url=#{api_url}" else cmd = "socotraadmin tenant add_tenant #{tenant_name} --tenant_hostname=#{tenant_name}.co.#{domain} --tenant_path=. --admin_username=#{admin_username} --admin_password=#{admin_password} --apidoc_url=#{apidoc_url} --api_url=#{api_url}" end system_safe(cmd, "load_branch_assets_for_pr", "Failed to load prod asset for PR") end |
.load_production_assets(version, github_username, github_password, tenant_name, domain, socotra_username, socotra_password, api_url, apidoc_url) ⇒ Object
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/tenant.rb', line 50 def self.load_production_assets(version, github_username, github_password, tenant_name, domain, socotra_username, socotra_password, api_url, apidoc_url) url = "https://github.com/socotra/prime/archive/#{version}.tar.gz" assets_dir = Dir.mktmpdir assets_artifact = "#{assets_dir}/#{version}.tar.gz" open(assets_artifact, "w").write(open(url, :http_basic_authentication => [github_username, github_password]).read) tar_extract = Gem::Package::TarReader.new(Zlib::GzipReader.open(assets_artifact)) tar_extract.rewind tar_extract.each do |entry| if entry.file? FileUtils.mkdir_p(File.dirname("#{assets_dir}/#{entry.full_name}")) File.open("#{assets_dir}/#{entry.full_name}", "wb") do |f| f.write(entry.read) end File.chmod(entry.header.mode, "#{assets_dir}/#{entry.full_name}") end end tar_extract.close cmd = "socotraadmin tenant add_tenant #{tenant_name} --tenant_hostname=#{tenant_name}.co.#{domain} --tenant_path=#{assets_dir}/prime-#{version} --overwrite_ontology --admin_username=#{socotra_username} --admin_password=#{socotra_password} --apidoc_url=#{apidoc_url} --api_url=#{api_url}" system_safe(cmd, "load_prod_assets_for_pr", "Failed to load prod asset for PR") end |
.load_tabular_datasources(jwtsecret, api_url, apidoc_url, admin_username, admin_password, tenant_name) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/tenant.rb', line 74 def self.load_tabular_datasources(jwtsecret, api_url, apidoc_url, admin_username, admin_password, tenant_name) cmd = "socotraadmin tabular_datasource create_bulk \ --jwtsecret=#{$jwtsecret} \ --api_url=#{$api_url} \ --apidoc_url=#{$apidoc_url} \ --admin_username=#{$admin_username} \ --admin_password=#{$admin_password} \ #{$tenant_name} \ $(pwd)/data/tables.json" system_safe(cmd, "load_tabular_datasources", "Failed to load tabular datasources") end |
.load_tasks(version, environment, tenant_name) ⇒ Object
96 97 98 99 |
# File 'lib/tenant.rb', line 96 def self.load_tasks(version, environment, tenant_name) cmd = "sg docker -c \'tasker --path=reports --tag=#{$version} --environment=#{$environment} --timezone='Africa/Kigali' --tenant=#{$tenant_name} -v\'" system_safe(cmd, "load_tasks", "Failed to load task for PR") end |
.log(level, message) ⇒ Object
97 98 99 100 |
# File 'lib/socotra-build.rb', line 97 def self.log(level, ) date = Time.now.strftime("%Y-%m-%d %H:%M:%S") puts "#{date} #{level}: #{}" end |
.logger(log, success, retry_exec, raise_on_fail, log_out, log_err, error_message, last_try) ⇒ Object
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
# File 'lib/socotra-build.rb', line 102 def self.logger(log, success, retry_exec, raise_on_fail, log_out, log_err, , last_try) if log log("INFO", "Logs available here: #{log_err} and #{log_out}" ) else log("INFO", "Logs unavailable due to user settings") end if not (success or retry_exec) log("ERROR", ) raise end if not success and retry_exec if last_try and raise_on_fail log_level = "ERROR" else log_level = "WARNING" end if log log(log_level, "see #{log_out} and #{log_err} for details") end log(log_level, ) if not last_try raise end end end |
.pid_exists(pid) ⇒ Object
57 58 59 60 61 62 63 64 65 |
# File 'lib/socotra-build.rb', line 57 def self.pid_exists(pid) begin Process.getpgid(pid) rescue Errno::ESRCH return false end return true end |
.put_secret(key, subkey_value_map, log_identifier) ⇒ Object
178 179 180 181 |
# File 'lib/socotra-build.rb', line 178 def self.put_secret(key, subkey_value_map, log_identifier) cmd = "vault write #{key} #{subkey_value_map}" system_safe(cmd, log_identifier, "Put secret failed", true, false) end |
.revoke_lease(lease_id, log_identifier) ⇒ Object
204 205 206 207 |
# File 'lib/socotra-build.rb', line 204 def self.revoke_lease(lease_id, log_identifier) cmd = "vault revoke #{lease_id}" safe_retry(cmd, log_identifier, "Revoking lease failed", false, "ERROR", false) end |
.safe_retry(cmd, description, error_message = "command failed", raise_on_fail = true, log = true, tries = 3, timeout = 0) ⇒ Object
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/socotra-build.rb', line 6 def self.safe_retry(cmd, description, ="command failed", raise_on_fail=true, log=true, tries=3, timeout=0) retry_count = 0 begin if retry_count == (tries - 1) last_try = true else last_try = false end status, output = system_safe(cmd, description, , raise_on_fail=raise_on_fail, log=log, print_command=true, retry_exec=true, timeout=timeout, log_file_number=retry_count, last_try=last_try) rescue sleep 5 retry if (retry_count += 1) < (tries) end if last_try and raise_on_fail and status != 0 raise else return status end end |
.sync_logs(repo, build_id) ⇒ Object
217 218 219 220 221 222 |
# File 'lib/socotra-build.rb', line 217 def self.sync_logs(repo, build_id) cmd = "cp -f console.log logs/" system_safe(cmd, "copy_console_log", "Failed to copy console log") upload_to_s3("logs", "socotra-builds/#{repo}/#{build_id}") end |
.system_safe(cmd = cmd, cmd_description = cmd_description, error_message = error_message, raise_on_fail = true, log = true, print_command = true, retry_exec = false, timeout = 0, log_file_number = 1, last_try = true) ⇒ Object
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/socotra-build.rb', line 134 def self.system_safe(cmd=cmd, cmd_description=cmd_description, =, raise_on_fail=true, log=true, print_command=true, retry_exec=false, timeout=0, log_file_number=1, last_try=true) start = Time.now.to_i cmd_sanitized = get_sanitized_cmd(cmd) if print_command log("INFO", "Executing command: #{cmd_sanitized}") else log("INFO", "Not logging command") end if log log_out = "logs/#{cmd_description}_out.log.#{log_file_number}" log_err = "logs/#{cmd_description}_err.log.#{log_file_number}" else log_out = "/dev/null" log_err = "/dev/null" end success = execute_cmd(cmd, timeout, log_out, log_err) elapsed = Time.now.to_i - start log("INFO", "#{cmd_description} took #{elapsed} seconds") file = File.open(log_out, "rb") out = file.read logger(log, success, retry_exec, raise_on_fail, log_out, log_err, , last_try) return success end |
.system_unsafe(cmd) ⇒ Object
166 167 168 169 |
# File 'lib/socotra-build.rb', line 166 def self.system_unsafe(cmd) success = system(cmd) return success end |
Instance Method Details
#copy_directory(s3_source, s3_destination) ⇒ Object
19 20 21 22 23 24 25 |
# File 'lib/s3_uploader.rb', line 19 def copy_directory(s3_source, s3_destination) cmd = "#{get_path_inject} aws s3 sync s3://#{s3_source} s3://#{s3_destination} --delete --acl public-read" source_sanitized = sanitize_for_filename(s3_source) destination_sanitized = sanitize_for_filename(s3_destination) system_safe(cmd, "s3_copy_#{source_sanitized}_to_#{destination_sanitized}", "distribution failed on aws copy") puts "distribution success to s3: #{s3_destination}" end |
#get_path_inject ⇒ Object
1 2 3 4 5 |
# File 'lib/s3_uploader.rb', line 1 def get_path_inject return path_inject = "AWS_DEFAULT_REGION=\"eu-west-1\" " + "AWS_ACCESS_KEY_ID=\"#{$master_access_key}\" " + "AWS_SECRET_ACCESS_KEY=\"#{$master_secret_key}\" " end |
#sanitize_for_filename(path) ⇒ Object
7 8 9 |
# File 'lib/s3_uploader.rb', line 7 def sanitize_for_filename(path) return path.tr("/", "_") end |
#upload_to_s3(source_dir, s3_destination) ⇒ Object
11 12 13 14 15 16 17 |
# File 'lib/s3_uploader.rb', line 11 def upload_to_s3 (source_dir, s3_destination) cmd_sync = "#{get_path_inject} aws s3 sync #{source_dir} s3://#{s3_destination} --acl public-read" source_sanitized = sanitize_for_filename(source_dir) destination_sanitized = sanitize_for_filename(s3_destination) system_safe(cmd_sync, "s3_upload_#{source_sanitized}_to_#{destination_sanitized}", "distribution failed on aws sync") puts "distribution success to s3: #{s3_destination}" end |