gazer 0.2.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +15 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +35 -0
- data/Gemfile.lock +150 -0
- data/LICENSE.txt +20 -0
- data/README.md +527 -0
- data/Rakefile +27 -0
- data/bin/console +35 -0
- data/bin/setup +30 -0
- data/exe/gzr +40 -0
- data/gzr.gemspec +67 -0
- data/lib/gzr.rb +25 -0
- data/lib/gzr/cli.rb +86 -0
- data/lib/gzr/command.rb +251 -0
- data/lib/gzr/commands/.gitkeep +1 -0
- data/lib/gzr/commands/connection.rb +69 -0
- data/lib/gzr/commands/connection/dialects.rb +72 -0
- data/lib/gzr/commands/connection/ls.rb +72 -0
- data/lib/gzr/commands/dashboard.rb +75 -0
- data/lib/gzr/commands/dashboard/cat.rb +67 -0
- data/lib/gzr/commands/dashboard/import.rb +256 -0
- data/lib/gzr/commands/dashboard/rm.rb +47 -0
- data/lib/gzr/commands/group.rb +87 -0
- data/lib/gzr/commands/group/ls.rb +73 -0
- data/lib/gzr/commands/group/member_groups.rb +74 -0
- data/lib/gzr/commands/group/member_users.rb +74 -0
- data/lib/gzr/commands/look.rb +75 -0
- data/lib/gzr/commands/look/cat.rb +55 -0
- data/lib/gzr/commands/look/import.rb +62 -0
- data/lib/gzr/commands/look/rm.rb +47 -0
- data/lib/gzr/commands/model.rb +51 -0
- data/lib/gzr/commands/model/ls.rb +72 -0
- data/lib/gzr/commands/plan.rb +149 -0
- data/lib/gzr/commands/plan/cat.rb +52 -0
- data/lib/gzr/commands/plan/disable.rb +49 -0
- data/lib/gzr/commands/plan/enable.rb +49 -0
- data/lib/gzr/commands/plan/failures.rb +98 -0
- data/lib/gzr/commands/plan/import.rb +69 -0
- data/lib/gzr/commands/plan/ls.rb +102 -0
- data/lib/gzr/commands/plan/rm.rb +47 -0
- data/lib/gzr/commands/plan/run.rb +58 -0
- data/lib/gzr/commands/query.rb +49 -0
- data/lib/gzr/commands/query/runquery.rb +102 -0
- data/lib/gzr/commands/role.rb +163 -0
- data/lib/gzr/commands/role/cat.rb +52 -0
- data/lib/gzr/commands/role/group_add.rb +51 -0
- data/lib/gzr/commands/role/group_ls.rb +76 -0
- data/lib/gzr/commands/role/group_rm.rb +51 -0
- data/lib/gzr/commands/role/ls.rb +75 -0
- data/lib/gzr/commands/role/rm.rb +47 -0
- data/lib/gzr/commands/role/user_add.rb +51 -0
- data/lib/gzr/commands/role/user_ls.rb +76 -0
- data/lib/gzr/commands/role/user_rm.rb +51 -0
- data/lib/gzr/commands/space.rb +137 -0
- data/lib/gzr/commands/space/cat.rb +53 -0
- data/lib/gzr/commands/space/create.rb +50 -0
- data/lib/gzr/commands/space/export.rb +117 -0
- data/lib/gzr/commands/space/ls.rb +97 -0
- data/lib/gzr/commands/space/rm.rb +56 -0
- data/lib/gzr/commands/space/top.rb +62 -0
- data/lib/gzr/commands/space/tree.rb +79 -0
- data/lib/gzr/commands/subcommandbase.rb +41 -0
- data/lib/gzr/commands/user.rb +111 -0
- data/lib/gzr/commands/user/cat.rb +52 -0
- data/lib/gzr/commands/user/disable.rb +47 -0
- data/lib/gzr/commands/user/enable.rb +47 -0
- data/lib/gzr/commands/user/ls.rb +82 -0
- data/lib/gzr/commands/user/me.rb +66 -0
- data/lib/gzr/modules/connection.rb +52 -0
- data/lib/gzr/modules/dashboard.rb +215 -0
- data/lib/gzr/modules/filehelper.rb +81 -0
- data/lib/gzr/modules/group.rb +93 -0
- data/lib/gzr/modules/look.rb +162 -0
- data/lib/gzr/modules/model.rb +40 -0
- data/lib/gzr/modules/plan.rb +216 -0
- data/lib/gzr/modules/role.rb +128 -0
- data/lib/gzr/modules/session.rb +203 -0
- data/lib/gzr/modules/space.rb +160 -0
- data/lib/gzr/modules/user.rb +114 -0
- data/lib/gzr/templates/.gitkeep +1 -0
- data/lib/gzr/templates/connection/dialects/.gitkeep +1 -0
- data/lib/gzr/templates/connection/ls/.gitkeep +1 -0
- data/lib/gzr/templates/dashboard/cat/.gitkeep +1 -0
- data/lib/gzr/templates/dashboard/import/.gitkeep +1 -0
- data/lib/gzr/templates/dashboard/rm/.gitkeep +1 -0
- data/lib/gzr/templates/group/ls/.gitkeep +1 -0
- data/lib/gzr/templates/group/member_groups/.gitkeep +1 -0
- data/lib/gzr/templates/group/member_users/.gitkeep +1 -0
- data/lib/gzr/templates/look/cat/.gitkeep +1 -0
- data/lib/gzr/templates/look/import/.gitkeep +1 -0
- data/lib/gzr/templates/look/rm/.gitkeep +1 -0
- data/lib/gzr/templates/model/ls/.gitkeep +1 -0
- data/lib/gzr/templates/plan/cat/.gitkeep +1 -0
- data/lib/gzr/templates/plan/disable/.gitkeep +1 -0
- data/lib/gzr/templates/plan/enable/.gitkeep +1 -0
- data/lib/gzr/templates/plan/failures/.gitkeep +1 -0
- data/lib/gzr/templates/plan/import/.gitkeep +1 -0
- data/lib/gzr/templates/plan/ls/.gitkeep +1 -0
- data/lib/gzr/templates/plan/rm/.gitkeep +1 -0
- data/lib/gzr/templates/plan/run/.gitkeep +1 -0
- data/lib/gzr/templates/query/run/.gitkeep +1 -0
- data/lib/gzr/templates/role/cat/.gitkeep +1 -0
- data/lib/gzr/templates/role/group_add/.gitkeep +1 -0
- data/lib/gzr/templates/role/group_ls/.gitkeep +1 -0
- data/lib/gzr/templates/role/group_rm/.gitkeep +1 -0
- data/lib/gzr/templates/role/ls/.gitkeep +1 -0
- data/lib/gzr/templates/role/rm/.gitkeep +1 -0
- data/lib/gzr/templates/role/user_add/.gitkeep +1 -0
- data/lib/gzr/templates/role/user_ls/.gitkeep +1 -0
- data/lib/gzr/templates/role/user_rm/.gitkeep +1 -0
- data/lib/gzr/templates/space/cat/.gitkeep +1 -0
- data/lib/gzr/templates/space/create/.gitkeep +1 -0
- data/lib/gzr/templates/space/export/.gitkeep +1 -0
- data/lib/gzr/templates/space/ls/.gitkeep +1 -0
- data/lib/gzr/templates/space/rm/.gitkeep +1 -0
- data/lib/gzr/templates/space/top/.gitkeep +1 -0
- data/lib/gzr/templates/space/tree/.gitkeep +1 -0
- data/lib/gzr/templates/user/cat/.gitkeep +1 -0
- data/lib/gzr/templates/user/disable/.gitkeep +1 -0
- data/lib/gzr/templates/user/enable/.gitkeep +1 -0
- data/lib/gzr/templates/user/ls/.gitkeep +1 -0
- data/lib/gzr/templates/user/me/.gitkeep +1 -0
- data/lib/gzr/version.rb +24 -0
- metadata +325 -0
data/Rakefile
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# The MIT License (MIT)
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Mike DeAngelo Looker Data Sciences, Inc.
|
4
|
+
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
# this software and associated documentation files (the "Software"), to deal in
|
7
|
+
# the Software without restriction, including without limitation the rights to
|
8
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
# subject to the following conditions:
|
11
|
+
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# 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, FITNESS
|
17
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
require "bundler/gem_tasks"
|
23
|
+
require "rspec/core/rake_task"
|
24
|
+
|
25
|
+
RSpec::Core::RakeTask.new(:spec)
|
26
|
+
|
27
|
+
task :default => :spec
|
data/bin/console
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
# The MIT License (MIT)
|
4
|
+
|
5
|
+
# Copyright (c) 2018 Mike DeAngelo Looker Data Sciences, Inc.
|
6
|
+
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
8
|
+
# this software and associated documentation files (the "Software"), to deal in
|
9
|
+
# the Software without restriction, including without limitation the rights to
|
10
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
11
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
12
|
+
# 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, FITNESS
|
19
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
20
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
21
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
22
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
require "bundler/setup"
|
25
|
+
require "gzr"
|
26
|
+
|
27
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
28
|
+
# with your gem easier. You can also use a different console, if you like.
|
29
|
+
|
30
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
31
|
+
# require "pry"
|
32
|
+
# Pry.start
|
33
|
+
|
34
|
+
require "irb"
|
35
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
# The MIT License (MIT)
|
4
|
+
|
5
|
+
# Copyright (c) 2018 Mike DeAngelo Looker Data Sciences, Inc.
|
6
|
+
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
8
|
+
# this software and associated documentation files (the "Software"), to deal in
|
9
|
+
# the Software without restriction, including without limitation the rights to
|
10
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
11
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
12
|
+
# 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, FITNESS
|
19
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
20
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
21
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
22
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
set -euo pipefail
|
25
|
+
IFS=$'\n\t'
|
26
|
+
set -vx
|
27
|
+
|
28
|
+
bundle install
|
29
|
+
|
30
|
+
# Do any other automated setup that you need to do here
|
data/exe/gzr
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# The MIT License (MIT)
|
4
|
+
|
5
|
+
# Copyright (c) 2018 Mike DeAngelo Looker Data Sciences, Inc.
|
6
|
+
|
7
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
8
|
+
# this software and associated documentation files (the "Software"), to deal in
|
9
|
+
# the Software without restriction, including without limitation the rights to
|
10
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
11
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
12
|
+
# 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, FITNESS
|
19
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
20
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
21
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
22
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
24
|
+
# frozen_string_literal: true
|
25
|
+
|
26
|
+
lib_path = File.expand_path('../lib', __dir__)
|
27
|
+
$:.unshift(lib_path) if !$:.include?(lib_path)
|
28
|
+
require 'gzr/cli'
|
29
|
+
|
30
|
+
Signal.trap('INT') do
|
31
|
+
warn("\n#{caller.join("\n")}: interrupted")
|
32
|
+
exit(1)
|
33
|
+
end
|
34
|
+
|
35
|
+
begin
|
36
|
+
Gzr::CLI.start
|
37
|
+
rescue Gzr::CLI::Error => err
|
38
|
+
puts "ERROR: #{err.message}"
|
39
|
+
exit 1
|
40
|
+
end
|
data/gzr.gemspec
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# The MIT License (MIT)
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Mike DeAngelo Looker Data Sciences, Inc.
|
4
|
+
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
# this software and associated documentation files (the "Software"), to deal in
|
7
|
+
# the Software without restriction, including without limitation the rights to
|
8
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
# subject to the following conditions:
|
11
|
+
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# 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, FITNESS
|
17
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
lib = File.expand_path("../lib", __FILE__)
|
23
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
24
|
+
require "gzr/version"
|
25
|
+
|
26
|
+
Gem::Specification.new do |spec|
|
27
|
+
spec.name = "gazer"
|
28
|
+
spec.license = "MIT"
|
29
|
+
spec.version = Gzr::VERSION
|
30
|
+
spec.authors = ["Mike DeAngelo"]
|
31
|
+
spec.email = ["deangelo@looker.com"]
|
32
|
+
|
33
|
+
spec.summary = %q{Command line tool to manage the content of a Looker instance.}
|
34
|
+
spec.description = %q{Command line tool to manage the content of a Looker instance.}
|
35
|
+
spec.homepage = "https://github.com/deangelo-llooker/gzr"
|
36
|
+
|
37
|
+
spec.required_ruby_version = '>= 2.3.0'
|
38
|
+
|
39
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
40
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
41
|
+
if spec.respond_to?(:metadata)
|
42
|
+
#spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
|
43
|
+
else
|
44
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
45
|
+
"public gem pushes."
|
46
|
+
end
|
47
|
+
|
48
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
49
|
+
f.match(%r{^(test|spec|features)/})
|
50
|
+
end
|
51
|
+
spec.bindir = "exe"
|
52
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
53
|
+
spec.require_paths = ["lib"]
|
54
|
+
|
55
|
+
spec.add_dependency "tty-reader", "~> 0.3.0"
|
56
|
+
spec.add_dependency "tty-table", "~> 0.10.0"
|
57
|
+
spec.add_dependency "tty-tree", "~> 0.1.0"
|
58
|
+
spec.add_dependency "pastel", "~> 0.7.2"
|
59
|
+
spec.add_dependency "thor", "~> 0.20.0"
|
60
|
+
spec.add_dependency 'netrc', "~> 0.11.0"
|
61
|
+
spec.add_dependency 'looker-sdk', "~> 0.0.6"
|
62
|
+
|
63
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
64
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
65
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
66
|
+
spec.add_development_dependency "tty", "~> 0.8"
|
67
|
+
end
|
data/lib/gzr.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# The MIT License (MIT)
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Mike DeAngelo Looker Data Sciences, Inc.
|
4
|
+
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
# this software and associated documentation files (the "Software"), to deal in
|
7
|
+
# the Software without restriction, including without limitation the rights to
|
8
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
# subject to the following conditions:
|
11
|
+
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# 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, FITNESS
|
17
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
require "gzr/version"
|
23
|
+
|
24
|
+
module Gzr
|
25
|
+
end
|
data/lib/gzr/cli.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# The MIT License (MIT)
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Mike DeAngelo Looker Data Sciences, Inc.
|
4
|
+
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
# this software and associated documentation files (the "Software"), to deal in
|
7
|
+
# the Software without restriction, including without limitation the rights to
|
8
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
# subject to the following conditions:
|
11
|
+
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# 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, FITNESS
|
17
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
# frozen_string_literal: true
|
23
|
+
|
24
|
+
require 'thor'
|
25
|
+
|
26
|
+
module Gzr
|
27
|
+
# Handle the application command line parsing
|
28
|
+
# and the dispatch to various command objects
|
29
|
+
#
|
30
|
+
# @api public
|
31
|
+
class CLI < Thor
|
32
|
+
class_option :debug, type: :boolean, default: false, desc: 'Run in debug mode'
|
33
|
+
class_option :host, type: :string, default: 'localhost', desc: 'Looker Host'
|
34
|
+
class_option :port, type: :string, default: '19999', desc: 'Looker API Port'
|
35
|
+
class_option :client_id, type: :string, desc: 'API3 Client Id'
|
36
|
+
class_option :client_secret, type: :string, desc: 'API3 Client Secret'
|
37
|
+
class_option :api_version, type: :string, desc: 'Looker API Version'
|
38
|
+
class_option :ssl, type: :boolean, default: true, desc: 'Use ssl to communicate with host'
|
39
|
+
class_option :verify_ssl, type: :boolean, default: true, desc: 'Verify the SSL certificate of the host'
|
40
|
+
class_option :timeout, type: :numeric, default: 60, desc: 'Seconds to wait for a response from the server'
|
41
|
+
class_option :http_proxy, type: :string, desc: 'HTTP Proxy for connecting to Looker host'
|
42
|
+
class_option :force, type: :boolean, default: false, desc: 'Overwrite objects on server'
|
43
|
+
class_option :su, type: :string, desc: 'After connecting, change to user_id given'
|
44
|
+
|
45
|
+
|
46
|
+
# Error raised by this runner
|
47
|
+
Error = Class.new(StandardError)
|
48
|
+
|
49
|
+
desc 'version', 'gzr version'
|
50
|
+
def version
|
51
|
+
require_relative 'version'
|
52
|
+
puts "v#{Gzr::VERSION}"
|
53
|
+
end
|
54
|
+
map %w(--version -v) => :version
|
55
|
+
|
56
|
+
require_relative 'commands/query'
|
57
|
+
register Gzr::Commands::Query, 'query', 'query [SUBCOMMAND]', 'Commands to retrieve and run queries'
|
58
|
+
|
59
|
+
require_relative 'commands/role'
|
60
|
+
register Gzr::Commands::Role, 'role', 'role [SUBCOMMAND]', 'Commands pertaining to roles'
|
61
|
+
|
62
|
+
require_relative 'commands/plan'
|
63
|
+
register Gzr::Commands::Plan, 'plan', 'plan [SUBCOMMAND]', 'Commands pertaining to plans'
|
64
|
+
|
65
|
+
require_relative 'commands/group'
|
66
|
+
register Gzr::Commands::Group, 'group', 'group [SUBCOMMAND]', 'Commands pertaining to groups'
|
67
|
+
|
68
|
+
require_relative 'commands/model'
|
69
|
+
register Gzr::Commands::Model, 'model', 'model [SUBCOMMAND]', 'Commands pertaining to LookML Models'
|
70
|
+
|
71
|
+
require_relative 'commands/connection'
|
72
|
+
register Gzr::Commands::Connection, 'connection', 'connection [SUBCOMMAND]', 'Commands pertaining to database connections and dialects'
|
73
|
+
|
74
|
+
require_relative 'commands/user'
|
75
|
+
register Gzr::Commands::User, 'user', 'user [SUBCOMMAND]', 'Commands pertaining to users'
|
76
|
+
|
77
|
+
require_relative 'commands/dashboard'
|
78
|
+
register Gzr::Commands::Dashboard, 'dashboard', 'dashboard [SUBCOMMAND]', 'Commands pertaining to dashboards'
|
79
|
+
|
80
|
+
require_relative 'commands/look'
|
81
|
+
register Gzr::Commands::Look, 'look', 'look [SUBCOMMAND]', 'Commands pertaining to looks'
|
82
|
+
|
83
|
+
require_relative 'commands/space'
|
84
|
+
register Gzr::Commands::Space, 'space', 'space [SUBCOMMAND]', 'Commands pertaining to spaces'
|
85
|
+
end
|
86
|
+
end
|
data/lib/gzr/command.rb
ADDED
@@ -0,0 +1,251 @@
|
|
1
|
+
# The MIT License (MIT)
|
2
|
+
|
3
|
+
# Copyright (c) 2018 Mike DeAngelo Looker Data Sciences, Inc.
|
4
|
+
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
# this software and associated documentation files (the "Software"), to deal in
|
7
|
+
# the Software without restriction, including without limitation the rights to
|
8
|
+
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
# the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
# subject to the following conditions:
|
11
|
+
|
12
|
+
# The above copyright notice and this permission notice shall be included in all
|
13
|
+
# 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, FITNESS
|
17
|
+
# FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
21
|
+
|
22
|
+
# frozen_string_literal: true
|
23
|
+
|
24
|
+
require 'forwardable'
|
25
|
+
require 'tty-reader'
|
26
|
+
require 'netrc'
|
27
|
+
require 'looker-sdk'
|
28
|
+
|
29
|
+
require_relative 'modules/session'
|
30
|
+
|
31
|
+
module Gzr
|
32
|
+
class Command
|
33
|
+
extend Forwardable
|
34
|
+
include Gzr::Session
|
35
|
+
|
36
|
+
def initialize
|
37
|
+
@sdk = nil
|
38
|
+
@access_token_stack = Array.new
|
39
|
+
@options = Hash.new
|
40
|
+
end
|
41
|
+
|
42
|
+
def_delegators :command, :run
|
43
|
+
|
44
|
+
# Execute this command
|
45
|
+
#
|
46
|
+
# @api public
|
47
|
+
def execute(*)
|
48
|
+
raise(
|
49
|
+
NotImplementedError,
|
50
|
+
"#{self.class}##{__method__} must be implemented"
|
51
|
+
)
|
52
|
+
end
|
53
|
+
|
54
|
+
def query(query_id)
|
55
|
+
data = nil
|
56
|
+
begin
|
57
|
+
data = @sdk.query(query_id)
|
58
|
+
rescue LookerSDK::Error => e
|
59
|
+
say_error "Error querying query(#{query_id})"
|
60
|
+
say_error e.message
|
61
|
+
raise
|
62
|
+
end
|
63
|
+
data
|
64
|
+
end
|
65
|
+
|
66
|
+
def create_query(query)
|
67
|
+
begin
|
68
|
+
data = @sdk.create_query(query)
|
69
|
+
rescue LookerSDK::Error => e
|
70
|
+
say_error "Error creating query(#{JSON.pretty_generate(query)})"
|
71
|
+
say_error e.message
|
72
|
+
raise
|
73
|
+
end
|
74
|
+
data
|
75
|
+
end
|
76
|
+
|
77
|
+
def merge_query(merge_result_id)
|
78
|
+
data = nil
|
79
|
+
begin
|
80
|
+
data = @sdk.merge_query(merge_result_id)
|
81
|
+
rescue NoMethodError => nme
|
82
|
+
say_error "The api endpoint merge_query(#{merge_result_id}) is not implemented on this Looker instance"
|
83
|
+
rescue LookerSDK::Error => e
|
84
|
+
say_error "Error querying merge_query(#{merge_result_id})"
|
85
|
+
say_error e.message
|
86
|
+
raise
|
87
|
+
end
|
88
|
+
data
|
89
|
+
end
|
90
|
+
|
91
|
+
def create_merge_query(merge_query)
|
92
|
+
begin
|
93
|
+
data = @sdk.create_merge_query(merge_query)
|
94
|
+
rescue NoMethodError => nme
|
95
|
+
say_error "The api endpoint create_merge_query() is not implemented on this Looker instance"
|
96
|
+
raise
|
97
|
+
rescue LookerSDK::Error => e
|
98
|
+
say_error "Error creating merge_query(#{JSON.pretty_generate(merge_query)})"
|
99
|
+
say_error e.message
|
100
|
+
raise
|
101
|
+
end
|
102
|
+
data
|
103
|
+
end
|
104
|
+
|
105
|
+
def run_inline_query(query)
|
106
|
+
begin
|
107
|
+
data = @sdk.run_inline_query("json",query)
|
108
|
+
rescue LookerSDK::Error => e
|
109
|
+
say_error "Error running inline_query(#{JSON.pretty_generate(query)})"
|
110
|
+
say_error e.message
|
111
|
+
raise
|
112
|
+
end
|
113
|
+
data
|
114
|
+
end
|
115
|
+
|
116
|
+
|
117
|
+
##
|
118
|
+
# This method accepts the name of an sdk operation, then finds the parameter for that
|
119
|
+
# operation in the data structures from the swagger.json file. The parameter is a
|
120
|
+
# json object. Some of the attributes of the json object are read-only, and some
|
121
|
+
# are read-write. A few are write-only. The list of read-write and write-only attribute
|
122
|
+
# names are returned as an array. That array can be used to take the json document that
|
123
|
+
# describes an object and strip out the read-only values, creating a document that can
|
124
|
+
# be used to create or update an object.
|
125
|
+
#
|
126
|
+
# The pattern typically looks like this...
|
127
|
+
#
|
128
|
+
# new_obj_hash = existing_obj_hash.select do |k,v|
|
129
|
+
# keys_to_keep('create_new_obj').include? k
|
130
|
+
# end
|
131
|
+
|
132
|
+
def keys_to_keep(operation)
|
133
|
+
o = @sdk.operations[operation]
|
134
|
+
begin
|
135
|
+
say_error "Operation #{operation} not found"
|
136
|
+
return []
|
137
|
+
end unless o
|
138
|
+
|
139
|
+
parameters = o[:info][:parameters].select { |p| p[:in] == "body" && p[:schema] }
|
140
|
+
|
141
|
+
say_warning "Expecting exactly one body parameter with a schema for operation #{operation}" unless parameters.length == 1
|
142
|
+
schema_ref = parameters[0][:schema][:$ref].split(/\//)
|
143
|
+
return @sdk.swagger[schema_ref[1].to_sym][schema_ref[2].to_sym][:properties].reject { |k,v| v[:readOnly] }.keys
|
144
|
+
end
|
145
|
+
|
146
|
+
##
|
147
|
+
# The tty-table gem is normally used to output tabular data. This method accepts a Table
|
148
|
+
# object as used by the tty-table gem, and generates CSV output. It returns a string
|
149
|
+
# with crlf encoding
|
150
|
+
|
151
|
+
def render_csv(t)
|
152
|
+
io = StringIO.new
|
153
|
+
io.puts (
|
154
|
+
t.header.collect do |v|
|
155
|
+
v ? "\"#{v.to_s.gsub(/"/, '""')}\"" : ""
|
156
|
+
end.join(',')
|
157
|
+
) unless @options[:plain]
|
158
|
+
t.each do |row|
|
159
|
+
next if row === t.header
|
160
|
+
io.puts (
|
161
|
+
row.collect do |v|
|
162
|
+
v ? "\"#{v.to_s.gsub(/"/, '""')}\"" : ""
|
163
|
+
end.join(',')
|
164
|
+
)
|
165
|
+
end
|
166
|
+
io.rewind
|
167
|
+
io.gets(nil).encode(crlf_newline: true)
|
168
|
+
end
|
169
|
+
|
170
|
+
##
|
171
|
+
# This method accepts a string containing a list of fields. The fields can be nested
|
172
|
+
# in a format like...
|
173
|
+
#
|
174
|
+
# 'a,b,c(d,e(f,g)),h'
|
175
|
+
#
|
176
|
+
# representing a structure like
|
177
|
+
#
|
178
|
+
# {
|
179
|
+
# a: "val",
|
180
|
+
# b: "val",
|
181
|
+
# c: {
|
182
|
+
# d: "val",
|
183
|
+
# e: {
|
184
|
+
# f: "val",
|
185
|
+
# g: "val"
|
186
|
+
# }
|
187
|
+
# },
|
188
|
+
# h: "val"
|
189
|
+
# }
|
190
|
+
#
|
191
|
+
# That string will get parsed and yield an array like
|
192
|
+
# [ a, b, c.d, c.e.f, c.e.g, h ]
|
193
|
+
#
|
194
|
+
|
195
|
+
def field_names(opt_fields)
|
196
|
+
fields = []
|
197
|
+
token_stack = []
|
198
|
+
last_token = false
|
199
|
+
tokens = opt_fields.split /(\(|,|\))/
|
200
|
+
tokens << nil
|
201
|
+
tokens.each do |t|
|
202
|
+
if t.nil? then
|
203
|
+
fields << (token_stack + [last_token]).join('.') if last_token
|
204
|
+
elsif t.empty? then
|
205
|
+
next
|
206
|
+
elsif t == ',' then
|
207
|
+
fields << (token_stack + [last_token]).join('.') if last_token
|
208
|
+
elsif t == '(' then
|
209
|
+
token_stack.push(last_token)
|
210
|
+
elsif t == ')' then
|
211
|
+
fields << (token_stack + [last_token]).join('.') if last_token
|
212
|
+
token_stack.pop
|
213
|
+
last_token = false
|
214
|
+
else
|
215
|
+
last_token = t
|
216
|
+
end
|
217
|
+
end
|
218
|
+
fields
|
219
|
+
end
|
220
|
+
|
221
|
+
##
|
222
|
+
# This method will accept a field name in a format like 'c.e.g'
|
223
|
+
# and convert it into 'c&.e&.g', which can be evaluated to get
|
224
|
+
# the value of g, or nil if any intermediate value is nil.
|
225
|
+
|
226
|
+
def field_expression(name)
|
227
|
+
parts = name.split(/\./)
|
228
|
+
parts.join('&.')
|
229
|
+
end
|
230
|
+
|
231
|
+
##
|
232
|
+
# This method will accept two arrays, a and b, and create a third array
|
233
|
+
# like [ [a[0],b[0]], [a[1],b[1]], [a[2],b[2]], ...].
|
234
|
+
# If either array is longer than the other, additional pairs
|
235
|
+
# will be generated with the shorter array padded out with nil values.
|
236
|
+
#
|
237
|
+
# Any additional args will be added to each inner array.
|
238
|
+
|
239
|
+
def pairs(a, b, *args)
|
240
|
+
pair_array = Array.new([a.count,b.count].max) do |i|
|
241
|
+
pair = [a.fetch(i,nil),b.fetch(i,nil)]
|
242
|
+
pair += args if args
|
243
|
+
pair
|
244
|
+
end
|
245
|
+
|
246
|
+
return pair_array unless block_given?
|
247
|
+
|
248
|
+
pair_array.collect { |e| yield(e) }
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|