gclouder_undefined_resources 0.1.0
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/bin/gclouder_undefined_resources +7 -0
- data/lib/gclouder_undefined_resources/cli_args.rb +35 -0
- data/lib/gclouder_undefined_resources/local_resources.rb +39 -0
- data/lib/gclouder_undefined_resources/remote_resources/remote.rb +52 -0
- data/lib/gclouder_undefined_resources/remote_resources/resource.rb +190 -0
- data/lib/gclouder_undefined_resources/remote_resources.rb +126 -0
- data/lib/gclouder_undefined_resources/resource.rb +29 -0
- data/lib/gclouder_undefined_resources/self_link.rb +19 -0
- data/lib/gclouder_undefined_resources/shell.rb +18 -0
- data/lib/gclouder_undefined_resources/version.rb +5 -0
- data/lib/gclouder_undefined_resources.rb +41 -0
- metadata +98 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 53f02cbd3cea848631504944efa920e5ced3574e
|
4
|
+
data.tar.gz: 98d661239064f19b793a6f5992cec119e37c1a7a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: e4719ab0e87f18ed531b3bcdc18b7948ae0d3e1a2e1edd37dfa7d1cd756056d42ae33eeefd8de4a6ef407bf98f41c2ef55d4431062467f0a0cd5c800142fa23b
|
7
|
+
data.tar.gz: d29e31aef7a439ec592be10c0691942ff8e71a55d6f8a03096480967dd2eca81948006671cb43cd76257d09de7683654c0f70f48952d43df280b3558b36e429c
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module GClouderUndefinedResources
|
4
|
+
module CLIArgs
|
5
|
+
def self.cli_args
|
6
|
+
@cli_args ||= { debug: false }
|
7
|
+
end
|
8
|
+
|
9
|
+
def cli_args
|
10
|
+
CLIArgs.cli_args
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.included(klass)
|
14
|
+
klass.extend CLIArgs
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.load
|
18
|
+
option_parser = Trollop::Parser.new do
|
19
|
+
banner "\n undefined gcp resources\n "
|
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 :verbose, "verbose\n ", type: :bool
|
27
|
+
end
|
28
|
+
|
29
|
+
@cli_args = Trollop.with_standard_exception_handling(option_parser) do
|
30
|
+
raise Trollop::HelpNeeded if ARGV.empty?
|
31
|
+
option_parser.parse ARGV
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module GClouderUndefinedResources
|
4
|
+
class LocalResources
|
5
|
+
extend Forwardable
|
6
|
+
|
7
|
+
def initialize(file)
|
8
|
+
@resources = yaml_load(file)
|
9
|
+
end
|
10
|
+
|
11
|
+
def_delegator :@resources, :[]
|
12
|
+
|
13
|
+
def yaml_load(file)
|
14
|
+
@resources = YAML.load_file(file)
|
15
|
+
rescue => e
|
16
|
+
raise StandardError, "failed to load local resource file: #{e}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def global?(key, name)
|
20
|
+
#ap @resources
|
21
|
+
#puts "looking up: #{key}, name: #{name}"
|
22
|
+
match = @resources.dig(*key)
|
23
|
+
return false if match.nil?
|
24
|
+
found_resources = match.select { |hash| hash["name"] == name }
|
25
|
+
!found_resources.empty?
|
26
|
+
rescue TypeError, "type table lookup failure"
|
27
|
+
end
|
28
|
+
|
29
|
+
def regional?(region, key, name)
|
30
|
+
#ap @resources
|
31
|
+
#puts "looking up: #{key}, name: #{name}"
|
32
|
+
match = @resources.dig("regions", region, *key)
|
33
|
+
return false if match.nil?
|
34
|
+
found_resources = match.select { |hash| hash["name"] == name }
|
35
|
+
!found_resources.empty?
|
36
|
+
rescue TypeError, "type table lookup failure"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module GClouderUndefinedResources
|
4
|
+
class RemoteResources
|
5
|
+
module Remote
|
6
|
+
module GCloud
|
7
|
+
def self.fetch(project_id)
|
8
|
+
modules.map { |m| m.send(:fetch, project_id) }.flatten
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.modules
|
12
|
+
[
|
13
|
+
ServiceAccounts,
|
14
|
+
ResourcesList
|
15
|
+
]
|
16
|
+
end
|
17
|
+
|
18
|
+
module ServiceAccounts
|
19
|
+
def self.fetch(project_id)
|
20
|
+
json = JSON.parse(Shell.run("gcloud iam service-accounts list --format json"))
|
21
|
+
|
22
|
+
json.map do |resource|
|
23
|
+
resource["@type"] = "serviceAccount"
|
24
|
+
Resource.new(resource["email"], resource)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
module ResourcesList
|
30
|
+
def self.fetch(project_id)
|
31
|
+
json = JSON.parse(Shell.run("gcloud alpha resources list --format json"))
|
32
|
+
|
33
|
+
json.select do |resource|
|
34
|
+
result = true
|
35
|
+
|
36
|
+
result = nil unless resource["selfLink"] =~ /projects\/#{project_id}\//
|
37
|
+
|
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
|
41
|
+
end
|
42
|
+
|
43
|
+
result
|
44
|
+
end.map do |resource|
|
45
|
+
Resource.new(resource["name"], resource)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,190 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module GClouderUndefinedResources
|
4
|
+
class RemoteResources
|
5
|
+
class Resource
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
attr_accessor :name, :data
|
9
|
+
|
10
|
+
def initialize(name, data)
|
11
|
+
if name.nil?
|
12
|
+
ap data
|
13
|
+
raise StandardError, "can't find name for resource"
|
14
|
+
end
|
15
|
+
|
16
|
+
@name = name
|
17
|
+
@data = data
|
18
|
+
end
|
19
|
+
|
20
|
+
def_delegator :@data, :[]
|
21
|
+
|
22
|
+
def region
|
23
|
+
return unless @data.key?("selfLink")
|
24
|
+
match = @data["selfLink"].match(/.*\/regions\/([^\/]+)/)
|
25
|
+
return match[1] if match
|
26
|
+
zone[0..-3] if zone
|
27
|
+
end
|
28
|
+
|
29
|
+
def zone
|
30
|
+
return unless @data.key?("selfLink")
|
31
|
+
match = @data["selfLink"].match(/.*\/zones\/([^\/]+)/)
|
32
|
+
match[1] if match
|
33
|
+
end
|
34
|
+
|
35
|
+
def global?
|
36
|
+
return true if zone.nil? && region.nil?
|
37
|
+
return unless @data.key?("selfLink")
|
38
|
+
!@data["selfLink"].match(/.*\/projects\/[^\/]+\/global/).nil?
|
39
|
+
end
|
40
|
+
|
41
|
+
# type is the Remote version of Local path.., use this to check against local data structure
|
42
|
+
def type
|
43
|
+
@type ||= get_type
|
44
|
+
end
|
45
|
+
|
46
|
+
# check for local regional and local global definitions
|
47
|
+
def defined?
|
48
|
+
local_resources = GClouderUndefinedResources.local_resources
|
49
|
+
|
50
|
+
if global?
|
51
|
+
local_resources.global?(type, name)
|
52
|
+
else
|
53
|
+
local_resources.regional?(region, type, name)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# check to see if this resource has been filtered
|
58
|
+
def filtered?
|
59
|
+
unless CLIArgs.cli_args[:filter_config_given]
|
60
|
+
puts "no filter config given" if CLIArgs.cli_args["verbose"]
|
61
|
+
return false
|
62
|
+
end
|
63
|
+
|
64
|
+
unless filters.key?("filters")
|
65
|
+
raise StandardError, "no filters key found in filter config"
|
66
|
+
end
|
67
|
+
|
68
|
+
original_type = @data["@type"]
|
69
|
+
|
70
|
+
filters["filters"].each do |filter|
|
71
|
+
if filter["region"] != region && filter["region"] != "*"
|
72
|
+
next
|
73
|
+
end
|
74
|
+
|
75
|
+
if filter["zone"] != zone && filter["zone"] != "*"
|
76
|
+
next
|
77
|
+
end
|
78
|
+
|
79
|
+
if filter["type"] != original_type && filter["type"] != "*"
|
80
|
+
next
|
81
|
+
end
|
82
|
+
|
83
|
+
if (name !~ Regexp.new(filter["name"]) ? true : false) && filter["name"] != "*"
|
84
|
+
next
|
85
|
+
end
|
86
|
+
|
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
|
101
|
+
|
102
|
+
return true
|
103
|
+
end
|
104
|
+
|
105
|
+
false
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
|
110
|
+
def filters
|
111
|
+
@filters ||= YAML.load_file(CLIArgs.cli_args[:filter_config])
|
112
|
+
rescue => error
|
113
|
+
puts "failed to load filter config: #{error}"
|
114
|
+
exit 1
|
115
|
+
end
|
116
|
+
|
117
|
+
# FIXME - add more types
|
118
|
+
def get_type
|
119
|
+
case @data["@type"]
|
120
|
+
when "serviceAccount"
|
121
|
+
[ "service_accounts" ]
|
122
|
+
#when "type.googleapis.com/cloud.bigstore.api.Bucket"
|
123
|
+
|
124
|
+
when "type.googleapis.com/cloud.dns.api.ManagedZone"
|
125
|
+
[ "dns", "zones" ]
|
126
|
+
|
127
|
+
#when "type.googleapis.com/cloud.resourcemanager.Organization"
|
128
|
+
|
129
|
+
when "type.googleapis.com/compute.BackendBucket"
|
130
|
+
[ "compute", "backend-buckets" ]
|
131
|
+
|
132
|
+
when "type.googleapis.com/compute.Disk"
|
133
|
+
[ "compute", "disks" ]
|
134
|
+
|
135
|
+
when "type.googleapis.com/compute.Firewall"
|
136
|
+
[ "firewall", "rules" ]
|
137
|
+
|
138
|
+
when "type.googleapis.com/compute.HealthCheck"
|
139
|
+
[ "compute", "health_check" ]
|
140
|
+
|
141
|
+
when "type.googleapis.com/compute.HttpHealthCheck"
|
142
|
+
[ "compute", "http_health_check" ]
|
143
|
+
|
144
|
+
when "type.googleapis.com/compute.HttpsHealthCheck"
|
145
|
+
[ "compute", "https_health_check" ]
|
146
|
+
|
147
|
+
when "type.googleapis.com/compute.Image"
|
148
|
+
["compute", "images"]
|
149
|
+
|
150
|
+
when "type.googleapis.com/compute.Instance"
|
151
|
+
["compute", "instances"]
|
152
|
+
|
153
|
+
when "type.googleapis.com/compute.InstanceTemplate"
|
154
|
+
["compute", "instance_templates"]
|
155
|
+
|
156
|
+
#when "type.googleapis.com/compute.InstanceTemplate"
|
157
|
+
|
158
|
+
when "type.googleapis.com/compute.Network"
|
159
|
+
[ "networks" ]
|
160
|
+
|
161
|
+
when "type.googleapis.com/compute.Router"
|
162
|
+
[ "compute", "router" ]
|
163
|
+
|
164
|
+
#when "type.googleapis.com/compute.SslCertificate"
|
165
|
+
|
166
|
+
when "type.googleapis.com/compute.Subnetwork"
|
167
|
+
[ "subnets" ]
|
168
|
+
|
169
|
+
#when "type.googleapis.com/compute.TargetHttpProxy"
|
170
|
+
#when "type.googleapis.com/compute.TargetHttpsProxy"
|
171
|
+
|
172
|
+
when "type.googleapis.com/compute.UrlMap"
|
173
|
+
[ "compute", "url-maps" ]
|
174
|
+
|
175
|
+
#when "type.googleapis.com/google.api.servicemanagement.v1.ManagedService"
|
176
|
+
#when "type.googleapis.com/google.appengine.v1.Application"
|
177
|
+
#when "type.googleapis.com/google.appengine.v1.Service"
|
178
|
+
#when "type.googleapis.com/google.appengine.v1.Version"
|
179
|
+
#when "type.googleapis.com/google.cloud.billing.v1.BillingAccount"
|
180
|
+
#when "type.googleapis.com/google.cloud.dataproc.v1.Cluster"
|
181
|
+
#when "type.googleapis.com/google.cloudresourcemanager.projects.v1beta1.Project"
|
182
|
+
else
|
183
|
+
puts "error: unknown or no '@type' property found for data:"
|
184
|
+
ap @data
|
185
|
+
exit 1
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module GClouderUndefinedResources
|
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
|
+
def initialize(project_id)
|
24
|
+
@project_id = project_id
|
25
|
+
@resources = []
|
26
|
+
end
|
27
|
+
|
28
|
+
def collect
|
29
|
+
add Remote::GCloud.fetch(@project_id)
|
30
|
+
end
|
31
|
+
|
32
|
+
def add(resources)
|
33
|
+
@resources += resources
|
34
|
+
end
|
35
|
+
|
36
|
+
# display: type, region, zone, name
|
37
|
+
def display_by_type
|
38
|
+
types = @resources.group_by { |resource| resource.type }
|
39
|
+
|
40
|
+
types.each do |type, resources_by_type|
|
41
|
+
regions = resources_by_type.group_by { |resource| resource.region }
|
42
|
+
|
43
|
+
next if regions.empty?
|
44
|
+
|
45
|
+
puts
|
46
|
+
puts
|
47
|
+
puts " #{type.join(' / ')}"
|
48
|
+
|
49
|
+
regions.each do |region, resources_by_region|
|
50
|
+
zones = resources_by_region.group_by { |resource| resource.zone }
|
51
|
+
|
52
|
+
next if zones.empty?
|
53
|
+
|
54
|
+
region ||= "global"
|
55
|
+
|
56
|
+
puts
|
57
|
+
puts " #{region}"
|
58
|
+
|
59
|
+
zones.each do |zone, resources_by_zone|
|
60
|
+
next if resources_by_zone.empty?
|
61
|
+
|
62
|
+
zone ||= "none"
|
63
|
+
|
64
|
+
puts
|
65
|
+
puts " #{zone}"
|
66
|
+
puts
|
67
|
+
|
68
|
+
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}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def display_by_location
|
85
|
+
# display: region, zone, type, name
|
86
|
+
regions = @resources.group_by { |resource| resource.region }
|
87
|
+
|
88
|
+
regions.each do |region, resources_by_region|
|
89
|
+
region ||= "global"
|
90
|
+
|
91
|
+
puts
|
92
|
+
puts
|
93
|
+
puts " #{region}"
|
94
|
+
|
95
|
+
zones = resources_by_region.group_by { |resource| resource.zone }
|
96
|
+
|
97
|
+
zones.each do |zone, resources_by_zone|
|
98
|
+
zone ||= "none"
|
99
|
+
|
100
|
+
puts
|
101
|
+
puts " #{zone}"
|
102
|
+
|
103
|
+
types = resources_by_zone.group_by { |resource| resource.type }
|
104
|
+
|
105
|
+
types.each do |type, resources_by_type|
|
106
|
+
puts
|
107
|
+
puts " #{type.join(' / ')}"
|
108
|
+
puts
|
109
|
+
|
110
|
+
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}"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module GClouderUndefinedResources
|
4
|
+
module Resource
|
5
|
+
def self.local=(file)
|
6
|
+
@local_resources = YAML.load_file(file)
|
7
|
+
rescue => e
|
8
|
+
raise StandardError, "failed to load local resource file: #{e}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.local
|
12
|
+
@local_resources
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.global?(key, name)
|
16
|
+
resources = local.dig(*key)
|
17
|
+
return false if resources.nil?
|
18
|
+
found_resources = resources.select { |hash| hash["name"] == name }
|
19
|
+
!found_resources.empty?
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.regional?(region, key, name)
|
23
|
+
resources = local.dig("regions", region, *key)
|
24
|
+
return false if resources.nil?
|
25
|
+
found_resources = resources.select { |hash| hash["name"] == name }
|
26
|
+
!found_resources.empty?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module GClouderUndefinedResources
|
4
|
+
module SelfLink
|
5
|
+
def self.region(resource)
|
6
|
+
r = resource["selfLink"].match(/.*\/regions\/([^\/]+)/)
|
7
|
+
r.nil? ? nil : r[1]
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.zone(resource)
|
11
|
+
r = resource["selfLink"].match(/.*\/zones\/([^\/]+)/)
|
12
|
+
r.nil? ? nil : r[1]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.global(resource)
|
16
|
+
!resource["selfLink"].match(/.*\/projects\/[^\/]+\/global/).nil?
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module GClouderUndefinedResources
|
4
|
+
module Shell
|
5
|
+
def self.run(command)
|
6
|
+
puts "running command: #{command}" if CLIArgs.cli_args[:verbose]
|
7
|
+
stdout, stderr, status = Open3.capture3(command)
|
8
|
+
|
9
|
+
if status.to_i.nonzero?
|
10
|
+
raise StandardError, "command failed: #{command}\n#{stderr}\n#{stdout}"
|
11
|
+
end
|
12
|
+
|
13
|
+
stdout
|
14
|
+
rescue => error
|
15
|
+
puts error
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
require "json"
|
5
|
+
require "trollop"
|
6
|
+
require "open3"
|
7
|
+
require "awesome_print"
|
8
|
+
require "colorize"
|
9
|
+
require "forwardable"
|
10
|
+
require "gclouder_undefined_resources/cli_args"
|
11
|
+
require "gclouder_undefined_resources/shell"
|
12
|
+
require "gclouder_undefined_resources/local_resources"
|
13
|
+
require "gclouder_undefined_resources/remote_resources"
|
14
|
+
require "gclouder_undefined_resources/remote_resources/remote"
|
15
|
+
require "gclouder_undefined_resources/remote_resources/resource"
|
16
|
+
|
17
|
+
module GClouderUndefinedResources
|
18
|
+
def self.run
|
19
|
+
undefined
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.local_resources
|
23
|
+
@local_resources ||= LocalResources.new(CLIArgs.cli_args[:local_resources])
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.undefined
|
27
|
+
CLIArgs.load
|
28
|
+
|
29
|
+
remote_resources = RemoteResources.new(local_resources["project_id"])
|
30
|
+
remote_resources.collect
|
31
|
+
|
32
|
+
case CLIArgs.cli_args[:group_by].to_sym
|
33
|
+
when :location
|
34
|
+
remote_resources.display_by_location
|
35
|
+
when :type
|
36
|
+
remote_resources.display_by_type
|
37
|
+
else
|
38
|
+
puts "unknown group-by type"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gclouder_undefined_resources
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Rob Wilson
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-01-23 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: trollop
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: awesome_print
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: colorize
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
description: A tool to compare deployed resources to resources defined in gclouder(1)
|
56
|
+
manifests
|
57
|
+
email: roobert@gmail.com
|
58
|
+
executables:
|
59
|
+
- gclouder_undefined_resources
|
60
|
+
extensions: []
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- bin/gclouder_undefined_resources
|
64
|
+
- lib/gclouder_undefined_resources.rb
|
65
|
+
- lib/gclouder_undefined_resources/cli_args.rb
|
66
|
+
- lib/gclouder_undefined_resources/local_resources.rb
|
67
|
+
- lib/gclouder_undefined_resources/remote_resources.rb
|
68
|
+
- lib/gclouder_undefined_resources/remote_resources/remote.rb
|
69
|
+
- lib/gclouder_undefined_resources/remote_resources/resource.rb
|
70
|
+
- lib/gclouder_undefined_resources/resource.rb
|
71
|
+
- lib/gclouder_undefined_resources/self_link.rb
|
72
|
+
- lib/gclouder_undefined_resources/shell.rb
|
73
|
+
- lib/gclouder_undefined_resources/version.rb
|
74
|
+
homepage: https://github.com/roobert/gclouder_undefined_resources
|
75
|
+
licenses:
|
76
|
+
- MIT
|
77
|
+
metadata: {}
|
78
|
+
post_install_message:
|
79
|
+
rdoc_options: []
|
80
|
+
require_paths:
|
81
|
+
- lib
|
82
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: '0'
|
87
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '0'
|
92
|
+
requirements: []
|
93
|
+
rubyforge_project:
|
94
|
+
rubygems_version: 2.6.8
|
95
|
+
signing_key:
|
96
|
+
specification_version: 4
|
97
|
+
summary: GClouder undefined resource detection
|
98
|
+
test_files: []
|