gclouder_undefined_resources 0.2.4 → 0.2.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 56c98b99f115e32b4cfcae1b07742311f64be18d
4
- data.tar.gz: 63e9d56682db03437461db4339da7988018a148a
3
+ metadata.gz: 20430b49eb8ba80923b7f889e8ea10e4231a69fd
4
+ data.tar.gz: 526c81e66012a0d5638deb36cd7f3e062ca52759
5
5
  SHA512:
6
- metadata.gz: cb17a0352d4631617f9994bd744520c83a728da139070cd15ca31d2c85e88c4aebfc23aaf7591854f5bb70f39561ae0b59bbda6e05a115ab9c3097fb2a2027a9
7
- data.tar.gz: 1dd7b59229eb2ed4a929a86aa35eca7db6fcfb85a46dc101a12bad0339059a416ed0e23ff9fa67858d621db61f710f69f051a7bbdb5334be7d73370b7a9ffc2d
6
+ metadata.gz: b5c005bda0d49fd5ae55b65aab68262a45da0eaa89d170b7634ae59bfb141a8381c70b53dbb7c5fc0ae990075f70406f7d8f5cbb0534451cea1bacfab1d53644
7
+ data.tar.gz: d9ee105a14940609a5850ebfe1f918aeb428b8c43a04f1899ab9f32048c4f8f7d5f86479b4245d16d70873d12b37da827234b4af284ff00727221cada9aea1bb
@@ -13,6 +13,7 @@ require "gclouder_undefined_resources/local_resources"
13
13
  require "gclouder_undefined_resources/remote_resources"
14
14
  require "gclouder_undefined_resources/remote_resources/remote"
15
15
  require "gclouder_undefined_resources/remote_resources/resource"
16
+ require "gclouder_undefined_resources/remote_resources/resource/symbols"
16
17
 
17
18
  module GClouderUndefinedResources
18
19
  def self.run
@@ -50,5 +51,9 @@ module GClouderUndefinedResources
50
51
  else
51
52
  puts "unknown group-by type"
52
53
  end
54
+
55
+ remote_resources.display_report unless CLIArgs.cli_args[:hide_report]
56
+
57
+ exit 1 if remote_resources.any_undefined_and_unfiltered?
53
58
  end
54
59
  end
@@ -18,13 +18,20 @@ module GClouderUndefinedResources
18
18
  option_parser = Trollop::Parser.new do
19
19
  banner "\n undefined gcp resources\n "
20
20
 
21
- opt :local_resources, "file containing local resource definitions", type: :string, required: true
22
- #opt :remote_resources, "file containing remote resource definitions\n ", type: :string, required: true
23
- opt :group_by, "how to format output. valid values include: location, type", type: :string, default: "location"
24
- opt :filter_config, "file containing filter config", type: :string
25
- opt :show_filtered, "show filter matching output\n ", type: :bool
26
- opt :key_file, "specify key file for gcloud(1) authentication\n ", type: :string
27
- opt :verbose, "verbose\n ", type: :bool
21
+ opt :local_resources, "file containing local resource definitions", type: :string, required: true
22
+ opt :filter_config, "file containing filter config", type: :string
23
+ opt :key_file, "specify key file for gcloud(1) authentication\n ", type: :string
24
+
25
+ opt :group_by, "how to format output. valid values include: location, type\n ", type: :string, default: "location"
26
+
27
+ opt :show_filter_rule, "show filter matching output", type: :bool
28
+ opt :show_filter_name, "include filter rule name in output\n ", type: :bool
29
+
30
+ opt :hide_filtered, "hide filtered results from output", type: :bool, default: false
31
+ opt :hide_defined, "hide defined results from output", type: :bool, default: false
32
+ opt :hide_report, "display statistics for each resource status type\n ", type: :bool
33
+
34
+ opt :verbose, "verbose\n ", type: :bool
28
35
  end
29
36
 
30
37
  @cli_args = Trollop.with_standard_exception_handling(option_parser) do
@@ -2,24 +2,6 @@
2
2
 
3
3
  module GClouderUndefinedResources
4
4
  class RemoteResources
