gazer 0.2.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.rspec +3 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +5 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +35 -0
  8. data/Gemfile.lock +150 -0
  9. data/LICENSE.txt +20 -0
  10. data/README.md +527 -0
  11. data/Rakefile +27 -0
  12. data/bin/console +35 -0
  13. data/bin/setup +30 -0
  14. data/exe/gzr +40 -0
  15. data/gzr.gemspec +67 -0
  16. data/lib/gzr.rb +25 -0
  17. data/lib/gzr/cli.rb +86 -0
  18. data/lib/gzr/command.rb +251 -0
  19. data/lib/gzr/commands/.gitkeep +1 -0
  20. data/lib/gzr/commands/connection.rb +69 -0
  21. data/lib/gzr/commands/connection/dialects.rb +72 -0
  22. data/lib/gzr/commands/connection/ls.rb +72 -0
  23. data/lib/gzr/commands/dashboard.rb +75 -0
  24. data/lib/gzr/commands/dashboard/cat.rb +67 -0
  25. data/lib/gzr/commands/dashboard/import.rb +256 -0
  26. data/lib/gzr/commands/dashboard/rm.rb +47 -0
  27. data/lib/gzr/commands/group.rb +87 -0
  28. data/lib/gzr/commands/group/ls.rb +73 -0
  29. data/lib/gzr/commands/group/member_groups.rb +74 -0
  30. data/lib/gzr/commands/group/member_users.rb +74 -0
  31. data/lib/gzr/commands/look.rb +75 -0
  32. data/lib/gzr/commands/look/cat.rb +55 -0
  33. data/lib/gzr/commands/look/import.rb +62 -0
  34. data/lib/gzr/commands/look/rm.rb +47 -0
  35. data/lib/gzr/commands/model.rb +51 -0
  36. data/lib/gzr/commands/model/ls.rb +72 -0
  37. data/lib/gzr/commands/plan.rb +149 -0
  38. data/lib/gzr/commands/plan/cat.rb +52 -0
  39. data/lib/gzr/commands/plan/disable.rb +49 -0
  40. data/lib/gzr/commands/plan/enable.rb +49 -0
  41. data/lib/gzr/commands/plan/failures.rb +98 -0
  42. data/lib/gzr/commands/plan/import.rb +69 -0
  43. data/lib/gzr/commands/plan/ls.rb +102 -0
  44. data/lib/gzr/commands/plan/rm.rb +47 -0
  45. data/lib/gzr/commands/plan/run.rb +58 -0
  46. data/lib/gzr/commands/query.rb +49 -0
  47. data/lib/gzr/commands/query/runquery.rb +102 -0
  48. data/lib/gzr/commands/role.rb +163 -0
  49. data/lib/gzr/commands/role/cat.rb +52 -0
  50. data/lib/gzr/commands/role/group_add.rb +51 -0
  51. data/lib/gzr/commands/role/group_ls.rb +76 -0
  52. data/lib/gzr/commands/role/group_rm.rb +51 -0
  53. data/lib/gzr/commands/role/ls.rb +75 -0
  54. data/lib/gzr/commands/role/rm.rb +47 -0
  55. data/lib/gzr/commands/role/user_add.rb +51 -0
  56. data/lib/gzr/commands/role/user_ls.rb +76 -0
  57. data/lib/gzr/commands/role/user_rm.rb +51 -0
  58. data/lib/gzr/commands/space.rb +137 -0
  59. data/lib/gzr/commands/space/cat.rb +53 -0
  60. data/lib/gzr/commands/space/create.rb +50 -0
  61. data/lib/gzr/commands/space/export.rb +117 -0
  62. data/lib/gzr/commands/space/ls.rb +97 -0
  63. data/lib/gzr/commands/space/rm.rb +56 -0
  64. data/lib/gzr/commands/space/top.rb +62 -0
  65. data/lib/gzr/commands/space/tree.rb +79 -0
  66. data/lib/gzr/commands/subcommandbase.rb +41 -0
  67. data/lib/gzr/commands/user.rb +111 -0
  68. data/lib/gzr/commands/user/cat.rb +52 -0
  69. data/lib/gzr/commands/user/disable.rb +47 -0
  70. data/lib/gzr/commands/user/enable.rb +47 -0
  71. data/lib/gzr/commands/user/ls.rb +82 -0
  72. data/lib/gzr/commands/user/me.rb +66 -0
  73. data/lib/gzr/modules/connection.rb +52 -0
  74. data/lib/gzr/modules/dashboard.rb +215 -0
  75. data/lib/gzr/modules/filehelper.rb +81 -0
  76. data/lib/gzr/modules/group.rb +93 -0
  77. data/lib/gzr/modules/look.rb +162 -0
  78. data/lib/gzr/modules/model.rb +40 -0
  79. data/lib/gzr/modules/plan.rb +216 -0
  80. data/lib/gzr/modules/role.rb +128 -0
  81. data/lib/gzr/modules/session.rb +203 -0
  82. data/lib/gzr/modules/space.rb +160 -0
  83. data/lib/gzr/modules/user.rb +114 -0
  84. data/lib/gzr/templates/.gitkeep +1 -0
  85. data/lib/gzr/templates/connection/dialects/.gitkeep +1 -0
  86. data/lib/gzr/templates/connection/ls/.gitkeep +1 -0
  87. data/lib/gzr/templates/dashboard/cat/.gitkeep +1 -0
  88. data/lib/gzr/templates/dashboard/import/.gitkeep +1 -0
  89. data/lib/gzr/templates/dashboard/rm/.gitkeep +1 -0
  90. data/lib/gzr/templates/group/ls/.gitkeep +1 -0
  91. data/lib/gzr/templates/group/member_groups/.gitkeep +1 -0
  92. data/lib/gzr/templates/group/member_users/.gitkeep +1 -0
  93. data/lib/gzr/templates/look/cat/.gitkeep +1 -0
  94. data/lib/gzr/templates/look/import/.gitkeep +1 -0
  95. data/lib/gzr/templates/look/rm/.gitkeep +1 -0
  96. data/lib/gzr/templates/model/ls/.gitkeep +1 -0
  97. data/lib/gzr/templates/plan/cat/.gitkeep +1 -0
  98. data/lib/gzr/templates/plan/disable/.gitkeep +1 -0
  99. data/lib/gzr/templates/plan/enable/.gitkeep +1 -0
  100. data/lib/gzr/templates/plan/failures/.gitkeep +1 -0
  101. data/lib/gzr/templates/plan/import/.gitkeep +1 -0
  102. data/lib/gzr/templates/plan/ls/.gitkeep +1 -0
  103. data/lib/gzr/templates/plan/rm/.gitkeep +1 -0
  104. data/lib/gzr/templates/plan/run/.gitkeep +1 -0
  105. data/lib/gzr/templates/query/run/.gitkeep +1 -0
  106. data/lib/gzr/templates/role/cat/.gitkeep +1 -0
  107. data/lib/gzr/templates/role/group_add/.gitkeep +1 -0
  108. data/lib/gzr/templates/role/group_ls/.gitkeep +1 -0
  109. data/lib/gzr/templates/role/group_rm/.gitkeep +1 -0
  110. data/lib/gzr/templates/role/ls/.gitkeep +1 -0
  111. data/lib/gzr/templates/role/rm/.gitkeep +1 -0
  112. data/lib/gzr/templates/role/user_add/.gitkeep +1 -0
  113. data/lib/gzr/templates/role/user_ls/.gitkeep +1 -0
  114. data/lib/gzr/templates/role/user_rm/.gitkeep +1 -0
  115. data/lib/gzr/templates/space/cat/.gitkeep +1 -0
  116. data/lib/gzr/templates/space/create/.gitkeep +1 -0
  117. data/lib/gzr/templates/space/export/.gitkeep +1 -0
  118. data/lib/gzr/templates/space/ls/.gitkeep +1 -0
  119. data/lib/gzr/templates/space/rm/.gitkeep +1 -0
  120. data/lib/gzr/templates/space/top/.gitkeep +1 -0
  121. data/lib/gzr/templates/space/tree/.gitkeep +1 -0
  122. data/lib/gzr/templates/user/cat/.gitkeep +1 -0
  123. data/lib/gzr/templates/user/disable/.gitkeep +1 -0
  124. data/lib/gzr/templates/user/enable/.gitkeep +1 -0
  125. data/lib/gzr/templates/user/ls/.gitkeep +1 -0
  126. data/lib/gzr/templates/user/me/.gitkeep +1 -0
  127. data/lib/gzr/version.rb +24 -0
  128. 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