tableau_server_client 0.0.17 → 0.2.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 +4 -4
- data/lib/tableau_server_client/client.rb +22 -12
- data/lib/tableau_server_client/exception.rb +5 -0
- data/lib/tableau_server_client/resources/datasource.rb +1 -1
- data/lib/tableau_server_client/resources/extract_refresh.rb +13 -1
- data/lib/tableau_server_client/resources/project.rb +7 -0
- data/lib/tableau_server_client/resources/resource.rb +8 -0
- data/lib/tableau_server_client/resources/site.rb +9 -0
- data/lib/tableau_server_client/resources/view.rb +45 -0
- data/lib/tableau_server_client/resources/workbook.rb +24 -3
- data/lib/tableau_server_client/server.rb +52 -6
- data/lib/tableau_server_client/version.rb +1 -1
- data/tableau_server_client.gemspec +2 -2
- metadata +9 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1558ccb1a6e4e24c51290e44d1731769cbd4097ba15f7234b109182ad9104e8
|
4
|
+
data.tar.gz: 7d64b81492f87d2f180cf7ca0e744dda911af13b9aa3e7646a7f8ccbf9c51b2a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47b55e561f1b3a4d4d793c902fe4ed68812371abc8d0a787db0601d49875b788ca46ac352e53852d7a7a6ed9807e8c84ffdee5c82c0d32f3371bc27ae7e2e9de
|
7
|
+
data.tar.gz: a975ceace9239d04b36eb5c392b34ae1a8b6df969f1c564b58feb9d5a500ae83691aa09fc88d6813552f3c5bc4447c08a261d8a2fcedb78b1b197765362a97e7
|
@@ -14,17 +14,18 @@ module TableauServerClient
|
|
14
14
|
class Client
|
15
15
|
include RequestBuilder
|
16
16
|
|
17
|
-
def initialize(server_url, username, password,
|
17
|
+
def initialize(server_url, username, password, content_url, api_version, token_lifetime, logger, impersonation_user_id)
|
18
18
|
@server_url = server_url
|
19
19
|
@username = username
|
20
20
|
@password = password
|
21
|
-
@
|
21
|
+
@content_url = content_url
|
22
22
|
@api_version = api_version
|
23
23
|
@token_lifetime = token_lifetime
|
24
24
|
@logger = logger
|
25
|
+
@impersonation_user_id = impersonation_user_id
|
25
26
|
end
|
26
27
|
|
27
|
-
attr_reader :
|
28
|
+
attr_reader :content_url, :username, :api_version, :token_lifetime, :logger, :impersonation_user_id
|
28
29
|
|
29
30
|
def server_url
|
30
31
|
@_server_url ||= URI(@server_url.chomp("/"))
|
@@ -65,15 +66,27 @@ module TableauServerClient
|
|
65
66
|
return response
|
66
67
|
end
|
67
68
|
|
68
|
-
def
|
69
|
+
def download_image(resource_location, file_path: nil)
|
70
|
+
req_url = request_url("#{resource_location.path}/image", resource_location.query_params)
|
71
|
+
response = session.get req_url.to_s
|
72
|
+
if file_path
|
73
|
+
File.write(file_path, response.body)
|
74
|
+
end
|
75
|
+
return response.body
|
76
|
+
end
|
77
|
+
|
78
|
+
def update(resource, path: nil, request: nil)
|
79
|
+
path = path || resource.path
|
80
|
+
request = request || resource.to_request
|
69
81
|
session.put do |req|
|
70
|
-
req.url request_url(
|
71
|
-
req.body =
|
82
|
+
req.url request_url(path).to_s
|
83
|
+
req.body = request
|
72
84
|
end
|
73
85
|
end
|
74
86
|
|
75
|
-
def delete(resource)
|
76
|
-
|
87
|
+
def delete(resource, path: nil)
|
88
|
+
path = path || resource.path
|
89
|
+
session.delete request_url(path).to_s
|
77
90
|
end
|
78
91
|
|
79
92
|
def session
|
@@ -104,6 +117,7 @@ module TableauServerClient
|
|
104
117
|
request = request_body {|b|
|
105
118
|
b.credentials(name: username, password: password) {
|
106
119
|
b.site(contentUrl: content_url)
|
120
|
+
b.user(id: impersonation_user_id) if impersonation_user_id
|
107
121
|
}
|
108
122
|
}
|
109
123
|
# POST without Token
|
@@ -114,10 +128,6 @@ module TableauServerClient
|
|
114
128
|
@token = TableauServerClient::Token.parse(res.body, token_lifetime)
|
115
129
|
end
|
116
130
|
|
117
|
-
def content_url
|
118
|
-
site_name == 'default' ? "" : site_name
|
119
|
-
end
|
120
|
-
|
121
131
|
def faraday
|
122
132
|
@faraday ||= Faraday.new(request: {params_encoder: EmptyEncoder.new}, headers: {'Content-Type' => 'application/xml'}) do |f|
|
123
133
|
f.response :raise_error
|
@@ -9,7 +9,7 @@ module TableauServerClient
|
|
9
9
|
class Datasource < Resource
|
10
10
|
include Downloadable
|
11
11
|
|
12
|
-
attr_reader :id, :name, :content_url, :type, :created_at, :updated_at, :is_certified
|
12
|
+
attr_reader :id, :name, :webpage_url, :content_url, :type, :created_at, :updated_at, :is_certified
|
13
13
|
attr_writer :owner
|
14
14
|
|
15
15
|
def self.from_response(client, path, xml)
|
@@ -41,7 +41,15 @@ module TableauServerClient
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def schedule
|
44
|
-
@client.get_collection(Resources::Schedule.location(nil)).
|
44
|
+
@client.get_collection(Resources::Schedule.location(nil)).find {|s| s.id == schedule_id }
|
45
|
+
end
|
46
|
+
|
47
|
+
def workbook
|
48
|
+
@client.get_collection(Workbook.location(site_path)).find {|w| w.id == workbook_id }
|
49
|
+
end
|
50
|
+
|
51
|
+
def datasource
|
52
|
+
@client.get_collection(Datasource.location(site_path)).find {|d| d.id == datasource_id }
|
45
53
|
end
|
46
54
|
|
47
55
|
def run_now
|
@@ -50,6 +58,10 @@ module TableauServerClient
|
|
50
58
|
Job.from_response(@client, Job.location(site_path, id = job_id).path, resp)
|
51
59
|
end
|
52
60
|
|
61
|
+
def delete!
|
62
|
+
resp = @client.delete(self)
|
63
|
+
end
|
64
|
+
|
53
65
|
end
|
54
66
|
end
|
55
67
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'tableau_server_client/resources/resource'
|
2
|
+
require 'tableau_server_client/resources/workbook'
|
2
3
|
|
3
4
|
module TableauServerClient
|
4
5
|
module Resources
|
@@ -59,6 +60,12 @@ module TableauServerClient
|
|
59
60
|
@hierarchy ||= (parent_projects << self).map {|p| p.name }.join('/')
|
60
61
|
end
|
61
62
|
|
63
|
+
def workbooks
|
64
|
+
@client.get_collection(Workbook.location(site_path, filter: [])).select {|w|
|
65
|
+
w.project_id == id
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
62
69
|
def extract_values_in_description
|
63
70
|
@values_in_description ||=\
|
64
71
|
description.lines.map { |l|/^(.*):\s*(.*)$/.match(l) }.reject { |m| m.nil? }.map { |m| m[1,2] }.to_h
|
@@ -4,6 +4,7 @@ require 'tableau_server_client/resources/workbook'
|
|
4
4
|
require 'tableau_server_client/resources/user'
|
5
5
|
require 'tableau_server_client/resources/subscription'
|
6
6
|
require 'tableau_server_client/resources/extract_refresh'
|
7
|
+
require 'tableau_server_client/resources/view'
|
7
8
|
|
8
9
|
module TableauServerClient
|
9
10
|
module Resources
|
@@ -40,6 +41,14 @@ module TableauServerClient
|
|
40
41
|
@client.get Workbook.location(path, id)
|
41
42
|
end
|
42
43
|
|
44
|
+
def views(filter: [])
|
45
|
+
@client.get_collection View.location(path, filter: filter)
|
46
|
+
end
|
47
|
+
|
48
|
+
def view(id)
|
49
|
+
@client.get View.location(path, id)
|
50
|
+
end
|
51
|
+
|
43
52
|
def users(filter: [])
|
44
53
|
@client.get_collection User.location(path, filter: filter)
|
45
54
|
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'tableau_server_client/resources/resource'
|
2
|
+
require 'tableau_server_client/resources/workbook'
|
3
|
+
|
4
|
+
module TableauServerClient
|
5
|
+
module Resources
|
6
|
+
|
7
|
+
class View < Resource
|
8
|
+
|
9
|
+
attr_reader :id, :name, :content_url, :workbook_id
|
10
|
+
attr_writer :owner
|
11
|
+
|
12
|
+
def self.from_response(client, path, xml)
|
13
|
+
attrs = extract_attributes(xml)
|
14
|
+
attrs['workbook_id'] = xml.xpath("xmlns:workbook")[0]['id']
|
15
|
+
new(client, path, attrs)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.from_collection_response(client, path, xml)
|
19
|
+
xml.xpath("//xmlns:views/xmlns:view").each do |s|
|
20
|
+
id = s['id']
|
21
|
+
yield from_response(client, "#{path}/#{id}", s)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def workbook
|
26
|
+
client.get Workbook.location(site_path, workbook_id)
|
27
|
+
end
|
28
|
+
|
29
|
+
def webpage_url
|
30
|
+
"#{server_url}#{content}/#/views/#{webpage_path}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def webpage_path
|
34
|
+
content_url.gsub('/sheets/', '/')
|
35
|
+
end
|
36
|
+
|
37
|
+
def image(query_params: {}, file_path: nil)
|
38
|
+
return @image if @iamge
|
39
|
+
@image = client.download_image(location(query_params: query_params), file_path: file_path)
|
40
|
+
@image
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -3,6 +3,7 @@ require 'tableau_server_client/resources/project'
|
|
3
3
|
require 'tableau_server_client/resources/connection'
|
4
4
|
require 'tableau_server_client/resources/downloadable'
|
5
5
|
require 'tableau_server_client/resources/datasource'
|
6
|
+
require 'tableau_server_client/resources/view'
|
6
7
|
|
7
8
|
module TableauServerClient
|
8
9
|
module Resources
|
@@ -10,13 +11,14 @@ module TableauServerClient
|
|
10
11
|
class Workbook < Resource
|
11
12
|
include Downloadable
|
12
13
|
|
13
|
-
attr_reader :id, :name, :content_url, :show_tabs, :size, :created_at, :updated_at
|
14
|
+
attr_reader :id, :name, :webpage_url, :content_url, :show_tabs, :size, :created_at, :updated_at, :project_id, :owner_id, :tags
|
14
15
|
attr_writer :owner
|
15
16
|
|
16
17
|
def self.from_response(client, path, xml)
|
17
18
|
attrs = extract_attributes(xml)
|
18
19
|
attrs['project_id'] = xml.xpath("xmlns:project")[0]['id']
|
19
|
-
attrs['owner_id']
|
20
|
+
attrs['owner_id'] = xml.xpath("xmlns:owner")[0]['id']
|
21
|
+
attrs['tags'] = xml.xpath("xmlns:tags/xmlns:tag").map {|t| t['label'] }
|
20
22
|
new(client, path, attrs)
|
21
23
|
end
|
22
24
|
|
@@ -32,13 +34,17 @@ module TableauServerClient
|
|
32
34
|
end
|
33
35
|
|
34
36
|
def project
|
35
|
-
@project ||= @client.get_collection(Project.location(site_path)).find {|p| p.id ==
|
37
|
+
@project ||= @client.get_collection(Project.location(site_path)).find {|p| p.id == project_id }
|
36
38
|
end
|
37
39
|
|
38
40
|
def owner
|
39
41
|
@owner ||= @client.get User.location(site_path, @owner_id)
|
40
42
|
end
|
41
43
|
|
44
|
+
def views
|
45
|
+
@views ||= @client.get_collection(View.location(site_path)).select {|v| v.workbook_id == id }
|
46
|
+
end
|
47
|
+
|
42
48
|
def to_request
|
43
49
|
request = build_request {|b|
|
44
50
|
b.workbook {|w|
|
@@ -52,6 +58,21 @@ module TableauServerClient
|
|
52
58
|
@client.update self
|
53
59
|
end
|
54
60
|
|
61
|
+
def add_tags!(tags)
|
62
|
+
request = build_request {|b|
|
63
|
+
b.tags {
|
64
|
+
tags.each do |t|
|
65
|
+
b.tag(label: t)
|
66
|
+
end
|
67
|
+
}
|
68
|
+
}
|
69
|
+
resp = @client.update(self, path: "#{path}/tags", request: request)
|
70
|
+
end
|
71
|
+
|
72
|
+
def delete_tag!(tag)
|
73
|
+
@client.delete(self, path: "#{path}/tags/#{tag}")
|
74
|
+
end
|
75
|
+
|
55
76
|
def embedded_datasources
|
56
77
|
download.xpath('//datasources//datasource').map do |ds|
|
57
78
|
Datasource::DatasourceContent.new(ds)
|
@@ -1,25 +1,43 @@
|
|
1
1
|
require 'tableau_server_client/client'
|
2
2
|
require 'tableau_server_client/resources/site'
|
3
3
|
require 'tableau_server_client/resources/schedule'
|
4
|
+
require 'tableau_server_client/exception'
|
4
5
|
require 'logger'
|
5
6
|
|
6
7
|
module TableauServerClient
|
7
8
|
class Server
|
8
9
|
|
10
|
+
#Implement for_token
|
11
|
+
#def for_token(token)
|
12
|
+
|
9
13
|
def initialize(server_url, username, password,
|
10
|
-
|
11
|
-
log_level: :info)
|
14
|
+
content_url: "", api_version: "3.1", token_lifetime: 240,
|
15
|
+
log_level: :info, impersonation_username: nil)
|
16
|
+
@server_url = server_url
|
17
|
+
@username = username
|
18
|
+
@password = password
|
19
|
+
@content_url = content_url
|
20
|
+
@api_version = api_version
|
21
|
+
@token_lifetime = token_lifetime
|
12
22
|
@logger = ::Logger.new(STDOUT)
|
13
23
|
@logger.level = ::Logger.const_get(log_level.upcase.to_sym)
|
14
|
-
@
|
24
|
+
@impersonation_username = impersonation_username
|
15
25
|
end
|
16
26
|
|
27
|
+
attr_reader :server_url, :username, :content_url, :api_version, :token_lifetime, :logger, :impersonation_username
|
28
|
+
|
17
29
|
def sites
|
18
|
-
client.get_collection
|
30
|
+
client.get_collection(Resources::Site.location(path)).map {|s|
|
31
|
+
client_for_site(s.content_url).get_collection(Resources::Site.location(path)).select {|x| x.id == s.id }.first
|
32
|
+
}
|
19
33
|
end
|
20
34
|
|
21
35
|
def site(id)
|
22
|
-
|
36
|
+
sites.select { |s| s.id == id }.first
|
37
|
+
end
|
38
|
+
|
39
|
+
def full_site(id)
|
40
|
+
client_for_site(client.get(Resources::Site.location(path, id)).content_url).get Resources::Site.location(path, id)
|
23
41
|
end
|
24
42
|
|
25
43
|
def schedules
|
@@ -32,7 +50,35 @@ module TableauServerClient
|
|
32
50
|
|
33
51
|
private
|
34
52
|
|
35
|
-
attr_reader :
|
53
|
+
attr_reader :password
|
54
|
+
|
55
|
+
def client
|
56
|
+
@client ||= client_for_site(content_url)
|
57
|
+
end
|
58
|
+
|
59
|
+
def client_for_site(_content_url)
|
60
|
+
Client.new(server_url, username, password, _content_url, api_version, token_lifetime, @logger, impersonation_user_id)
|
61
|
+
end
|
62
|
+
|
63
|
+
def site_id
|
64
|
+
admin_client.get_collection(Resources::Site.location(path)).each do |site|
|
65
|
+
if site.content_url == content_url
|
66
|
+
return site.id
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def impersonation_user_id
|
72
|
+
return @impersonation_user_id if @impersonation_user_id
|
73
|
+
return nil unless impersonation_username
|
74
|
+
user = admin_client.get(Resources::Site.location(path, site_id)).users(filter: ["name:eq:#{impersonation_username}"]).first
|
75
|
+
return @impersonation_user_id = user.id if user
|
76
|
+
raise TableauServerClientError.new("User '#{username}' not found.")
|
77
|
+
end
|
78
|
+
|
79
|
+
def admin_client
|
80
|
+
@admin_client ||= Client.new(server_url, username, password, content_url, api_version, token_lifetime, @logger, nil)
|
81
|
+
end
|
36
82
|
|
37
83
|
end
|
38
84
|
end
|
@@ -21,8 +21,8 @@ Gem::Specification.new do |spec|
|
|
21
21
|
spec.executables = ["console"]
|
22
22
|
spec.require_paths = ["lib"]
|
23
23
|
|
24
|
-
spec.add_development_dependency "bundler", "~> 1
|
25
|
-
spec.add_development_dependency "rake", "~>
|
24
|
+
spec.add_development_dependency "bundler", "~> 2.1"
|
25
|
+
spec.add_development_dependency "rake", "~> 12.3.3"
|
26
26
|
spec.add_development_dependency "rspec", "~> 3.0"
|
27
27
|
spec.add_development_dependency "byebug"
|
28
28
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tableau_server_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- shimpeko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-06-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '1
|
19
|
+
version: '2.1'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '1
|
26
|
+
version: '2.1'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 12.3.3
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 12.3.3
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -137,6 +137,7 @@ files:
|
|
137
137
|
- bin/console
|
138
138
|
- lib/tableau_server_client.rb
|
139
139
|
- lib/tableau_server_client/client.rb
|
140
|
+
- lib/tableau_server_client/exception.rb
|
140
141
|
- lib/tableau_server_client/paginatable_response.rb
|
141
142
|
- lib/tableau_server_client/request_builder.rb
|
142
143
|
- lib/tableau_server_client/request_url.rb
|
@@ -151,6 +152,7 @@ files:
|
|
151
152
|
- lib/tableau_server_client/resources/site.rb
|
152
153
|
- lib/tableau_server_client/resources/subscription.rb
|
153
154
|
- lib/tableau_server_client/resources/user.rb
|
155
|
+
- lib/tableau_server_client/resources/view.rb
|
154
156
|
- lib/tableau_server_client/resources/workbook.rb
|
155
157
|
- lib/tableau_server_client/server.rb
|
156
158
|
- lib/tableau_server_client/token.rb
|
@@ -175,8 +177,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
175
177
|
- !ruby/object:Gem::Version
|
176
178
|
version: '0'
|
177
179
|
requirements: []
|
178
|
-
|
179
|
-
rubygems_version: 2.7.7
|
180
|
+
rubygems_version: 3.0.3
|
180
181
|
signing_key:
|
181
182
|
specification_version: 4
|
182
183
|
summary: Tableau Server REST API Client
|