looker-sdk 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
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