gazer 0.2.9
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 +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
|