require 'pp' module Henk class Runner attr_accessor :options_mapping def initialize @options_mapping = { "organization_name" => { "name" => "organization-name" }, "modules" => { "name" => "modules", "type" => "array" }, "database_source" => { "name" => "database-source" }, "target_domain" => { "name" => "target-domain" }, "copy_data" => { "name" => "copy-data" }, "source_environment" => { "name" => "source-environment" }, "target_environment" => { "name" => "target-environment" }, "user_email" => { "name" => "user-email" } } end def run command if !system command raise command.red end rescue Interrupt end def verify_cluster_active required_containers = [ "proactive-config", "proactive-frame", "mysql-service" ] if !system "docker network inspect spend-cloud > /dev/null" puts "Error: ".red + "The local spend-cloud cluster doesn't seem to be running." exit(1) end connected_to_network = `docker network inspect spend-cloud | jq '.[0] | .Containers | map(select((.Name | test("^#{required_containers.join('|^')}")))) | length'` if connected_to_network.to_s.strip! != "5" puts "Error: ".red + "Not all required services are running or connected to the cluster (#{connected_to_network}/5)" exit(1) end return true end def henk command, options = {} begin volumes = get_volumes_string(options.dev) image = get_latest_image verbose = options.verbose options = options_to_string options to_run = "docker run -it --rm --network spend-cloud #{volumes} #{image} #{command} #{options}" if verbose puts "Running: #{to_run.green}" end self.run to_run end end def list_clients self.run "docker exec -it mysql-service mysql -u root -sN -e 'SELECT `043` FROM `spend-cloud-config`.`00_settings` ORDER BY `043` ASC'" end def encrypt_config_data domain puts "Manually encrypting config data for #{domain}".green php_command = "php /var/www/scripts/encryptConfigData.php -c='#{domain}' --execute" command = 'docker exec -it proactive-config-php bash -c "#{php_command}"' self.run command end def synchronize_employees domain puts "Manually synchronizing employees with shared storage for #{domain}".green php_command = "php /var/www/scripts/syncEmployees.php --client='#{domain}'" command = 'docker exec -it proactive-frame bash -c "#{php_command}"' self.run command end def get_latest_image latest_version = `gcloud container images list-tags eu.gcr.io/dev-pasc-vcdm/henk-app --limit 1 --format=\"json\" | jq -r '[.[0].tags | sort_by(length)[] | select(match(\"^[0-9]+$\"))] | first'` return "eu.gcr.io/dev-pasc-vcdm/henk-app:#{latest_version.strip}" end def get_volumes_string dev = false volumes = { "spend-cloud_shared-storage" => "/data" } if dev repoPath = Sct::Helper.homePath + "/development/henk" if not Dir.exists?(repoPath) puts "Warning: ".yellow + "To run in development mode you need a checkout for the Henk repository. Continuing in normal mode." else dev_volumes = { repoPath + "/modules" => "/var/scripts/modules", repoPath + "/client.py" => "/var/scripts/client.py", repoPath + "/environment_mapping.json" => "/var/scripts/environment_mapping.json", repoPath + "/logging-config.json" => "/var/scripts/logging-config.json", repoPath + "/schemas" => "/var/scripts/schemas", repoPath + "/resources" => "/var/local" } volumes = volumes.merge(dev_volumes) end end return volumes.map{|k,v| "-v #{k}:#{v}"}.join(' ') end def options_to_string options = {} options_str = '' if options.verbose options_str += '--verbose ' end if options.overwrite options_str += '--overwrite ' end if options.copy_data options_str += '--copy-data ' end options = options.__hash__ options.delete(:dev) options.delete(:verbose) options.delete(:overwrite) options.delete(:copy_data) parsed_options = [] options.each do |k,v| if self.options_mapping["#{k}"] mapping = self.options_mapping["#{k}"] k = mapping['name'] if mapping['type'] == "array" v = v.split(',').join(' ') end end parsed_options << "--#{k} #{v}" end options_str += parsed_options.join(' ') return options_str end def list_dumps args, options run "gsutil ls gs://henk-db-dumps/" end def import args, options, dump_url puts "Going to import #{dump_url}".blue dir = Dir.mktmpdir begin zip = download_and_unzip dump_url, dir customer = zip.slice 0, zip.rindex("_") customer_database = customer.gsub "-", "_" remove_customer customer copy_db_encryption_key customer, dir run_sql_files dir add_customer_account customer, customer_database update_and_encrypt_customer_config customer, customer_database puts "Finished importing #{customer}".green ensure run "rm -r #{dir}" end end def download_and_unzip dump_url, dir run "gsutil cp #{dump_url} #{dir}" zip_path = Dir["#{dir}/*.zip"].first run "unzip #{zip_path} -d #{dir}" zip = File.basename zip_path end def remove_customer customer local_customers = `sct henk list-clients`.lines chomp: true if local_customers.include? customer puts "Customer already exists. Removing customer before importing...".yellow run "sct henk remove --domain #{customer}" puts "Removed existing customer".green end end def copy_db_encryption_key customer, dir run "docker exec proactive-config-php mkdir /data/#{customer}" run "docker cp #{dir}/db_encryption.key proactive-config-php:/data/#{customer}/" puts "Copied db_encryption.key to proactive-config-php:/data/#{customer}/".green end def run_sql_files dir sql_paths = Dir["#{dir}/*.sql"] sql_paths.each_with_index do |path, index| file = File.basename path database = File.basename path, ".*" puts "Running #{file} (#{index + 1}/#{sql_paths.length})".blue run_query "CREATE DATABASE IF NOT EXISTS `#{database}`" run_query "source /sql/#{file}", database: database, volume: "#{dir}:/sql" end puts "Finished running SQL files".green end def add_customer_account customer, customer_database account_data = "\n[#{customer}]\ndatabase = #{customer_database}\ndomain = NULL\nrewrite = #{customer}\nimport_planning = 1\njobs = 1\nscan_upload = 0\nfiatteren_mailbox = 1\ncontracten_mailbox = 1" run "docker exec proactive-config-php sh -c 'echo \"#{account_data}\" >> /data/proactive_accounts.ini'" puts "Added account to proactive_accounts.ini".green end def update_and_encrypt_customer_config customer, customer_database dsn = "mysql:host=mysql-service;user=root;dbname=#{customer_database};config=proactive-php;config-path=cfg/db;" website_application = "https://#{customer}.dev.spend.cloud" email_administrator = "noreply@dev.spend.cloud" debug_email_address = "noreply@dev.spend.cloud" query = "UPDATE `00_settings` SET `045` = \"#{dsn}\", `029` = \"#{website_application}\", `002` = \"#{email_administrator}\", `031` = \"#{debug_email_address}\" WHERE `043` = \"#{customer}\"" run_query query, database: "spend-cloud-config" puts "Updated config values".green run "docker exec proactive-config-php php /var/www/scripts/encryptConfigData.php -c='#{customer}' --execute" puts "Encrypted config values".green end def run_query query, database: nil, volume: nil command = "docker run --rm --network container:mysql-service" if volume command = "#{command} -v #{volume}" end command = "#{command} arey/mysql-client -h mysql-service" if database command = "#{command} -D #{database}" end run "#{command} -e '#{query}'" end end end