glb 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.
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