glb 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +3 -0
  4. data/CHANGELOG.md +7 -0
  5. data/Gemfile +6 -0
  6. data/Guardfile +19 -0
  7. data/LICENSE.txt +1 -0
  8. data/README.md +51 -0
  9. data/Rakefile +6 -0
  10. data/docs/external.md +19 -0
  11. data/docs/internal.md +65 -0
  12. data/docs/ssl.md +33 -0
  13. data/docs/static-ip-address.md +30 -0
  14. data/exe/glb +14 -0
  15. data/glb.gemspec +33 -0
  16. data/lib/glb/autoloader.rb +21 -0
  17. data/lib/glb/cli/base.rb +15 -0
  18. data/lib/glb/cli/help/completion.md +20 -0
  19. data/lib/glb/cli/help/completion_script.md +3 -0
  20. data/lib/glb/cli/help.rb +11 -0
  21. data/lib/glb/cli.rb +48 -0
  22. data/lib/glb/command.rb +91 -0
  23. data/lib/glb/completer/script.rb +8 -0
  24. data/lib/glb/completer/script.sh +10 -0
  25. data/lib/glb/completer.rb +159 -0
  26. data/lib/glb/config.rb +147 -0
  27. data/lib/glb/core.rb +27 -0
  28. data/lib/glb/lb/args.rb +66 -0
  29. data/lib/glb/lb/backend_service/backend.rb +94 -0
  30. data/lib/glb/lb/backend_service.rb +19 -0
  31. data/lib/glb/lb/firewall_rule.rb +9 -0
  32. data/lib/glb/lb/forwarding_rule.rb +16 -0
  33. data/lib/glb/lb/forwarding_rule_https.rb +24 -0
  34. data/lib/glb/lb/health_check.rb +13 -0
  35. data/lib/glb/lb/names.rb +50 -0
  36. data/lib/glb/lb/resource.rb +119 -0
  37. data/lib/glb/lb/target_http_proxy.rb +9 -0
  38. data/lib/glb/lb/target_https_proxy.rb +4 -0
  39. data/lib/glb/lb/url_map.rb +9 -0
  40. data/lib/glb/lb.rb +110 -0
  41. data/lib/glb/util/sh.rb +37 -0
  42. data/lib/glb/util/sure.rb +18 -0
  43. data/lib/glb/version.rb +3 -0
  44. data/lib/glb.rb +22 -0
  45. data/spec/cli_spec.rb +26 -0
  46. data/spec/spec_helper.rb +29 -0
  47. metadata +245 -0
