diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..77de21a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM ubuntu:latest + +RUN apt-get update \ + && apt-get install -y \ + curl \ + make \ + build-essential \ + g++ \ + libssl-dev \ + ruby-dev +RUN mkdir /src + +COPY . /src + +RUN cd /src \ + && gem build logstream \ + && gem install logstream-*.gem + +ENTRYPOINT ["/bin/bash"] \ No newline at end of file diff --git a/LICENSE b/LICENSE index 6fc5df8..e81ec6e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Acquia, Inc. +Copyright (c) 2020 Acquia, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index a7df732..cf6fd77 100644 --- a/README.md +++ b/README.md @@ -15,25 +15,24 @@ UI as well. ## Quick start -* Logstream works in conjunction with Acquia's Cloud API. If you haven't already, -install your Acquia -Cloud Drush integration files, which includes your Cloud API credentials. +* Logstream works in conjunction with Acquia's [Cloud API](https://cloudapi-docs.acquia.com/). In order to use Cloud API you will need to generate credentials for your account. [Cloud API v2 authentication](https://docs.acquia.com/acquia-cloud/develop/api/auth/#generating-an-api-token) explains how to generate the credentials. Place the credentials in `$HOME/.acquia/cloudapiv2.conf` . This file is in JSON format with api_key and api_secret defined. +``` +{ + "api_key" : "key", + "api_secret" : "secret" +} +``` * Install the Logstream CLI: ``` $ gem install logstream ``` -* List all the sites you have access to: -``` -$ drush ac-site-list -devcloud:mysite -``` +* Find the UUID of the application you would like to stream logs for. Documentation on how to find applicaiton UUID can be found [here](https://docs.acquia.com/acquia-cloud/manage/applications/#obtaining-your-subscription-s-application-id) * Stream logs from the production environment: ``` -$ logstream tail devcloud:mysite prod +$ logstream tail 55ea1945-4aa6-4c56-bb7b-2108565e22d6 prod 127.0.0.1 - - [11/Jun/2014:17:28:47 +0000] "GET / HTTP/1.1" 200 7708 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36" http_host=mysite.com affinity="-" upstream_addr="10.218.29.150:80" hosting_site=mysite request_time=0.030 forwarded_for="64.80.128.4" upstream_status="200" ... etc ... ``` @@ -44,11 +43,10 @@ A variety of filtering and display options are available: $ logstream help tail ``` -## API v1 +## API v2 -Logstream communicates over TCP using the WebSocket protocol. Use the logstream -Cloud API call to retrieve the URL to connect to and an authenticated +Logstream communicates over TCP using the WebSocket protocol. Use the [logstream +Cloud API call](https://cloudapi-docs.acquia.com/#/Environments/getEnvironmentsLogstream) to retrieve the URL to connect to and an authenticated message to initial streaming for a particular Cloud environment. Messages use text data frames, and contain JSON-encoded hashes. Each message @@ -73,7 +71,7 @@ default, the CLI enables the log types apache-request, php-error, drupal-watchdog, and varnish-request. ``` -$ logstream tail devcloud:mysite dev --debug +$ logstream tail 55ea1945-4aa6-4c56-bb7b-2108565e22d6 dev --debug -> connect to wss://logstream.acquia.com/ah_websocket/logstream/v1 -> {"site":"devcloud:mysite","d":"deaefc1f42a4d18cb932c2eb9fa75115fba5ab83f1a3c564767ef1ce8dabf2cc","t":1404764927,"env":"dev","cmd":"stream-environment"} <- {"cmd":"connected","server":"logstream-api-61"} diff --git a/bin/logstream b/bin/logstream index f8b31f6..cfbef73 100755 --- a/bin/logstream +++ b/bin/logstream @@ -1,45 +1,13 @@ #!/usr/bin/env ruby require 'rubygems' -require 'net/https' -require 'json' require 'thor' +require 'json' require 'logstream/client' - -# @todo: Yeah, this is terrible. Replace it with a real Cloud API gem. -class QuickCloudAPI - class Error < StandardError; end - - def self.get(path, opts = {}) - confpath = "#{ENV['HOME']}/.acquia/cloudapi.conf" - begin - json = File.read(confpath) - config = JSON.load(json) - rescue Errno::ENOENT, JSON::ParserError => e - raise Error, "#{confpath} is missing or invalid. Download your Drush aliases from https://accounts.acquia.com/account/security to initialize it." - end - opts[:endpoint] ||= "https://cloudapi.acquia.com/v1" - uri = URI.parse("#{opts[:endpoint]}#{path}.json") - http = Net::HTTP.new(uri.host, uri.port) - http.use_ssl = true - http.ca_file = File.dirname(__FILE__) + "/../etc/ca.pem" - http.verify_mode = OpenSSL::SSL::VERIFY_PEER - request = Net::HTTP::Get.new(uri.request_uri) - request.basic_auth(config['email'], config['key']) - response = http.request(request) - parsed = JSON.parse(response.body) rescue nil - case response.code.to_i - when 200 - raise Error, "Unexpected reply #{response.body}" unless parsed - parsed - else - raise Error, "HTTP #{response.code}: #{response.body}" - end - end -end +require 'logstream/cloudapi_v2' class LogTailorCLI < Thor - desc "tail SITE ENV", "Stream log information for the specified site environment." + desc "tail APPLICATION_UUID ENV", "Stream log information for the specified application environment." method_option(:types, :type => :array, :aliases => '-t', :desc => "Only display listed log types", :default => %w(apache-request php-error drupal-watchdog varnish-request), @@ -59,15 +27,30 @@ class LogTailorCLI < Thor :banner => "disp_time http_status log_type request_id server text" ) method_option(:color, :type => :boolean, :default => true, :desc => 'Turn on or off colorized lines.') - method_option(:endpoint, :type => :string, :desc => 'The Cloud API URL to connect to.') method_option(:debug, :type => :boolean, :default => false, :desc => 'Turn on debugging.') - def tail(site, env) + def tail(application_uuid, env) begin shows = Hash[options[:show].map { |s| s.split('=') }.map { |k,v| [k, Regexp.new(v)] }] rescue {} hides = Hash[options[:hide].map { |h| h.split('=') }.map { |k,v| [k, Regexp.new(v)] }] rescue {} begin - info = QuickCloudAPI.get("/sites/#{site}/envs/#{env}/logstream", { :endpoint => options[:endpoint] }) + confpath = "#{ENV['HOME']}/.acquia/cloudapiv2.conf" + begin + json = File.read(confpath) + config = JSON.load(json) + rescue Errno::ENOENT, JSON::ParserError => e + raise Error, "#{confpath} is missing or invalid. Please configure your Cloud API v2 credentials" + end + cloudapi_client = Logstream::CloudAPIV2.new(config['api_key'], config['api_secret']) + environments = cloudapi_client.get_application_environments(application_uuid) + environment_uuid = nil + environments.each do |environment| + if environment['name'] == env + environment_uuid = environment['id'] + end + end + raise Error, "No environment found with #{env} name." unless environment_uuid + stream_info = cloudapi_client.get_envirornment_logstream(environment_uuid) logstream = Logstream::Client.new({ :columns => options[:columns], :types => options[:types], @@ -76,8 +59,8 @@ class LogTailorCLI < Thor :no_color => !options[:color], :debug => options[:debug], }) - logstream.run(info['url'], info['msg']) - rescue QuickCloudAPI::Error => e + logstream.run(stream_info['url'], stream_info['params']) + rescue Logstream::CloudAPIV2::Error => e puts "Cloud API error: #{e.message}" exit(1) end @@ -85,5 +68,5 @@ class LogTailorCLI < Thor end end -LogTailorCLI.start +LogTailorCLI.start(ARGV) diff --git a/etc/ca.pem b/etc/ca.pem deleted file mode 100644 index 55bf40e..0000000 --- a/etc/ca.pem +++ /dev/null @@ -1,98 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIGvzCCBaegAwIBAgIQD1pdYvA5l5l2ezeWEsVwNTANBgkqhkiG9w0BAQUFADBm -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSUwIwYDVQQDExxEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -ZSBDQS0zMB4XDTEyMDgyNzAwMDAwMFoXDTE1MDkwOTEyMDAwMFowfzELMAkGA1UE -BhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxEzARBgNVBAcTCkJ1cmxpbmd0 -b24xEzARBgNVBAoTCkFjcXVpYSBJbmMxFzAVBgNVBAsTDkFjcXVpYSBIb3N0aW5n -MRUwEwYDVQQDDAwqLmFjcXVpYS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw -ggEKAoIBAQCVmcKz54qAbNO9NyP3hA96gzGRORSB9Bz4EOuFM1kfD/gvZoXoqk87 -NC/jPrvPAxNZDJ33IrO08WDWxBVi6UQ7Q9YYFgU1mm0se4qjwld7dtziDnaq2zXc -x4Q+AVfBj92w+RsVDWA2mNtMSaDePqXGzLOz4muUCA5oCtMg2QD+XIEp1yt13nQb -5nW6PbY6kHHviepNX3wj7TdqTLNPdCVcK9BJz2YTjfHtBBxnGxR/m804RL9fYWKz -r6XUbbf+gcKFwMqRI54Qs5cD20jmYnYgXFYwAx6HvOH9Lr969xMq5ePIQkKc66kG -Opie8unjAQRgd6T7lL+zvpaen1UhJruhAgMBAAGjggNOMIIDSjAfBgNVHSMEGDAW -gBRQ6nOJ2yn7EI+e5QEg1N55mUiD9zAdBgNVHQ4EFgQUJuo64qCLWo0Fvi6AsOYG -IiNj+s8wIwYDVR0RBBwwGoIMKi5hY3F1aWEuY29tggphY3F1aWEuY29tMA4GA1Ud -DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwYQYDVR0f -BFowWDAqoCigJoYkaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL2NhMy1nMjcuY3Js -MCqgKKAmhiRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vY2EzLWcyNy5jcmwwggHE -BgNVHSAEggG7MIIBtzCCAbMGCWCGSAGG/WwBATCCAaQwOgYIKwYBBQUHAgEWLmh0 -dHA6Ly93d3cuZGlnaWNlcnQuY29tL3NzbC1jcHMtcmVwb3NpdG9yeS5odG0wggFk -BggrBgEFBQcCAjCCAVYeggFSAEEAbgB5ACAAdQBzAGUAIABvAGYAIAB0AGgAaQBz -ACAAQwBlAHIAdABpAGYAaQBjAGEAdABlACAAYwBvAG4AcwB0AGkAdAB1AHQAZQBz -ACAAYQBjAGMAZQBwAHQAYQBuAGMAZQAgAG8AZgAgAHQAaABlACAARABpAGcAaQBD -AGUAcgB0ACAAQwBQAC8AQwBQAFMAIABhAG4AZAAgAHQAaABlACAAUgBlAGwAeQBp -AG4AZwAgAFAAYQByAHQAeQAgAEEAZwByAGUAZQBtAGUAbgB0ACAAdwBoAGkAYwBo -ACAAbABpAG0AaQB0ACAAbABpAGEAYgBpAGwAaQB0AHkAIABhAG4AZAAgAGEAcgBl -ACAAaQBuAGMAbwByAHAAbwByAGEAdABlAGQAIABoAGUAcgBlAGkAbgAgAGIAeQAg -AHIAZQBmAGUAcgBlAG4AYwBlAC4wewYIKwYBBQUHAQEEbzBtMCQGCCsGAQUFBzAB -hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wRQYIKwYBBQUHMAKGOWh0dHA6Ly9j -YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEhpZ2hBc3N1cmFuY2VDQS0zLmNy -dDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBBQUAA4IBAQCwbrUX+rSNdiS1ivce -pI3gzzlOG9FjcPPTfoLD/+eiysiTKe7d3Hb9urHZWGuEWWxXRl+6tND3TAt8ONpM -ZCs+nls+qvspG8ApQMZLgak4kb4+CaLMi6ZpQ2JTI89iChonOjI0OP6dVDbGbTvV -a7LKkiZw1xJNYUnhIiqOE1B9Ww3SUUpe1TLmiAYiiYiiuiyBxMz48sARHXnlEbWw -0dHOnU51tvG1zkv9sATYwv3LtIjf9pmXZnS1W0j5Ap0JeFbgFywVi0zSpbix0fzr -pyArWETFKxirR2bCVFH0sVZ2q3/sznguUx1QgH+tese0hqHm2epRORcOi69mcDYi -Cf5v ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIGWDCCBUCgAwIBAgIQCl8RTQNbF5EX0u/UA4w/OzANBgkqhkiG9w0BAQUFADBs -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -ZSBFViBSb290IENBMB4XDTA4MDQwMjEyMDAwMFoXDTIyMDQwMzAwMDAwMFowZjEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 -LmRpZ2ljZXJ0LmNvbTElMCMGA1UEAxMcRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug -Q0EtMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9hCikQH17+NDdR -CPge+yLtYb4LDXBMUGMmdRW5QYiXtvCgFbsIYOBC6AUpEIc2iihlqO8xB3RtNpcv -KEZmBMcqeSZ6mdWOw21PoF6tvD2Rwll7XjZswFPPAAgyPhBkWBATaccM7pxCUQD5 -BUTuJM56H+2MEb0SqPMV9Bx6MWkBG6fmXcCabH4JnudSREoQOiPkm7YDr6ictFuf -1EutkozOtREqqjcYjbTCuNhcBoz4/yO9NV7UfD5+gw6RlgWYw7If48hl66l7XaAs -zPw82W3tzPpLQ4zJ1LilYRyyQLYoEt+5+F/+07LJ7z20Hkt8HEyZNp496+ynaF4d -32duXvsCAwEAAaOCAvowggL2MA4GA1UdDwEB/wQEAwIBhjCCAcYGA1UdIASCAb0w -ggG5MIIBtQYLYIZIAYb9bAEDAAIwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3 -LmRpZ2ljZXJ0LmNvbS9zc2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUH -AgIwggFWHoIBUgBBAG4AeQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQBy -AHQAaQBmAGkAYwBhAHQAZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBj -AGUAcAB0AGEAbgBjAGUAIABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAg -AEMAUAAvAEMAUABTACAAYQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQ -AGEAcgB0AHkAIABBAGcAcgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBt -AGkAdAAgAGwAaQBhAGIAaQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBj -AG8AcgBwAG8AcgBhAHQAZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBl -AHIAZQBuAGMAZQAuMBIGA1UdEwEB/wQIMAYBAf8CAQAwNAYIKwYBBQUHAQEEKDAm -MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wgY8GA1UdHwSB -hzCBhDBAoD6gPIY6aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0SGln -aEFzc3VyYW5jZUVWUm9vdENBLmNybDBAoD6gPIY6aHR0cDovL2NybDQuZGlnaWNl -cnQuY29tL0RpZ2lDZXJ0SGlnaEFzc3VyYW5jZUVWUm9vdENBLmNybDAfBgNVHSME -GDAWgBSxPsNpA/i/RwHUmCYaCALvY2QrwzAdBgNVHQ4EFgQUUOpzidsp+xCPnuUB -INTeeZlIg/cwDQYJKoZIhvcNAQEFBQADggEBAB7ipUiebNtTOA/vphoqrOIDQ+2a -vD6OdRvw/S4iWawTwGHi5/rpmc2HCXVUKL9GYNy+USyS8xuRfDEIcOI3ucFbqL2j -CwD7GhX9A61YasXHJJlIR0YxHpLvtF9ONMeQvzHB+LGEhtCcAarfilYGzjrpDq6X -dF3XcZpCdF/ejUN83ulV7WkAywXgemFhM9EZTfkI7qA5xSU1tyvED7Ld8aW3DiTE -JiiNeXf1L/BXunwH1OH8zVowV36GEEfdMR/X/KLCvzB8XSSq6PmuX2p0ws5rs0bY -Ib4p1I5eFdZCSucyb6Sxa1GDWL4/bcf72gMhy2oWGU4K8K2Eyl2Us1p292E= ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs -MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 -d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j -ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL -MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 -LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug -RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm -+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW -PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM -xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB -Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3 -hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg -EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF -MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA -FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec -nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z -eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF -hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2 -Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe -vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep -+OkuE6N36B9K ------END CERTIFICATE----- \ No newline at end of file diff --git a/lib/logstream.rb b/lib/logstream.rb index b487b0e..0bc22db 100644 --- a/lib/logstream.rb +++ b/lib/logstream.rb @@ -1 +1,2 @@ require 'logstream/client' +require 'logstream/cloudapi_v2' \ No newline at end of file diff --git a/lib/logstream/client.rb b/lib/logstream/client.rb index a475144..191b6c6 100644 --- a/lib/logstream/client.rb +++ b/lib/logstream/client.rb @@ -39,18 +39,28 @@ def debug_recv(msg) debug("<- #{msg}") end - def run(url, connect_message) + def run(url, info) EM.run do debug_send("connect to #{url}") + connect_message = { + 'cmd' => 'stream-environment', + 'site' => info['site'], + 'env' => info['environment'], + 't' => info['t'], + 'd' => info['hmac'], + } ws = Faye::WebSocket::Client.new(url) ws.on :open do - debug_send(connect_message) - ws.send(connect_message) + @running = false end ws.on :message do |body,type| debug_recv(body.data) msg = JSON.parse(body.data) case msg['cmd'] + when 'connected' + debug_send(connect_message.to_json) + ws.send(connect_message.to_json) unless @running + @running = true when 'success' color('logtailor-error', msg['code']) do # puts "#{msg.inspect}" diff --git a/lib/logstream/cloudapi_v2.rb b/lib/logstream/cloudapi_v2.rb new file mode 100644 index 0000000..bfcf4fd --- /dev/null +++ b/lib/logstream/cloudapi_v2.rb @@ -0,0 +1,60 @@ +require 'net/https' +require 'json' + +module Logstream + class CloudAPIV2 + class Error < StandardError; end + + attr_accessor :client_id, :client_secret, :endpoint + CLOUDAPI_ENDPOINT = 'https://cloud.acquia.com/api' + + def initialize(client_id, client_secret) + @client_id = client_id + @client_secret = client_secret + end + + def get(path) + bearer_token = get_token + uri = URI.parse("#{CLOUDAPI_ENDPOINT}#{path}") + http = Net::HTTP.new(uri.host, uri.port) + http.use_ssl = true + request = Net::HTTP::Get.new(uri.request_uri) + request['Authorization'] = "Bearer #{bearer_token}" + response = http.request(request) + parsed = JSON.parse(response.body) rescue nil + case response.code.to_i + when 200 + raise Error, "Unexpected reply #{response.body}" unless parsed + parsed + else + raise Error, "HTTP #{response.code}: #{response.body}" + end + end + + def get_application_environments(application_uuid) + response = get("/applications/#{application_uuid}/environments") #, { :query => { "filter" => "name%3D#{env}"}}) + raise Error, "No Environments found." if response['total'] == 0 + raise Error, "Unexpected reply #{response}" unless response['_embedded']['items'] + response['_embedded']['items'] + end + + def get_envirornment_logstream(environment_uuid) + response = get("/environments/#{environment_uuid}/logstream") + raise Error, "Unexpected reply #{response}" unless response['logstream'] + response['logstream'] + end + + def get_token + uri = URI.parse("https://accounts.acquia.com/api/auth/oauth/token") + response = Net::HTTP.post_form(uri, 'client_id' => @client_id, 'client_secret' => @client_secret, 'grant_type' => 'client_credentials') + parsed = JSON.parse(response.body) rescue nil + case response.code.to_i + when 200 + raise Error, "Unexpected reply #{response.body}" unless parsed["access_token"] + parsed["access_token"] + else + raise Error, "HTTP #{response.code}: #{response.body}" + end + end + end +end diff --git a/logstream.gemspec b/logstream.gemspec index 8df25ea..5f9e336 100644 --- a/logstream.gemspec +++ b/logstream.gemspec @@ -3,11 +3,10 @@ $LOAD_PATH.unshift(libpath) unless $LOAD_PATH.include?(libpath) Gem::Specification.new do |s| s.name = "logstream" - s.version = "0.0.8" + s.version = "2.0.0" s.date = Time.now.strftime("%Y-%m-%d") - s.author = "Barry Jaspan" - s.email = "barry.jaspan@acquia.com" + s.author = "Acquia Engineering" s.homepage = "https://github.com/acquia/logstream" s.licenses = ['MIT'] @@ -21,7 +20,6 @@ Gem::Specification.new do |s| s.test_files = Dir["test/**/*"] s.add_runtime_dependency('faye-websocket', ['~> 0.10.0']) - s.add_runtime_dependency('json', ['>= 1.7.7']) s.add_runtime_dependency('thor', ['~> 0.20.0']) s.required_ruby_version = '>= 2.4'