mina-kubernetes 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 1f1fd603c840045e6402d4eee5e82b997a3e31459b2e33f904bff8541cf4ce42
4
+ data.tar.gz: b31401cfce0e729fabbc51e0aa37841a7b6e907639fc5fa572046ac4e3916924
5
+ SHA512:
6
+ metadata.gz: 83b16882b97e8b5a1e2bfd13a2143955443c39d9fb3166c457457510cffd375e32b468a1d4fba608e0822425ebd61d9abd40a12a38fbcc037ea6d6707ad0abd4
7
+ data.tar.gz: 8cfc7cc45cb7dbf508a97ad3c3c6ecff2d094530672a3fb38676426d25448a2d676a0e362d45507cbf89066caa06db971864cfbf26878f360446f5c117f54ca3
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pkg/
data/README.md ADDED
@@ -0,0 +1,55 @@
1
+ # mina-kubernetes
2
+ Plugin for the [mina](https://github.com/mina-deploy/mina) deployment tool to streamline deployment of resources to Kubernetes cluster, using the [kubernetes-deploy](https://github.com/Shopify/kubernetes-deploy) gem and [mina-multistage](https://github.com/endoze/mina-multistage) plugin.
3
+
4
+ Requires local Docker and [kubectl](https://cloud.google.com/kubernetes-engine/docs/quickstart) with authentication set up to connect to the destination Kubernetes cluster.
5
+
6
+ ## Usage
7
+
8
+ Add `mina-kubernetes` to your local Gemfile.
9
+
10
+ Create a configuration file for mina in `config/deploy.rb` like the one below:
11
+ ```ruby
12
+ require "mina/default"
13
+ require "mina/kubernetes"
14
+
15
+ task :deploy do
16
+ invoke :"kubernetes:deploy"
17
+ end
18
+ ```
19
+
20
+ Add the following variables to your stage configuration i.e. `config/deploy/production.rb`:
21
+ ```ruby
22
+ set :app_name, "my_app"
23
+ set :image_repository, "gcr.io/project-id/myapp"
24
+ set :kubernetes_cluster, "kubernetes_cluster_name"
25
+ set :kubernetes_user, "kubernetes_user_name"
26
+ ```
27
+
28
+ If `set :image_tag, "my_image_tag"` is also defined, it'll be used to deploy the image tagged with this tag on the repository. Otherwise you'll be prompted to pick a branch from current working Git repository and the image to deploy will be assumed to be tagged with the Git commit hash, i.e. `gcr.io/project-123456/my_app:abcd1234`.
29
+
30
+ Optional configuration (showing default values):
31
+ ```ruby
32
+ set :kube_config, "~/.kube/config"
33
+ ```
34
+
35
+ Then create `*.yml.erb` Kubernetes resource definition files in the stage folder, i.e. `config/deploy/production/app.yml.erb`. Occurences of `<%= image_repo %>` and `<%= current_sha %>` in these files will be dynamically replaced on deploy by the image repository URL and the latest commit hash of the selected branch on its git origin.
36
+
37
+ When you run `mina production deploy`, a namespace labelled `my_app-production` will be created on the Kubernetes cluster and set as a local kubectl context. Then the resources are applied to the cluster after checking/waiting for the image to be available on the repository.
38
+
39
+ ### Tasks available
40
+
41
+ #### `kubernetes:deploy`
42
+
43
+ Creates namespace on cluster and assigns it to a local kubectl context, prompts for git branch if no image tag specified, applies all resources to cluster after checking tagged image is available.
44
+
45
+ #### `kubernetes:bash`
46
+
47
+ Prompts for branch unless image tag is set, then spins up a temporary pod with the image and opens up a remote bash terminal.
48
+
49
+ #### `kubernetes:command`
50
+
51
+ Prompts for branch unless image tag is set, then spins up a temporary pod with the image and run command given by task variable `command`, for instance with `set :command, "rails console"`. Environment variables can also be given by defining`env_hash`, i.e. `set :env_hash, {"RAILS_ENV" => "production", "MY_VAR" => "abcd123"}`
52
+
53
+ #### `kubernetes:delete`
54
+
55
+ Confirms and delete all resources on cluster under namespace `app_name-stage`.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,108 @@
1
+ require "tty-prompt"
2
+ require "tty-spinner"
3
+ require "securerandom"
4
+ require "json"
5
+ require "base64"
6
+
7
+ # required by mina
8
+ set :execution_mode, :pretty
9
+
10
+ # default for kubernetes-deploy
11
+ set :kube_config, "~/.kube/config"
12
+
13
+ namespace :kubernetes do
14
+
15
+ set :namespace, fetch(:app_name)
16
+ set :context, "#{fetch(:namespace)}-#{fetch(:stage)}"
17
+
18
+ task :deploy do
19
+ desc "Set image tag to be latest commit of prompted branch (unless provided) then applies resources to cluster"
20
+ set_tag_from_branch_commit unless fetch(:image_tag)
21
+ wait_until_image_ready(fetch(:image_tag))
22
+ create_namespace_on_cluster
23
+ set_local_config_context
24
+ apply_kubernetes_resources
25
+ end
26
+
27
+ task :bash do
28
+ desc "Spins up temporary pod with image and opens remote interactive bash"
29
+ set_tag_from_branch_commit unless fetch(:image_tag)
30
+ wait_until_image_ready(fetch(:image_tag))
31
+ run_terminal_command("bash")
32
+ end
33
+
34
+ task :command do
35
+ desc "Spins up temporary pod with image and runs given command in interactive shell, passing given environment variable"
36
+ set_tag_from_branch_commit unless fetch(:image_tag)
37
+ wait_until_image_ready(fetch(:image_tag))
38
+ run_terminal_command(fetch(:command), fetch(:env_hash))
39
+ end
40
+
41
+ task :delete do
42
+ desc "Delete all resources in namespace on cluster"
43
+ if TTY::Prompt.new.yes?("This will delete all resources in namespace #{fetch(:namespace)} on cluster #{fetch(:kubernetes_cluster)}, are you sure?")
44
+ run :local do
45
+ comment "Deleting all resources in #{fetch(:namespace)}..."
46
+ command "kubectl delete namespace #{fetch(:namespace)} --cluster=#{fetch(:kubernetes_cluster)}"
47
+ comment "Removing local config context..."
48
+ command "kubectl config unset contexts.#{fetch(:context)}"
49
+ end
50
+ end
51
+ end
52
+
53
+ end
54
+
55
+ private
56
+
57
+ def set_tag_from_branch_commit
58
+ run :local do
59
+ comment "Updating Git branches..."
60
+ end
61
+ remote_branches = `git fetch --prune && git branch -r --no-merged master --sort=-committerdate | grep origin`.split("\n").collect { |b| b.strip.gsub("origin/", "") }.reject { |b| b == "master" }
62
+ set :branch, TTY::Prompt.new.select("Which branch?", ["master"].concat(remote_branches))
63
+ set :image_tag, `git rev-parse origin/#{fetch(:branch)}`.split("\n")[0]
64
+ end
65
+
66
+ def create_namespace_on_cluster
67
+ run :local do
68
+ comment "Create/update namespace on Kubernetes cluster..."
69
+ command "kubectl create namespace #{fetch(:namespace)} --dry-run -o yaml | kubectl apply -f - --cluster=#{fetch(:kubernetes_cluster)}"
70
+ end
71
+ end
72
+
73
+ def set_local_config_context
74
+ run :local do
75
+ comment "Set up local Kubernetes config context..."
76
+ command "kubectl config set-context #{fetch(:context)} --namespace=#{fetch(:namespace)} --cluster=#{fetch(:kubernetes_cluster)} --user=#{fetch(:kubernetes_user)}"
77
+ end
78
+ end
79
+
80
+ def wait_until_image_ready(commit)
81
+ run :local do
82
+ comment "Check image #{fetch(:image_repo)}:#{commit} is available..."
83
+ end
84
+ spinner = TTY::Spinner.new
85
+ spinner.auto_spin
86
+ while !image_available?(commit)
87
+ sleep 5
88
+ end
89
+ spinner.stop
90
+ end
91
+
92
+ def image_available?(commit)
93
+ system("docker manifest inspect #{fetch(:image_repo)}:#{commit} > /dev/null") == true
94
+ end
95
+
96
+ def run_terminal_command(command, env_hash = {})
97
+ env = env_hash.collect{|k,v| "--env #{k}=#{v}" }.join(" ")
98
+ label = command.downcase.gsub(" ", "-").gsub(":", "-")
99
+ # using system instead of mina's command so tty opens successfully
100
+ system "kubectl run #{label}-#{SecureRandom.hex(4)} --rm -i --tty --restart=Never --context=#{fetch(:context)} --image #{fetch(:image_repo)}:#{fetch(:image_tag)} #{env} -- #{command}"
101
+ end
102
+
103
+ def apply_kubernetes_resources
104
+ run :local do
105
+ comment "Apply all Kubernetes resources..."
106
+ command "REVISION=#{fetch(:image_tag)} KUBECONFIG=#{fetch(:kube_config)} ENVIRONMENT=#{fetch(:stage)} kubernetes-deploy --bindings=image_repo=#{fetch(:image_repo)},image_tag=#{fetch(:image_tag)},namespace=#{fetch(:namespace)} #{fetch(:namespace)} #{fetch(:context)}"
107
+ end
108
+ end
@@ -0,0 +1,5 @@
1
+ module Mina
2
+ module Kubernetes
3
+ VERSION = "1.0.1"
4
+ end
5
+ end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mina/kubernetes/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'mina-kubernetes'
8
+ spec.version = Mina::Kubernetes::VERSION
9
+ spec.authors = ['Antoine Sabourin']
10
+ spec.email = ['antoine@streem.com.au']
11
+
12
+ spec.summary = %q{Mina plugin to streamline deployment of resources to Kubernetes cluster}
13
+ spec.description = %q{Mina plugin to streamline deployment of resources to Kubernetes cluster}
14
+ spec.homepage = 'https://github.com/streemau/mina-kubernetes'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0")
18
+ spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency 'bundler', '~> 1.11'
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+
25
+ spec.add_runtime_dependency 'mina', '~> 1.0'
26
+ spec.add_runtime_dependency 'mina-multistage', '~> 1.0'
27
+ spec.add_runtime_dependency 'kubernetes-deploy'
28
+ spec.add_runtime_dependency 'tty-prompt'
29
+ spec.add_runtime_dependency 'tty-spinner'
30
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mina-kubernetes
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Antoine Sabourin
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-05-20 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: '1.11'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.11'
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: mina
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mina-multistage
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: kubernetes-deploy
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: tty-prompt
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: tty-spinner
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: Mina plugin to streamline deployment of resources to Kubernetes cluster
112
+ email:
113
+ - antoine@streem.com.au
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".gitignore"
119
+ - README.md
120
+ - Rakefile
121
+ - lib/mina/kubernetes.rb
122
+ - lib/mina/kubernetes/version.rb
123
+ - mina-kubernetes.gemspec
124
+ homepage: https://github.com/streemau/mina-kubernetes
125
+ licenses:
126
+ - MIT
127
+ metadata: {}
128
+ post_install_message:
129
+ rdoc_options: []
130
+ require_paths:
131
+ - lib
132
+ required_ruby_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">="
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ required_rubygems_version: !ruby/object:Gem::Requirement
138
+ requirements:
139
+ - - ">="
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ requirements: []
143
+ rubygems_version: 3.0.3
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: Mina plugin to streamline deployment of resources to Kubernetes cluster
147
+ test_files: []