# canzea --role=operatingsystem --solution=centos --remote --hostname=192.34.56.119 --privateKey=/var/go/.ssh/id_rsa_digitalocean

require 'net/ssh'
require 'net/sftp'
require 'json'
require 'openssl'
require 'base64'

class RemoteCall
    def initialize ()
        @log = Logger.new(Canzea::config[:logging_root] + '/plans.log')
    end

    def exec (hostname, privateKey, cmd, ref = "")

        @username = "root"

        @log.info("    R [#{ref}] COMMAND: #{cmd}")

        begin
            Net::SSH.start(hostname, @username, :paranoid => false, :keys => [privateKey]) do |ssh|

                chan = ssh.open_channel do |channel|
                    channel.request_pty
                    channel.env("DIGITAL_OCEAN_API_KEY", ENV['DIGITAL_OCEAN_API_KEY'])
                    channel.env("VAULT_TOKEN", ENV['VAULT_TOKEN'])
                    channel.env("CONSUL_URL", ENV['CONSUL_URL'])
                    channel.env("WORK_DIR", ENV['WORK_DIR'])
                    channel.env("ES_REF", ref)
                    channel.exec(cmd) do |ch, success|
                        abort "could not execute command" unless success

                        channel.on_data do |ch, data|
                          puts data

                          data.sub(/\n/, '').scan(/.{1,80}/).each do | line |
                              @log.info("    R [#{ref}]  STDOUT: #{line}")
                          end
                        end

                        channel.on_request("exit-status") do |ch, data|
                            exit_code = data.read_long
                            @log.info("    R [#{ref}] Exit status: #{exit_code}")
                            if (exit_code == 0)
                            else
                                abort()
                            end
                        end

                        channel.on_close do |ch|
                        end
                    end
                end
                chan.wait
            end
        rescue
            @log.info("    R ABORTED!")
            raise
        end
    end

    def encrypt (contents, publicKey)
        pubkey_pem = File.read publicKey
        key = OpenSSL::PKey::RSA.new pubkey_pem
        output = Base64.urlsafe_encode64 key.public_encrypt contents
        puts output
    end

    def decrypt (contents, privateKey)
        privkey_pem = File.read privateKey
        key = OpenSSL::PKey::RSA.new privkey_pem
        output = key.private_decrypt Base64.urlsafe_decode64 contents
        puts output
    end

    # Secure copy - use the public key to encrypt the contents before sent across
    #
    def put (hostname, privateKey, localFile, remoteFile = nil)

        @username = "root"

        puts "Uploading #{localFile} to #{remoteFile}"
        @log.info("    R : Uploading to #{hostname}")
        @log.info("    R : Uploading #{localFile} to #{remoteFile}")
        Net::SSH.start(hostname, @username, :paranoid => false, :keys => [privateKey]) do |ssh|
            ssh.sftp.upload!(localFile, remoteFile)
        end
    end

    def get (hostname, privateKey, remoteFile, localFile = nil)

        @username = "root"

        @log.info("    R : Getting from #{hostname}")
        @log.info("    R : Getting file #{remoteFile}")

        Net::SSH.start(hostname, @username, :paranoid => false, :keys => [privateKey]) do |ssh|
            ssh.sftp.download!(remoteFile, localFile)
        end
        @log.info("    R : Saved to #{localFile}")
    end

end