@@ -0,0 +1,119 @@
1
+ class Glb::Lb
2
+ class Resource < Glb::CLI::Base
3
+ extend Memoist
4
+ include Glb::Util::Sure
5
+ include Names
6
+
7
+ def up
8
+ sh up_command if up_command
9
+ end
10
+
11
+ # gcloud compute firewall-rules create demo-web-dev
12
+ # --network=#{network}
13
+ # --action=allow
14
+ # --direction=ingress
15
+ # --source-ranges=130.211.0.0/22,35.191.0.0/16,0.0.0.0/0
16
+ # --target-tags=#{target_tags}
17
+ # --rules=tcp:80
18
+ def up_command
19
+ "gcloud compute #{gcloud_compute_command} #{action} #{resource_name} #{args}" if valid?
20
+ end
21
+
22
+ # Examples: firewall-rules url-maps target-http-proxies health-checks forwarding-rules
23
+ def gcloud_compute_command
24
+ resource_type.pluralize.dasherize
25
+ end
26
+
27
+ def action
28
+ exist? ? "update" : "create"
29
+ end
30
+ memoize :action
31
+
32
+ # Example: url_map_name
33
+ def resource_name
34
+ send("#{resource_type}_name")
35
+ end
36
+
37
+ # Example: url_map
38
+ def resource_type
39
+ self.class.name.split('::').last.underscore
40
+ end
41
+
42
+ # Designed to be overridden by subclass
43
+ # These options are only available at runtime
44
+ def default_options
45
+ {}
46
+ end
47
+
48
+ def args
49
+ opts = default_options.merge(resource_config)
50
+ # Example: Args.new("url-maps create", opts).transform
51
+ Args.new("#{gcloud_compute_command} #{action}", opts).transform
52
+ end
53
+
54
+ # Example: gcloud compute url-maps describe NAME --region=REGION --format json
55
+ def show
56
+ sh "gcloud compute #{gcloud_compute_command} describe #{resource_name} #{region_option} #{format_option}", exit_on_fail: false
57
+ end
58
+
59
+ # Example: gcloud compute url-maps delete NAME --region=REGION -q
60
+ def down_command
61
+ "gcloud compute #{gcloud_compute_command} delete #{resource_name} #{region_option} -q"
62
+ end
63
+
64
+ # Example: gcloud compute url-maps describe NAME --region=REGION > /dev/null 2>&1
65
+ def exist?
66
+ sh "gcloud compute #{gcloud_compute_command} describe #{resource_name} #{region_option} > /dev/null 2>&1", exit_on_fail: false
67
+ end
68
+
69
+ # Example: config.url_map or config.firewall_rule
70
+ def resource_config
71
+ config.send(resource_type)
72
+ end
73
+
74
+ def region_option
75
+ return if gcloud_compute_command == "firewall-rules" # does not use --region or --global
76
+ resource_config.region ? "--region=#{resource_config.region}" : "--global"
77
+ end
78
+
79
+ def valid?
80
+ !invalid?
81
+ end
82
+
83
+ def invalid?
84
+ empty_update? || invalid_command?
85
+ end
86
+
87
+ def invalid_command?
88
+ gcloud_compute_command == "url-maps" && action == "update"
89
+ end
90
+
91
+ def empty_update?
92
+ # Example: --global only is considered an empty update
93
+ # A non-empty update would be --port=80
94
+ action == "update" && !args.include?('=') ||
95
+ action == "update" && args == "--region=us-central1" # Command failed: gcloud compute forwarding-rules update demo-dev --region=us-central1
96
+ end
97
+
98
+ def down
99
+ sh down_command if exist?
100
+ end
101
+
102
+ def config
103
+ Glb.config
104
+ end
105
+
106
+ def format_option
107
+ format = ENV['GLB_SHOW_FORMAT'] || @options[:format] || Glb.config.show.format
108
+ option = "--format #{format}" if format
109
+ if format == "json"
110
+ option += " | jq" if installed?("jq")
111
+ end
112
+ option
113
+ end
114
+
115
+ def installed?(command)
116
+ system("type #{command} > /dev/null 2>&1")
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,9 @@
1
+ class Glb::Lb
2
+ class TargetHttpProxy < Resource
3
+ def default_options
4
+ {
5
+ url_map: url_map_name,
6
+ }
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ class Glb::Lb
2
+ class TargetHttpsProxy < TargetHttpProxy
3
+ end
4
+ end
@@ -0,0 +1,9 @@
1
+ class Glb::Lb
2
+ class UrlMap < Resource
3
+ def default_options
4
+ {
5
+ default_service: backend_service_name,
6
+ }
7
+ end
8
+ end
9
+ end
data/lib/glb/lb.rb ADDED
@@ -0,0 +1,110 @@
1
+ module Glb
2
+ class Lb < Glb::CLI::Base
3
+ include Util::Sure
4
+
5
+ def initialize(*)
6
+ super
7
+ @firewall_rule = FirewallRule.new(@options)
8
+ @health_check = HealthCheck.new(@options)
9
+ @backend_service = BackendService.new(@options)
10
+ @url_map = UrlMap.new(@options)
11
+ @target_http_proxy = TargetHttpProxy.new(@options)
12
+ @forwarding_rule = ForwardingRule.new(@options)
13
+ @target_https_proxy = TargetHttpsProxy.new(@options) if ssl?
14
+ @forwarding_rule_https = ForwardingRuleHttps.new(@options) if ssl?
15
+ end
16
+
17
+ def plan
18
+ puts "Planning..."
19
+ commands = [
20
+ @firewall_rule.up_command,
21
+ @health_check.up_command,
22
+ @backend_service.up_command,
23
+ @backend_service.backend.add_commands,
24
+ @url_map.up_command,
25
+ @target_http_proxy.up_command,
26
+ @forwarding_rule.up_command,
27
+ ].flatten.compact
28
+ if ssl?
29
+ commands += [
30
+ @target_https_proxy.up_command,
31
+ @forwarding_rule_https.up_command,
32
+ ]
33
+ end
34
+ print_will_run(commands)
35
+ end
36
+
37
+ def up
38
+ plan unless @options[:yes]
39
+ sure?
40
+ @firewall_rule.up
41
+ @health_check.up
42
+ @backend_service.up
43
+ @url_map.up
44
+ @target_http_proxy.up
45
+ @forwarding_rule.up
46
+ if ssl?
47
+ @target_https_proxy.up
48
+ @forwarding_rule_https.up
49
+ end
50
+ @forwarding_rule.show_ip
51
+ @forwarding_rule_https.show_ip if ssl?
52
+ end
53
+
54
+ def show
55
+ @firewall_rule.show
56
+ @health_check.show
57
+ @backend_service.show
58
+ @url_map.show
59
+ @target_http_proxy.show
60
+ @forwarding_rule.show
61
+ if ssl?
62
+ @target_https_proxy.show
63
+ @forwarding_rule_https.show
64
+ end
65
+ end
66
+
67
+ def print_will_run(commands)
68
+ list = commands.map { |command| " #{command}" }.join("\n")
69
+ puts "Will try to run:\n\n"
70
+ puts list
71
+ puts
72
+ end
73
+
74
+ def down_plan
75
+ commands = [
76
+ @forwarding_rule.down_command,
77
+ @target_http_proxy.down_command,
78
+ @url_map.down_command,
79
+ @backend_service.down_command,
80
+ @health_check.down_command,
81
+ @firewall_rule.down_command,
82
+ ]
83
+ if ssl?
84
+ commands = [
85
+ @forwarding_rule_https.down_command,
86
+ @target_https_proxy.down_command,
87
+ ] + commands
88
+ end
89
+ print_will_run(commands)
90
+ end
91
+
92
+ def down
93
+ down_plan unless @options[:yes]
94
+ sure?
95
+ @forwarding_rule_https.down if ssl?
96
+ @target_https_proxy.down if ssl?
97
+ @forwarding_rule.down
98
+ @target_http_proxy.down
99
+ @url_map.down
100
+ @backend_service.down
101
+ @health_check.down
102
+ @firewall_rule.down
103
+ end
104
+
105
+ private
106
+ def ssl?
107
+ Glb.config.lb.ssl_enabled
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,37 @@
1
+ module Glb::Util
2
+ module Sh
3
+ def sh(command, options={})
4
+ command.squish!
5
+ if options[:sure_prompt]
6
+ sure? <<~EOL.chomp
7
+ Will run: #{command}
8
+ Are you sure?
9
+ EOL
10
+ end
11
+
12
+ exit_on_fail = options[:exit_on_fail].nil? ? true : options[:exit_on_fail]
13
+ show_command = options[:show_command] != false
14
+
15
+ puts "=> #{command}".color(:green) if show_command
16
+ return if ENV['DRY_RUN']
17
+
18
+ success = system(command)
19
+ if !success && exit_on_fail
20
+ puts "Command failed: #{command}"
21
+ exit $?.exitstatus
22
+ end
23
+ success
24
+ end
25
+
26
+ def capture(command, options={})
27
+ command.squish!
28
+ puts "=> #{command}" unless options[:show_command] == false
29
+ out = `#{command}`
30
+ if $?.exitstatus != 0
31
+ puts "Error running command: #{command}"
32
+ exit $?.exitstatus
33
+ end
34
+ out
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,18 @@
1
+
2
+ module Glb::Util
3
+ module Sure
4
+ def sure?(message="Are you sure?")
5
+ if @options[:yes] || ENV['GLB_YES']
6
+ sure = 'y'
7
+ else
8
+ print "#{message} (y/N) "
9
+ sure = $stdin.gets
10
+ end
11
+
12
+ unless sure =~ /^y/
13
+ puts "Whew! Exiting."
14
+ exit 0
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Glb
2
+ VERSION = "0.1.1"
3
+ end
data/lib/glb.rb ADDED
@@ -0,0 +1,22 @@
1
+ $stdout.sync = true unless ENV["GLB_STDOUT_SYNC"] == "0"
2
+
3
+ $:.unshift(File.expand_path("../", __FILE__))
4
+
5
+ require "glb/autoloader"
6
+ Glb::Autoloader.setup
7
+
8
+ require "memoist"
9
+ require "rainbow/ext/string"
10
+ require "active_support"
11
+ require "active_support/core_ext/hash"
12
+ require "active_support/core_ext/string"
13
+ require "json"
14
+ require "dsl_evaluator"
15
+
16
+ DslEvaluator.backtrace_reject = "lib/glb"
17
+
18
+ module Glb
19
+ extend Memoist
20
+ class Error < StandardError; end
21
+ extend Core
22
+ end
data/spec/cli_spec.rb ADDED
@@ -0,0 +1,26 @@
1
+ describe Glb::CLI do
2
+ before(:all) do
3
+ @args = "--from Tung"
4
+ end
5
+
6
+ describe "glb" do
7
+ it "hello" do
8
+ out = execute("exe/glb hello world #{@args}")
9
+ expect(out).to include("from: Tung\nHello world")
10
+ end
11
+
12
+ commands = {
13
+ "hell" => "hello",
14
+ "hello" => "name",
15
+ "hello -" => "--from",
16
+ "hello name" => "--from",
17
+ "hello name --" => "--from",
18
+ }
19
+ commands.each do |command, expected_word|
20
+ it "completion #{command}" do
21
+ out = execute("exe/glb completion #{command}")
22
+ expect(out).to include(expected_word) # only checking for one word for simplicity
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ ENV["GLB_TEST"] = "1"
2
+
3
+ # CodeClimate test coverage: https://docs.codeclimate.com/docs/configuring-test-coverage
4
+ # require 'simplecov'
5
+ # SimpleCov.start
6
+
7
+ require "pp"
8
+ require "byebug"
9
+ root = File.expand_path("../", File.dirname(__FILE__))
10
+ require "#{root}/lib/glb"
11
+
12
+ module Helper
13
+ def execute(cmd)
14
+ puts "Running: #{cmd}" if show_command?
15
+ out = `#{cmd}`
16
+ puts out if show_command?
17
+ out
18
+ end
19
+
20
+ # Added SHOW_COMMAND because DEBUG is also used by other libraries like
21
+ # bundler and it shows its internal debugging logging also.
22
+ def show_command?
23
+ ENV['DEBUG'] || ENV['SHOW_COMMAND']
24
+ end
25
+ end
26
+
27
+ RSpec.configure do |c|
28
+ c.include Helper
29
+ end
metadata ADDED
@@ -0,0 +1,245 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: glb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Tung Nguyen
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-05-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
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: dsl_evaluator
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: memoist
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
+ - !ruby/object:Gem::Dependency
56
+ name: rainbow
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: thor
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: zeitwerk
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: bundler
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: byebug
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: cli_markdown
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rake
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: rspec
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ description:
168
+ email:
169
+ - tongueroo@gmail.com
170
+ executables:
171
+ - glb
172
+ extensions: []
173
+ extra_rdoc_files: []
174
+ files:
175
+ - ".gitignore"
176
+ - ".rspec"
177
+ - CHANGELOG.md
178
+ - Gemfile
179
+ - Guardfile
180
+ - LICENSE.txt
181
+ - README.md
182
+ - Rakefile
183
+ - docs/external.md
184
+ - docs/internal.md
185
+ - docs/ssl.md
186
+ - docs/static-ip-address.md
187
+ - exe/glb
188
+ - glb.gemspec
189
+ - lib/glb.rb
190
+ - lib/glb/autoloader.rb
191
+ - lib/glb/cli.rb
192
+ - lib/glb/cli/base.rb
193
+ - lib/glb/cli/help.rb
194
+ - lib/glb/cli/help/completion.md
195
+ - lib/glb/cli/help/completion_script.md
196
+ - lib/glb/command.rb
197
+ - lib/glb/completer.rb
198
+ - lib/glb/completer/script.rb
199
+ - lib/glb/completer/script.sh
200
+ - lib/glb/config.rb
201
+ - lib/glb/core.rb
202
+ - lib/glb/lb.rb
203
+ - lib/glb/lb/args.rb
204
+ - lib/glb/lb/backend_service.rb
205
+ - lib/glb/lb/backend_service/backend.rb
206
+ - lib/glb/lb/firewall_rule.rb
207
+ - lib/glb/lb/forwarding_rule.rb
208
+ - lib/glb/lb/forwarding_rule_https.rb
209
+ - lib/glb/lb/health_check.rb
210
+ - lib/glb/lb/names.rb
211
+ - lib/glb/lb/resource.rb
212
+ - lib/glb/lb/target_http_proxy.rb
213
+ - lib/glb/lb/target_https_proxy.rb
214
+ - lib/glb/lb/url_map.rb
215
+ - lib/glb/util/sh.rb
216
+ - lib/glb/util/sure.rb
217
+ - lib/glb/version.rb
218
+ - spec/cli_spec.rb
219
+ - spec/spec_helper.rb
220
+ homepage: https://github.com/boltops-tools/glb
221
+ licenses:
222
+ - Apache2.0
223
+ metadata: {}
224
+ post_install_message:
225
+ rdoc_options: []
226
+ require_paths:
227
+ - lib
228
+ required_ruby_version: !ruby/object:Gem::Requirement
229
+ requirements:
230
+ - - ">="
231
+ - !ruby/object:Gem::Version
232
+ version: '0'
233
+ required_rubygems_version: !ruby/object:Gem::Requirement
234
+ requirements:
235
+ - - ">="
236
+ - !ruby/object:Gem::Version
237
+ version: '0'
238
+ requirements: []
239
+ rubygems_version: 3.3.26
240
+ signing_key:
241
+ specification_version: 4
242
+ summary: Google Load Balanacer Tool
243
+ test_files:
244
+ - spec/cli_spec.rb
245
+ - spec/spec_helper.rb