gclouder 0.1.1
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/README.md +104 -0
- data/bin/gclouder +7 -0
- data/lib/gclouder/config/arguments.rb +35 -0
- data/lib/gclouder/config/cli_args.rb +77 -0
- data/lib/gclouder/config/cluster.rb +66 -0
- data/lib/gclouder/config/defaults.rb +35 -0
- data/lib/gclouder/config/files/project.rb +24 -0
- data/lib/gclouder/config/project.rb +34 -0
- data/lib/gclouder/config/resource_representations.rb +31 -0
- data/lib/gclouder/config_loader.rb +25 -0
- data/lib/gclouder/config_section.rb +26 -0
- data/lib/gclouder/dependencies.rb +11 -0
- data/lib/gclouder/gcloud.rb +39 -0
- data/lib/gclouder/gsutil.rb +25 -0
- data/lib/gclouder/header.rb +9 -0
- data/lib/gclouder/helpers.rb +77 -0
- data/lib/gclouder/logging.rb +181 -0
- data/lib/gclouder/mappings/argument.rb +31 -0
- data/lib/gclouder/mappings/file.rb +31 -0
- data/lib/gclouder/mappings/property.rb +31 -0
- data/lib/gclouder/mappings/resource_representation.rb +31 -0
- data/lib/gclouder/monkey_patches/array.rb +19 -0
- data/lib/gclouder/monkey_patches/boolean.rb +12 -0
- data/lib/gclouder/monkey_patches/hash.rb +44 -0
- data/lib/gclouder/monkey_patches/ipaddr.rb +10 -0
- data/lib/gclouder/monkey_patches/string.rb +30 -0
- data/lib/gclouder/resource.rb +63 -0
- data/lib/gclouder/resource_cleaner.rb +58 -0
- data/lib/gclouder/resources/compute/addresses.rb +108 -0
- data/lib/gclouder/resources/compute/bgp-vpns.rb +220 -0
- data/lib/gclouder/resources/compute/disks.rb +99 -0
- data/lib/gclouder/resources/compute/firewall_rules.rb +82 -0
- data/lib/gclouder/resources/compute/instances.rb +147 -0
- data/lib/gclouder/resources/compute/networks/subnets.rb +104 -0
- data/lib/gclouder/resources/compute/networks.rb +110 -0
- data/lib/gclouder/resources/compute/project_info/ssh_keys.rb +171 -0
- data/lib/gclouder/resources/compute/routers.rb +83 -0
- data/lib/gclouder/resources/compute/vpns.rb +199 -0
- data/lib/gclouder/resources/container/clusters.rb +257 -0
- data/lib/gclouder/resources/container/node_pools.rb +193 -0
- data/lib/gclouder/resources/dns.rb +390 -0
- data/lib/gclouder/resources/logging/sinks.rb +98 -0
- data/lib/gclouder/resources/project/iam_policy_binding.rb +293 -0
- data/lib/gclouder/resources/project.rb +85 -0
- data/lib/gclouder/resources/project_id.rb +71 -0
- data/lib/gclouder/resources/pubsub/subscriptions.rb +100 -0
- data/lib/gclouder/resources/pubsub/topics.rb +95 -0
- data/lib/gclouder/resources/storagebuckets.rb +103 -0
- data/lib/gclouder/resources/validate/global.rb +27 -0
- data/lib/gclouder/resources/validate/local.rb +68 -0
- data/lib/gclouder/resources/validate/region.rb +28 -0
- data/lib/gclouder/resources/validate/remote.rb +78 -0
- data/lib/gclouder/resources.rb +148 -0
- data/lib/gclouder/shell.rb +71 -0
- data/lib/gclouder/version.rb +5 -0
- data/lib/gclouder.rb +278 -0
- metadata +102 -0
@@ -0,0 +1,181 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "stringio"
|
4
|
+
require "logger"
|
5
|
+
|
6
|
+
module GClouder
|
7
|
+
module Logging
|
8
|
+
class << self
|
9
|
+
attr_accessor :appenders
|
10
|
+
end
|
11
|
+
|
12
|
+
@@good ||= 0
|
13
|
+
@@bad ||= 0
|
14
|
+
@@add ||= 0
|
15
|
+
@@change ||= 0
|
16
|
+
@@remove ||= 0
|
17
|
+
@@warning ||= 0
|
18
|
+
|
19
|
+
def self.loggers
|
20
|
+
@loggers ||= setup
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.included(klass)
|
24
|
+
klass.extend Logging
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.setup
|
28
|
+
appenders.map do |appender|
|
29
|
+
appender[:appender].formatter = appender[:format]
|
30
|
+
appender[:appender].level = Logger::DEBUG
|
31
|
+
appender[:appender]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.log(message, level: :info, indent: 0, heading: false, title: false)
|
36
|
+
loggers.each do |log|
|
37
|
+
message = case message
|
38
|
+
when "" || nil
|
39
|
+
[ "" ]
|
40
|
+
when String
|
41
|
+
message.split("\n")
|
42
|
+
when Array
|
43
|
+
message
|
44
|
+
else
|
45
|
+
fatal "unknown message type: #{message.class}"
|
46
|
+
end
|
47
|
+
|
48
|
+
message = [ "", "" ] + message if title
|
49
|
+
message = [ "" ] + message if heading
|
50
|
+
|
51
|
+
if title
|
52
|
+
prefix = " " * 1
|
53
|
+
else
|
54
|
+
prefix = " " * indent
|
55
|
+
end
|
56
|
+
|
57
|
+
message.each { |line| log.send(level, prefix + line) }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.appenders
|
62
|
+
@appenders ||= [Appenders.stdout, Appenders.file]
|
63
|
+
end
|
64
|
+
|
65
|
+
module Appenders
|
66
|
+
def self.stdout
|
67
|
+
{
|
68
|
+
appender: ::Logger.new(STDOUT),
|
69
|
+
format: proc { |_, _, _, message| "#{message}\n" }
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.file
|
74
|
+
{
|
75
|
+
appender: ::Logger.new(File.join(File.dirname(__FILE__), "../../log.txt")),
|
76
|
+
format: proc { |severity, datetime, _, message| "#{severity} - #{datetime}: #{message}\n" }
|
77
|
+
}
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.stringio(obj = StringIO.new)
|
81
|
+
{
|
82
|
+
appender: ::Logger.new(StringIO.new),
|
83
|
+
format: proc { |severity, datetime, _, message| "#{severity} - #{datetime}: #{message}\n" }
|
84
|
+
}
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def debug(message = "")
|
89
|
+
Logging.log message, level: :debug
|
90
|
+
end
|
91
|
+
|
92
|
+
def info(message = "", indent: 0, heading: false, title: false)
|
93
|
+
Logging.log message, level: :info, indent: indent, heading: heading, title: title
|
94
|
+
end
|
95
|
+
|
96
|
+
def warn(message = "", heading: false)
|
97
|
+
Logging.log message, level: :warn, heading: heading
|
98
|
+
end
|
99
|
+
|
100
|
+
def error(message = "", heading: false)
|
101
|
+
Logging.log message, level: :error, heading: heading
|
102
|
+
end
|
103
|
+
|
104
|
+
def fatal(message = "", status: 1, heading: false)
|
105
|
+
Logging.log "\n#{message}", level: :fatal, heading: heading
|
106
|
+
exit status
|
107
|
+
end
|
108
|
+
|
109
|
+
def resource_state(message, indent: 0, heading: false, level: :info)
|
110
|
+
Logging.log "#{' ' * indent}#{message}", level: level, heading: heading
|
111
|
+
end
|
112
|
+
|
113
|
+
def good(message, indent: 3, heading: false)
|
114
|
+
@@good += 1
|
115
|
+
resource_state("#{Symbols.tick} #{message}", indent: indent, heading: heading)
|
116
|
+
end
|
117
|
+
|
118
|
+
def bad(message, indent: 3, heading: false)
|
119
|
+
@@bad += 1
|
120
|
+
resource_state("#{Symbols.x} #{message}", indent: indent, heading: heading)
|
121
|
+
end
|
122
|
+
|
123
|
+
def add(message, indent: 3, heading: false)
|
124
|
+
@@add += 1
|
125
|
+
resource_state("#{Symbols.plus} #{message}", indent: indent, heading: heading)
|
126
|
+
end
|
127
|
+
|
128
|
+
def change(message, indent: 3, heading: false)
|
129
|
+
@@change += 1
|
130
|
+
resource_state("#{Symbols.o} #{message}", indent: indent, heading: heading)
|
131
|
+
end
|
132
|
+
|
133
|
+
def remove(message, indent: 3, heading: false)
|
134
|
+
@@remove += 1
|
135
|
+
resource_state("#{Symbols.minus} #{message}", indent: indent, heading: heading)
|
136
|
+
end
|
137
|
+
|
138
|
+
def warning(message, indent: 3, heading: false)
|
139
|
+
@@warning += 1
|
140
|
+
resource_state("#{Symbols.bang} #{message}", indent: indent, heading: heading)
|
141
|
+
end
|
142
|
+
|
143
|
+
module Symbols
|
144
|
+
def self.tick
|
145
|
+
"✓".green
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.x
|
149
|
+
"✗".red
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.plus
|
153
|
+
"+".blue
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.o
|
157
|
+
"o".yellow
|
158
|
+
end
|
159
|
+
|
160
|
+
def self.minus
|
161
|
+
"-".red
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.bang
|
165
|
+
"!".yellow
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def self.report
|
170
|
+
Logging.log "\n\n [report]"
|
171
|
+
Logging.log " "
|
172
|
+
Logging.log " #{Symbols.tick} - #{@@good}"
|
173
|
+
Logging.log " #{Symbols.bang} - #{@@warning}"
|
174
|
+
Logging.log " #{Symbols.x} - #{@@bad}"
|
175
|
+
Logging.log " "
|
176
|
+
Logging.log " #{Symbols.plus} - #{@@add}"
|
177
|
+
Logging.log " #{Symbols.o} - #{@@change}"
|
178
|
+
Logging.log " #{Symbols.minus} - #{@@remove}"
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
module GClouder
|
6
|
+
module Mappings
|
7
|
+
module Argument
|
8
|
+
include GClouder::Logging
|
9
|
+
|
10
|
+
def self.mappings
|
11
|
+
GClouder::ConfigLoader.load("../../assets/mappings/argument")
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.load
|
15
|
+
mappings
|
16
|
+
end
|
17
|
+
|
18
|
+
def mappings
|
19
|
+
Argument.mappings
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.included(klass)
|
23
|
+
klass.extend Argument
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.section(section)
|
27
|
+
GClouder::ConfigSection.find(section, mappings)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
module GClouder
|
6
|
+
module Mappings
|
7
|
+
module File
|
8
|
+
include GClouder::Logging
|
9
|
+
|
10
|
+
def self.mappings
|
11
|
+
GClouder::ConfigLoader.load("../../assets/mappings/file")
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.load
|
15
|
+
mappings
|
16
|
+
end
|
17
|
+
|
18
|
+
def file
|
19
|
+
File.mappings
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.included(klass)
|
23
|
+
klass.extend File
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.section(section)
|
27
|
+
GClouder::ConfigSection.find(section, mappings)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
module GClouder
|
6
|
+
module Mappings
|
7
|
+
module Property
|
8
|
+
include GClouder::Logging
|
9
|
+
|
10
|
+
def self.mappings
|
11
|
+
YAML.load_file(::File.join(::File.dirname(__FILE__), "../../../assets/mappings/property.yml"))
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.load
|
15
|
+
mappings
|
16
|
+
end
|
17
|
+
|
18
|
+
def mappings
|
19
|
+
Property.mappings
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.included(klass)
|
23
|
+
klass.extend Property
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.section(section)
|
27
|
+
GClouder::ConfigSection.find(section, mappings)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
module GClouder
|
6
|
+
module Mappings
|
7
|
+
module ResourceRepresentation
|
8
|
+
include GClouder::Logging
|
9
|
+
|
10
|
+
def self.mappings
|
11
|
+
GClouder::ConfigLoader.load("../../assets/resource_representations")
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.load
|
15
|
+
mappings
|
16
|
+
end
|
17
|
+
|
18
|
+
def resource_representation
|
19
|
+
ResourceRepresentation.mappings
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.included(klass)
|
23
|
+
klass.extend ResourceRepresentation
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.section(section)
|
27
|
+
GClouder::ConfigSection.find(section, mappings)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
class Array
|
4
|
+
def clean
|
5
|
+
uniq.delete_if(&:nil?)
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_snake_keys
|
9
|
+
each_with_index do |v, i|
|
10
|
+
self[i] = v.to_snake_keys if v.is_a?(Hash)
|
11
|
+
end
|
12
|
+
self
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch_with_default(key, name, default)
|
16
|
+
results = find { |e| e[key] == name }
|
17
|
+
results || default
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
class Hash
|
4
|
+
# sourced from: https://github.com/futurechimp/plissken/blob/master/lib/plissken/ext/hash/to_snake_keys.rb
|
5
|
+
def to_snake_keys(value = self)
|
6
|
+
case value
|
7
|
+
when Array
|
8
|
+
value.map { |v| to_snake_keys(v) }
|
9
|
+
when Hash
|
10
|
+
snake_hash(value)
|
11
|
+
else
|
12
|
+
value
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def snake_hash(value)
|
19
|
+
Hash[value.map { |k, v| [underscore_key(k), to_snake_keys(v)] }]
|
20
|
+
end
|
21
|
+
|
22
|
+
def underscore_key(k)
|
23
|
+
if k.is_a? Symbol
|
24
|
+
underscore(k.to_s)
|
25
|
+
elsif k.is_a? String
|
26
|
+
underscore(k)
|
27
|
+
else
|
28
|
+
k
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def underscore(string)
|
33
|
+
string.gsub(/::/, '/')
|
34
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
35
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
36
|
+
.tr('-', '_')
|
37
|
+
.downcase
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class DeepMergeHash < Hash
|
42
|
+
include Hashie::Extensions::MergeInitializer
|
43
|
+
include Hashie::Extensions::DeepMerge
|
44
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
class String
|
4
|
+
include GClouder::Shell
|
5
|
+
|
6
|
+
def snakecase
|
7
|
+
self.gsub(/::/, '/').
|
8
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
9
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
10
|
+
tr("-", "_").
|
11
|
+
downcase
|
12
|
+
end
|
13
|
+
|
14
|
+
def mixedcase
|
15
|
+
self.split('_').collect(&:capitalize).join.sub(/^[A-Z]/, &:downcase)
|
16
|
+
end
|
17
|
+
|
18
|
+
def truncate(length = 32)
|
19
|
+
raise 'Pleasant: Length should be greater than 3' unless length > 3
|
20
|
+
|
21
|
+
truncated_string = self.to_s
|
22
|
+
|
23
|
+
if truncated_string.length > length
|
24
|
+
truncated_string = truncated_string[0...(length - 3)]
|
25
|
+
truncated_string += "..."
|
26
|
+
end
|
27
|
+
|
28
|
+
truncated_string
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module GClouder
|
4
|
+
module Resource
|
5
|
+
include GClouder::GCloud
|
6
|
+
include GClouder::Config::CLIArgs
|
7
|
+
include GClouder::Logging
|
8
|
+
|
9
|
+
def self.feedback(action, resource, name, extra_info: nil, indent: 3, silent: false)
|
10
|
+
return if silent
|
11
|
+
send action, "#{name} #{extra_info}", indent: indent
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.resource?(resource, name, args = nil, filter_key: "name", filter: "#{filter_key} ~ ^#{name}$", project_id: nil, silent: false, extra_info: nil, indent: 3)
|
15
|
+
exists = \
|
16
|
+
gcloud("#{resource} list --filter '#{filter}' #{args} | jq '. | length'", force: true, silent: silent, project_id: project_id)
|
17
|
+
|
18
|
+
if exists
|
19
|
+
feedback("good", resource, name, extra_info: extra_info, indent: indent, silent: silent)
|
20
|
+
return true
|
21
|
+
end
|
22
|
+
|
23
|
+
false
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.describe(resource, name, args = nil, force: true, failure: true, silent: false, project_id: nil)
|
27
|
+
return if resource?(resource, name, silent: silent, project_id: project_id)
|
28
|
+
gcloud "#{resource} describe #{name} #{args}", force: force, failure: failure, silent: silent, project_id: project_id
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.ensure(resource, name, args = nil, project_id: nil, extra_info: nil, silent: false, indent: 3, filter_key: "name")
|
32
|
+
return if resource?(resource, name, project_id: project_id, extra_info: extra_info, silent: silent, indent: indent, filter_key: filter_key)
|
33
|
+
feedback("add", resource, name, extra_info: extra_info, indent: indent, silent: silent)
|
34
|
+
gcloud "#{resource} create #{name} #{args}", project_id: project_id, silent: silent
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.purge(resource, name, args = nil, project_id: nil, silent: false, indent: 3)
|
38
|
+
return unless resource?(resource, name, project_id: project_id, silent: true, indent: indent)
|
39
|
+
extra_info = "[skipped] (--purge not specified)" unless cli_args[:purge]
|
40
|
+
feedback("remove", resource, name, extra_info: extra_info, indent: indent, silent: silent)
|
41
|
+
gcloud "#{resource} delete #{name} #{args}", project_id: project_id if cli_args[:purge]
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.list(resource, args = nil, snake_case: false, project_id: nil)
|
45
|
+
list = gcloud "#{resource} list #{args}", force: true, project_id: project_id
|
46
|
+
snake_case ? list.to_snake_keys : list
|
47
|
+
end
|
48
|
+
|
49
|
+
module Find
|
50
|
+
include GClouder::GCloud
|
51
|
+
|
52
|
+
def self.zone(resource, name, region, project_id: nil)
|
53
|
+
zones = %w(b c d).map { |zone| region + "-" + zone }
|
54
|
+
|
55
|
+
zones.each do |zone|
|
56
|
+
return zone if gcloud "#{resource} describe #{name} --zone=#{zone}", force: true, failure: false, silent: true, project_id: project_id
|
57
|
+
end
|
58
|
+
|
59
|
+
false
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module GClouder
|
4
|
+
module Resource
|
5
|
+
module Cleaner
|
6
|
+
def self.included(klass)
|
7
|
+
klass.extend Cleaner
|
8
|
+
end
|
9
|
+
|
10
|
+
def clean
|
11
|
+
return if undefined.empty?
|
12
|
+
|
13
|
+
header :clean
|
14
|
+
|
15
|
+
undefined.each do |namespace, resources|
|
16
|
+
info namespace, indent: 2, heading: true
|
17
|
+
info
|
18
|
+
resources.each do |resource|
|
19
|
+
message = resource['name']
|
20
|
+
message += " (not defined locally)"
|
21
|
+
warning message
|
22
|
+
# FIXME: enable purge on --purge flag..
|
23
|
+
#Resource.symlink.send(:purge, namespace, resource)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
module Default
|
30
|
+
def self.cleaner
|
31
|
+
Proc.new do |resources, resource|
|
32
|
+
resources.map do |r|
|
33
|
+
r['name'] == resource
|
34
|
+
end.include?(true)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def cleaner
|
40
|
+
(self.const_defined?(:Cleaner) && self::Cleaner.respond_to?(:custom)) ? self::Cleaner.custom : Default.cleaner
|
41
|
+
end
|
42
|
+
|
43
|
+
def undefined
|
44
|
+
self::Remote.list.each_with_object({}) do |(namespace, resources), collection|
|
45
|
+
resources.each do |resource|
|
46
|
+
namespace_resources = self::Local.list[namespace]
|
47
|
+
|
48
|
+
# accept PROC for custom matching of undefined resources
|
49
|
+
next if namespace_resources && cleaner.call(namespace_resources, resource["name"])
|
50
|
+
|
51
|
+
collection[namespace] ||= []
|
52
|
+
collection[namespace] << resource
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
module GClouder
|
4
|
+
module Resources
|
5
|
+
module Compute
|
6
|
+
module Addresses
|
7
|
+
include GClouder::GCloud
|
8
|
+
include GClouder::Logging
|
9
|
+
include GClouder::Resource::Cleaner
|
10
|
+
|
11
|
+
def self.header(stage = :ensure)
|
12
|
+
info "[#{stage}] compute / addresses", title: true
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.ensure
|
16
|
+
return if Local.list.empty?
|
17
|
+
header
|
18
|
+
|
19
|
+
if Local.list.key?("global")
|
20
|
+
info "global", indent: 2, heading: true
|
21
|
+
info
|
22
|
+
Local.list["global"].each { |address| Address.ensure(address["name"], "--global") }
|
23
|
+
end
|
24
|
+
|
25
|
+
Local.list.each do |region, addresses|
|
26
|
+
next if region == "global"
|
27
|
+
next unless addresses
|
28
|
+
|
29
|
+
info region, indent: 2, heading: true
|
30
|
+
info
|
31
|
+
addresses.each do |address|
|
32
|
+
Address.ensure(address["name"], "--region #{region}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.check
|
38
|
+
return if Remote.list.empty?
|
39
|
+
return if Local.list.empty?
|
40
|
+
header :check
|
41
|
+
Resources::Validate::Remote.instances(Local.list, Remote.list)
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.validate
|
45
|
+
return if Local.list.empty?
|
46
|
+
header :validate
|
47
|
+
Local.validate
|
48
|
+
end
|
49
|
+
|
50
|
+
module Local
|
51
|
+
include GClouder::Config::Project
|
52
|
+
|
53
|
+
def self.list
|
54
|
+
addresses = global.merge regional
|
55
|
+
addresses.delete_if { |_k, v| v.empty? }
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.global
|
59
|
+
Resources::Global.instances(path: ["addresses"])
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.section
|
63
|
+
%w(compute addresses)
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.validate
|
67
|
+
Resources::Validate::Region.instances(
|
68
|
+
list,
|
69
|
+
required_keys: GClouder::Config::Arguments.required(section),
|
70
|
+
permitted_keys: GClouder::Config::Arguments.permitted(section)
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.regional
|
75
|
+
resources = Resources::Region.instances(path: ["addresses"])
|
76
|
+
|
77
|
+
# get_instances_from_region assumes all keys have configs.. this normalizes
|
78
|
+
# the data to match self.global
|
79
|
+
resources.each { |k, v| resources[k] = v.to_a.flatten.delete_if(&:nil?) }
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
module Remote
|
84
|
+
def self.list
|
85
|
+
Resources::Remote.instances(
|
86
|
+
path: ["compute", "addresses"]
|
87
|
+
)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
module Address
|
92
|
+
def self.ensure(name, args)
|
93
|
+
GClouder::Resource.ensure :"compute addresses", name, args
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.purge(namespace, name, args = nil)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
module Resource
|
101
|
+
def self.symlink
|
102
|
+
Module.const_get "#{self.name.delete(/::Resource$/)}::Address"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|