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'