5
- module Symbols
6
- def self.tick
7
- "✓".green
8
- end
9
-
10
- def self.x
11
- "✗".red
12
- end
13
-
14
- def self.tick_filtered
15
- "✓".yellow
16
- end
17
-
18
- def self.x_filtered
19
- "✗".yellow
20
- end
21
- end
22
-
23
5
  def initialize(project_id)
24
6
  @project_id = project_id
25
7
  @resources = []
@@ -27,6 +9,14 @@ module GClouderUndefinedResources
27
9
 
28
10
  def collect
29
11
  add Remote::GCloud.fetch(@project_id)
12
+
13
+ @resources = @resources.reject do |resource|
14
+ CLIArgs.cli_args[:hide_filtered] && resource.filtered?
15
+ end
16
+
17
+ @resources = @resources.reject do |resource|
18
+ CLIArgs.cli_args[:hide_defined] && resource.defined?
19
+ end
30
20
  end
31
21
 
32
22
  def add(resources)
@@ -66,15 +56,7 @@ module GClouderUndefinedResources
66
56
  puts
67
57
 
68
58
  resources_by_region.each do |resource|
69
- if resource.filtered?
70
- status = resource.defined? ? Symbols.tick_filtered : Symbols.x_filtered
71
- else
72
- status = resource.defined? ? Symbols.tick : Symbols.x
73
- end
74
-
75
- # FIXME: do the skipping stuff here, or display status of the resource name..
76
- # FIXME: to_s in resource could include x or tick or whatever
77
- puts " #{status} #{resource.name}"
59
+ puts " #{resource}"
78
60
  end
79
61
  end
80
62
  end
@@ -108,19 +90,33 @@ module GClouderUndefinedResources
108
90
  puts
109
91
 
110
92
  resources_by_type.each do |resource|
111
- if resource.filtered?
112
- status = resource.defined? ? Symbols.tick_filtered : Symbols.x_filtered
113
- else
114
- status = resource.defined? ? Symbols.tick : Symbols.x
115
- end
116
-
117
- # FIXME: do the skipping stuff here, or display status of the resource name..
118
- # FIXME: to_s in resource could include x or tick or whatever
119
- puts " #{status} #{resource.name}"
93
+ puts " #{resource}"
120
94
  end
121
95
  end
122
96
  end
123
97
  end
124
98
  end
99
+
100
+ def display_report
101
+ status_types = @resources.group_by { |resource| resource.status }
102
+
103
+ return if status_types.empty?
104
+
105
+ puts
106
+ puts " report"
107
+ puts
108
+ status_types.each do |status_type, resources|
109
+ puts " #{status_type} - #{resources.length}"
110
+ end
111
+ puts
112
+ end
113
+
114
+ def any_undefined_and_unfiltered?
115
+ status_types = @resources.group_by { |resource| resource.status }
116
+
117
+ return if status_types.empty?
118
+
119
+ status_types.key?("✗".red)
120
+ end
125
121
  end
126
122
  end
@@ -26,6 +26,7 @@ module GClouderUndefinedResources
26
26
  end
27
27
  end
28
28
 
29
+ # FIXME: refactor
29
30
  module ResourcesList
30
31
  def self.fetch(project_id)
31
32
  json = JSON.parse(Shell.run("gcloud alpha resources list --format json"))
@@ -33,15 +34,31 @@ module GClouderUndefinedResources
33
34
  json.select do |resource|
34
35
  result = true
35
36
 
36
- result = nil unless resource["selfLink"] =~ /projects\/#{project_id}\//
37
+ if resource.key?("projectId")
38
+ result = nil if resource["projectId"] != project_id
39
+ #puts "skipping resource because project id does not match: #{resource['projectId']}"
40
+ elsif resource.key?("selfLink")
41
+ result = nil if resource["selfLink"] !~ /projects\/#{project_id}\//
42
+ #puts "skipping resource because project id does not match: #{resource['selfLink']}"
43
+ else
44
+ ap resource
45
+ puts "error: resource has no selfLink or projectId property, unable to determine project id"
46
+ exit 1
47
+ end
37
48
 
