looker-sdk 0.0.7 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/Gemfile +1 -1
- data/Makefile +81 -0
- data/Rakefile +0 -27
- data/authentication.md +3 -3
- data/lib/looker-sdk/authentication.rb +1 -1
- data/lib/looker-sdk/client/dynamic.rb +25 -18
- data/lib/looker-sdk/client.rb +27 -15
- data/lib/looker-sdk/configurable.rb +4 -2
- data/lib/looker-sdk/default.rb +6 -0
- data/lib/looker-sdk/response/raise_error.rb +1 -3
- data/lib/looker-sdk/version.rb +1 -1
- data/lib/looker-sdk.rb +0 -1
- data/looker-sdk.gemspec +2 -2
- data/readme.md +5 -3
- data/test/helper.rb +2 -2
- data/test/looker/swagger.json +1 -1
- data/test/looker/test_client.rb +71 -5
- data/test/looker/test_dynamic_client.rb +45 -29
- metadata +16 -16
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 03c0187c3befd7923934d6e0d6fdc2cf376cec20c3befab062e831266e191863
|
|
4
|
+
data.tar.gz: '082e731d16af22fa6ccdc3853c7451ff641b016c52ee25d76b6f52d1af6072bd'
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ed80dfc335ba667ee501a734f86d13788552e1903208bc36e8407354ea3aa51fd5bbc6fde6c0e58a728469781c95c975de555e246d75c82cb83484e07b8ba727
|
|
7
|
+
data.tar.gz: 21edf0dc58ebcd17102b9ec7c88006fdda9b229b46ee463d06c8a454ced09d06154a5e6fe8720a3de8dcbf2b819e16947cedb38d91e86aab2cdd60e36e492380
|
data/Gemfile
CHANGED
data/Makefile
ADDED
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#############################################################################################
|
|
2
|
+
# The MIT License (MIT)
|
|
3
|
+
#
|
|
4
|
+
# Copyright (c) 2014 Zee Spencer
|
|
5
|
+
# Copyright (c) 2020 Google LLC
|
|
6
|
+
#
|
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
# of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
# in the Software without restriction, including without limitation the rights
|
|
10
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
# copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
# furnished to do so, subject to the following conditions:
|
|
13
|
+
#
|
|
14
|
+
# The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
# copies or substantial portions of the Software.
|
|
16
|
+
#
|
|
17
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
# SOFTWARE.
|
|
24
|
+
#############################################################################################
|
|
25
|
+
|
|
26
|
+
# Allows running (and re-running) of tests against several ruby versions,
|
|
27
|
+
# assuming you use rbenv instead of rvm.
|
|
28
|
+
|
|
29
|
+
# Uses pattern rules (task-$:) and automatic variables ($*).
|
|
30
|
+
# Pattern rules: http://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_10.html#SEC98
|
|
31
|
+
# Automatic variables: http://ftp.gnu.org/old-gnu/Manuals/make-3.79.1/html_chapter/make_10.html#SEC101
|
|
32
|
+
|
|
33
|
+
# Rbenv-friendly version identifiers for supported Rubys
|
|
34
|
+
25_version = 2.5.7
|
|
35
|
+
jruby_92160_version = jruby-9.2.16.0
|
|
36
|
+
|
|
37
|
+
# The ruby version for use in a given rule.
|
|
38
|
+
# Requires a matched pattern rule and a supported ruby version.
|
|
39
|
+
#
|
|
40
|
+
# Given a pattern rule defined as "install-ruby-%"
|
|
41
|
+
# When the rule is ran as "install-ruby-193"
|
|
42
|
+
# Then the inner addsuffix call evaluates to "193_version"
|
|
43
|
+
# And given_ruby_version becomes "1.9.3-p551"
|
|
44
|
+
given_ruby_version = $($(addsuffix _version, $*))
|
|
45
|
+
|
|
46
|
+
# Instruct rbenv on which Ruby version to use when running a command.
|
|
47
|
+
# Requires a pattern rule and a supported ruby version.
|
|
48
|
+
#
|
|
49
|
+
# Given a pattern rule defined as "test-%"
|
|
50
|
+
# When the rule is ran as "test-187"
|
|
51
|
+
# Then with_given_ruby becomes "RBENV_VERSION=1.8.7-p375"
|
|
52
|
+
with_given_ruby = RBENV_VERSION=$(given_ruby_version)
|
|
53
|
+
|
|
54
|
+
# Runs tests for all supported ruby versions.
|
|
55
|
+
test: test-25 test-jruby_92160
|
|
56
|
+
|
|
57
|
+
# Runs tests against a specific ruby version
|
|
58
|
+
test-%:
|
|
59
|
+
rm -f Gemfile.lock
|
|
60
|
+
$(with_given_ruby) bundle install --quiet
|
|
61
|
+
$(with_given_ruby) rake
|
|
62
|
+
|
|
63
|
+
# Installs all ruby versions and their gems
|
|
64
|
+
install: install-25 install-jruby_92160
|
|
65
|
+
|
|
66
|
+
# Install a particular ruby version
|
|
67
|
+
install-ruby-%:
|
|
68
|
+
rm -f Gemfile.lock
|
|
69
|
+
rbenv install -s $(given_ruby_version)
|
|
70
|
+
|
|
71
|
+
# Install gems into a specific ruby version
|
|
72
|
+
install-gems-%:
|
|
73
|
+
rm -f Gemfile.lock
|
|
74
|
+
$(with_given_ruby) gem update --system
|
|
75
|
+
$(with_given_ruby) gem install bundler
|
|
76
|
+
$(with_given_ruby) bundle install
|
|
77
|
+
|
|
78
|
+
# Installs a specific ruby version and it's gems
|
|
79
|
+
# At the bottom so it doesn't match install-gems and install-ruby tasks.
|
|
80
|
+
install-%:
|
|
81
|
+
make install-ruby-$* install-gems-$*
|
data/Rakefile
CHANGED
|
@@ -22,7 +22,6 @@
|
|
|
22
22
|
# THE SOFTWARE.
|
|
23
23
|
############################################################################################
|
|
24
24
|
|
|
25
|
-
require 'bundler'
|
|
26
25
|
require "bundler/gem_tasks"
|
|
27
26
|
|
|
28
27
|
require "rake/testtask"
|
|
@@ -32,30 +31,4 @@ Rake::TestTask.new do |t|
|
|
|
32
31
|
t.verbose = true
|
|
33
32
|
end
|
|
34
33
|
|
|
35
|
-
namespace :test do
|
|
36
|
-
desc "Run tests against all supported Rubies"
|
|
37
|
-
task :all do
|
|
38
|
-
supported_rubies = %w(ruby-2.0 ruby-2.1 ruby-2.3.1 jruby-1.7.19 jruby-9.1.5.0)
|
|
39
|
-
failing_rubies = []
|
|
40
|
-
|
|
41
|
-
supported_rubies.each do |ruby|
|
|
42
|
-
cmd = "rvm install #{ruby} && rvm #{ruby} exec gem install bundler && rvm #{ruby} exec bundle install && rvm #{ruby} exec bundle exec rake"
|
|
43
|
-
system cmd
|
|
44
|
-
if $? != 0
|
|
45
|
-
failing_rubies << ruby
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
failing_rubies.each do |ruby|
|
|
50
|
-
puts "FAIL: #{ruby}. Problem with the tests on #{ruby}."
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
if failing_rubies
|
|
54
|
-
exit 1
|
|
55
|
-
else
|
|
56
|
-
exit 0
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
end
|
|
60
|
-
|
|
61
34
|
task :default => :test
|
data/authentication.md
CHANGED
|
@@ -22,7 +22,7 @@ Note that API 3 tokens should be created for 'regular' Looker users and *not* vi
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
### Ensure that the API is accessible
|
|
25
|
-
Looker versions 3.4 (and beyond) expose the
|
|
25
|
+
Looker versions 3.4 (and beyond) expose the API via a port different from the port used by the web app.
|
|
26
26
|
The default port is 19999. It may be necessary to have the Ops team managing the looker instance ensure that this
|
|
27
27
|
port is made accessible network-wise to client software running on non-local hosts.
|
|
28
28
|
|
|
@@ -78,14 +78,14 @@ Content-Length: 99
|
|
|
78
78
|
{"access_token":"4QDkCyCtZzYgj4C2p2cj3csJH7zqS5RzKs2kTnG4","token_type":"Bearer","expires_in":3600}
|
|
79
79
|
|
|
80
80
|
# Use an access_token (the token can be used over and over for API calls until it expires)
|
|
81
|
-
> curl -i -H "Authorization: token 4QDkCyCtZzYgj4C2p2cj3csJH7zqS5RzKs2kTnG4" https://localhost:19999/api/
|
|
81
|
+
> curl -i -H "Authorization: token 4QDkCyCtZzYgj4C2p2cj3csJH7zqS5RzKs2kTnG4" https://localhost:19999/api/4.0/user
|
|
82
82
|
HTTP/1.1 200 OK
|
|
83
83
|
Content-Type: application/json;charset=utf-8
|
|
84
84
|
Vary: Accept-Encoding
|
|
85
85
|
X-Content-Type-Options: nosniff
|
|
86
86
|
Content-Length: 502
|
|
87
87
|
|
|
88
|
-
{"id":14,"first_name":"Plain","last_name":"User","email":"dude+1@looker.com","models_dir":null,"is_disabled":false,"look_access":[14],"avatar_url":"https://www.gravatar.com/avatar/b7f792a6180a36a4058f36875584bc45?s=156&d=mm","credentials_email":{"email":"dude+1@looker.com","url":"https://localhost:19999/api/
|
|
88
|
+
{"id":14,"first_name":"Plain","last_name":"User","email":"dude+1@looker.com","models_dir":null,"is_disabled":false,"look_access":[14],"avatar_url":"https://www.gravatar.com/avatar/b7f792a6180a36a4058f36875584bc45?s=156&d=mm","credentials_email":{"email":"dude+1@looker.com","url":"https://localhost:19999/api/4.0/users/14/credentials_email","user_url":"https://localhost:19999/api/4.0/users/14","password_reset_url":"https://localhost:19999/api/4.0"},"url":"https://localhost:19999/api/4.0/users/14"}
|
|
89
89
|
|
|
90
90
|
# Logout to revoke an access_token
|
|
91
91
|
> curl -i -X DELETE -H "Authorization: token 4QDkCyCtZzYgj4C2p2cj3csJH7zqS5RzKs2kTnG4" https://localhost:19999/logout
|
|
@@ -51,7 +51,7 @@ module LookerSDK
|
|
|
51
51
|
|
|
52
52
|
set_access_token_from_params(nil)
|
|
53
53
|
without_authentication do
|
|
54
|
-
encoded_auth = Faraday::Utils.build_query
|
|
54
|
+
encoded_auth = Faraday::Utils.build_query(application_credentials)
|
|
55
55
|
post("#{URI.parse(api_endpoint).path}/login", encoded_auth, header: {:'Content-Type' => 'application/x-www-form-urlencoded'})
|
|
56
56
|
raise "login failure #{last_response.status}" unless last_response.status == 200
|
|
57
57
|
set_access_token_from_params(last_response.data)
|
|
@@ -53,20 +53,17 @@ module LookerSDK
|
|
|
53
53
|
@swagger ||= without_authentication { try_load_swagger }
|
|
54
54
|
|
|
55
55
|
unless @swagger
|
|
56
|
-
# capture the bits we may need later, avoiding potential buffer reuse in last_response between requests
|
|
57
|
-
response_wo_auth_status = last_response&.status
|
|
58
|
-
response_wo_auth_data = last_response&.data
|
|
59
|
-
|
|
60
56
|
# try again, this time with authentication
|
|
61
57
|
@swagger = try_load_swagger
|
|
62
58
|
end
|
|
63
59
|
|
|
64
60
|
# in unit tests, @swagger may be nil and last_response nil because no HTTP request was made
|
|
65
|
-
if @swagger.nil?
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
61
|
+
if @swagger.nil?
|
|
62
|
+
if @last_error
|
|
63
|
+
raise @last_error
|
|
64
|
+
else
|
|
65
|
+
raise "Load of swagger.json failed."
|
|
66
|
+
end
|
|
70
67
|
end
|
|
71
68
|
|
|
72
69
|
@swagger
|
|
@@ -75,12 +72,16 @@ module LookerSDK
|
|
|
75
72
|
def operations
|
|
76
73
|
return @@sharable_operations[api_endpoint] if shared_swagger && @@sharable_operations[api_endpoint]
|
|
77
74
|
|
|
75
|
+
if !@swagger && @lazy_swagger
|
|
76
|
+
load_swagger
|
|
77
|
+
end
|
|
78
|
+
|
|
78
79
|
return nil unless @swagger
|
|
79
80
|
@operations ||= Hash[
|
|
80
81
|
@swagger[:paths].map do |path_name, path_info|
|
|
81
82
|
path_info.map do |method, route_info|
|
|
82
83
|
route = @swagger[:basePath].to_s + path_name.to_s
|
|
83
|
-
[route_info[:operationId], {:route => route, :method => method, :info => route_info}]
|
|
84
|
+
[route_info[:operationId].to_sym, {:route => route, :method => method, :info => route_info}]
|
|
84
85
|
end
|
|
85
86
|
end.reduce(:+)
|
|
86
87
|
].freeze
|
|
@@ -113,7 +114,7 @@ module LookerSDK
|
|
|
113
114
|
private
|
|
114
115
|
|
|
115
116
|
def find_entry(method_name)
|
|
116
|
-
operations && operations[method_name.
|
|
117
|
+
operations && operations[method_name.to_sym] if dynamic
|
|
117
118
|
end
|
|
118
119
|
|
|
119
120
|
def invoke_remote(entry, method_name, *args, &block)
|
|
@@ -128,19 +129,25 @@ module LookerSDK
|
|
|
128
129
|
raise ArgumentError.new("wrong number of arguments (#{params_passed} for #{params_required}) in call to '#{method_name}'. See '#{method_link(entry)}'")
|
|
129
130
|
end
|
|
130
131
|
|
|
131
|
-
# substitute the actual params into the route template
|
|
132
|
-
params.each
|
|
132
|
+
# substitute the actual params into the route template, encoding if needed
|
|
133
|
+
params.each do |param|
|
|
134
|
+
value = args.shift.to_s
|
|
135
|
+
if value == CGI.unescape(value)
|
|
136
|
+
value = CGI.escape(value)
|
|
137
|
+
end
|
|
138
|
+
route.sub!("{#{param[:name]}}", value)
|
|
139
|
+
end
|
|
133
140
|
|
|
134
141
|
a = args.length > 0 ? args[0] : {}
|
|
135
142
|
b = args.length > 1 ? args[1] : {}
|
|
136
143
|
|
|
137
144
|
method = entry[:method].to_sym
|
|
138
145
|
case method
|
|
139
|
-
when :get then get(route, a, &block)
|
|
140
|
-
when :post then post(route, a, merge_content_type_if_body(a, b), &block)
|
|
141
|
-
when :put then put(route, a, merge_content_type_if_body(a, b), &block)
|
|
142
|
-
when :patch then patch(route, a, merge_content_type_if_body(a, b), &block)
|
|
143
|
-
when :delete then delete(route, a) ; @raw_responses ? last_response : delete_succeeded?
|
|
146
|
+
when :get then get(route, a, true, &block)
|
|
147
|
+
when :post then post(route, a, merge_content_type_if_body(a, b), true, &block)
|
|
148
|
+
when :put then put(route, a, merge_content_type_if_body(a, b), true, &block)
|
|
149
|
+
when :patch then patch(route, a, merge_content_type_if_body(a, b), true, &block)
|
|
150
|
+
when :delete then delete(route, a, true) ; @raw_responses ? last_response : delete_succeeded?
|
|
144
151
|
else raise "unsupported method '#{method}' in call to '#{method_name}'. See '#{method_link(entry)}'"
|
|
145
152
|
end
|
|
146
153
|
end
|
data/lib/looker-sdk/client.rb
CHANGED
|
@@ -58,7 +58,9 @@ module LookerSDK
|
|
|
58
58
|
@original_options = options.dup
|
|
59
59
|
|
|
60
60
|
load_credentials_from_netrc unless application_credentials?
|
|
61
|
-
|
|
61
|
+
if !@lazy_swagger
|
|
62
|
+
load_swagger
|
|
63
|
+
end
|
|
62
64
|
self.dynamic = true
|
|
63
65
|
end
|
|
64
66
|
|
|
@@ -89,11 +91,12 @@ module LookerSDK
|
|
|
89
91
|
#
|
|
90
92
|
# @param url [String] The path, relative to {#api_endpoint}
|
|
91
93
|
# @param options [Hash] Query and header params for request
|
|
94
|
+
# @param encoded [Boolean] true: url already encoded, false: url needs encoding
|
|
92
95
|
# @param &block [Block] Block to be called with |response, chunk| for each chunk of the body from
|
|
93
96
|
# the server. The block must return true to continue, or false to abort streaming.
|
|
94
97
|
# @return [Sawyer::Resource]
|
|
95
|
-
def get(url, options = {}, &block)
|
|
96
|
-
request :get, url, nil, parse_query_and_convenience_headers(options), &block
|
|
98
|
+
def get(url, options = {}, encoded=false, &block)
|
|
99
|
+
request :get, url, nil, parse_query_and_convenience_headers(options), encoded, &block
|
|
97
100
|
end
|
|
98
101
|
|
|
99
102
|
# Make a HTTP POST request
|
|
@@ -101,11 +104,12 @@ module LookerSDK
|
|
|
101
104
|
# @param url [String] The path, relative to {#api_endpoint}
|
|
102
105
|
# @param data [String|Array|Hash] Body and optionally header params for request
|
|
103
106
|
# @param options [Hash] Optional header params for request
|
|
107
|
+
# @param encoded [Boolean] true: url already encoded, false: url needs encoding
|
|
104
108
|
# @param &block [Block] Block to be called with |response, chunk| for each chunk of the body from
|
|
105
109
|
# the server. The block must return true to continue, or false to abort streaming.
|
|
106
110
|
# @return [Sawyer::Resource]
|
|
107
|
-
def post(url, data = {}, options = {}, &block)
|
|
108
|
-
request :post, url, data, parse_query_and_convenience_headers(options), &block
|
|
111
|
+
def post(url, data = {}, options = {}, encoded=false, &block)
|
|
112
|
+
request :post, url, data, parse_query_and_convenience_headers(options), encoded, &block
|
|
109
113
|
end
|
|
110
114
|
|
|
111
115
|
# Make a HTTP PUT request
|
|
@@ -113,11 +117,12 @@ module LookerSDK
|
|
|
113
117
|
# @param url [String] The path, relative to {#api_endpoint}
|
|
114
118
|
# @param data [String|Array|Hash] Body and optionally header params for request
|
|
115
119
|
# @param options [Hash] Optional header params for request
|
|
120
|
+
# @param encoded [Boolean] true: url already encoded, false: url needs encoding
|
|
116
121
|
# @param &block [Block] Block to be called with |response, chunk| for each chunk of the body from
|
|
117
122
|
# the server. The block must return true to continue, or false to abort streaming.
|
|
118
123
|
# @return [Sawyer::Resource]
|
|
119
|
-
def put(url, data = {}, options = {}, &block)
|
|
120
|
-
request :put, url, data, parse_query_and_convenience_headers(options), &block
|
|
124
|
+
def put(url, data = {}, options = {}, encoded=false, &block)
|
|
125
|
+
request :put, url, data, parse_query_and_convenience_headers(options), encoded, &block
|
|
121
126
|
end
|
|
122
127
|
|
|
123
128
|
# Make a HTTP PATCH request
|
|
@@ -125,29 +130,32 @@ module LookerSDK
|
|
|
125
130
|
# @param url [String] The path, relative to {#api_endpoint}
|
|
126
131
|
# @param data [String|Array|Hash] Body and optionally header params for request
|
|
127
132
|
# @param options [Hash] Optional header params for request
|
|
133
|
+
# @param encoded [Boolean] true: url already encoded, false: url needs encoding
|
|
128
134
|
# @param &block [Block] Block to be called with |response, chunk| for each chunk of the body from
|
|
129
135
|
# the server. The block must return true to continue, or false to abort streaming.
|
|
130
136
|
# @return [Sawyer::Resource]
|
|
131
|
-
def patch(url, data = {}, options = {}, &block)
|
|
132
|
-
request :patch, url, data, parse_query_and_convenience_headers(options), &block
|
|
137
|
+
def patch(url, data = {}, options = {}, encoded=false, &block)
|
|
138
|
+
request :patch, url, data, parse_query_and_convenience_headers(options), encoded, &block
|
|
133
139
|
end
|
|
134
140
|
|
|
135
141
|
# Make a HTTP DELETE request
|
|
136
142
|
#
|
|
137
143
|
# @param url [String] The path, relative to {#api_endpoint}
|
|
138
144
|
# @param options [Hash] Query and header params for request
|
|
145
|
+
# @param encoded [Boolean] true: url already encoded, false: url needs encoding
|
|
139
146
|
# @return [Sawyer::Resource]
|
|
140
|
-
def delete(url, options = {}, &block)
|
|
141
|
-
request :delete, url, nil, parse_query_and_convenience_headers(options)
|
|
147
|
+
def delete(url, options = {}, encoded=false, &block)
|
|
148
|
+
request :delete, url, nil, parse_query_and_convenience_headers(options), encoded, &block
|
|
142
149
|
end
|
|
143
150
|
|
|
144
151
|
# Make a HTTP HEAD request
|
|
145
152
|
#
|
|
146
153
|
# @param url [String] The path, relative to {#api_endpoint}
|
|
147
154
|
# @param options [Hash] Query and header params for request
|
|
155
|
+
# @param encoded [Boolean] true: url already encoded, false: url needs encoding
|
|
148
156
|
# @return [Sawyer::Resource]
|
|
149
|
-
def head(url, options = {}, &block)
|
|
150
|
-
request :head, url, nil, parse_query_and_convenience_headers(options)
|
|
157
|
+
def head(url, options = {}, encoded=false, &block)
|
|
158
|
+
request :head, url, nil, parse_query_and_convenience_headers(options), encoded
|
|
151
159
|
end
|
|
152
160
|
|
|
153
161
|
# Make one or more HTTP GET requests, optionally fetching
|
|
@@ -296,12 +304,16 @@ module LookerSDK
|
|
|
296
304
|
@agent = nil
|
|
297
305
|
end
|
|
298
306
|
|
|
299
|
-
def request(method, path, data, options, &block)
|
|
307
|
+
def request(method, path, data, options, encoded, &block)
|
|
300
308
|
ensure_logged_in
|
|
301
309
|
begin
|
|
310
|
+
path = path.to_s
|
|
311
|
+
if !encoded
|
|
312
|
+
path = URI::Parser.new.escape(path)
|
|
313
|
+
end
|
|
302
314
|
@last_response = @last_error = nil
|
|
303
315
|
return stream_request(method, path, data, options, &block) if block_given?
|
|
304
|
-
@last_response = response = agent.call(method,
|
|
316
|
+
@last_response = response = agent.call(method, path, data, options)
|
|
305
317
|
@raw_responses ? response : response.data
|
|
306
318
|
rescue StandardError => e
|
|
307
319
|
@last_error = e
|
|
@@ -66,7 +66,8 @@ module LookerSDK
|
|
|
66
66
|
attr_accessor :access_token, :auto_paginate, :client_id,
|
|
67
67
|
:client_secret, :default_media_type, :connection_options,
|
|
68
68
|
:middleware, :netrc, :netrc_file,
|
|
69
|
-
:per_page, :proxy, :user_agent, :faraday, :swagger, :shared_swagger, :raw_responses
|
|
69
|
+
:per_page, :proxy, :user_agent, :faraday, :swagger, :shared_swagger, :raw_responses,
|
|
70
|
+
:lazy_swagger
|
|
70
71
|
attr_writer :web_endpoint, :api_endpoint
|
|
71
72
|
|
|
72
73
|
class << self
|
|
@@ -92,7 +93,8 @@ module LookerSDK
|
|
|
92
93
|
:shared_swagger,
|
|
93
94
|
:swagger,
|
|
94
95
|
:raw_responses,
|
|
95
|
-
:web_endpoint
|
|
96
|
+
:web_endpoint,
|
|
97
|
+
:lazy_swagger,
|
|
96
98
|
]
|
|
97
99
|
end
|
|
98
100
|
end
|
data/lib/looker-sdk/default.rb
CHANGED
|
@@ -30,9 +30,7 @@ module LookerSDK
|
|
|
30
30
|
module Response
|
|
31
31
|
|
|
32
32
|
# HTTP status codes returned by the API
|
|
33
|
-
class RaiseError < Faraday::
|
|
34
|
-
|
|
35
|
-
private
|
|
33
|
+
class RaiseError < Faraday::Middleware
|
|
36
34
|
|
|
37
35
|
def on_complete(response)
|
|
38
36
|
if error = LookerSDK::Error.from_response(response)
|
data/lib/looker-sdk/version.rb
CHANGED
data/lib/looker-sdk.rb
CHANGED
data/looker-sdk.gemspec
CHANGED
|
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
|
|
|
15
15
|
'the Looker data analytics engine to fetch data or render visualizations defined in your Looker data models. '+
|
|
16
16
|
'For more information, see https://looker.com.'
|
|
17
17
|
s.license = 'MIT'
|
|
18
|
-
s.required_ruby_version = '>= 2.
|
|
18
|
+
s.required_ruby_version = '>= 2.5'
|
|
19
19
|
s.requirements = 'Looker version 4.0 or later' # informational
|
|
20
20
|
|
|
21
21
|
s.files = `git ls-files`.split("\n")
|
|
@@ -24,5 +24,5 @@ Gem::Specification.new do |s|
|
|
|
24
24
|
s.require_paths = %w(lib)
|
|
25
25
|
s.add_dependency 'jruby-openssl' if s.platform == :jruby
|
|
26
26
|
s.add_dependency 'sawyer', '~> 0.8'
|
|
27
|
-
s.add_dependency 'faraday', ['>=
|
|
27
|
+
s.add_dependency 'faraday', ['>= 1.0', '< 2.0']
|
|
28
28
|
end
|
data/readme.md
CHANGED
|
@@ -23,10 +23,12 @@ $ rake install
|
|
|
23
23
|
|
|
24
24
|
### Development
|
|
25
25
|
|
|
26
|
+
Customize test/fixtures/.netrc for tests to pass
|
|
27
|
+
Comment out coverage configuration in test/helper.rb for debugging
|
|
26
28
|
```bash
|
|
27
29
|
$ bundle install
|
|
28
30
|
$ rake test # run the test suite
|
|
29
|
-
$
|
|
31
|
+
$ make install test # run the test suite on all supported Rubies
|
|
30
32
|
```
|
|
31
33
|
|
|
32
34
|
### Basic Usage
|
|
@@ -39,7 +41,7 @@ require 'looker-sdk'
|
|
|
39
41
|
sdk = LookerSDK::Client.new(
|
|
40
42
|
:client_id => "4CN7jzm7yrkcy2MC4CCG",
|
|
41
43
|
:client_secret => "Js3rZZ7vHfbc2hBynSj7zqKh",
|
|
42
|
-
:api_endpoint => "https://mygreatcompany.looker.com:19999/api/
|
|
44
|
+
:api_endpoint => "https://mygreatcompany.looker.com:19999/api/4.0"
|
|
43
45
|
)
|
|
44
46
|
|
|
45
47
|
# If you don't want to provide explicit credentials: (trust me you don't)
|
|
@@ -53,7 +55,7 @@ sdk = LookerSDK::Client.new(
|
|
|
53
55
|
sdk = LookerSDK::Client.new(
|
|
54
56
|
:netrc => true,
|
|
55
57
|
:netrc_file => "~/.net_rc",
|
|
56
|
-
:api_endpoint => "https://mygreatcompany.looker.com:19999/api/
|
|
58
|
+
:api_endpoint => "https://mygreatcompany.looker.com:19999/api/4.0",
|
|
57
59
|
|
|
58
60
|
# Set longer timeout to allow for long running queries. The default is 60 seconds and can be problematic.
|
|
59
61
|
:connection_options => {:request => {:timeout => 60 * 60, :open_timeout => 30}},
|
data/test/helper.rb
CHANGED
|
@@ -57,6 +57,7 @@ fix_netrc_permissions(File.join(fixture_path, '.netrc'))
|
|
|
57
57
|
def setup_sdk
|
|
58
58
|
LookerSDK.reset!
|
|
59
59
|
LookerSDK.configure do |c|
|
|
60
|
+
c.lazy_swagger = true
|
|
60
61
|
c.connection_options = {:ssl => {:verify => false}}
|
|
61
62
|
c.netrc = true
|
|
62
63
|
c.netrc_file = File.join(fixture_path, '.netrc')
|
|
@@ -64,7 +65,6 @@ def setup_sdk
|
|
|
64
65
|
end
|
|
65
66
|
|
|
66
67
|
def teardown_sdk
|
|
68
|
+
setup_sdk # put back initial config
|
|
67
69
|
LookerSDK.logout
|
|
68
70
|
end
|
|
69
|
-
|
|
70
|
-
|
data/test/looker/swagger.json
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"title": "Looker API",
|
|
6
6
|
"description": "This document is a representative sample (subset) of the Looker API that should only be used to unit test the Looker ruby sdk. To get the current, actual Looker API metadata visit /api/3.0/swagger.json on your Looker instance.",
|
|
7
7
|
"contact": {
|
|
8
|
-
"name": "Looker Team <
|
|
8
|
+
"name": "Looker Team <https://help.looker.com>"
|
|
9
9
|
},
|
|
10
10
|
"license": {
|
|
11
11
|
"name": "EULA",
|
data/test/looker/test_client.rb
CHANGED
|
@@ -30,8 +30,31 @@ describe LookerSDK::Client do
|
|
|
30
30
|
setup_sdk
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
describe "lazy load swagger" do
|
|
34
|
+
|
|
35
|
+
it "lazy loads swagger" do
|
|
36
|
+
LookerSDK.reset!
|
|
37
|
+
client = LookerSDK::Client.new(
|
|
38
|
+
:lazy_swagger => true,
|
|
39
|
+
:netrc => true,
|
|
40
|
+
:netrc_file => File.join(fixture_path, '.netrc'),
|
|
41
|
+
:connection_options => {:ssl => {:verify => false}},
|
|
42
|
+
)
|
|
43
|
+
assert_nil client.swagger
|
|
44
|
+
client.me()
|
|
45
|
+
assert client.swagger
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "loads swagger initially" do
|
|
49
|
+
LookerSDK.reset!
|
|
50
|
+
client = LookerSDK::Client.new(
|
|
51
|
+
:lazy_swagger => false,
|
|
52
|
+
:netrc => true,
|
|
53
|
+
:netrc_file => File.join(fixture_path, '.netrc'),
|
|
54
|
+
:connection_options => {:ssl => {:verify => false}},
|
|
55
|
+
)
|
|
56
|
+
assert client.swagger
|
|
57
|
+
end
|
|
35
58
|
end
|
|
36
59
|
|
|
37
60
|
describe "module configuration" do
|
|
@@ -50,8 +73,9 @@ describe LookerSDK::Client do
|
|
|
50
73
|
end
|
|
51
74
|
|
|
52
75
|
it "inherits the module configuration" do
|
|
53
|
-
client = LookerSDK::Client.new
|
|
76
|
+
client = LookerSDK::Client.new(:lazy_swagger => true)
|
|
54
77
|
LookerSDK::Configurable.keys.each do |key|
|
|
78
|
+
next if key == :lazy_swagger
|
|
55
79
|
client.instance_variable_get(:"@#{key}").must_equal("Some #{key}")
|
|
56
80
|
end
|
|
57
81
|
end
|
|
@@ -63,7 +87,8 @@ describe LookerSDK::Client do
|
|
|
63
87
|
:connection_options => {:ssl => {:verify => false}},
|
|
64
88
|
:per_page => 40,
|
|
65
89
|
:client_id => "looker_client_id",
|
|
66
|
-
:client_secret => "client_secret2"
|
|
90
|
+
:client_secret => "client_secret2",
|
|
91
|
+
:lazy_swagger => true,
|
|
67
92
|
}
|
|
68
93
|
end
|
|
69
94
|
|
|
@@ -111,7 +136,11 @@ describe LookerSDK::Client do
|
|
|
111
136
|
describe "with .netrc" do
|
|
112
137
|
it "can read .netrc files" do
|
|
113
138
|
LookerSDK.reset!
|
|
114
|
-
client = LookerSDK::Client.new(
|
|
139
|
+
client = LookerSDK::Client.new(
|
|
140
|
+
:lazy_swagger => true,
|
|
141
|
+
:netrc => true,
|
|
142
|
+
:netrc_file => File.join(fixture_path, '.netrc'),
|
|
143
|
+
)
|
|
115
144
|
client.client_id.wont_be_nil
|
|
116
145
|
client.client_secret.wont_be_nil
|
|
117
146
|
end
|
|
@@ -122,6 +151,9 @@ describe LookerSDK::Client do
|
|
|
122
151
|
|
|
123
152
|
before do
|
|
124
153
|
LookerSDK.reset!
|
|
154
|
+
LookerSDK.configure do |c|
|
|
155
|
+
c.lazy_swagger = true
|
|
156
|
+
end
|
|
125
157
|
end
|
|
126
158
|
|
|
127
159
|
it "sets oauth token with .configure" do
|
|
@@ -232,6 +264,40 @@ describe LookerSDK::Client do
|
|
|
232
264
|
end
|
|
233
265
|
end
|
|
234
266
|
|
|
267
|
+
[
|
|
268
|
+
[:get, '/api/3.0/users/foo%2Fbar', false],
|
|
269
|
+
[:get, '/api/3.0/users/foo%252Fbar', true],
|
|
270
|
+
[:post, '/api/3.0/users/foo%2Fbar', false],
|
|
271
|
+
[:post, '/api/3.0/users/foo%252Fbar', true],
|
|
272
|
+
[:put, '/api/3.0/users/foo%2Fbar', false],
|
|
273
|
+
[:put, '/api/3.0/users/foo%252Fbar', true],
|
|
274
|
+
[:patch, '/api/3.0/users/foo%2Fbar', false],
|
|
275
|
+
[:patch, '/api/3.0/users/foo%252Fbar', true],
|
|
276
|
+
[:delete, '/api/3.0/users/foo%2Fbar', false],
|
|
277
|
+
[:delete, '/api/3.0/users/foo%252Fbar', true],
|
|
278
|
+
[:head, '/api/3.0/users/foo%2Fbar', false],
|
|
279
|
+
[:head, '/api/3.0/users/foo%252Fbar', true],
|
|
280
|
+
].each do |method, path, encoded|
|
|
281
|
+
it "handles request path encoding" do
|
|
282
|
+
expected_path = '/api/3.0/users/foo%252Fbar'
|
|
283
|
+
|
|
284
|
+
resp = OpenStruct.new(:data => "hi", :status => 204)
|
|
285
|
+
mock = MiniTest::Mock.new.expect(:call, resp, [method, expected_path, nil, {}])
|
|
286
|
+
Sawyer::Agent.stubs(:new).returns(mock, mock)
|
|
287
|
+
|
|
288
|
+
sdk = LookerSDK::Client.new
|
|
289
|
+
if [:get, :delete, :head].include? method
|
|
290
|
+
args = [method, path, nil, encoded]
|
|
291
|
+
else
|
|
292
|
+
args = [method, path, nil, nil, encoded]
|
|
293
|
+
end
|
|
294
|
+
sdk.without_authentication do
|
|
295
|
+
value = sdk.public_send *args
|
|
296
|
+
assert_equal "hi", value
|
|
297
|
+
end
|
|
298
|
+
mock.verify
|
|
299
|
+
end
|
|
300
|
+
end
|
|
235
301
|
end
|
|
236
302
|
|
|
237
303
|
describe 'Sawyer date/time parsing patch' do
|
|
@@ -36,6 +36,7 @@ class LookerDynamicClientTest < MiniTest::Spec
|
|
|
36
36
|
conn.adapter :rack, engine
|
|
37
37
|
end
|
|
38
38
|
|
|
39
|
+
LookerSDK.reset!
|
|
39
40
|
LookerSDK::Client.new do |config|
|
|
40
41
|
config.swagger = swagger
|
|
41
42
|
config.access_token = access_token
|
|
@@ -92,41 +93,30 @@ class LookerDynamicClientTest < MiniTest::Spec
|
|
|
92
93
|
|
|
93
94
|
describe "swagger" do
|
|
94
95
|
|
|
95
|
-
it "
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
sdk.stubs(:looker_warn).once
|
|
101
|
-
|
|
102
|
-
sdk.load_swagger
|
|
96
|
+
it "raises when swagger.json can't be loaded" do
|
|
97
|
+
mock = MiniTest::Mock.new.expect(:call, nil) {raise "no swagger for you"}
|
|
98
|
+
mock.expect(:call, nil) {raise "still no swagger for you"}
|
|
99
|
+
err = assert_raises(RuntimeError) { sdk_client(nil, mock) }
|
|
100
|
+
assert_equal "still no swagger for you", err.message
|
|
103
101
|
end
|
|
104
102
|
|
|
105
|
-
it "
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
sdk.stubs(:try_load_swagger).returns(nil, {key: "my data"})
|
|
111
|
-
sdk.stubs(:looker_warn).never
|
|
112
|
-
|
|
113
|
-
sdk.load_swagger
|
|
103
|
+
it "loads swagger without authentication" do
|
|
104
|
+
resp = [200, {'Content-Type' => 'application/json'}, [default_swagger.to_json]]
|
|
105
|
+
mock = MiniTest::Mock.new.expect(:call, resp, [Hash])
|
|
106
|
+
sdk = sdk_client(nil, mock)
|
|
107
|
+
assert_equal default_swagger, sdk.swagger
|
|
114
108
|
end
|
|
115
109
|
|
|
116
|
-
it "
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
sdk.stubs(:looker_warn).never
|
|
123
|
-
|
|
124
|
-
sdk.load_swagger
|
|
110
|
+
it "loads swagger with authentication" do
|
|
111
|
+
resp = [200, {'Content-Type' => 'application/json'}, [default_swagger.to_json]]
|
|
112
|
+
mock = MiniTest::Mock.new.expect(:call, nil) {raise "login first!"}
|
|
113
|
+
mock.expect(:call, resp, [Hash])
|
|
114
|
+
sdk = sdk_client(nil, mock)
|
|
115
|
+
assert_equal default_swagger, sdk.swagger
|
|
125
116
|
end
|
|
126
117
|
|
|
127
118
|
it "invalid method name" do
|
|
128
|
-
|
|
129
|
-
sdk = sdk_client(default_swagger, mock)
|
|
119
|
+
sdk = sdk_client(default_swagger, nil)
|
|
130
120
|
assert_raises NoMethodError do
|
|
131
121
|
sdk.this_method_name_doesnt_exist()
|
|
132
122
|
end
|
|
@@ -136,18 +126,44 @@ class LookerDynamicClientTest < MiniTest::Spec
|
|
|
136
126
|
end
|
|
137
127
|
end
|
|
138
128
|
|
|
129
|
+
describe "operation maps" do
|
|
130
|
+
it "invoke by string operationId" do
|
|
131
|
+
verify(response, :get, '/api/3.0/user') do |sdk|
|
|
132
|
+
sdk.invoke('me')
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it "invoke by symbol operationId" do
|
|
137
|
+
verify(response, :get, '/api/3.0/user') do |sdk|
|
|
138
|
+
sdk.invoke(:me)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
139
143
|
it "get no params" do
|
|
140
144
|
verify(response, :get, '/api/3.0/user') do |sdk|
|
|
141
145
|
sdk.me
|
|
142
146
|
end
|
|
143
147
|
end
|
|
144
148
|
|
|
145
|
-
it "get with
|
|
149
|
+
it "get with params" do
|
|
146
150
|
verify(response, :get, '/api/3.0/users/25') do |sdk|
|
|
147
151
|
sdk.user(25)
|
|
148
152
|
end
|
|
149
153
|
end
|
|
150
154
|
|
|
155
|
+
it "get with params that need encoding" do
|
|
156
|
+
verify(response, :get, '/api/3.0/users/foo%2Fbar') do |sdk|
|
|
157
|
+
sdk.user("foo/bar")
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
it "get with params already encoded" do
|
|
162
|
+
verify(response, :get, '/api/3.0/users/foo%2Fbar') do |sdk|
|
|
163
|
+
sdk.user("foo%2Fbar")
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
151
167
|
it "get with query" do
|
|
152
168
|
verify(response, :get, '/api/3.0/user', '', {bar:"foo"}) do |sdk|
|
|
153
169
|
sdk.me({bar:'foo'})
|
metadata
CHANGED
|
@@ -1,49 +1,49 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: looker-sdk
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0
|
|
4
|
+
version: 0.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Looker
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-08-23 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: sawyer
|
|
14
15
|
requirement: !ruby/object:Gem::Requirement
|
|
15
16
|
requirements:
|
|
16
17
|
- - "~>"
|
|
17
18
|
- !ruby/object:Gem::Version
|
|
18
19
|
version: '0.8'
|
|
19
|
-
name: sawyer
|
|
20
|
-
prerelease: false
|
|
21
20
|
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '0.8'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: faraday
|
|
28
29
|
requirement: !ruby/object:Gem::Requirement
|
|
29
30
|
requirements:
|
|
30
31
|
- - ">="
|
|
31
32
|
- !ruby/object:Gem::Version
|
|
32
|
-
version:
|
|
33
|
+
version: '1.0'
|
|
33
34
|
- - "<"
|
|
34
35
|
- !ruby/object:Gem::Version
|
|
35
|
-
version: '
|
|
36
|
-
name: faraday
|
|
37
|
-
prerelease: false
|
|
36
|
+
version: '2.0'
|
|
38
37
|
type: :runtime
|
|
38
|
+
prerelease: false
|
|
39
39
|
version_requirements: !ruby/object:Gem::Requirement
|
|
40
40
|
requirements:
|
|
41
41
|
- - ">="
|
|
42
42
|
- !ruby/object:Gem::Version
|
|
43
|
-
version:
|
|
43
|
+
version: '1.0'
|
|
44
44
|
- - "<"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '
|
|
46
|
+
version: '2.0'
|
|
47
47
|
description: Use this SDK to access the Looker API. The Looker API provides functions
|
|
48
48
|
to perform administrative tasks such as provisioning users, configuring database
|
|
49
49
|
connections, and so on. It also enables you to leverage the Looker data analytics
|
|
@@ -60,6 +60,7 @@ files:
|
|
|
60
60
|
- CODE_OF_CONDUCT.md
|
|
61
61
|
- Gemfile
|
|
62
62
|
- LICENSE.md
|
|
63
|
+
- Makefile
|
|
63
64
|
- Rakefile
|
|
64
65
|
- authentication.md
|
|
65
66
|
- examples/.netrc
|
|
@@ -110,7 +111,7 @@ homepage: https://github.com/looker/looker-sdk-ruby
|
|
|
110
111
|
licenses:
|
|
111
112
|
- MIT
|
|
112
113
|
metadata: {}
|
|
113
|
-
post_install_message:
|
|
114
|
+
post_install_message:
|
|
114
115
|
rdoc_options: []
|
|
115
116
|
require_paths:
|
|
116
117
|
- lib
|
|
@@ -118,7 +119,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
118
119
|
requirements:
|
|
119
120
|
- - ">="
|
|
120
121
|
- !ruby/object:Gem::Version
|
|
121
|
-
version: '2.
|
|
122
|
+
version: '2.5'
|
|
122
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
123
124
|
requirements:
|
|
124
125
|
- - ">="
|
|
@@ -126,9 +127,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
126
127
|
version: '0'
|
|
127
128
|
requirements:
|
|
128
129
|
- Looker version 4.0 or later
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
signing_key:
|
|
130
|
+
rubygems_version: 3.2.25
|
|
131
|
+
signing_key:
|
|
132
132
|
specification_version: 4
|
|
133
133
|
summary: Looker Ruby SDK
|
|
134
134
|
test_files: []
|