looker-sdk 0.1.11 → 0.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bd7f1ae1fc17049a2495fbe59b5daa30922eeee81324c198a14bd6e39714e4d6
4
- data.tar.gz: 000eec5248e5cdee93e02a780822460a7c7adf10ebee87c645379a97eb8e2cf3
3
+ metadata.gz: b66e79758ed96fe627d9ecb1c0337c4b842bf136943e24b07c9431e96ba76a1f
4
+ data.tar.gz: a6ba6ba2672b8efcb98f10e2450ed30aa8eb9b136648c65e677307ab79a12b4c
5
5
  SHA512:
6
- metadata.gz: 5d11ee93d5ea36eae97c8a2fff92c5505a3b1df8c750609cef85d431ca744ca188adfe8a1d17850ada2d9ac8bdf31129daef06713f5080303327f7360d366089
7
- data.tar.gz: af88d3c1185927d26624900e6ed9794b3091415038aeba1f92a65c8d51daff308b3cc17f297709bd644cbb28e36d34011eccac83fa3f9aa0b3197e6af713dec6
6
+ metadata.gz: 731ecb6c91196e366e842b1dfe68ae75b492b82fdf189f5859c5007dee06c145b236b3221b15ef27ee882a46367efa60b31da068f4ff3003a42ec70f338b4652
7
+ data.tar.gz: 0a4e3f74db38d3e243b4e3b24274eee327355f9e99a73791224047238bca0fe090eee9098c2d5e69f186b255aafc6343187e0c8b1aec02bfb51cbf08cb0b8953
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.1](https://github.com/looker-open-source/looker-sdk-ruby/compare/v0.2.0...v0.2.1) (2026-11-04)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * configure release-please manifest and version-file for ruby code ([#171](https://github.com/looker-open-source/looker-sdk-ruby/issues/171)) ([7f9aa51](https://github.com/looker-open-source/looker-sdk-ruby/commit/7f9aa5187b4a59b6fae36d5b1bdc50859b352077))
9
+ * enable SSL certificate verification by default in streaming requests ([#169](https://github.com/looker-open-source/looker-sdk-ruby/issues/169)) ([824f90e](https://github.com/looker-open-source/looker-sdk-ruby/commit/824f90e406a6a21bf1bdc8f6aa9d49ffe05f8a1b))
10
+
11
+ ## [0.2.0](https://github.com/looker-open-source/looker-sdk-ruby/compare/v0.1.11...v0.2.0) (2026-03-08)
12
+
13
+
14
+ ### Features
15
+
16
+ * Allow query parameters to be passed in the body for POST, PUT, and PATCH requests when no body parameter is explicitly defined. ([#156](https://github.com/looker-open-source/looker-sdk-ruby/issues/156)) ([6bb702b](https://github.com/looker-open-source/looker-sdk-ruby/commit/6bb702bd8c40bc2efdfad25df60a1a661e00e16b))
17
+
18
+
19
+ ### Bug Fixes
20
+
21
+ * allow tests to run against remote server ([#155](https://github.com/looker-open-source/looker-sdk-ruby/issues/155)) ([1156d52](https://github.com/looker-open-source/looker-sdk-ruby/commit/1156d52c849197176ee62e8a122d2e5bab71f4be))
22
+ * move query params -> body only on form ([#158](https://github.com/looker-open-source/looker-sdk-ruby/issues/158)) ([87e7280](https://github.com/looker-open-source/looker-sdk-ruby/commit/87e72805d479906ebd7d4753898d7609c9a33016))
23
+ * send proper content-type header at /login ([#160](https://github.com/looker-open-source/looker-sdk-ruby/issues/160)) ([36866eb](https://github.com/looker-open-source/looker-sdk-ruby/commit/36866eb7d3414c2b00a65f3ee8b3b3784416bdf8))
24
+
3
25
  ## [0.1.11](https://github.com/looker-open-source/looker-sdk-ruby/compare/v0.1.10...v0.1.11) (2025-01-13)
4
26
 
5
27
 
@@ -52,8 +52,7 @@ module LookerSDK
52
52
  set_access_token_from_params(nil)
53
53
  without_authentication do
54
54
  encoded_auth = Faraday::Utils.build_query(application_credentials)
55
- post("#{URI.parse(api_endpoint).path}/login", encoded_auth, header: {:'Content-Type' => 'application/x-www-form-urlencoded'})
56
- raise "login failure #{last_response.status}" unless last_response.status == 200
55
+ post(File.join(URI.parse(api_endpoint).path, 'login'), encoded_auth, headers: {:'Content-Type' => 'application/x-www-form-urlencoded'})
57
56
  set_access_token_from_params(last_response.data)
58
57
  end
59
58
  end
@@ -144,6 +144,22 @@ module LookerSDK
144
144
  b = args.length > 1 ? args[1] : {}
145
145
 
146
146
  method = entry[:method].to_sym
147
+
148
+ if [:post, :put, :patch].include?(method) && (entry[:info][:consumes] || []).include?("application/x-www-form-urlencoded")
149
+ if empty_body?(a) && !empty_body?(b)
150
+ a = {} if empty_body?(a)
151
+ if b.key?(:query)
152
+ a.merge!(b.delete(:query))
153
+ end
154
+
155
+ b.keys.each do |k|
156
+ next if k == :headers
157
+ next if Client::CONVENIENCE_HEADERS.include?(k)
158
+ a[k] = b.delete(k)
159
+ end
160
+ end
161
+ end
162
+
147
163
  case method
148
164
  when :get then get(route, a, true, &block)
149
165
  when :post then post(route, a, merge_content_type_if_body(a, b), true, &block)
@@ -154,6 +170,9 @@ module LookerSDK
154
170
  end
155
171
  end
156
172
 
173
+ def empty_body?(body)
174
+ body.nil? || (body.respond_to?(:empty?) && body.empty?)
175
+ end
157
176
  end
158
177
  end
159
178
  end
@@ -385,7 +385,7 @@ module LookerSDK
385
385
 
386
386
  connect_opts = {
387
387
  :use_ssl => !!connection.ssl,
388
- :verify_mode => (connection.ssl.verify rescue true) ?
388
+ :verify_mode => ((connection.ssl.verify != false) rescue true) ?
389
389
  OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE,
390
390
  }
391
391
 
@@ -26,6 +26,6 @@ module LookerSDK
26
26
 
27
27
  # Current version
28
28
  # @return [String]
29
- VERSION = "0.1.11"
29
+ VERSION = "0.2.1"
30
30
 
31
31
  end
data/test/helper.rb CHANGED
@@ -22,9 +22,13 @@
22
22
  # THE SOFTWARE.
23
23
  ############################################################################################
24
24
 
25
- require 'simplecov'
26
- SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new SimpleCov::Formatter::HTMLFormatter
27
- SimpleCov.start
25
+ begin
26
+ require 'simplecov'
27
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new SimpleCov::Formatter::HTMLFormatter
28
+ SimpleCov.start
29
+ rescue LoadError
30
+ # ignore simplecov if not installed
31
+ end
28
32
 
29
33
  require 'rubygems'
30
34
  require 'bundler/setup'
@@ -94,6 +98,7 @@ def setup_sdk
94
98
  else
95
99
  c.netrc = true
96
100
  c.netrc_file = File.join(fixture_path, '.netrc')
101
+ c.api_endpoint = "#{base_url}/api/#{api_version}"
97
102
  end
98
103
  end
99
104
  end
@@ -0,0 +1,150 @@
1
+ require_relative '../helper'
2
+
3
+
4
+ class LookerBodyParamsTest < Minitest::Spec
5
+
6
+ def access_token
7
+ '87614b09dd141c22800f96f11737ade5226d7ba8'
8
+ end
9
+
10
+ def sdk_client(swagger, engine)
11
+ faraday = Faraday.new do |conn|
12
+ conn.use LookerSDK::Response::RaiseError
13
+ conn.adapter :rack, engine
14
+ end
15
+
16
+ LookerSDK.reset!
17
+ LookerSDK::Client.new do |config|
18
+ config.swagger = swagger
19
+ config.access_token = access_token
20
+ config.faraday = faraday
21
+ end
22
+ end
23
+
24
+ def default_swagger
25
+ json = <<-JSON
26
+ {
27
+ "swagger": "2.0",
28
+ "basePath": "/api/4.0",
29
+ "paths": {
30
+ "/test_post_urlencoded": {
31
+ "post": {
32
+ "operationId": "test_post_urlencoded",
33
+ "consumes": ["application/x-www-form-urlencoded"],
34
+ "parameters": [
35
+ {
36
+ "name": "param1",
37
+ "in": "query",
38
+ "type": "string"
39
+ },
40
+ {
41
+ "name": "param2",
42
+ "in": "query",
43
+ "type": "string"
44
+ }
45
+ ],
46
+ "responses": {
47
+ "200": { "description": "Success" }
48
+ }
49
+ }
50
+ },
51
+ "/test_post_json": {
52
+ "post": {
53
+ "operationId": "test_post_json",
54
+ "consumes": ["application/json"],
55
+ "parameters": [
56
+ {
57
+ "name": "param1",
58
+ "in": "query",
59
+ "type": "string"
60
+ }
61
+ ],
62
+ "responses": {
63
+ "200": { "description": "Success" }
64
+ }
65
+ }
66
+ },
67
+ "/test_post_default": {
68
+ "post": {
69
+ "operationId": "test_post_default",
70
+ "parameters": [
71
+ {
72
+ "name": "param1",
73
+ "in": "query",
74
+ "type": "string"
75
+ }
76
+ ],
77
+ "responses": {
78
+ "200": { "description": "Success" }
79
+ }
80
+ }
81
+ }
82
+ }
83
+ }
84
+ JSON
85
+ @swagger ||= JSON.parse(json, :symbolize_names => true)
86
+ end
87
+
88
+ def verify(response, method, path, expected_body='', expected_query={}, content_type = nil)
89
+ mock = Minitest::Mock.new.expect(:call, response) do |env|
90
+ req = Rack::Request.new(env)
91
+ req_body = req.body&.gets || ''
92
+
93
+ # Parse body if it's JSON
94
+ begin
95
+ parsed_body = JSON.parse(req_body, :symbolize_names => true)
96
+ rescue JSON::ParserError
97
+ parsed_body = req_body
98
+ end
99
+
100
+ # Check method
101
+ method_match = req.request_method == method.to_s.upcase
102
+
103
+ # Check path
104
+ path_match = req.path_info == path
105
+
106
+ # Check query params
107
+ parsed_query = JSON.parse(req.params.to_json, :symbolize_names => true)
108
+ query_match = parsed_query == expected_query
109
+
110
+ # Check body
111
+ body_match = parsed_body == expected_body
112
+
113
+ if !body_match
114
+ puts "Body mismatch! Expected: #{expected_body.inspect}, Got: #{parsed_body.inspect}"
115
+ end
116
+ method_match && path_match && query_match && body_match
117
+ end
118
+
119
+
120
+ yield sdk_client(default_swagger, mock)
121
+ mock.verify
122
+ end
123
+
124
+ def response
125
+ [200, {'Content-Type' => 'application/json'}, [{}.to_json]]
126
+ end
127
+
128
+ describe "Body Params Refactor" do
129
+ it "moves query params to body for POST when consumes is x-www-form-urlencoded" do
130
+ # Expect body to have params, query to be empty
131
+ verify(response, :post, '/api/4.0/test_post_urlencoded', {param1: 'foo', param2: 'bar'}, {}) do |sdk|
132
+ sdk.test_post_urlencoded(nil, param1: 'foo', param2: 'bar')
133
+ end
134
+ end
135
+
136
+ it "keeps params in query for POST when consumes is application/json" do
137
+ # Expect body to be empty (or nil), query to have params
138
+ verify(response, :post, '/api/4.0/test_post_json', '', {param1: 'foo'}) do |sdk|
139
+ sdk.test_post_json(nil, param1: 'foo')
140
+ end
141
+ end
142
+
143
+ it "keeps params in query for POST when consumes is unspecified" do
144
+ # Expect body to be empty, query to have params
145
+ verify(response, :post, '/api/4.0/test_post_default', '', {param1: 'foo'}) do |sdk|
146
+ sdk.test_post_default(nil, param1: 'foo')
147
+ end
148
+ end
149
+ end
150
+ end
@@ -57,6 +57,7 @@ describe LookerSDK::Client do
57
57
  opts.merge!({
58
58
  :netrc => true,
59
59
  :netrc_file => File.join(fixture_path, '.netrc'),
60
+ :api_endpoint => "#{base_url}/api/#{api_version}",
60
61
  :connection_options => {:ssl => {:verify => false}},
61
62
  })
62
63
 
@@ -156,12 +157,14 @@ describe LookerSDK::Client do
156
157
 
157
158
  describe "with .netrc" do
158
159
  it "can read .netrc files" do
159
- skip unless File.exist?(File.join(fixture_path, '.netrc'))
160
+ netrc_file = File.expand_path('../../../examples/.netrc', __FILE__)
161
+ skip unless File.exist?(netrc_file)
160
162
  LookerSDK.reset!
163
+ File.chmod(0600, netrc_file)
161
164
  client = LookerSDK::Client.new(
162
165
  :lazy_swagger => true,
163
166
  :netrc => true,
164
- :netrc_file => File.join(fixture_path, '.netrc'),
167
+ :netrc_file => netrc_file,
165
168
  )
166
169
  client.client_id.wont_be_nil
167
170
  client.client_secret.wont_be_nil
@@ -373,6 +376,132 @@ describe LookerSDK::Client do
373
376
  end
374
377
  end
375
378
 
379
+ describe "authentication" do
380
+ it "sets the proper content type header on login" do
381
+ LookerSDK.reset!
382
+ client = LookerSDK::Client.new(
383
+ client_id: 'a',
384
+ client_secret: 'b',
385
+ api_endpoint: 'https://localhost:19999/api/4.0',
386
+ connection_options: {ssl: {verify: false}},
387
+ lazy_swagger: true
388
+ )
389
+
390
+ # login returns token info
391
+ token_response = OpenStruct.new(status: 200, data: {access_token: 'token', token_type: 'Bearer', expires_in: 3600})
392
+
393
+ # expect the post to have the right url, body, and headers
394
+ mock = Minitest::Mock.new.expect(:call, token_response) do |method, path, body, options|
395
+ method == :post &&
396
+ path == '/api/4.0/login' &&
397
+ body == 'client_id=a&client_secret=b' &&
398
+ options == {headers: {:'Content-Type' => 'application/x-www-form-urlencoded'}}
399
+ end
400
+
401
+ # test_client.rb uses mocha for mocking/stubbing usually:
402
+ Sawyer::Agent.stubs(:new).returns(mock)
403
+
404
+ client.authenticate
405
+
406
+ mock.verify
407
+ end
408
+ end
409
+
410
+ describe "streaming client SSL verification" do
411
+ it "verifies SSL peer by default when ssl.verify is not explicitly configured" do
412
+ client = LookerSDK::Client.new(lazy_swagger: true)
413
+ streaming_client = LookerSDK::Client::StreamingClient.new(client)
414
+
415
+ mock_ssl = OpenStruct.new(verify: nil)
416
+ mock_conn = OpenStruct.new(
417
+ ssl: mock_ssl,
418
+ options: OpenStruct.new(open_timeout: 30, timeout: 60)
419
+ )
420
+ def mock_conn.build_exclusive_url(*); "https://localhost:19999/api/4.0/test"; end
421
+
422
+ mock_req = OpenStruct.new(
423
+ path: "/api/4.0/test",
424
+ params: {},
425
+ options: OpenStruct.new(params_encoder: nil),
426
+ http_method: :get,
427
+ headers: {},
428
+ body: nil
429
+ )
430
+
431
+ Net::HTTP.expects(:start).with do |host, port, opts|
432
+ assert_equal "localhost", host
433
+ assert_equal 19999, port
434
+ assert_equal true, opts[:use_ssl]
435
+ assert_equal OpenSSL::SSL::VERIFY_PEER, opts[:verify_mode]
436
+ true
437
+ end
438
+
439
+ streaming_client.build_response(mock_conn, mock_req)
440
+ end
441
+
442
+ it "disables SSL verification when ssl.verify is explicitly false" do
443
+ client = LookerSDK::Client.new(lazy_swagger: true)
444
+ streaming_client = LookerSDK::Client::StreamingClient.new(client)
445
+
446
+ mock_ssl = OpenStruct.new(verify: false)
447
+ mock_conn = OpenStruct.new(
448
+ ssl: mock_ssl,
449
+ options: OpenStruct.new(open_timeout: 30, timeout: 60)
450
+ )
451
+ def mock_conn.build_exclusive_url(*); "https://localhost:19999/api/4.0/test"; end
452
+
453
+ mock_req = OpenStruct.new(
454
+ path: "/api/4.0/test",
455
+ params: {},
456
+ options: OpenStruct.new(params_encoder: nil),
457
+ http_method: :get,
458
+ headers: {},
459
+ body: nil
460
+ )
461
+
462
+ Net::HTTP.expects(:start).with do |host, port, opts|
463
+ assert_equal "localhost", host
464
+ assert_equal 19999, port
465
+ assert_equal true, opts[:use_ssl]
466
+ assert_equal OpenSSL::SSL::VERIFY_NONE, opts[:verify_mode]
467
+ true
468
+ end
469
+
470
+ streaming_client.build_response(mock_conn, mock_req)
471
+ end
472
+
473
+ it "verifies SSL peer when ssl.verify is explicitly true" do
474
+ client = LookerSDK::Client.new(lazy_swagger: true)
475
+ streaming_client = LookerSDK::Client::StreamingClient.new(client)
476
+
477
+ mock_ssl = OpenStruct.new(verify: true)
478
+ mock_conn = OpenStruct.new(
479
+ ssl: mock_ssl,
480
+ options: OpenStruct.new(open_timeout: 30, timeout: 60)
481
+ )
482
+ def mock_conn.build_exclusive_url(*); "https://localhost:19999/api/4.0/test"; end
483
+
484
+ mock_req = OpenStruct.new(
485
+ path: "/api/4.0/test",
486
+ params: {},
487
+ options: OpenStruct.new(params_encoder: nil),
488
+ http_method: :get,
489
+ headers: {},
490
+ body: nil
491
+ )
492
+
493
+ Net::HTTP.expects(:start).with do |host, port, opts|
494
+ assert_equal "localhost", host
495
+ assert_equal 19999, port
496
+ assert_equal true, opts[:use_ssl]
497
+ assert_equal OpenSSL::SSL::VERIFY_PEER, opts[:verify_mode]
498
+ true
499
+ end
500
+
501
+ streaming_client.build_response(mock_conn, mock_req)
502
+ end
503
+ end
504
+
376
505
  # TODO: Convert the old tests that were here to deal with swagger/dynamic way of doing things. Perhaps
377
506
  # with a dedicated server that serves swagger customized to the test suite. Also, bring the auth tests
378
507
  # to life here on the SDK client end.
@@ -57,6 +57,7 @@ describe LookerSDK::Client do
57
57
  opts.merge!({
58
58
  :netrc => true,
59
59
  :netrc_file => File.join(fixture_path, '.netrc'),
60
+ :api_endpoint => "#{base_url}/api/#{api_version}",
60
61
  :connection_options => {:ssl => {:verify => false}},
61
62
  })
62
63
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: looker-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.11
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Looker
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-01-13 00:00:00.000000000 Z
11
+ date: 2026-11-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sawyer
@@ -131,6 +131,7 @@ files:
131
131
  - streaming.md
132
132
  - test/helper.rb
133
133
  - test/looker/swagger.json
134
+ - test/looker/test_body_params.rb
134
135
  - test/looker/test_client.rb
135
136
  - test/looker/test_dynamic_client.rb
136
137
  - test/looker/test_dynamic_client_agent.rb
@@ -156,15 +157,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
157
  version: '0'
157
158
  requirements:
158
159
  - Looker version 4.0 or later
159
- rubygems_version: 3.1.6
160
+ rubygems_version: 3.3.27
160
161
  signing_key:
161
162
  specification_version: 4
162
163
  summary: Looker Ruby SDK
163
164
  test_files:
164
165
  - test/helper.rb
166
+ - test/looker/swagger.json
167
+ - test/looker/test_body_params.rb
168
+ - test/looker/test_client.rb
165
169
  - test/looker/test_dynamic_client.rb
166
- - test/looker/test_inline_query.rb
167
170
  - test/looker/test_dynamic_client_agent.rb
168
- - test/looker/test_client.rb
171
+ - test/looker/test_inline_query.rb
169
172
  - test/looker/user.json
170
- - test/looker/swagger.json