lib/envirobly/container_shell.rb
# frozen_string_literal: true class Envirobly::ContainerShell AWS_ENV = [ "AWS_ACCESS_KEY_ID='%s'", "AWS_SECRET_ACCESS_KEY='%s'", "AWS_SESSION_TOKEN='%s'" ] SSH = [ "ssh -i %s", "-o StrictHostKeyChecking=accept-new", "-o SendEnv=ENVIROBLY_SERVICE_INTERACTIVE_SHELL", "-o SendEnv=ENVIROBLY_SERVICE_SHELL_USER", "-o ProxyCommand='aws ec2-instance-connect open-tunnel --instance-id %s --region %s'" ] USER_AND_HOST = "envirobly-service@%s" attr_reader :options, :service_name def initialize(service_name, options) @service_name = service_name @options = options commit = Envirobly::Git::Commit.new "HEAD" @params = { account_id: options.account_id || Envirobly::Defaults::Account.new.id, project_name: options.project_name || File.basename(Dir.pwd), # TODO: Extract into Defaults::ProjectName project_id: options.project_id, environ_name: options.environ_name || commit.current_branch, service_name: service_name, instance_slot: options.instance_slot || 0 } if options.project_name.blank? && options.account_id.blank? && options.project_id.blank? @params[:project_id] = Envirobly::Defaults::Project.new.id end end def exec(command = nil) with_private_key do system join(env_vars, ssh, user_and_host, command) end end def rsync(source, destination) with_private_key do system join( env_vars, %(rsync #{options.args} -e "#{ssh}"), source.sub("#{service_name}:", "#{user_and_host}:"), destination.sub("#{service_name}:", "#{user_and_host}:") ) end end private def join(*parts) parts.flatten.compact.join(" ") end def connect_data @connect_data ||= begin api = Envirobly::Api.new api.create_service_shell_connection(@params).object end end def with_private_key Tempfile.create do |file| file.write connect_data.fetch("instance").fetch("private_key") file.flush @private_key_path = file.path yield end end def env_vars credentials = connect_data.fetch("open_tunnel_credentials") result = sprintf( join(AWS_ENV), credentials.fetch("access_key_id"), credentials.fetch("secret_access_key"), credentials.fetch("session_token") ) if options.shell.present? result = join "ENVIROBLY_SERVICE_INTERACTIVE_SHELL='#{options.shell}'", result end if options.user.present? result = join "ENVIROBLY_SERVICE_SHELL_USER='#{options.user}'", result end result end def ssh sprintf( join(SSH), @private_key_path, connect_data.fetch("instance").fetch("aws_id"), connect_data.fetch("region") ) end def user_and_host sprintf USER_AND_HOST, connect_data.fetch("instance").fetch("private_ipv4") end end