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
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9e9b2940b5d66eed7e9a2a998d8f2a6d38a0407277d22fdc242371b44235e5cc
4
+ data.tar.gz: 21bc007d1f5347d8948492e291ba7f0d238d4c7005124b367ab14bf9e423ab7a
5
+ SHA512:
6
+ metadata.gz: 6e9a3a1d25a8ccb9ab4d03eb35d049db46f67a1dfe5562a839840a6c510f5bda518c261dcc02d3dc0cb970e2a8ff3ef2e6bf5ae50137f1fa223b77f927b5056b
7
+ data.tar.gz: 3b1a02edecf4226c17708d3d92d541e3f5ac2ddb4ebfa8a79687f7833a8da139333970db4685cf7d7e9cd89eac98082a7e2ffd6ba90850ced95012586a451f44
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ /.bundle
4
+ /.config
5
+ /.yardoc
6
+ /_yardoc
7
+ /coverage
8
+ /doc/
9
+ /Gemfile.lock
10
+ /InstalledFiles
11
+ /lib/bundler/man
12
+ /pkg
13
+ /rdoc
14
+ /spec/reports
15
+ /test/tmp
16
+ /test/version_tmp
17
+ /tmp
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --require spec_helper
2
+ --color
3
+ --format documentation
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Change Log
2
+
3
+ All notable changes to this project will be documented in this file.
4
+ This project *loosely tries* to adhere to [Semantic Versioning](http://semver.org/), even before v1.0.
5
+
6
+ ## [0.1.0]
7
+ - Initial release.
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem dependencies in glb.gemspec
4
+ gemspec
5
+
6
+ gem "codeclimate-test-reporter", group: :test, require: nil
data/Guardfile ADDED
@@ -0,0 +1,19 @@
1
+ guard "bundler", cmd: "bundle" do
2
+ watch("Gemfile")
3
+ watch(/^.+\.gemspec/)
4
+ end
5
+
6
+ guard :rspec, cmd: "bundle exec rspec" do
7
+ require "guard/rspec/dsl"
8
+ dsl = Guard::RSpec::Dsl.new(self)
9
+
10
+ # RSpec files
11
+ rspec = dsl.rspec
12
+ watch(rspec.spec_helper) { rspec.spec_dir }
13
+ watch(rspec.spec_support) { rspec.spec_dir }
14
+ watch(rspec.spec_files)
15
+
16
+ # Ruby files
17
+ ruby = dsl.ruby
18
+ dsl.watch_spec_files_for(ruby.lib_files)
19
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1 @@
1
+ Proprietary, All rights reserved. For licensing and terms, please refer to https://www.boltops.com/terms
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # Glb
2
+
3
+ Create and delete Google Load Balancer components.
4
+
5
+ Pros:
6
+
7
+ * The tool wraps gcloud commands. This helps those who are familiar with gcloud commands and are referencing google cloud docs.
8
+
9
+ Cons/Limitations:
10
+
11
+ * The tool assumes that the source of truth is the configuration. It does not detect and will update and overwrite any manual changes that does not match the configuration.
12
+ * This is notably different from terraform which will perform a diff calculation, which can provide a diff in the plan.
13
+ * The `gcloud compute [RESOURCE] update` will not run if there are no attributes in the command, else `gcloud` reports an error.
14
+
15
+ ## Usage
16
+
17
+ Commands:
18
+
19
+ glb plan APP
20
+ glb up APP
21
+ glb down APP
22
+ glb show APP
23
+
24
+ APP is your app name. IE: demo
25
+
26
+ ## Docs
27
+
28
+ * [External Load Balancer (Global)](docs/external.md)
29
+ * [Internal Load Balancer (Region)](docs/internal.md)
30
+
31
+ ## Resources
32
+
33
+ The tool creates these resources:
34
+
35
+ * firewall rule
36
+ * health check
37
+ * backend service
38
+ * url map
39
+ * target http proxy
40
+ * forwarding rule
41
+
42
+ If SSL is enabled it'll also create a
43
+
44
+ * target https proxy (associated with the same url map)
45
+ * forwarding rule (associated with the target https proxy)
46
+
47
+ The same url map is used because that's what shows up as a Load Balancer in the Google console.
48
+
49
+ ## Installation
50
+
51
+ gem install glb
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ task default: :spec
5
+
6
+ RSpec::Core::RakeTask.new
data/docs/external.md ADDED
@@ -0,0 +1,19 @@
1
+ # External Load Balancer (global)
2
+
3
+ .glb/config.rb
4
+
5
+ ```ruby
6
+ Glb.configure do |config|
7
+ config.firewall_rule.network = "dev"
8
+ config.firewall_rule.target_tags = "demo-web-dev"
9
+ config.firewall_rule.rules = "tcp:8080"
10
+
11
+ config.network_endpoint_group = "demo-web-dev-80-neg"
12
+
13
+ config.health_check.port = 8080
14
+ end
15
+ ```
16
+
17
+ To create load balancer run:
18
+
19
+ glb up demo
data/docs/internal.md ADDED
@@ -0,0 +1,65 @@
1
+ # Internal Load Balancer (region)
2
+
3
+ Internal load balancers require a configuration that includes region, network, and subnet. It also requires a firewall rule allowing the access from the load balancer proxy only subnet.
4
+
5
+ ## Recommended config.lb shorthand
6
+
7
+ Here's an example with the suggested `config.rb` options:
8
+
9
+ ```ruby
10
+ Glb.configure do |config|
11
+ config.firewall_rule.target_tags = "gke-dev-cluster-9696112c-node"
12
+ config.firewall_rule.rules = "tcp:8080"
13
+ config.health_check.port = 8080
14
+ config.backend_service.add_backend.network_endpoint_group = "demo-web-dev-80-neg"
15
+
16
+ # ranges:
17
+ # load balancer health check: 130.211.0.0/22,35.191.0.0/16
18
+ # dev-proxy: 10.80.1.0/24
19
+ config.firewall_rule.source_ranges = "130.211.0.0/22,35.191.0.0/16,10.80.1.0/24"
20
+
21
+ # internal load balancer shorthand config.lb. maps to health_check, backend_service, url_map, target_http_proxy, forwarding_rule options
22
+ config.lb.region = "us-central1"
23
+ config.lb.load_balancing_scheme = "INTERNAL_MANAGED"
24
+ config.lb.network = "dev"
25
+ config.lb.subnet = "dev-app"
26
+ end
27
+ ```
28
+
29
+ ## Explicit config long form
30
+
31
+ You can also more explicitly set each component options. The previous config is the same as this one below. The `config.lb` options simply map to the underlying resource options.
32
+
33
+ ```ruby
34
+ Glb.configure do |config|
35
+ config.firewall_rule.target_tags = "gke-dev-cluster-9696112c-node"
36
+ config.firewall_rule.rules = "tcp:8080"
37
+ config.health_check.port = 8080
38
+ config.backend_service.add_backend.network_endpoint_group = "demo-web-dev-80-neg"
39
+
40
+ # ranges:
41
+ # load balancer health check: 130.211.0.0/22,35.191.0.0/16
42
+ # dev-proxy: 10.80.1.0/24
43
+ # IMPORTANT: allow the proxy only subnet to access in the firewall rule
44
+ # or else you won't be able to reach the internal LB IP
45
+ config.firewall_rule.source_ranges = "130.211.0.0/22,35.191.0.0/16,10.80.1.0/24"
46
+
47
+ # internal load balancer: specific resource options
48
+ config.health_check.region = "us-central1"
49
+ config.backend_service.load_balancing_scheme = "INTERNAL_MANAGED"
50
+ config.backend_service.region = "us-central1"
51
+ config.backend_service.health_checks_region = "us-central1"
52
+ config.backend_service.add_backend.region = "us-central1"
53
+ config.url_map.region = "us-central1" # not updatable
54
+ config.target_http_proxy.region = "us-central1"
55
+ config.forwarding_rule.region = "us-central1"
56
+ config.forwarding_rule.network = "dev"
57
+ config.forwarding_rule.subnet = "dev-app"
58
+ config.forwarding_rule.load_balancing_scheme = "INTERNAL_MANAGED"
59
+ config.forwarding_rule.target_http_proxy_region = "us-central1"
60
+ end
61
+ ```
62
+
63
+ To create load balancer run:
64
+
65
+ glb up demo
data/docs/ssl.md ADDED
@@ -0,0 +1,33 @@
1
+ # SSL or HTTPS support
2
+
3
+ Below are examples on how to configure ssl.
4
+
5
+ ## External (global)
6
+
7
+ Create the google managed cert.
8
+
9
+ gcloud compute ssl-certificates create demo-dev --global --domains demo-dev.example.com
10
+
11
+ .glb/config.rb
12
+
13
+ ```ruby
14
+ Glb.configure do |config|
15
+ config.lb.ssl_enabled = true
16
+ config.lb.ssl_certificates = "demo-dev"
17
+ end
18
+ ```
19
+
20
+ ## Internal (region)
21
+
22
+ Create the google unmanaged cert.
23
+
24
+ gcloud compute ssl-certificates create demo-dev --certificate certificate.crt --certificate ca_bundle.crt --private-key private.key
25
+
26
+ .glb/config.rb
27
+
28
+ ```ruby
29
+ Glb.configure do |config|
30
+ config.lb.ssl_enabled = true
31
+ config.lb.ssl_certificates = "demo-dev"
32
+ end
33
+ ```
@@ -0,0 +1,30 @@
1
+ # Static IP Address
2
+
3
+ ## External (global)
4
+
5
+ To configure a pre-allocated static ip address:
6
+
7
+ gcloud compute addresses create demo-dev --global
8
+ gcloud compute addresses create demo-https-dev --global # if using https
9
+
10
+ .glb/config.rb
11
+
12
+ ```ruby
13
+ Glb.configure do |config|
14
+ config.firewall_rule.network = "dev"
15
+ config.firewall_rule.target_tags = "demo-web-dev"
16
+ config.firewall_rule.rules = "tcp:8080"
17
+
18
+ config.network_endpoint_group = "demo-web-dev-80-neg"
19
+
20
+ config.health_check.port = 8080
21
+
22
+ config.forwarding_rule.address = "demo-dev"
23
+ # config.forwarding_rule_https.address = "demo-https-dev" # if using https
24
+ end
25
+ ```
26
+
27
+ IMPORTANT: The [gcloud compute forwarding-rules update](https://cloud.google.com/sdk/gcloud/reference/compute/forwarding-rules/update) command does not support updating the static IP address. You have to delete the forwarding rule and recreate it.
28
+
29
+ gcloud compute forwarding-rules delete demo-dev --global
30
+
data/exe/glb ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Trap ^C
4
+ Signal.trap("INT") {
5
+ puts "\nCtrl-C detected. Exiting..."
6
+ sleep 0.1
7
+ exit
8
+ }
9
+
10
+ $:.unshift(File.expand_path("../../lib", __FILE__))
11
+ require "glb"
12
+ require "glb/cli"
13
+
14
+ Glb::CLI.start(ARGV)
data/glb.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "glb/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "glb"
8
+ spec.version = Glb::VERSION
9
+ spec.authors = ["Tung Nguyen"]
10
+ spec.email = ["tongueroo@gmail.com"]
11
+ spec.summary = "Google Load Balanacer Tool"
12
+ spec.homepage = "https://github.com/boltops-tools/glb"
13
+ spec.license = "Apache2.0"
14
+
15
+ spec.files = File.directory?('.git') ? `git ls-files`.split($/) : Dir.glob("**/*")
16
+ spec.bindir = "exe"
17
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activesupport"
22
+ spec.add_dependency "dsl_evaluator"
23
+ spec.add_dependency "memoist"
24
+ spec.add_dependency "rainbow"
25
+ spec.add_dependency "thor"
26
+ spec.add_dependency "zeitwerk"
27
+
28
+ spec.add_development_dependency "bundler"
29
+ spec.add_development_dependency "byebug"
30
+ spec.add_development_dependency "cli_markdown"
31
+ spec.add_development_dependency "rake"
32
+ spec.add_development_dependency "rspec"
33
+ end
@@ -0,0 +1,21 @@
1
+ require "zeitwerk"
2
+
3
+ module Glb
4
+ class Autoloader
5
+ class Inflector < Zeitwerk::Inflector
6
+ def camelize(basename, _abspath)
7
+ map = { cli: "CLI", version: "VERSION" }
8
+ map[basename.to_sym] || super
9
+ end
10
+ end
11
+
12
+ class << self
13
+ def setup
14
+ loader = Zeitwerk::Loader.new
15
+ loader.inflector = Inflector.new
16
+ loader.push_dir(File.dirname(__dir__)) # lib
17
+ loader.setup
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ class Glb::CLI
2
+ class Base
3
+ include Glb::Util::Sh
4
+
5
+ attr_reader :options
6
+ def initialize(options)
7
+ @options = options
8
+ @name = options[:name] # IE: demo-web-dev
9
+ end
10
+
11
+ def region
12
+ @options[:region] || ENV['GOOGLE_REGION'] || "us-central1"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,20 @@
1
+ ## Examples
2
+
3
+ glb completion
4
+
5
+ Prints words for TAB auto-completion.
6
+
7
+ glb completion
8
+ glb completion hello
9
+ glb completion hello name
10
+
11
+ To enable, TAB auto-completion add the following to your profile:
12
+
13
+ eval $(glb completion_script)
14
+
15
+ Auto-completion example usage:
16
+
17
+ glb [TAB]
18
+ glb hello [TAB]
19
+ glb hello name [TAB]
20
+ glb hello name --[TAB]
@@ -0,0 +1,3 @@
1
+ To use, add the following to your `~/.bashrc` or `~/.profile`
2
+
3
+ eval $(glb completion_script)
@@ -0,0 +1,11 @@
1
+ class Glb::CLI
2
+ module Help
3
+ class << self
4
+ def text(namespaced_command)
5
+ path = namespaced_command.to_s.gsub(':','/')
6
+ path = File.expand_path("../help/#{path}.md", __FILE__)
7
+ IO.read(path) if File.exist?(path)
8
+ end
9
+ end
10
+ end
11
+ end
data/lib/glb/cli.rb ADDED
@@ -0,0 +1,48 @@
1
+ module Glb
2
+ class CLI < Command
3
+ class_option :verbose, type: :boolean
4
+ class_option :noop, type: :boolean
5
+
6
+ desc "plan", "plan load balancer"
7
+ long_desc Help.text("plan")
8
+ def plan(name)
9
+ Glb::Lb.new(@options.merge(name: name)).plan
10
+ end
11
+
12
+ desc "up", "create or update load balancer"
13
+ long_desc Help.text("up")
14
+ def up(name)
15
+ Glb::Lb.new(@options.merge(name: name)).up
16
+ end
17
+
18
+ desc "show", "show load balancer"
19
+ long_desc Help.text("show")
20
+ option :format, desc: "formats: config, csv, default, diff, disable, flattened, get, json, list, multi, none, object, table, text, value, yaml"
21
+ def show(name)
22
+ Glb::Lb.new(@options.merge(name: name)).show
23
+ end
24
+
25
+ desc "down", "down load balancer"
26
+ long_desc Help.text("down")
27
+ def down(name)
28
+ Glb::Lb.new(@options.merge(name: name)).down
29
+ end
30
+
31
+ desc "completion *PARAMS", "Prints words for auto-completion."
32
+ long_desc Help.text(:completion)
33
+ def completion(*params)
34
+ Completer.new(CLI, *params).run
35
+ end
36
+
37
+ desc "completion_script", "Generates a script that can be eval to setup auto-completion."
38
+ long_desc Help.text(:completion_script)
39
+ def completion_script
40
+ Completer::Script.generate
41
+ end
42
+
43
+ desc "version", "prints version"
44
+ def version
45
+ puts VERSION
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,91 @@
1
+ require "thor"
2
+
3
+ # Override thor's long_desc identation behavior
4
+ # https://github.com/erikhuda/thor/issues/398
5
+ class Thor
6
+ module Shell
7
+ class Basic
8
+ def print_wrapped(message, options = {})
9
+ message = "\n#{message}" unless message[0] == "\n"
10
+ stdout.puts message
11
+ end
12
+ end
13
+ end
14
+ end
15
+
16
+ module Glb
17
+ class Command < Thor
18
+ class_option :yes, aliases: :y, type: :boolean
19
+
20
+ class << self
21
+ def dispatch(m, args, options, config)
22
+ # Allow calling for help via:
23
+ # glb command help
24
+ # glb command -h
25
+ # glb command --help
26
+ # glb command -D
27
+ #
28
+ # as well thor's normal way:
29
+ #
30
+ # glb help command
31
+ help_flags = Thor::HELP_MAPPINGS + ["help"]
32
+ if args.length > 1 && !(args & help_flags).empty?
33
+ args -= help_flags
34
+ args.insert(-2, "help")
35
+ end
36
+
37
+ # glb version
38
+ # glb --version
39
+ # glb -v
40
+ version_flags = ["--version", "-v"]
41
+ if args.length == 1 && !(args & version_flags).empty?
42
+ args = ["version"]
43
+ end
44
+
45
+ super
46
+ end
47
+
48
+ # Override command_help to include the description at the top of the
49
+ # long_description.
50
+ def command_help(shell, command_name)
51
+ meth = normalize_command_name(command_name)
52
+ command = all_commands[meth]
53
+ alter_command_description(command)
54
+ super
55
+ end
56
+
57
+ def alter_command_description(command)
58
+ return unless command
59
+
60
+ # Add description to beginning of long_description
61
+ long_desc = if command.long_description
62
+ "#{command.description}\n\n#{command.long_description}"
63
+ else
64
+ command.description
65
+ end
66
+
67
+ # add reference url to end of the long_description
68
+ unless website.empty?
69
+ full_command = [command.ancestor_name, command.name].compact.join('-')
70
+ url = "#{website}/reference/glb-#{full_command}"
71
+ long_desc += "\n\nHelp also available at: #{url}"
72
+ end
73
+
74
+ command.long_description = long_desc
75
+ end
76
+ private :alter_command_description
77
+
78
+ # meant to be overriden
79
+ def website
80
+ ""
81
+ end
82
+
83
+ # https://github.com/erikhuda/thor/issues/244
84
+ # Deprecation warning: Thor exit with status 0 on errors. To keep this behavior, you must define `exit_on_failure?` in `Lono::CLI`
85
+ # You can silence deprecations warning by setting the environment variable THOR_SILENCE_DEPRECATION.
86
+ def exit_on_failure?
87
+ true
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,8 @@
1
+ class Glb::Completer
2
+ class Script
3
+ def self.generate
4
+ bash_script = File.expand_path("script.sh", File.dirname(__FILE__))
5
+ puts "source #{bash_script}"
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,10 @@
1
+ _glb() {
2
+ COMPREPLY=()
3
+ local word="${COMP_WORDS[COMP_CWORD]}"
4
+ local words=("${COMP_WORDS[@]}")
5
+ unset words[0]
6
+ local completion=$(glb completion ${words[@]})
7
+ COMPREPLY=( $(compgen -W "$completion" -- "$word") )
8
+ }
9
+
10
+ complete -F _glb glb