looker-sdk 0.0.5

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.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +52 -0
  3. data/.ruby-gemset +1 -0
  4. data/.travis.yml +16 -0
  5. data/Gemfile +22 -0
  6. data/LICENSE +21 -0
  7. data/Rakefile +37 -0
  8. data/authentication.md +104 -0
  9. data/examples/add_delete_users.rb +94 -0
  10. data/examples/change_credentials_email_address_for_users.rb +23 -0
  11. data/examples/create_credentials_email_for_users.rb +19 -0
  12. data/examples/delete_all_user_sessions.rb +15 -0
  13. data/examples/delete_credentials_google_for_users.rb +19 -0
  14. data/examples/generate_password_reset_tokens_for_users.rb +19 -0
  15. data/examples/ldap_roles_test.rb +50 -0
  16. data/examples/me.rb +3 -0
  17. data/examples/refresh_user_notification_addresses.rb +10 -0
  18. data/examples/roles_and_users_with_permission.rb +22 -0
  19. data/examples/sdk_setup.rb +21 -0
  20. data/examples/streaming_downloads.rb +20 -0
  21. data/examples/users_with_credentials_email.rb +6 -0
  22. data/examples/users_with_credentials_google.rb +8 -0
  23. data/examples/users_with_credentials_google_without_credentials_email.rb +6 -0
  24. data/lib/looker-sdk.rb +32 -0
  25. data/lib/looker-sdk/authentication.rb +104 -0
  26. data/lib/looker-sdk/client.rb +445 -0
  27. data/lib/looker-sdk/client/dynamic.rb +107 -0
  28. data/lib/looker-sdk/configurable.rb +116 -0
  29. data/lib/looker-sdk/default.rb +148 -0
  30. data/lib/looker-sdk/error.rb +235 -0
  31. data/lib/looker-sdk/rate_limit.rb +33 -0
  32. data/lib/looker-sdk/response/raise_error.rb +20 -0
  33. data/lib/looker-sdk/sawyer_patch.rb +33 -0
  34. data/lib/looker-sdk/version.rb +7 -0
  35. data/looker-sdk.gemspec +27 -0
  36. data/readme.md +117 -0
  37. data/shell/.gitignore +41 -0
  38. data/shell/Gemfile +6 -0
  39. data/shell/readme.md +18 -0
  40. data/shell/shell.rb +37 -0
  41. data/streaming.md +59 -0
  42. data/test/helper.rb +46 -0
  43. data/test/looker/swagger.json +1998 -0
  44. data/test/looker/test_client.rb +258 -0
  45. data/test/looker/test_dynamic_client.rb +158 -0
  46. data/test/looker/test_dynamic_client_agent.rb +131 -0
  47. data/test/looker/user.json +1 -0
  48. metadata +107 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a9c372139d8df28af2b71bce4382f3badfa6d1c8
