128 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			128 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
| require "providers/provider_factory"
 | |
| require "fileutils"
 | |
| require "commands/status"
 | |
| 
 | |
| module Devops
 | |
|   module Version2_0
 | |
|     module Handler
 | |
|       class Script
 | |
| 
 | |
|         def self.get_scripts
 | |
|           lambda {
 | |
|             check_privileges("script", "r")
 | |
|             res = []
 | |
|             Dir.foreach(DevopsService.config[:scripts_dir]) {|f| res.push(f) unless f.start_with?(".")}
 | |
|             json res
 | |
|           }
 | |
|         end
 | |
| 
 | |
|         def self.execute_command
 | |
|           lambda {
 | |
|             check_privileges("script", "x")
 | |
|             user = request.env['REMOTE_USER']
 | |
|             s = ::Devops::Db.connector.server_by_chef_node_name params[:node_name]
 | |
|             ::Devops::Db.connector.check_project_auth s.project, s.deploy_env, user
 | |
|             cert = ::Devops::Db.connector.key s.key
 | |
|             cmd = request.body.read
 | |
|             addr = "#{s.remote_user}@#{s.public_ip || s.private_ip}"
 | |
|             ssh_cmd = "ssh -i %s #{addr} '#{cmd}'"
 | |
|             stream() do |out|
 | |
|               begin
 | |
|                 out << ssh_cmd % File.basename(cert.path)
 | |
|                 out << "\n"
 | |
|                 IO.popen((ssh_cmd % cert.path) + " 2>&1") do |so|
 | |
|                   while line = so.gets do
 | |
|                     out << line
 | |
|                   end
 | |
|                 end
 | |
|                 out << "\nDone"
 | |
|               rescue IOError => e
 | |
|                 logger.error e.message
 | |
|               end
 | |
|             end
 | |
|           }
 | |
|         end
 | |
| 
 | |
|         def self.run_script
 | |
|           lambda {
 | |
|             check_privileges("script", "x")
 | |
|             file_name = params[:script_name]
 | |
|             @file = File.join(DevopsService.config[:scripts_dir], check_filename(file_name, "Parameter 'script_name' must be a not empty string", false))
 | |
|             halt(404, "File '#{file_name}' does not exist") unless File.exists?(@file)
 | |
|             body = create_object_from_json_body
 | |
|             nodes = check_array(body["nodes"], "Parameter 'nodes' must be a not empty array of strings")
 | |
|             p = check_array(body["params"], "Parameter 'params' should be a not empty array of strings", String, true)
 | |
|             servers = ::Devops::Db.connector.servers_by_names(nodes)
 | |
|             return [404, "No servers found for names '#{nodes.join("', '")}'"] if servers.empty?
 | |
|             user = request.env['REMOTE_USER']
 | |
|             servers.each do |s|
 | |
|               ::Devops::Db.connector.check_project_auth s.project, s.deploy_env, user
 | |
|             end
 | |
|             stream() do |out|
 | |
|               begin
 | |
|                 status = []
 | |
|                 servers.each do |s|
 | |
|                   cert = begin
 | |
|                     ::Devops::Db.connector.key s.key
 | |
|                   rescue
 | |
|                     out << "No key found for '#{s.chef_node_name}'"
 | |
|                     status.push 2
 | |
|                     next
 | |
|                   end
 | |
|                   ssh_cmd = "ssh -i #{cert.path} #{s.remote_user}@#{s.public_ip || s.private_ip} 'bash -s' < %s"
 | |
|                   out << "\nRun script on '#{s.chef_node_name}'\n"
 | |
|                   unless p.nil?
 | |
|                     ssh_cmd += " " + p.join(" ")
 | |
|                   end
 | |
|                   out << (ssh_cmd % [params[:script_name]])
 | |
|                   out << "\n"
 | |
| 
 | |
|                   begin
 | |
|                     IO.popen( (ssh_cmd % [@file]) + " 2>&1") do |so|
 | |
|                       while line = so.gets do
 | |
|                         out << line
 | |
|                       end
 | |
|                       so.close
 | |
|                       status.push $?.to_i
 | |
|                     end
 | |
|                   rescue IOError => e
 | |
|                     logger.error e.message
 | |
|                     out << e.message
 | |
|                     status.push 3
 | |
|                   end
 | |
|                 end
 | |
|                 out << create_status(status)
 | |
|               rescue IOError => e
 | |
|                 logger.error e.message
 | |
|               end
 | |
|             end
 | |
|           }
 | |
|         end
 | |
| 
 | |
|         def self.create_script
 | |
|           lambda {
 | |
|             check_privileges("script", "w")
 | |
|             file_name = params[:script_name]
 | |
|             file = File.join(DevopsService.config[:scripts_dir], check_filename(file_name, "Parameter 'script_name' must be a not empty string"))
 | |
|             halt_response("File '#{file_name}' already exist") if File.exists?(file)
 | |
|             File.open(file, "w") {|f| f.write(request.body.read)}
 | |
|             create_response("File '#{params[:script_name]}' created", nil, 201)
 | |
|           }
 | |
|         end
 | |
| 
 | |
|         def self.delete_script
 | |
|           lambda {
 | |
|             check_privileges("script", "w")
 | |
|             file_name = params[:script_name]
 | |
|             file = File.join(DevopsService.config[:scripts_dir], check_filename(file_name, "Parameter 'script_name' must be a not empty string"))
 | |
|             halt_response("File '#{file_name}' does not exist", 404) unless File.exists?(file)
 | |
|             FileUtils.rm(file)
 | |
|             create_response("File '#{params[:script_name]}' deleted")
 | |
|           }
 | |
|         end
 | |
|       end
 | |
|     end
 | |
|   end
 | |
| end
 | |
| 
 | 