38
- if resource["@type"] == "type.googleapis.com/google.cloud.dataproc.v1.Job"
39
- puts "skipping data proc resource: #{resource['reference']}, #{resource['placement']}"
40
- result = nil
49
+ if !resource.key?("name")
50
+ puts "resource has no name key:"
51
+ ap resource
41
52
  end
42
53
 
43
54
  result
44
55
  end.map do |resource|
56
+ if !resource.key?("name")
57
+ ap resource
58
+ puts "error: resource has no name key"
59
+ exit 1
60
+ end
61
+
45
62
  Resource.new(resource["name"], resource)
46
63
  end
47
64
  end
@@ -22,6 +22,8 @@ module GClouderUndefinedResources
22
22
  def region
23
23
  return unless @data.key?("selfLink")
24
24
  match = @data["selfLink"].match(/.*\/regions\/([^\/]+)/)
25
+ match = @data["location"].downcase if @data.key?("location") && !match[1]
26
+ return unless @data.key?("location") && @data["location"] == "global"
25
27
  return match[1] if match
26
28
  zone[0..-3] if zone
27
29
  end
@@ -34,6 +36,7 @@ module GClouderUndefinedResources
34
36
 
35
37
  def global?
36
38
  return true if zone.nil? && region.nil?
39
+ return true if @data.key?("location") && @data["location"] == "global"
37
40
  return unless @data.key?("selfLink")
38
41
  !@data["selfLink"].match(/.*\/projects\/[^\/]+\/global/).nil?
39
42
  end
@@ -84,20 +87,7 @@ module GClouderUndefinedResources
84
87
  next
85
88
  end
86
89
 
87
- if CLIArgs.cli_args[:show_filtered]
88
- puts "filter: "
89
- puts " description: #{filter['description']}"
90
- puts " region: #{filter['region']}"
91
- puts " zone: #{filter['zone']}"
92
- puts " type: #{filter['type']}"
93
- puts " name: #{filter['name']}"
94
- puts "match: "
95
- puts " region: #{region}"
96
- puts " zone: #{zone}"
97
- puts " type: #{original_type}"
98
- puts " name: #{name}"
99
- puts
100
- end
90
+ @filter_rule = filter
101
91
 
102
92
  return true
103
93
  end
@@ -105,6 +95,54 @@ module GClouderUndefinedResources
105
95
  false
106
96
  end
107
97
 
