69383d12f63f22ded7957c25fd012d7530763ae4
[arvados.git] / sdk / ruby / lib / arvados / google_api_client.rb
1 # Copyright (C) The Arvados Authors. All rights reserved.
2 #
3 # SPDX-License-Identifier: Apache-2.0
4
5 require 'google/api_client'
6 # Monkeypatch google-api-client gem to avoid sending newline characters
7 # on headers to make ruby-2.3.7+ happy.
8 # See: https://dev.arvados.org/issues/13920
9 Google::APIClient::ENV::OS_VERSION.strip!
10
11 require 'json'
12 require 'tempfile'
13
14 class Google::APIClient
15   def discovery_document(api, version)
16     api = api.to_s
17     discovery_uri = self.discovery_uri(api, version)
18     discovery_uri_hash = Digest::MD5.hexdigest(discovery_uri)
19     discovery_cache_path =
20       File.expand_path("~/.cache/arvados/discovery-#{discovery_uri_hash}.json")
21     @discovery_documents[discovery_uri_hash] ||=
22       disk_cached_discovery_document(discovery_cache_path) or
23       fetched_discovery_document(discovery_uri, discovery_cache_path)
24   end
25
26   private
27
28   def disk_cached_discovery_document(cache_path)
29     begin
30       if (Time.now - File.mtime(cache_path)) < 86400
31         open(cache_path) do |cache_file|
32           return JSON.load(cache_file)
33         end
34       end
35     rescue IOError, SystemCallError, JSON::JSONError
36       # Error reading the cache.  Act like it doesn't exist.
37     end
38     nil
39   end
40
41   def write_cached_discovery_document(cache_path, body)
42     cache_dir = File.dirname(cache_path)
43     cache_file = nil
44     begin
45       FileUtils.makedirs(cache_dir)
46       cache_file = Tempfile.new("discovery", cache_dir)
47       cache_file.write(body)
48       cache_file.flush
49       File.rename(cache_file.path, cache_path)
50     rescue IOError, SystemCallError
51       # Failure to write the cache is non-fatal.  Do nothing.
52     ensure
53       cache_file.close! unless cache_file.nil?
54     end
55   end
56
57   def fetched_discovery_document(uri, cache_path)
58     response = self.execute!(:http_method => :get,
59                              :uri => uri,
60                              :authenticated => false)
61     write_cached_discovery_document(cache_path, response.body)
62     JSON.load(response.body)
63   end
64 end