gitlab-cluster-helper 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 4b0d3dfbb8dee26f71a7365cf7bd10d21388154e4e17dfc7289ccfe58afe12ee
4
+ data.tar.gz: ad916830538153410269717311b0da002d72817457b840475dfd45945fd863c7
5
+ SHA512:
6
+ metadata.gz: 6222e71d29a7144f954147187e482373e047990d46bd719502d4c2d5a1d236e58b0dba38eb0ae077ef75c14f3c4991cde17ef0e1feaa2ffa92a658e1734208f8
7
+ data.tar.gz: 8fc553492b555b557e225e1b9b6f5b01a5377a7d714b3c7b683ec9f3a154eb962a672947330a68dcaea6d785dd95b348f11b806460e2d4e641a4bf2f3316e2a3
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+
10
+ # rspec failure tracking
11
+ .rspec_status
12
+ /Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.5.3
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ sudo: false
3
+ language: ruby
4
+ cache: bundler
5
+ rvm:
6
+ - 2.4.4
7
+ before_install: gem install bundler -v 2.0.1
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in gitlab-cluster-helper.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Dylan Griffith
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # Gitlab Cluster Helper
2
+ This is a command line tool you can run locally to help you create and delete clusters easily for doing local development with GitLab features that require a Kubernetes cluster. It will orchestrate Kubernetes cluster and should speed up your development compared to doing all of the setup manually each time you want to try something out.
3
+ It's very common to need to create a new cluster every time you need to test
4
+ out a new feature and then since it's difficult to re-use a cluster for running
5
+ the same test again you will usually find that you need to destroy and recreate
6
+ a new cluster which can take time.
7
+
8
+ The goal of this tool is to speed up this flow by doing the following things
9
+ for you:
10
+
11
+ - [X] Create clusters
12
+ - [X] Delete clusters when you are done with them
13
+ - [X] Have one spare cluster ready to go at all times (so you don't need to
14
+ wait minutes to get a new cluster)
15
+ - [ ] Add the cluster directly to GitLab to save you copy/pasting
16
+
17
+ ## Installation
18
+
19
+ ```
20
+ $ gem install gitlab-cluster-helper
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ### Setup `gcloud` and `kubectl`
26
+
27
+ If you have been doing GCP and Kubernetes stuff locally you will probably
28
+ already have these setup and can therefor skip these instructions.
29
+
30
+ If not following the instructions at https://cloud.google.com/sdk/install .
31
+
32
+ After installing `gcloud` you can install `kubectl` like:
33
+
34
+ ```
35
+ $ gcloud components install kubectl
36
+ ```
37
+
38
+ Make sure you're also signed in to `gcloud` by running:
39
+
40
+ ```
41
+ $ gcloud auth login
42
+ ```
43
+
44
+ ### Set up the config file
45
+
46
+ Create a file at `~/.gitlab-cluster-helper-config.json` with the following content:
47
+
48
+ ```json
49
+ {
50
+ "gcp_project": "Enter the GCP project ID here",
51
+ "gcp_zone": "The zone where clusters are created (eg. us-central1-a)",
52
+ "cluster_prefix": "The prefix to use for naming your clusters (eg. dgriffith)"
53
+ }
54
+ ```
55
+
56
+ ### Run the application
57
+
58
+ ```
59
+ $ gitlab-cluster-helper
60
+ c) Create new cluster and show credentials
61
+ q) Quit application and clean up any clusters that were created
62
+ ```
63
+
64
+ ## Development
65
+
66
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run
67
+ `rake spec` to run the tests. You can also run `bin/console` for an interactive
68
+ prompt that will allow you to experiment.
69
+
70
+ To install this gem onto your local machine, run `bundle exec rake install`. To
71
+ release a new version, update the version number in `version.rb`, and then run
72
+ `bundle exec rake release`, which will create a git tag for the version, push
73
+ git commits and tags, and push the `.gem` file to
74
+ [rubygems.org](https://rubygems.org).
75
+
76
+ ### Running mocked GCP locally
77
+
78
+ When testing the application locally you may prefer to not really be creating
79
+ GCP clusters. So you can easily used a mocked version that sleeps for 5s before
80
+ creating a fake cluster:
81
+
82
+ ```bash
83
+ $ ruby -I lib -r gitlab_cluster_helper/dummy_gcp_client exe/gitlab-cluster-helper
84
+ ```
85
+
86
+ The 5s delay helps with testing out the behaviour where it starts creating the
87
+ next cluster before you've asked for it.
88
+
89
+ ## Contributing
90
+
91
+ Bug reports and pull requests are welcome on GitLab at
92
+ https://gitlab.com/DylanGriffith/gitlab-cluster-helper/issues .
93
+
94
+ ## License
95
+
96
+ The gem is available as open source under the terms of the [MIT
97
+ License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "gitlab/cluster/helper"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'gitlab_cluster_helper'
4
+
5
+ GitlabClusterHelper::Runner.new.start
@@ -0,0 +1,39 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "gitlab_cluster_helper/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "gitlab-cluster-helper"
8
+ spec.version = GitlabClusterHelper::VERSION
9
+ spec.authors = ["Dylan Griffith"]
10
+ spec.email = ["dyl.griffith@gmail.com"]
11
+
12
+ spec.summary = %q{GitLab Cluster Helper helps you work with clusters when doing local GitLab development.}
13
+ spec.description = %q{GitLab Cluster Helper helps you work with clusters when doing local GitLab development.}
14
+ spec.homepage = "https://gitlab.com/DylanGriffith/gitlab-cluster-helper"
15
+ spec.license = "MIT"
16
+
17
+ # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
18
+ # to allow pushing to a single host or delete this section to allow pushing to any host.
19
+ if spec.respond_to?(:metadata)
20
+ spec.metadata["homepage_uri"] = spec.homepage
21
+ spec.metadata["source_code_uri"] = "https://gitlab.com/DylanGriffith/gitlab-cluster-helper"
22
+ else
23
+ raise "RubyGems 2.0 or newer is required to protect against " \
24
+ "public gem pushes."
25
+ end
26
+
27
+ # Specify which files should be added to the gem when it is released.
28
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
29
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
30
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
31
+ end
32
+ spec.bindir = "exe"
33
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
34
+ spec.require_paths = ["lib"]
35
+
36
+ spec.add_development_dependency "bundler", "~> 2.0"
37
+ spec.add_development_dependency "rake", "~> 10.0"
38
+ spec.add_development_dependency "rspec", "~> 3.0"
39
+ end
@@ -0,0 +1,11 @@
1
+ require "gitlab_cluster_helper/cluster"
2
+ require "gitlab_cluster_helper/config"
3
+ require "gitlab_cluster_helper/gcp_client"
4
+ require "gitlab_cluster_helper/manager"
5
+ require "gitlab_cluster_helper/messages"
6
+ require "gitlab_cluster_helper/runner"
7
+ require "gitlab_cluster_helper/shell"
8
+ require "gitlab_cluster_helper/version"
9
+
10
+ class GitlabClusterHelper
11
+ end
@@ -0,0 +1,12 @@
1
+ class GitlabClusterHelper
2
+ class Cluster
3
+ attr_reader :name, :api_url, :ca_certificate, :token
4
+
5
+ def initialize(name:,api_url:,ca_certificate:,token:)
6
+ @name = name
7
+ @api_url = api_url
8
+ @ca_certificate = ca_certificate
9
+ @token = token
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,27 @@
1
+ require 'singleton'
2
+ require 'pathname'
3
+
4
+ class GitlabClusterHelper
5
+ class Config
6
+ include Singleton
7
+
8
+ class Error < StandardError; end
9
+
10
+ attr_reader :gcp_project, :gcp_zone, :cluster_prefix
11
+
12
+ DEFAULT_PATH = Pathname.new('~').join('.gitlab-cluster-helper-config.json').expand_path
13
+
14
+ def initialize
15
+ path = ENV["GITLAB_CLUSTER_HELPER_CONFIG"] || DEFAULT_PATH
16
+
17
+ raise Error, "Config file does not exist at path: #{path}" unless Pathname.new(path).file?
18
+
19
+ json = File.read(path)
20
+ data = JSON.parse(json)
21
+
22
+ @gcp_project = data['gcp_project']
23
+ @gcp_zone = data['gcp_zone']
24
+ @cluster_prefix = data['cluster_prefix']
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ require 'gitlab_cluster_helper'
2
+
3
+ class GitlabClusterHelper
4
+ class GcpClient
5
+ def create_cluster
6
+ sleep 5
7
+
8
+ Cluster.new({
9
+ name: "fake-cluster-#{Time.now.strftime("%Y-%m-%dt%Hh%Mm%Ss")}",
10
+ api_url: 'fake-url',
11
+ ca_certificate: 'fake certificate',
12
+ token: 'fake-token'
13
+ })
14
+ end
15
+
16
+ def delete_cluster(cluster_name)
17
+ puts "Deleting: #{cluster_name}"
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,62 @@
1
+ require 'json'
2
+ require 'base64'
3
+
4
+ class GitlabClusterHelper
5
+ class GcpClient
6
+ def initialize(config: GitlabClusterHelper::Config.instance, shell: GitlabClusterHelper::Shell.new)
7
+ @config = config
8
+ @shell = shell
9
+ end
10
+
11
+ def create_cluster
12
+ cluster_name = "#{@config.cluster_prefix}-#{Time.now.strftime("%Y-%m-%dt%Hh%Mm%Ss")}"
13
+ @shell.run([*gcloud, 'container', 'clusters', 'create', '--zone', @config.gcp_zone, cluster_name, '--enable-basic-auth'])
14
+
15
+ @shell.run([*gcloud, 'container', 'clusters', 'get-credentials', '--zone', @config.gcp_zone, cluster_name])
16
+
17
+ api_url = @shell.run(['kubectl', 'config', 'view', '--minify', '-o', "jsonpath='{.clusters[].cluster.server}'"])
18
+
19
+ auth_json = @shell.run([*gcloud, 'container', 'clusters', 'describe', '--zone', @config.gcp_zone, cluster_name, '--format', "json(masterAuth.username, masterAuth.password)"])
20
+
21
+ auth_data = JSON.parse(auth_json)
22
+ username = auth_data['masterAuth']['username']
23
+ password = auth_data['masterAuth']['password']
24
+
25
+ @shell.run(['kubectl', 'config', 'set-credentials', cluster_name, '--username', username, '--password', password])
26
+
27
+ @shell.run(['kubectl', 'create', 'serviceaccount', 'gitlab'])
28
+
29
+ @shell.run([
30
+ 'kubectl', '--user', username,
31
+ 'create', 'clusterrolebinding',
32
+ '--serviceaccount=default:gitlab', '--clusterrole=cluster-admin', 'gitlab-admin'
33
+ ])
34
+
35
+ secrets_json = @shell.run(['kubectl', 'get', 'secrets', '-o', 'json'])
36
+ secrets_data = JSON.parse(secrets_json)
37
+ gitlab_account = secrets_data['items'].find do |item|
38
+ item['metadata']['annotations']['kubernetes.io/service-account.name'] == 'gitlab'
39
+ end
40
+
41
+ ca_certificate = Base64.decode64(gitlab_account['data']['ca.crt'])
42
+ token = Base64.decode64(gitlab_account['data']['token'])
43
+
44
+ Cluster.new(
45
+ name: cluster_name,
46
+ api_url: api_url,
47
+ ca_certificate: ca_certificate,
48
+ token: token
49
+ )
50
+ end
51
+
52
+ def delete_cluster(cluster_name)
53
+ @shell.run([*gcloud, 'container', 'clusters', 'delete', '--zone', @config.gcp_zone, cluster_name, '--quiet', '--async'])
54
+ end
55
+
56
+ private
57
+
58
+ def gcloud
59
+ ['gcloud', '--project', @config.gcp_project]
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,38 @@
1
+ class GitlabClusterHelper
2
+ class Manager
3
+ def initialize(gcp_client: GitlabClusterHelper::GcpClient.new)
4
+ @gcp_client = gcp_client
5
+ @clusters = []
6
+ @next_cluster = nil
7
+ create_next_cluster
8
+ end
9
+
10
+ def create
11
+ @next_cluster_thread.join
12
+ cluster = @next_cluster
13
+ @next_cluster = nil
14
+ @clusters << cluster
15
+
16
+ create_next_cluster
17
+ cluster
18
+ end
19
+
20
+ def cleanup
21
+ @clusters.each do |cluster|
22
+ @gcp_client.delete_cluster(cluster.name)
23
+ end
24
+
25
+ @next_cluster_thread.join
26
+
27
+ @gcp_client.delete_cluster(@next_cluster.name)
28
+ end
29
+
30
+ def create_next_cluster
31
+ @next_cluster_thread = Thread.new {
32
+ next_cluster = @gcp_client.create_cluster
33
+
34
+ @next_cluster = next_cluster
35
+ }
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,7 @@
1
+ class GitlabClusterHelper
2
+ module Messages
3
+ CREATE = "Create new cluster and show credentials"
4
+ QUIT = "Quit application and clean up any clusters that were created"
5
+ GOODBYE = "Goodbye!"
6
+ end
7
+ end
@@ -0,0 +1,52 @@
1
+ require 'readline'
2
+
3
+ class GitlabClusterHelper
4
+ class Runner
5
+ def initialize(manager: GitlabClusterHelper::Manager.new, readline_class: Readline, output: $stdout)
6
+ @manager = manager
7
+ @readline_class = readline_class
8
+ @output = output
9
+ end
10
+
11
+ def start
12
+ print_help
13
+
14
+ while line = @readline_class.readline('> ', true)
15
+ if command = commands[line]
16
+ command[:command].call
17
+ end
18
+
19
+ @output.puts Messages::GOODBYE && break if line == 'q'
20
+
21
+ print_help
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def commands
28
+ {
29
+ 'c' => { message: Messages::CREATE, command: method(:create) },
30
+ 'q' => { message: Messages::QUIT, command: @manager.method(:cleanup) },
31
+ }
32
+ end
33
+
34
+ def create
35
+ cluster = @manager.create
36
+
37
+ @output.puts <<~END
38
+ Name: #{cluster.name}
39
+ Api URL: #{cluster.api_url}
40
+ Ca Certificate:
41
+ #{cluster.ca_certificate}
42
+ Token: #{cluster.token}
43
+ END
44
+ end
45
+
46
+ def print_help
47
+ commands.each do |key, command|
48
+ @output.puts "#{key}) #{command[:message]}"
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,26 @@
1
+ require 'open3'
2
+
3
+ class GitlabClusterHelper
4
+ class Shell
5
+ class Error < StandardError; end
6
+
7
+ def run(command)
8
+ puts "Running command: #{command.join(" ")}"
9
+ stdin, stdout, stderr, wait_thr = Open3.popen3(*command)
10
+
11
+ stdin.close
12
+
13
+ out = stdout.read
14
+ stdout.close
15
+
16
+ err = stderr.read
17
+ stderr.close
18
+
19
+ exit_status = wait_thr.value
20
+
21
+ raise Error, out + err unless exit_status.success?
22
+
23
+ out.chomp
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ class GitlabClusterHelper
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gitlab-cluster-helper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dylan Griffith
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-05-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ description: GitLab Cluster Helper helps you work with clusters when doing local GitLab
56
+ development.
57
+ email:
58
+ - dyl.griffith@gmail.com
59
+ executables:
60
+ - gitlab-cluster-helper
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".gitignore"
65
+ - ".rspec"
66
+ - ".ruby-version"
67
+ - ".travis.yml"
68
+ - Gemfile
69
+ - LICENSE.txt
70
+ - README.md
71
+ - Rakefile
72
+ - bin/console
73
+ - bin/setup
74
+ - exe/gitlab-cluster-helper
75
+ - gitlab-cluster-helper.gemspec
76
+ - lib/gitlab_cluster_helper.rb
77
+ - lib/gitlab_cluster_helper/cluster.rb
78
+ - lib/gitlab_cluster_helper/config.rb
79
+ - lib/gitlab_cluster_helper/dummy_gcp_client.rb
80
+ - lib/gitlab_cluster_helper/gcp_client.rb
81
+ - lib/gitlab_cluster_helper/manager.rb
82
+ - lib/gitlab_cluster_helper/messages.rb
83
+ - lib/gitlab_cluster_helper/runner.rb
84
+ - lib/gitlab_cluster_helper/shell.rb
85
+ - lib/gitlab_cluster_helper/version.rb
86
+ homepage: https://gitlab.com/DylanGriffith/gitlab-cluster-helper
87
+ licenses:
88
+ - MIT
89
+ metadata:
90
+ homepage_uri: https://gitlab.com/DylanGriffith/gitlab-cluster-helper
91
+ source_code_uri: https://gitlab.com/DylanGriffith/gitlab-cluster-helper
92
+ post_install_message:
93
+ rdoc_options: []
94
+ require_paths:
95
+ - lib
96
+ required_ruby_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ required_rubygems_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ requirements: []
107
+ rubyforge_project:
108
+ rubygems_version: 2.7.6
109
+ signing_key:
110
+ specification_version: 4
111
+ summary: GitLab Cluster Helper helps you work with clusters when doing local GitLab
112
+ development.
113
+ test_files: []