mina-kubernetes 1.0.1 → 2.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1f1fd603c840045e6402d4eee5e82b997a3e31459b2e33f904bff8541cf4ce42
4
- data.tar.gz: b31401cfce0e729fabbc51e0aa37841a7b6e907639fc5fa572046ac4e3916924
3
+ metadata.gz: 7930f648e0b70eeb94a1413fee561b8edcdac3c28918bf003bee6c77749f9537
4
+ data.tar.gz: 5df185bd2d8cf21dbe0d520b799e8654d793400822a9d2522a760614dabf4e97
5
5
  SHA512:
6
- metadata.gz: 83b16882b97e8b5a1e2bfd13a2143955443c39d9fb3166c457457510cffd375e32b468a1d4fba608e0822425ebd61d9abd40a12a38fbcc037ea6d6707ad0abd4
7
- data.tar.gz: 8cfc7cc45cb7dbf508a97ad3c3c6ecff2d094530672a3fb38676426d25448a2d676a0e362d45507cbf89066caa06db971864cfbf26878f360446f5c117f54ca3
6
+ metadata.gz: 47f3c48b9157ca35688e8b45cee5e20c8c844c05b128e899f5cee1c15b9db60773a16f6b636fcf15c84bcbf27b78b4c66e6c4f5758397c693d277615f7b23abf
7
+ data.tar.gz: ce3221d0774d3d386c95af184798c9a98d67559f43481ea84b75a13119a6bb57fc35b5eafa9ca60a9a5d4e879805328b0dc5b47f162ff20d885d5e4aea95228c
@@ -0,0 +1,45 @@
1
+ ## 2.4.0
2
+
3
+ *Enhancements*
4
+
5
+ - Use `secrets.ejson` if present
6
+
7
+ ## 2.3.0
8
+
9
+ *Enhancements*
10
+
11
+ - Allow using a proxy to connect to a Kubernetes cluster
12
+
13
+ ## 2.2.4
14
+
15
+ *Fixes*
16
+
17
+ - run custom command within given namespace instead of `default`
18
+
19
+ ## 2.2.1 to 2.2.3
20
+
21
+ *Fixes*
22
+
23
+ - handle nil/undefined options passed to `krane`
24
+
25
+ ## 2.2.0
26
+
27
+ *Enhancements*
28
+
29
+ - Using `krane` 1.0.0 (previously `kubernetes-deploy`)
30
+ - Allow passing of options to `krane`
31
+
32
+ ## 2.1.0
33
+
34
+ Yanked release.
35
+
36
+ ## 2.0.0
37
+
38
+ *Breaking*
39
+
40
+ - Using `namespace` config variable instead of `app_name`
41
+ - Using `kubernetes_context` config variable linking directly to a context set in $KUBE_CONFIG instead of creating a new context from separate `kubernetes_cluster` and `kubernetes_user` config variables
42
+
43
+ *Fixes*
44
+
45
+ - Not overriding $KUBE_CONFIG environment variable anymore
data/README.md CHANGED
@@ -1,15 +1,19 @@
1
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.
2
+ Plugin for the [mina](https://github.com/mina-deploy/mina) deployment tool to streamline deployment of resources to Kubernetes clusters, using the [krane](https://github.com/Shopify/krane) gem and [mina-multistage](https://github.com/endoze/mina-multistage) plugin.
3
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.
4
+ Requires local Docker and [kubectl](https://cloud.google.com/kubernetes-engine/docs/quickstart) with local authentication set up to connect to the destination Kubernetes cluster as context in your local KUBE_CONFIG. See https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl#generate_kubeconfig_entry for example with Google Kubernetes Engine.
5
+
6
+ NB: `docker manifest inspect` is used to check whether the Docker image with requested tag is available. This requires experimental features to be enabled in your local Docker config by adding `"experimental": "enabled"` to `~/.docker/config.json`.
7
+ If the image repository is not public authentication will need to be set up for your local Docker, for instance see https://cloud.google.com/container-registry/docs/advanced-authentication#gcloud_as_a_docker_credential_helper for images hosted on the Google Cloud Registry
5
8
 
6
9
  ## Usage
7
10
 
8
- Add `mina-kubernetes` to your local Gemfile.
11
+ Add `mina-kubernetes` to your local Gemfile.
9
12
 
10
13
  Create a configuration file for mina in `config/deploy.rb` like the one below:
11
14
  ```ruby
12
15
  require "mina/default"
16
+ require "mina/multistage"
13
17
  require "mina/kubernetes"
14
18
 
15
19
  task :deploy do
@@ -19,22 +23,39 @@ end
19
23
 
20
24
  Add the following variables to your stage configuration i.e. `config/deploy/production.rb`:
21
25
  ```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
+ set :namespace, "my_app"
27
+ set :image_repo, "gcr.io/project-id/myapp"
28
+ set :kubernetes_context, "kubernetes_context_name"
26
29
  ```
27
30
 
28
31
  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
32
 
30
- Optional configuration (showing default values):
31
- ```ruby
32
- set :kube_config, "~/.kube/config"
33
+ Then add `*.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.
34
+
35
+ You can also get the RAILS_MASTER_KEY for encrypted credentials deployed as a Kubernetes secrets by adding a secrets.yml.erb like below:
36
+ ```yml
37
+ apiVersion: v1
38
+ kind: Secret
39
+ metadata:
40
+ name: secrets
41
+ data:
42
+ RAILS_MASTER_KEY: <%= Base64.strict_encode64(File.read("#{Dir.pwd}/config/credentials/production.key").strip) %>
33
43
  ```
34
44
 
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.
45
+ When running `mina production deploy`, it'll prompt for a branch and check the image tagged with current commit hash from selected branch is available on the repository. Then the `krane` executable is called to fill in the variables in the resource templates and apply them all to the cluster under the given namespace (see https://github.com/Shopify/krane#deploy-walkthrough for more details)\
46
+
47
+ ### EJSON Encrypted secrets
48
+
49
+ Krane supports generating Kubernetes secrets from an encrypted EJSON file: https://github.com/Shopify/krane#deploying-kubernetes-secrets-from-ejson. As per current Krane documentation "The ejson file must be included in the resources passed to --filenames it can not be read through stdin.", so
50
+ following convention-over-configuration principles `mina-kubernetes` checks for the presence of a file named `secrets.ejson` in the stage folder and uses it if available.
51
+
52
+ ### Passing options to krane
53
+
54
+ ```ruby
55
+ invoke :"kubernetes:deploy", "--no-prune"
56
+ ```
36
57
 
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.
58
+ Refer to https://github.com/Shopify/krane#usage for a complete set of options
38
59
 
39
60
  ### Tasks available
40
61
 
@@ -52,4 +73,4 @@ Prompts for branch unless image tag is set, then spins up a temporary pod with t
52
73
 
53
74
  #### `kubernetes:delete`
54
75
 
55
- Confirms and delete all resources on cluster under namespace `app_name-stage`.
76
+ Confirms and delete all resources on cluster under namespace.
@@ -7,45 +7,37 @@ require "base64"
7
7
  # required by mina
8
8
  set :execution_mode, :pretty
9
9
 
10
- # default for kubernetes-deploy
11
- set :kube_config, "~/.kube/config"
12
-
13
10
  namespace :kubernetes do
11
+ set :proxy, nil
14
12
 
15
- set :namespace, fetch(:app_name)
16
- set :context, "#{fetch(:namespace)}-#{fetch(:stage)}"
17
-
18
- task :deploy do
13
+ task :deploy, [:options] do |task, args|
19
14
  desc "Set image tag to be latest commit of prompted branch (unless provided) then applies resources to cluster"
20
15
  set_tag_from_branch_commit unless fetch(:image_tag)
21
16
  wait_until_image_ready(fetch(:image_tag))
22
17
  create_namespace_on_cluster
23
- set_local_config_context
24
- apply_kubernetes_resources
18
+ apply_kubernetes_resources(args[:options])
25
19
  end
26
20
 
27
21
  task :bash do
28
22
  desc "Spins up temporary pod with image and opens remote interactive bash"
29
23
  set_tag_from_branch_commit unless fetch(:image_tag)
30
24
  wait_until_image_ready(fetch(:image_tag))
31
- run_terminal_command("bash")
25
+ run_command("bash")
32
26
  end
33
27
 
34
28
  task :command do
35
29
  desc "Spins up temporary pod with image and runs given command in interactive shell, passing given environment variable"
36
30
  set_tag_from_branch_commit unless fetch(:image_tag)
37
31
  wait_until_image_ready(fetch(:image_tag))
38
- run_terminal_command(fetch(:command), fetch(:env_hash))
32
+ run_command(fetch(:command), env_hash_arg)
39
33
  end
40
34
 
41
35
  task :delete do
42
36
  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?")
37
+ if TTY::Prompt.new.yes?("This will delete all resources in namespace #{fetch(:namespace)} on context #{fetch(:kubernetes_context)}, are you sure?")
44
38
  run :local do
45
39
  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)}"
40
+ command "kubectl delete namespace #{fetch(:namespace)} --context=#{fetch(:kubernetes_context)}"
49
41
  end
50
42
  end
51
43
  end
@@ -54,6 +46,10 @@ end
54
46
 
55
47
  private
56
48
 
49
+ def env_hash_arg
50
+ @env_hash_arg ||= (fetch(:env_hash).is_a?(String) ? JSON.parse(fetch(:env_hash)) : fetch(:env_hash)) || {}
51
+ end
52
+
57
53
  def set_tag_from_branch_commit
58
54
  run :local do
59
55
  comment "Updating Git branches..."
@@ -66,14 +62,8 @@ end
66
62
  def create_namespace_on_cluster
67
63
  run :local do
68
64
  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)}"
65
+ proxy_env = "HTTPS_PROXY=#{fetch(:proxy)}" if fetch(:proxy)
66
+ command "kubectl create namespace #{fetch(:namespace)} --dry-run -o yaml | #{proxy_env} kubectl apply -f - --context=#{fetch(:kubernetes_context)}"
77
67
  end
78
68
  end
79
69
 
@@ -93,16 +83,29 @@ def image_available?(commit)
93
83
  system("docker manifest inspect #{fetch(:image_repo)}:#{commit} > /dev/null") == true
94
84
  end
95
85
 
96
- def run_terminal_command(command, env_hash = {})
86
+ def run_command(command, env_hash = {})
97
87
  env = env_hash.collect{|k,v| "--env #{k}=#{v}" }.join(" ")
98
88
  label = command.downcase.gsub(" ", "-").gsub(":", "-")
89
+ proxy_env = "HTTPS_PROXY=#{fetch(:proxy)}" if fetch(:proxy)
90
+
99
91
  # 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}"
92
+ system "#{proxy_env} kubectl run #{label}-#{SecureRandom.hex(4)} --rm -i --tty --restart=Never --context=#{fetch(:kubernetes_context)} --namespace=#{fetch(:namespace)} --image #{fetch(:image_repo)}:#{fetch(:image_tag)} #{env} -- #{command}"
101
93
  end
102
94
 
103
- def apply_kubernetes_resources
95
+ def apply_kubernetes_resources(options)
104
96
  run :local do
105
97
  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)}"
98
+
99
+ proxy_env = "HTTPS_PROXY=#{fetch(:proxy)}" if fetch(:proxy)
100
+ filepaths = options&.[](:filepaths) || "config/deploy/#{fetch(:stage)}"
101
+
102
+ render_cmd = "#{proxy_env} krane render --bindings=image_repo=#{fetch(:image_repo)},image_tag=#{fetch(:image_tag)},namespace=#{fetch(:namespace)} --current_sha #{fetch(:image_tag)} -f #{filepaths}"
103
+ deploy_cmd = "#{proxy_env} krane deploy #{fetch(:namespace)} #{fetch(:kubernetes_context)} --stdin "
104
+ deploy_cmd += options[:deployment_options] if options&.[](:deployment_options)
105
+
106
+ ejson_secrets_path = "#{filepaths}/secrets.ejson"
107
+ deploy_cmd += " --filenames #{ejson_secrets_path}" if File.exists?(ejson_secrets_path)
108
+
109
+ command "#{render_cmd} | #{deploy_cmd}"
107
110
  end
108
111
  end
@@ -1,5 +1,5 @@
1
1
  module Mina
2
2
  module Kubernetes
3
- VERSION = "1.0.1"
3
+ VERSION = "2.4.1"
4
4
  end
5
- end
5
+ end
@@ -20,11 +20,11 @@ Gem::Specification.new do |spec|
20
20
  spec.require_paths = ["lib"]
21
21
 
22
22
  spec.add_development_dependency 'bundler', '~> 1.11'
23
- spec.add_development_dependency 'rake', '~> 10.0'
24
-
23
+ spec.add_development_dependency 'rake', '>= 12.3.3'
24
+
25
25
  spec.add_runtime_dependency 'mina', '~> 1.0'
26
26
  spec.add_runtime_dependency 'mina-multistage', '~> 1.0'
27
- spec.add_runtime_dependency 'kubernetes-deploy'
27
+ spec.add_runtime_dependency 'krane', '~> 1.0'
28
28
  spec.add_runtime_dependency 'tty-prompt'
29
29
  spec.add_runtime_dependency 'tty-spinner'
30
- end
30
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mina-kubernetes
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 2.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Antoine Sabourin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-05-20 00:00:00.000000000 Z
11
+ date: 2020-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -28,16 +28,16 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: 12.3.3
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: 12.3.3
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: mina
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -67,19 +67,19 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: '1.0'
69
69
  - !ruby/object:Gem::Dependency
70
- name: kubernetes-deploy
70
+ name: krane
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - ">="
73
+ - - "~>"
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '1.0'
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - ">="
80
+ - - "~>"
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '1.0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: tty-prompt
85
85
  requirement: !ruby/object:Gem::Requirement
@@ -116,6 +116,7 @@ extensions: []
116
116
  extra_rdoc_files: []
117
117
  files:
118
118
  - ".gitignore"
119
+ - CHANGELOG.md
119
120
  - README.md
120
121
  - Rakefile
121
122
  - lib/mina/kubernetes.rb