4
+ data.tar.gz: 66910d788e066ef3767f76966e1973ca7312e3c4
5
+ SHA512:
6
+ metadata.gz: 043052d8df89d53724b1fe23e181ae5eafb598ff4aca2dd44d8d030510ffe98dffeb8c51a9a180c594b64597500d42b13db84f08d1969fcdb3d571c98e9eb49e
7
+ data.tar.gz: 8627156eb5061245b16330094381786800e1c32c1fbb8340297e962429a97ad14cc75e2fc2fe8073297e4c7b61751298c629da8ee65721c38c0b5975b643f644
@@ -0,0 +1,52 @@
1
+ # Numerous always-ignore extensions
2
+ *.diff
3
+ *.err
4
+ *.orig
5
+ *.log
6
+ *.rej
7
+ *.swo
8
+ *.swp
9
+ *.vi
10
+ *~
11
+ *.sass-cache
12
+ *.iml
13
+
14
+ # OS or Editor folders
15
+ .DS_Store
16
+ .cache
17
+ .project
18
+ .settings
19
+ .tmproj
20
+ nbproject
21
+ Thumbs.db
22
+
23
+ # Folders to ignore
24
+ intermediate
25
+ publish
26
+ target
27
+ .idea
28
+ out
29
+
30
+ # markdown previews
31
+ *.md.html
32
+
33
+ # bundler suggested ignores
34
+ *.gem
35
+ *.rbc
36
+ .bundle
37
+ .config
38
+ .yardoc
39
+ Gemfile.lock
40
+ Gemfile.optional.lock
41
+ InstalledFiles
42
+ _yardoc
43
+ coverage
44
+ doc/
45
+ lib/bundler/man
46
+ pkg
47
+ rdoc
48
+ spec/reports
49
+ test/tmp
50
+ test/version_tmp
51
+ tmp
52
+ *.netrc
@@ -0,0 +1 @@
1
+ looker-sdk-ruby
@@ -0,0 +1,16 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0
5
+ - 2.1
6
+ - 2.3.1
7
+ - jruby-1.7.19
8
+ - jruby-9.1.5.0
9
+ cache:
10
+ bundler: true
11
+ matrix:
12
+ fast_finish: true
13
+ allow_failures:
14
+ - rvm: ruby-head
15
+ - rvm: jruby-head
16
+ - rvm: ree
data/Gemfile ADDED
@@ -0,0 +1,22 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group :development do
4
+ gem 'awesome_print', '~>1.6.1', :require => 'ap'
5
+ gem 'redcarpet', '~>3.1.2', :platforms => :ruby
6
+ end
7
+
8
+ group :development, :test do
9
+ gem 'rake', '< 11.0'
10
+ end
11
+
12
+ group :test do
13
+ # gem 'json', '~> 1.7', :platforms => [:jruby] look TODO needed?
14
+ gem 'minitest', '5.3.5'
15
+ gem 'mocha', '1.1.0'
16
+ gem 'rack', '1.6.4'
17
+ gem 'rack-test', '0.6.2'
18
+ gem 'netrc', '~> 0.7.7'
19
+ gem 'simplecov', '~> 0.7.1', :require => false
20
+ end
21
+
22
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Looker Data Sciences, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,37 @@
1
+ require 'bundler'
2
+ require "bundler/gem_tasks"
3
+
4
+ require "rake/testtask"
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "test"
7
+ t.test_files = FileList["test/**/test_*.rb"]
8
+ t.verbose = true
9
+ end
10
+
11
+ namespace :test do
12
+ desc "Run tests against all supported Rubies"
13
+ task :all do
14
+ supported_rubies = ['ruby-1.9.3', 'ruby-2.0', 'ruby-2.1', 'ruby-2.3.1', 'jruby-1.7.19', 'jruby-9.1.5.0']
15
+ failing_rubies = []
16
+
17
+ supported_rubies.each do |ruby|
18
+ cmd = "rvm install #{ruby} && rvm #{ruby} exec gem install bundler && rvm #{ruby} exec bundle install && rvm #{ruby} exec bundle exec rake"
19
+ system cmd
20
+ if $? != 0
21
+ failing_rubies << ruby
22
+ end
23
+ end
24
+
25
+ failing_rubies.each do |ruby|
26
+ puts "FAIL: #{ruby}. Problem with the tests on #{ruby}."
27
+ end
28
+
29
+ if failing_rubies
30
+ exit 1
31
+ else
32
+ exit 0
33
+ end
34
+ end
35
+ end
36
+
37
+ task :default => :test
@@ -0,0 +1,104 @@
1
+ ## How to authenticate to Looker's API 3
2
+
3
+ The preferred way to authenticate is to use the looker SDK to manage the login and the passing of
4
+ access_tokens as needed. This doc, however, explains how to do this authentication in a generic way without the SDK and using curl instead for illustration.
5
+
6
+ Looker API 3 implements OAuth 2's "Resource Owner Password Credentials Grant" pattern,
7
+ See: http://tools.ietf.org/html/rfc6749#section-4.3
8
+
9
+ ### Setup an API key
10
+ An 'API 3' key is required in order to login and use the API. The key consists of a client_id and a client_secret.
11
+ 'Login' consists of using these credentials to generate a short-term access_token which is then used to make API calls.
12
+
13
+ The client_id could be considered semi-public. While, the client_secret is a secret password and MUST be
14
+ carefully protected. These credentials should not be hard-coded into client code. They should be read from
15
+ a closely guarded data file when used by client processes.
16
+
17
+ Admins can create an API 3 key for a user on looker's user edit page. All requests made using these
18
+ credentials are made 'as' that user and limited to the role permissions specified for that user. A user
19
+ account with an appropriate role may be created as needed for the API client's use.
20
+
21
+ Note that API 3 tokens should be created for 'regular' Looker users and *not* via the legacy 'Add API User' button.
22
+
23
+
24
+ ### Ensure that the API is accessible
25
+ Looker versions 3.4 (and beyond) expose the 3.0 API via a port different from the port used by the web app.
26
+ The default port is 19999. It may be necessary to have the Ops team managing the looker instance ensure that this
27
+ port is made accessible network-wise to client software running on non-local hosts.
28
+
29
+ The '/alive' url can be used to detect if the server is reachable
30
+
31
+
32
+ ### Login
33
+ To access the API it is necessary to 'login' using the client_id and client_secret in order to acquire an
34
+ access_token that will be used in actual API requests. This is done by POSTing to the /login url. The access_token is returned in a short json body and has a limited time before it expires (the default at this point is 1 hour).
35
+ An 'expires_in' field is provided to tell client software how long they should expect the token to last.
36
+
37
+ A new token is created for each /login call and remains valid until it expires or is revoked via /logout.
38
+
39
+ It is VERY important that these tokens never be sent in the clear or exposed in any other way.
40
+
41
+
42
+ ### Call the API
43
+ API calls then pass the access_token to looker using an 'Authorization' header. API calls are
44
+ done using GET, PUT, POST, PATCH, or DELETE as appropriate for the specific call. Normal REST stuff.
45
+
46
+
47
+ ### Logout
48
+ A '/logout' url is available if the client wants to revoke an access_token. It requires a DELETE request.
49
+ Looker reserves the right to limit the number of 'live' access_tokens per user.
50
+
51
+ -------------------------------------------------------------------------------------------------
52
+
53
+ The following is an example session using Curl. The '-i' param is used to show returned headers.
54
+
55
+ The simple flow in this example is to login, get info about the current user, then logout.
56
+
57
+ Note that in this example the client_id and client_secret params are passed using '-d' which causes the
58
+ request to be done as a POST. And, the -H param is used to specify http headers to add for API requests.
59
+
60
+ ```
61
+ # Check that the port is reachable
62
+ > curl -i https://localhost:19999/alive
63
+ HTTP/1.1 200 OK
64
+ Content-Type: application/json;charset=utf-8
65
+ Vary: Accept-Encoding
66
+ X-Content-Type-Options: nosniff
67
+ Content-Length: 0
68
+
69
+
70
+ # Do the login to get an access_token
71
+ > curl -i -d "client_id=4j3SD8W5RchHw5gvZ5Yd&client_secret=sVySctSMpQQG3TzdNQ5d2dND" https://localhost:19999/login
72
+ HTTP/1.1 200 OK
73
+ Content-Type: application/json;charset=utf-8
74
+ Vary: Accept-Encoding
75
+ X-Content-Type-Options: nosniff
76
+ Content-Length: 99
77
+
78
+ {"access_token":"4QDkCyCtZzYgj4C2p2cj3csJH7zqS5RzKs2kTnG4","token_type":"Bearer","expires_in":3600}
79
+
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/3.0/user
82
+ HTTP/1.1 200 OK
83
+ Content-Type: application/json;charset=utf-8
84
+ Vary: Accept-Encoding
85
+ X-Content-Type-Options: nosniff
86
+ Content-Length: 502
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/3.0/users/14/credentials_email","user_url":"https://localhost:19999/api/3.0/users/14","password_reset_url":"https://localhost:19999/api/3.0"},"url":"https://localhost:19999/api/3.0/users/14"}
89
+
90
+ # Logout to revoke an access_token
91
+ > curl -i -X DELETE -H "Authorization: token 4QDkCyCtZzYgj4C2p2cj3csJH7zqS5RzKs2kTnG4" https://localhost:19999/logout
92
+ HTTP/1.1 204 No Content
93
+ X-Content-Type-Options: nosniff
94
+
95
+ # Show that the access_token is no longer valid
96
+ > curl -i -X DELETE -H "Authorization: token 4QDkCyCtZzYgj4C2p2cj3csJH7zqS5RzKs2kTnG4" https://localhost:19999/logout
97
+ HTTP/1.1 404 Not Found
98
+ Content-Type: application/json;charset=utf-8
99
+ Vary: Accept-Encoding
100
+ X-Content-Type-Options: nosniff
101
+ Content-Length: 69
102
+
103
+ {"message":"Not found","documentation_url":"http://docs.looker.com/"}
104
+ ```
@@ -0,0 +1,94 @@
1
+ require './sdk_setup'
2
+
3
+ ############################################################################################
4
+ # simulate a list read from file
5
+
6
+ user_list = <<-ENDMARK
7
+
8
+ Joe Williams, joe@mycoolcompany.com, Admin
9
+ Jane Schumacher, jane@mycoolcompany.com, User SuperDeveloper
10
+ Jim Watson, jim@mycoolcompany.com, User
11
+ Jim Wu, jimw@mycoolcompany.com, User
12
+
13
+ ENDMARK
14
+
15
+ ############################################################################################
16
+
17
+ def create_users(lines)
18
+ # create a hash to use below. role.name => role.id
19
+ roles_by_name = Hash[ sdk.all_roles.map{|role| [role.name, role.id] } ]
20
+
21
+ # for each line, try to create that user with name, email credentials, and roles
22
+ lines.each_line do |line|
23
+ line.strip!
24
+ next if line.empty?
25
+
26
+ # quicky parsing: note lack of error handling!
27
+
28
+ name, email, roles = line.split(',')
29
+ fname, lname = name.split(' ')
30
+ [fname, lname, email, roles].each(&:strip!)
31
+
32
+ role_ids = []
33
+ roles.split(' ').each do |role_name|
34
+ if id = roles_by_name[role_name]
35
+ role_ids << id
36
+ else
37
+ raise "#{role_name} does not exist. ABORTING!"
38
+ end
39
+ end
40
+
41
+ # for display
42
+ user_info = "#{fname} #{lname} <#{email}> as #{roles}"
43
+
44
+ begin
45
+ # call the SDK to create user with names, add email/password login credentials, set user roles
46
+ user = sdk.create_user({:first_name => fname, :last_name => lname})
47
+ sdk.create_user_credentials_email(user.id, {:email => email})
48
+ sdk.set_user_roles(user.id, role_ids)
49
+ puts "Created user: #{user_info}"
50
+ rescue LookerSDK::Error => e
51
+ # if any errors occur above then 'undo' by deleting the given user (if we got that far)
52
+ sdk.delete_user(user.id) if user
53
+ puts "FAILED to create user: #{user_info} (#{e.message}) "
54
+ end
55
+ end
56
+ end
57
+
58
+ ##################################################################
59
+
60
+ def delete_users(lines)
61
+ # create a hash to use below. user.credentials_email.email => user.id
62
+ users_by_email = Hash[ sdk.all_users.map{|user| [user.credentials_email.email, user.id] if user.credentials_email}.compact ]
63
+
64
+ lines.each_line do |line|
65
+ line.strip!
66
+ next if line.empty?
67
+
68
+ # quicky parsing: note lack of error handling!
69
+ name, email, roles = line.split(',')
70
+ fname, lname = name.split(' ')
71
+ [fname, lname, email, roles].each(&:strip!)
72
+
73
+ # for display
74
+ user_info = "#{fname} #{lname} <#{email}>"
75
+
76
+ begin
77
+ if id = users_by_email[email]
78
+ sdk.delete_user(id)
79
+ puts "Deleted user: #{user_info}>"
80
+ else
81
+ puts "Did not find user: #{user_info}>"
82
+ end
83
+ rescue LookerSDK::Error => e
84
+ puts "FAILED to delete user: #{user_info} (#{e.message}) "
85
+ end
86
+ end
87
+ end
88
+
89
+ ##################################################################
90
+
91
+ # call the methods
92
+ create_users(user_list)
93
+ puts
94
+ delete_users(user_list)
@@ -0,0 +1,23 @@
1
+ require './sdk_setup'
2
+
3
+ users = Hash[
4
+ sdk.all_users(:fields => 'id, credentials_email').
5
+ map{|u| [u.credentials_email.email, u.id] if u.credentials_email }.compact
6
+ ]
7
+
8
+ $stdin.each_line do |line|
9
+ line.chomp!
10
+
11
+ _, old_email, new_email = line.split(',', 3).map(&:strip)
12
+
13
+ if id = users[old_email]
14
+ begin
15
+ sdk.update_user_credentials_email(id, {:email => new_email})
16
+ puts "Successfully changed '#{old_email}' => '#{new_email}'"
17
+ rescue => e
18
+ puts "FAILED to changed '#{old_email}' => '#{new_email}' because of: #{e.class}:#{e.message}"
19
+ end
20
+ else
21
+ puts "FAILED: Could not find user with email '#{old_email}'"
22
+ end
23
+ end
@@ -0,0 +1,19 @@
1
+ require './sdk_setup'
2
+
3
+ $stdin.each_line do |line|
4
+ line.chomp!
5
+
6
+ id, email = line.split(',', 2).map(&:strip)
7
+
8
+ begin
9
+ user = sdk.user(id)
10
+ if user.credentials_email
11
+ puts "Error: User with id '#{id}' Already has credentials_email"
12
+ else
13
+ sdk.create_user_credentials_email(id, {:email => email})
14
+ puts "Success: Created credentials_email for User with id '#{id}' and email '#{email}'"
15
+ end
16
+ rescue LookerSDK::NotFound
17
+ puts "Error: User with id '#{id}' Not found"
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ require './sdk_setup'
2
+
3
+ total_count = 0
4
+ sdk.all_users(:fields => 'id, display_name').each do |user|
5
+ count = 0
6
+ sdk.all_user_sessions(user.id, :fields => 'id').each do |session|
7
+ sdk.delete_user_session(user.id, session.id)
8
+ count += 1
9
+ end
10
+ puts "Deleted #{count} sessions for #{user.id} #{user.display_name}"
11
+ total_count += count
12
+ end
13
+ puts "Deleted #{total_count} sessions"
14
+
15
+
@@ -0,0 +1,19 @@
1
+ require './sdk_setup'
2
+
3
+ $stdin.each_line do |line|
4
+ line.chomp!
5
+
6
+ id, _ = line.split(',', 2).map(&:strip)
7
+
8
+ begin
9
+ user = sdk.user(id)
10
+ if user.credentials_google
11
+ sdk.delete_user_credentials_google(id)
12
+ puts "Success: Deleted credentials_google for User with id '#{id}'"
13
+ else
14
+ puts "Error: User with id '#{id}' Does not have credentials_google"
15
+ end
16
+ rescue LookerSDK::NotFound
17
+ puts "Error: User with id '#{id}' Not found"
18
+ end
19
+ end