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
@@ -0,0 +1 @@
|
|
1
|
+
#
|
@@ -0,0 +1,69 @@
|
|
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_relative 'subcommandbase'
|
25
|
+
|
26
|
+
module Gzr
|
27
|
+
module Commands
|
28
|
+
class Connection < SubCommandBase
|
29
|
+
|
30
|
+
namespace :connection
|
31
|
+
|
32
|
+
desc 'dialects', 'List all available dialects'
|
33
|
+
method_option :help, aliases: '-h', type: :boolean,
|
34
|
+
desc: 'Display usage information'
|
35
|
+
method_option :fields, type: :string, default: 'name,label',
|
36
|
+
desc: 'Fields to display'
|
37
|
+
method_option :plain, type: :boolean, default: false,
|
38
|
+
desc: 'print without any extra formatting'
|
39
|
+
method_option :csv, type: :boolean, default: false,
|
40
|
+
desc: 'output in csv format per RFC4180'
|
41
|
+
def dialects(*)
|
42
|
+
if options[:help]
|
43
|
+
invoke :help, ['dialects']
|
44
|
+
else
|
45
|
+
require_relative 'connection/dialects'
|
46
|
+
Gzr::Commands::Connection::Dialects.new(options).execute
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
desc 'ls', 'List all available connections'
|
51
|
+
method_option :help, aliases: '-h', type: :boolean,
|
52
|
+
desc: 'Display usage information'
|
53
|
+
method_option :fields, type: :string, default: 'name,dialect(name),host,port,database,schema',
|
54
|
+
desc: 'Fields to display'
|
55
|
+
method_option :plain, type: :boolean, default: false,
|
56
|
+
desc: 'print without any extra formatting'
|
57
|
+
method_option :csv, type: :boolean, default: false,
|
58
|
+
desc: 'output in csv format per RFC4180'
|
59
|
+
def ls(*)
|
60
|
+
if options[:help]
|
61
|
+
invoke :help, ['ls']
|
62
|
+
else
|
63
|
+
require_relative 'connection/ls'
|
64
|
+
Gzr::Commands::Connection::Ls.new(options).execute
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,72 @@
|
|
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_relative '../../command'
|
25
|
+
require_relative '../../modules/connection'
|
26
|
+
require 'tty-table'
|
27
|
+
|
28
|
+
module Gzr
|
29
|
+
module Commands
|
30
|
+
class Connection
|
31
|
+
class Dialects < Gzr::Command
|
32
|
+
include Gzr::Connection
|
33
|
+
def initialize(options)
|
34
|
+
super()
|
35
|
+
@options = options
|
36
|
+
end
|
37
|
+
|
38
|
+
def execute(input: $stdin, output: $stdout)
|
39
|
+
say_warning(@options) if @options[:debug]
|
40
|
+
with_session do
|
41
|
+
data = query_all_dialects(@options[:fields])
|
42
|
+
begin
|
43
|
+
say_ok "No dialects found"
|
44
|
+
return nil
|
45
|
+
end unless data && data.length > 0
|
46
|
+
|
47
|
+
table_hash = Hash.new
|
48
|
+
fields = field_names(@options[:fields])
|
49
|
+
table_hash[:header] = data[0].to_attrs.keys unless @options[:plain]
|
50
|
+
expressions = fields.collect { |fn| field_expression(fn) }
|
51
|
+
table_hash[:rows] = data.map do |row|
|
52
|
+
expressions.collect do |e|
|
53
|
+
eval "row.#{e}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
table = TTY::Table.new(table_hash)
|
57
|
+
alignments = fields.collect do |k|
|
58
|
+
(k =~ /id$/) ? :right : :left
|
59
|
+
end
|
60
|
+
begin
|
61
|
+
if @options[:csv] then
|
62
|
+
output.puts render_csv(table)
|
63
|
+
else
|
64
|
+
output.puts table.render(if @options[:plain] then :basic else :ascii end, alignments: alignments)
|
65
|
+
end
|
66
|
+
end if table
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,72 @@
|
|
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_relative '../../command'
|
25
|
+
require_relative '../../modules/connection'
|
26
|
+
require 'tty-table'
|
27
|
+
|
28
|
+
module Gzr
|
29
|
+
module Commands
|
30
|
+
class Connection
|
31
|
+
class Ls < Gzr::Command
|
32
|
+
include Gzr::Connection
|
33
|
+
def initialize(options)
|
34
|
+
super()
|
35
|
+
@options = options
|
36
|
+
end
|
37
|
+
|
38
|
+
def execute(input: $stdin, output: $stdout)
|
39
|
+
say_warning(@options) if @options[:debug]
|
40
|
+
with_session do
|
41
|
+
data = query_all_connections(@options[:fields])
|
42
|
+
begin
|
43
|
+
say_ok "No connections found"
|
44
|
+
return nil
|
45
|
+
end unless data && data.length > 0
|
46
|
+
|
47
|
+
table_hash = Hash.new
|
48
|
+
fields = field_names(@options[:fields])
|
49
|
+
table_hash[:header] = fields unless @options[:plain]
|
50
|
+
expressions = fields.collect { |fn| field_expression(fn) }
|
51
|
+
table_hash[:rows] = data.map do |row|
|
52
|
+
expressions.collect do |e|
|
53
|
+
eval "row.#{e}"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
table = TTY::Table.new(table_hash)
|
57
|
+
alignments = fields.collect do |k|
|
58
|
+
(k =~ /id$/) ? :right : :left
|
59
|
+
end
|
60
|
+
begin
|
61
|
+
if @options[:csv] then
|
62
|
+
output.puts render_csv(table)
|
63
|
+
else
|
64
|
+
output.puts table.render(if @options[:plain] then :basic else :ascii end, alignments: alignments, width: 1024)
|
65
|
+
end
|
66
|
+
end if table
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,75 @@
|
|
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_relative 'subcommandbase'
|
25
|
+
|
26
|
+
module Gzr
|
27
|
+
module Commands
|
28
|
+
class Dashboard < SubCommandBase
|
29
|
+
|
30
|
+
namespace :dashboard
|
31
|
+
|
32
|
+
desc 'cat DASHBOARD_ID', 'Output the JSON representation of a dashboard to the screen or a file'
|
33
|
+
method_option :help, aliases: '-h', type: :boolean,
|
34
|
+
desc: 'Display usage information'
|
35
|
+
method_option :dir, type: :string,
|
36
|
+
desc: 'Directory to store output file'
|
37
|
+
method_option :plans, type: :boolean,
|
38
|
+
desc: 'Include scheduled plans'
|
39
|
+
def cat(dashboard_id)
|
40
|
+
if options[:help]
|
41
|
+
invoke :help, ['cat']
|
42
|
+
else
|
43
|
+
require_relative 'dashboard/cat'
|
44
|
+
Gzr::Commands::Dashboard::Cat.new(dashboard_id, options).execute
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
desc 'import FILE DEST_SPACE_ID', 'Import a dashboard from a file'
|
49
|
+
method_option :help, aliases: '-h', type: :boolean,
|
50
|
+
desc: 'Display usage information'
|
51
|
+
method_option :plain, type: :boolean,
|
52
|
+
desc: 'Provide minimal response information'
|
53
|
+
def import(file,dest_space_id)
|
54
|
+
if options[:help]
|
55
|
+
invoke :help, ['import']
|
56
|
+
else
|
57
|
+
require_relative 'dashboard/import'
|
58
|
+
Gzr::Commands::Dashboard::Import.new(file, dest_space_id, options).execute
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
desc 'rm DASHBOARD_ID', 'Remove or delete the given dashboard'
|
63
|
+
method_option :help, aliases: '-h', type: :boolean,
|
64
|
+
desc: 'Display usage information'
|
65
|
+
def rm(id)
|
66
|
+
if options[:help]
|
67
|
+
invoke :help, ['rm']
|
68
|
+
else
|
69
|
+
require_relative 'dashboard/rm'
|
70
|
+
Gzr::Commands::Dashboard::Rm.new(id, options).execute
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -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
|
+
# frozen_string_literal: true
|
23
|
+
|
24
|
+
require 'json'
|
25
|
+
require_relative '../../command'
|
26
|
+
require_relative '../../modules/dashboard'
|
27
|
+
require_relative '../../modules/plan'
|
28
|
+
require_relative '../../modules/filehelper'
|
29
|
+
|
30
|
+
module Gzr
|
31
|
+
module Commands
|
32
|
+
class Dashboard
|
33
|
+
class Cat < Gzr::Command
|
34
|
+
include Gzr::Dashboard
|
35
|
+
include Gzr::FileHelper
|
36
|
+
include Gzr::Plan
|
37
|
+
def initialize(dashboard_id,options)
|
38
|
+
super()
|
39
|
+
@dashboard_id = dashboard_id
|
40
|
+
@options = options
|
41
|
+
end
|
42
|
+
|
43
|
+
def execute(*args, input: $stdin, output: $stdout)
|
44
|
+
say_warning("options: #{@options.inspect}") if @options[:debug]
|
45
|
+
with_session("3.1") do
|
46
|
+
data = query_dashboard(@dashboard_id)
|
47
|
+
data.to_attrs()[:dashboard_elements].each_index do |i|
|
48
|
+
element = data[:dashboard_elements][i]
|
49
|
+
if element[:merge_result_id]
|
50
|
+
merge_result = merge_query(element[:merge_result_id])
|
51
|
+
merge_result[:source_queries].each_index do |j|
|
52
|
+
source_query = merge_result[:source_queries][j]
|
53
|
+
merge_result[:source_queries][j][:query] = query(source_query[:query_id])
|
54
|
+
end
|
55
|
+
data[:dashboard_elements][i][:merge_result] = merge_result
|
56
|
+
end
|
57
|
+
end
|
58
|
+
data[:scheduled_plans] = query_scheduled_plans_for_dashboard(@dashboard_id,"all") if @options[:plans]
|
59
|
+
write_file(@options[:dir] ? "Dashboard_#{data.id}_#{data.title}.json" : nil, @options[:dir], nil, output) do |f|
|
60
|
+
f.puts JSON.pretty_generate(data.to_attrs)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,256 @@
|
|
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_relative '../../../gzr'
|
25
|
+
require_relative '../../command'
|
26
|
+
require_relative '../../modules/dashboard'
|
27
|
+
require_relative '../../modules/look'
|
28
|
+
require_relative '../../modules/user'
|
29
|
+
require_relative '../../modules/plan'
|
30
|
+
require_relative '../../modules/filehelper'
|
31
|
+
|
32
|
+
module Gzr
|
33
|
+
module Commands
|
34
|
+
class Dashboard
|
35
|
+
class Import < Gzr::Command
|
36
|
+
include Gzr::Dashboard
|
37
|
+
include Gzr::Look
|
38
|
+
include Gzr::User
|
39
|
+
include Gzr::Plan
|
40
|
+
include Gzr::FileHelper
|
41
|
+
def initialize(file, dest_space_id, options)
|
42
|
+
super()
|
43
|
+
@file = file
|
44
|
+
@dest_space_id = dest_space_id
|
45
|
+
@options = options
|
46
|
+
end
|
47
|
+
|
48
|
+
def execute(input: $stdin, output: $stdout)
|
49
|
+
say_warning("options: #{@options.inspect}") if @options[:debug]
|
50
|
+
with_session("3.1") do
|
51
|
+
|
52
|
+
@me ||= query_me("id")
|
53
|
+
|
54
|
+
read_file(@file) do |data|
|
55
|
+
|
56
|
+
dashboard = sync_dashboard(data,@dest_space_id)
|
57
|
+
|
58
|
+
source_filters = data[:dashboard_filters].sort { |a,b| a[:row] <=> b[:row] }
|
59
|
+
existing_filters = dashboard.dashboard_filters.sort { |a,b| a.row <=> b.row }
|
60
|
+
existing_filters.collect! do |e|
|
61
|
+
matches_by_name_title = source_filters.select { |s| s[:row] != e.row && (s[:title] == e.title || s[:name] == e.name) }
|
62
|
+
if matches_by_name_title.length > 0
|
63
|
+
delete_dashboard_filter(e.id)
|
64
|
+
nil
|
65
|
+
else
|
66
|
+
e
|
67
|
+
end
|
68
|
+
end
|
69
|
+
pairs(source_filters,existing_filters,dashboard.id) do |source,target,id|
|
70
|
+
say_warning "Synching dashboard filter for dashboard #{id}" if @options[:debug]
|
71
|
+
sync_dashboard_filter(source,target,id)
|
72
|
+
end
|
73
|
+
|
74
|
+
elem_table = pairs(data[:dashboard_elements],dashboard.dashboard_elements,dashboard.id) do |source,target,id|
|
75
|
+
sync_dashboard_element(source,target,id)
|
76
|
+
end
|
77
|
+
|
78
|
+
source_dashboard_layouts = data[:dashboard_layouts].sort_by { |v| (v[:active] ? 0 : 1) }
|
79
|
+
existing_dashboard_layouts = dashboard.dashboard_layouts.sort_by { |v| (v.active ? 0 : 1) }
|
80
|
+
pairs(source_dashboard_layouts,existing_dashboard_layouts) do |s,t|
|
81
|
+
sync_dashboard_layout(dashboard.id,s,t) do |s,t|
|
82
|
+
sync_dashboard_layout_component(s,t,elem_table)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
upsert_plans_for_dashboard(dashboard.id,@me.id,data[:scheduled_plans]) if data[:scheduled_plans]
|
86
|
+
output.puts "Imported dashboard #{dashboard.id}" unless @options[:plain]
|
87
|
+
output.puts dashboard.id if @options[:plain]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def sync_dashboard(source,target_space_id)
|
93
|
+
existing_dashboard = search_dashboards_by_title(source[:title], target_space_id).fetch(0,nil)
|
94
|
+
slug_used = search_dashboards_by_slug(source[:slug]).fetch(0,nil) if source[:slug]
|
95
|
+
|
96
|
+
if slug_used then
|
97
|
+
if existing_dashboard then
|
98
|
+
if !(existing_dashboard.space_id == slug_used.space_id && existing_dashboard.title == slug_used.title) then
|
99
|
+
say_warning "slug #{slug_used.slug} already used for dashboard #{slug_used.title} in space #{slug_used.space_id}"
|
100
|
+
say_warning "dashboard will be imported with new slug"
|
101
|
+
end
|
102
|
+
else
|
103
|
+
say_warning "slug #{slug_used.slug} already used for dashboard #{slug_used.title} in space #{slug_used.space_id}"
|
104
|
+
say_warning "dashboard will be imported with new slug"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
if existing_dashboard then
|
109
|
+
if @options[:force] then
|
110
|
+
say_ok "Modifying existing dashboard #{existing_dashboard.id} #{existing_dashboard[:title]} in space #{target_space_id}"
|
111
|
+
new_dash = source.select do |k,v|
|
112
|
+
(keys_to_keep('update_dashboard') - [:space_id,:user_id,:title,:slug]).include? k
|
113
|
+
end
|
114
|
+
new_dash[:slug] = source[:slug] unless slug_used
|
115
|
+
return update_dashboard(existing_dashboard.id,new_dash)
|
116
|
+
else
|
117
|
+
raise Gzr::CLI::Error, "Dashboard #{source[:title]} already exists in space #{target_space_id}\nUse --force if you want to overwrite it"
|
118
|
+
end
|
119
|
+
else
|
120
|
+
new_dash = source.select do |k,v|
|
121
|
+
(keys_to_keep('create_dashboard') - [:space_id,:user_id,:slug]).include? k
|
122
|
+
end
|
123
|
+
new_dash[:slug] = source[:slug] unless slug_used
|
124
|
+
new_dash[:space_id] = target_space_id
|
125
|
+
new_dash[:user_id] = @me.id
|
126
|
+
return create_dashboard(new_dash)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def sync_dashboard_filter(new_filter,existing_filter,dashboard_id)
|
131
|
+
if new_filter && !existing_filter then
|
132
|
+
filter = new_filter.select do |k,v|
|
133
|
+
(keys_to_keep('create_dashboard_filter') + [:row]).include? k
|
134
|
+
end
|
135
|
+
filter[:dashboard_id] = dashboard_id
|
136
|
+
say_warning "Creating filter" if @options[:debug]
|
137
|
+
return create_dashboard_filter(filter)
|
138
|
+
end
|
139
|
+
if existing_filter && new_filter then
|
140
|
+
filter = new_filter.select do |k,v|
|
141
|
+
(keys_to_keep('update_dashboard_filter') + [:row]).include? k
|
142
|
+
end
|
143
|
+
say_warning "Updating filter #{existing_filter.id}" if @options[:debug]
|
144
|
+
return update_dashboard_filter(existing_filter.id,filter)
|
145
|
+
end
|
146
|
+
say_warning "Deleting filter #{existing_filter.id}" if @options[:debug]
|
147
|
+
return delete_dashboard_filter(existing_filter.id)
|
148
|
+
end
|
149
|
+
|
150
|
+
def copy_result_maker_filterables(new_element)
|
151
|
+
return nil unless new_element[:result_maker]
|
152
|
+
if new_element[:result_maker].fetch(:filterables,[]).length > 0
|
153
|
+
result_maker = { :filterables => [] }
|
154
|
+
new_element[:result_maker][:filterables].each do |filterable|
|
155
|
+
result_maker[:filterables] << filterable.select do |k,v|
|
156
|
+
true unless [:can].include? k
|
157
|
+
end
|
158
|
+
end
|
159
|
+
return result_maker
|
160
|
+
end
|
161
|
+
nil
|
162
|
+
end
|
163
|
+
|
164
|
+
def sync_dashboard_element(new_element,existing_element,dashboard_id)
|
165
|
+
if new_element && !existing_element then
|
166
|
+
element = new_element.select do |k,v|
|
167
|
+
(keys_to_keep('create_dashboard_element') - [:dashboard_id, :look_id, :query_id, :merge_result_id]).include? k
|
168
|
+
end
|
169
|
+
(element[:query_id],element[:look_id],element[:merge_result_id]) = process_dashboard_element(new_element)
|
170
|
+
say_warning "Creating dashboard element #{element.inspect}" if @options[:debug]
|
171
|
+
element[:dashboard_id] = dashboard_id
|
172
|
+
result_maker = copy_result_maker_filterables(new_element)
|
173
|
+
element[:result_maker] = result_maker if result_maker
|
174
|
+
return [new_element[:id], create_dashboard_element(element).id]
|
175
|
+
end
|
176
|
+
if existing_element && new_element then
|
177
|
+
element = keys_to_keep('update_dashboard_element').collect do |e|
|
178
|
+
[e,nil]
|
179
|
+
end.to_h
|
180
|
+
|
181
|
+
element.merge!( new_element.select do |k,v|
|
182
|
+
(keys_to_keep('update_dashboard_element') - [:dashboard_id, :look_id, :query_id, :merge_result_id]).include? k
|
183
|
+
end
|
184
|
+
)
|
185
|
+
(element[:query_id],element[:look_id],element[:merge_result_id]) = process_dashboard_element(new_element)
|
186
|
+
say_warning "Updating dashboard element #{existing_element.id}" if @options[:debug]
|
187
|
+
result_maker = copy_result_maker_filterables(new_element)
|
188
|
+
element[:result_maker] = result_maker if result_maker
|
189
|
+
return [new_element[:id], update_dashboard_element(existing_element.id,element).id]
|
190
|
+
end
|
191
|
+
say_warning "Deleting dashboard element #{existing_element.id}" if @options[:debug]
|
192
|
+
delete_dashboard_element(existing_element.id)
|
193
|
+
return [nil,existing_element.id]
|
194
|
+
end
|
195
|
+
|
196
|
+
def process_dashboard_element(dash_elem)
|
197
|
+
return [create_fetch_query(dash_elem[:query]).id, nil, nil] if dash_elem[:query]
|
198
|
+
return [nil, upsert_look(@me.id, create_fetch_query(dash_elem[:look][:query]).id, @dest_space_id, dash_elem[:look]).id, nil] if dash_elem[:look]
|
199
|
+
return [nil,nil,create_merge_result(dash_elem[:merge_result]).id] if dash_elem[:merge_result]
|
200
|
+
[nil,nil,nil]
|
201
|
+
end
|
202
|
+
|
203
|
+
def sync_dashboard_layout(dashboard_id,new_layout,existing_layout)
|
204
|
+
layout_obj = nil
|
205
|
+
if new_layout && !existing_layout then
|
206
|
+
layout = new_layout.select do |k,v|
|
207
|
+
(keys_to_keep('create_dashboard_layout') - [:dashboard_id]).include? k
|
208
|
+
end
|
209
|
+
layout[:dashboard_id] = dashboard_id
|
210
|
+
say_warning "Creating dashboard layout #{layout}" if @options[:debug]
|
211
|
+
layout_obj = create_dashboard_layout(layout)
|
212
|
+
end
|
213
|
+
if new_layout && existing_layout then
|
214
|
+
layout = new_layout.select do |k,v|
|
215
|
+
(keys_to_keep('update_dashboard_layout') - [:dashboard_id]).include? k
|
216
|
+
end
|
217
|
+
say_warning "Updating dashboard layout #{existing_layout.id}" if @options[:debug]
|
218
|
+
layout_obj = update_dashboard_layout(existing_layout.id,layout)
|
219
|
+
end
|
220
|
+
if !new_layout && existing_layout then
|
221
|
+
say_warning "Deleting dashboard layout #{existing_layout.id}" if @options[:debug]
|
222
|
+
delete_dashboard_layout(existing_layout.id)
|
223
|
+
end
|
224
|
+
|
225
|
+
return unless layout_obj
|
226
|
+
|
227
|
+
#say_warning "new_layout[:active] is #{new_layout&.fetch(:active)} for #{layout_obj.id}"
|
228
|
+
#if layout_obj && new_layout&.fetch(:active,false)
|
229
|
+
# say_warning "Setting layout #{layout_obj.id} active"
|
230
|
+
# update_dashboard_layout(layout_obj.id, { :active => true })
|
231
|
+
#end
|
232
|
+
|
233
|
+
layout_components = new_layout[:dashboard_layout_components].zip(layout_obj.dashboard_layout_components)
|
234
|
+
return layout_components unless block_given?
|
235
|
+
|
236
|
+
layout_components.each { |s,t| yield(s,t) }
|
237
|
+
end
|
238
|
+
|
239
|
+
def sync_dashboard_layout_component(source, target, elem_table)
|
240
|
+
component = keys_to_keep('update_dashboard_layout_component').collect do |e|
|
241
|
+
[e,nil]
|
242
|
+
end.to_h
|
243
|
+
component[:dashboard_layout_id] = target.dashboard_layout_id
|
244
|
+
|
245
|
+
component.merge!(source.select do |k,v|
|
246
|
+
(keys_to_keep('update_dashboard_layout_component') - [:id,:dashboard_layout_id]).include? k
|
247
|
+
end)
|
248
|
+
|
249
|
+
component[:dashboard_element_id] = elem_table.assoc(source[:dashboard_element_id])[1]
|
250
|
+
say_warning "Updating dashboard layout component #{target.id}" if @options[:debug]
|
251
|
+
update_dashboard_layout_component(target.id,component)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
end
|
256
|
+
end
|