98
+ # FIXME: refactor
99
+ def status
100
+ if self.filtered?
101
+ if self.defined?
102
+ if filter.dig("mark", "filtered")
103
+ filter["mark"]["filtered"]["symbol"].send(filter["mark"]["filtered"]["colour"])
104
+ else
105
+ Symbols.tick_filtered
106
+ end
107
+ else
108
+ if filter.dig("mark", "unfiltered")
109
+ filter["mark"]["unfiltered"]["symbol"].send(filter["mark"]["unfiltered"]["colour"])
110
+ else
111
+ Symbols.x_filtered
112
+ end
113
+ end
114
+ else
115
+ if self.defined?
116
+ Symbols.tick
117
+ else
118
+ Symbols.x
119
+ end
120
+ end
121
+ end
122
+
123
+ def filter
124
+ @filter_rule
125
+ end
126
+
127
+ def filter_description
128
+ if filter.key?("description")
129
+ "# #{filter["description"]}".gray
130
+ else
131
+ "# filter has no description".gray
132
+ end
133
+ end
134
+
135
+ def to_s
136
+ s = "#{status} #{name}"
137
+ s += " #{filter_description}" if CLIArgs.cli_args[:show_filter_name] and filtered?
138
+ s += "\n#{formatted_filter_rule}" if CLIArgs.cli_args[:show_filter_rule] and filtered?
139
+ s
140
+ end
141
+
142
+ def formatted_filter_rule
143
+ filter.ai.gsub("\n", "\n ").gsub(/^{/, " {")
144
+ end
145
+
108
146
  private
109
147
 
110
148
  def filters
@@ -120,13 +158,16 @@ module GClouderUndefinedResources
120
158
  when "serviceAccount"
121
159
  ["service_accounts"]
122
160
 
161
+ # TODO: not yet implemented in gclouder
123
162
  when "type.googleapis.com/cloud.bigstore.api.Bucket"
124
- []
163
+ ["buckets"]
125
164
 
126
165
  when "type.googleapis.com/cloud.dns.api.ManagedZone"
127
166
  ["dns", "zones"]
128
167
 
168
+ # TODO: not yet implemented in gclouder
129
169
  when "type.googleapis.com/cloud.resourcemanager.Organization"
170
+ ["resource_manager", "organization"]
130
171
 
131
172
  when "type.googleapis.com/compute.BackendBucket"
132
173
  ["compute", "backend-buckets"]
@@ -161,8 +202,9 @@ module GClouderUndefinedResources
161
202
  when "type.googleapis.com/compute.Router"
162
203
  ["compute", "router"]
163
204
 
205
+ # TODO: not yet implemented in gclouder
164
206
  when "type.googleapis.com/compute.SslCertificate"
165
- []
207
+ ["compute", "ssl_certificate"]
166
208
 
167
209
  when "type.googleapis.com/compute.Subnetwork"
168
210
  ["subnets"]
@@ -176,26 +218,37 @@ module GClouderUndefinedResources
176
218
  when "type.googleapis.com/compute.UrlMap"
177
219
  ["compute", "url_maps"]
178
220
 
221
+ # TODO: not yet implemented in gclouder
179
222
  when "type.googleapis.com/google.api.servicemanagement.v1.ManagedService"
180
- []
223
+ ["service_management", "service"]
181
224
 
225
+ # TODO: not yet implemented in gclouder
182
226
  when "type.googleapis.com/google.appengine.v1.Application"
183
- []
227
+ ["app", "app"]
184
228
 
229
+ # TODO: not yet implemented in gclouder
185
230
  when "type.googleapis.com/google.appengine.v1.Service"
186
- []
231
+ ["app", "service"]
187
232
 
233
+ # TODO: not yet implemented in gclouder
188
234
  when "type.googleapis.com/google.appengine.v1.Version"
189
- []
235
+ ["app", "version"]
190
236
 
237
+ # TODO: not yet implemented in gclouder
191
238
  when "type.googleapis.com/google.cloud.billing.v1.BillingAccount"
192
- []
239
+ ["billing", "account"]
193
240
 
241
+ # TODO: not yet implemented in gclouder
194
242
  when "type.googleapis.com/google.cloud.dataproc.v1.Cluster"
195
- []
243
+ ["dataproc", "cluster"]
196
244
 
245
+ # TODO: not yet implemented in gclouder
197
246
  when "type.googleapis.com/google.cloudresourcemanager.projects.v1beta1.Project"
198
- []
247
+ ["project"]
248
+
249
+ # TODO: not yet implemented in gclouder
250
+ when "type.googleapis.com/google.cloud.dataproc.v1.Job"
251
+ ["dataproc", "job"]
199
252
 
200
253
  else
201
254
  puts "error: unknown or no '@type' property found for data:"
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ module GClouderUndefinedResources
4
+ class RemoteResources
5
+ class Resource
6
+ module Symbols
7
+ def self.tick
8
+ "✓".green
9
+ end
10
+
11
+ def self.x
12
+ "✗".red
13
+ end
14
+
15
+ def self.tick_filtered
16
+ "✓".yellow
17
+ end
18
+
19
+ def self.x_filtered
20
+ "✗".yellow
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  module GClouderUndefinedResources
4
- VERSION = "0.2.4"
4
+ VERSION = "0.2.5"
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gclouder_undefined_resources
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.4
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Wilson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-01-29 00:00:00.000000000 Z
11
+ date: 2018-02-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: trollop
@@ -68,6 +68,7 @@ files:
68
68
  - lib/gclouder_undefined_resources/remote_resources.rb
69
69
  - lib/gclouder_undefined_resources/remote_resources/remote.rb
70
70
  - lib/gclouder_undefined_resources/remote_resources/resource.rb
71
+ - lib/gclouder_undefined_resources/remote_resources/resource/symbols.rb
71
72
  - lib/gclouder_undefined_resources/resource.rb
72
73
  - lib/gclouder_undefined_resources/self_link.rb
73
74
  - lib/gclouder_undefined_resources/shell.rb