stax-helm 0.0.4 → 0.0.9

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: 4c41b28fe1fde84c9dc771a618e0bfbeccd1718854aea285f41a4e115c73252f
4
- data.tar.gz: '09525e2ae890c6b35306b578ac7099488f734920ac5f8aea250413652f7eebf7'
3
+ metadata.gz: 53e53de7fb96d2b35470594bbb80e1de7bcbcf41aad867d6d20217db8bc20aef
4
+ data.tar.gz: 99f8d5f4a0964e66303803885d4f065d0979606f33cceed2afc7b5e82869f650
5
5
  SHA512:
6
- metadata.gz: f2a5c1f4c00e3211799a516e6645af725c537a7ad96bb4ae4f60dd48be1df90be961a78108fa0a11057f7ba9832a842561d9a47cd3d341b9aacaa83da87b7906
7
- data.tar.gz: 7260772678070aa147160ec8e072fe912a1bd79d772917b9a347fd65565c8ab5b2724f1fddc6d02e6c5e400a4748f9ec0523e01777686a980472c9215ca8d2e1
6
+ metadata.gz: 5cf3d1c0a868fdb26deb92346704bb3dacf507f28c3b70761b6525d3ecca93891fa0e1276533cfd3096913a1944d418469de7b7dbcf2383417803cc11fd7396c
7
+ data.tar.gz: d581092b08654b29454a72ab0c1ff198d47caa0aa1663baa17123898bc0cd738d01994cb4f7f9daf20cd19542124f3e8d630d55188f2bacc632339b889c556b4
@@ -1,7 +1,11 @@
1
+ require 'stax/helm/base'
1
2
  require 'stax/helm/cmd'
2
3
  require 'stax/helm/kubectl'
3
4
  require 'stax/helm/ingress'
4
5
  require 'stax/helm/pod'
5
6
  require 'stax/helm/deployment'
7
+ require 'stax/helm/jobs'
8
+ require 'stax/helm/cronjobs'
6
9
  require 'stax/helm/stern'
10
+ require 'stax/helm/runcmd'
7
11
  Stax.add_command(:helm, Stax::Helm::Cmd)
@@ -0,0 +1,16 @@
1
+ module Stax
2
+ class Base < Thor
3
+
4
+ no_commands do
5
+ def helm_release_name
6
+ @_helm_release_name ||= helm_safe("#{app_name}-#{branch_name}")
7
+ end
8
+
9
+ ## make string safe to use in naming helm stuff
10
+ def helm_safe(string)
11
+ string.slice(0, 53).gsub(/[\W_]/, '-').downcase
12
+ end
13
+ end
14
+
15
+ end
16
+ end
@@ -1,13 +1,10 @@
1
1
  module Stax
2
2
  module Helm
3
+
3
4
  class Cmd < Base
4
5
  class_option :recon, aliases: '--just-print', type: :boolean, default: false, desc: 'print command that would be run'
5
6
 
6
7
  no_commands do
7
- def helm_release_name
8
- @_helm_release_name ||= "#{app_name}-#{branch_name}"
9
- end
10
-
11
8
  ## location of helm chart
12
9
  def helm_dir
13
10
  File.join(Stax.root_path, 'helm')
@@ -0,0 +1,13 @@
1
+ ## tasks to get cronjob details
2
+ module Stax
3
+ module Helm
4
+ class Cmd < Base
5
+
6
+ desc 'cronjobs', 'list cronjobs'
7
+ def cronjobs
8
+ kubectl_run(:get, :cronjobs, '-l', helm_selector)
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -3,11 +3,54 @@ module Stax
3
3
  module Helm
4
4
  class Cmd < Base
5
5
 
6
+ no_commands do
7
+ def helm_deployments
8
+ jsonpath = '{.items[*].metadata.name}'
9
+ %x[kubectl get deployments -o=jsonpath='#{jsonpath}' -l #{helm_selector}].split
10
+ end
11
+
12
+ ## prompt user with a list of deployments to choose
13
+ def helm_ask_deployments(msg)
14
+ deployments = helm_deployments
15
+ if deployments.count > 1
16
+ puts deployments.each_with_index.map { |d, i| "#{i}: #{d}" }
17
+ resp = ask(msg, default: 'all')
18
+ if resp != 'all'
19
+ indices = resp.split.map(&:to_i)
20
+ deployments = Array(deployments.slice(*indices))
21
+ end
22
+ end
23
+ deployments
24
+ end
25
+ end
26
+
6
27
  desc 'deployments', 'list deployments'
7
28
  def deployments
8
29
  kubectl_run(:get, :deployments, '-l', helm_selector)
9
30
  end
10
31
 
32
+ desc 'restart', 'restart deployments'
33
+ def restart
34
+ helm_ask_deployments('choose deployments').each do |deployment|
35
+ kubectl_run(:rollout, :restart, :deployment, deployment)
36
+ end
37
+ end
38
+
39
+ desc 'scale', 'show/set scale for deployments'
40
+ method_option :replicas, aliases: '-r', type: :numeric, default: nil, desc: 'replicas'
41
+ def scale
42
+ if options[:replicas]
43
+ deployments = helm_ask_deployments('choose deployments').join(' ')
44
+ kubectl_run(:scale, :deployment, deployments, '--replicas', options[:replicas])
45
+ else
46
+ debug("Deployment replicas for #{helm_release_name}")
47
+ deployments = kubectl_json(:get, :deployments, '-l', helm_selector)
48
+ print_table deployments['items'].map { |i|
49
+ [ i['metadata']['name'], i['status']['replicas'] || 0 ]
50
+ }
51
+ end
52
+ end
53
+
11
54
  end
12
55
  end
13
56
  end
@@ -0,0 +1,13 @@
1
+ ## tasks to get job details
2
+ module Stax
3
+ module Helm
4
+ class Cmd < Base
5
+
6
+ desc 'jobs', 'list jobs'
7
+ def jobs
8
+ kubectl_run(:get, :jobs, '-l', helm_selector)
9
+ end
10
+
11
+ end
12
+ end
13
+ end
@@ -12,6 +12,12 @@ module Stax
12
12
  options[:recon] ? puts(cmd) : system(cmd)
13
13
  end
14
14
 
15
+ def kubectl_json(*args)
16
+ args.push('-o=json')
17
+ cmd = [kubectl_bin, *args].join(' ')
18
+ options[:recon] ? puts(cmd) : JSON.parse(%x(#{cmd}))
19
+ end
20
+
15
21
  ## override this to match all objects in your helm release
16
22
  def helm_selector
17
23
  "app.kubernetes.io/instance=#{helm_release_name}"
@@ -33,6 +33,7 @@ module Stax
33
33
 
34
34
  desc 'logs [OPTIONS]', 'run kubectl logs with same options'
35
35
  def logs(*args)
36
+ trap('SIGINT', 'EXIT') # clean exit with ctrl-c
36
37
  args = [ '--all-containers', '--prefix', '--follow' ] if args.empty? # helpful default args
37
38
  kubectl_run(:logs, '-l', helm_selector, *args)
38
39
  end
@@ -0,0 +1,108 @@
1
+ require 'securerandom'
2
+
3
+ module Stax
4
+ module Helm
5
+ class Cmd
6
+
7
+ no_commands do
8
+ ## construct a Job template
9
+ def helm_run_template(name)
10
+ {
11
+ apiVersion: 'batch/v1',
12
+ kind: :Job,
13
+ metadata: {
14
+ name: name,
15
+ labels: {
16
+ 'app.kubernetes.io/managed-by' => :stax
17
+ }
18
+ },
19
+ spec: {
20
+ template: {
21
+ spec: {
22
+ restartPolicy: :Never
23
+ }
24
+ }
25
+ }
26
+ }
27
+ end
28
+
29
+ ## Deployment to clone for container
30
+ def helm_run_deployment
31
+ "#{helm_release_name}-web"
32
+ end
33
+
34
+ ## name of container to clone from Deployment
35
+ def helm_run_container
36
+ 'web'
37
+ end
38
+
39
+ ## name for Job to create based on container
40
+ def helm_run_job
41
+ "#{helm_release_name}-run-#{SecureRandom.hex(4)}"
42
+ end
43
+
44
+ ## default command to run
45
+ def helm_run_cmd
46
+ 'bash'
47
+ end
48
+ end
49
+
50
+ ## task creates a dedicated unique kubernetes Job, with
51
+ ## container spec based on the helm release deployment
52
+ ## requested, then does an interactive exec to the pod and
53
+ ## container created, and deletes the Job on exit
54
+ desc 'runcmd [CMD]', 'run dedicated interactive container'
55
+ method_option :sleep, type: :string, default: '1h', description: 'kill container after time'
56
+ method_option :keep, type: :boolean, default: false, description: 'do not delete job'
57
+ def runcmd(*cmd)
58
+ ## use default if not set
59
+ cmd = Array(helm_run_cmd) if cmd.empty?
60
+
61
+ ## name of k8s Job to create, and basic template
62
+ job = helm_run_job
63
+ template = helm_run_template(job)
64
+
65
+ ## get deployment and extract container spec
66
+ deployment = kubectl_json(:get, :deployment, helm_run_deployment)
67
+ spec = deployment.dig('spec', 'template', 'spec', 'containers').find do |c|
68
+ c['name'] == helm_run_container
69
+ end
70
+
71
+ ## cleanup the container spec so we can use it in a Job
72
+ spec.delete('livenessProbe')
73
+ spec.delete('readinessProbe')
74
+ spec.delete('volumeMounts')
75
+ spec['name'] = 'run'
76
+ spec['args'] = ['sleep', options[:sleep]]
77
+
78
+ ## add container to Job template
79
+ template[:spec][:template][:spec][:containers] = [ spec ]
80
+
81
+ ## get service account and add to template
82
+ service_account = deployment.dig('spec', 'template', 'spec', 'serviceAccountName')
83
+ template[:spec][:template][:spec][:serviceAccountName] = service_account if service_account
84
+
85
+ ## create new unique Job based on the container spec
86
+ debug("Creating job #{job}")
87
+ Open3.popen2('kubectl create -f -') { |stdin, stdout, _|
88
+ stdin.print(template.to_json)
89
+ stdin.close
90
+ puts stdout.gets
91
+ }
92
+
93
+ ## get name of the Pod created by the Job
94
+ pod = kubectl_json(:get, :pod, '-l', "job-name=#{job}")['items'].first['metadata']['name']
95
+
96
+ ## exec into the pod and run interactive command
97
+ debug("Connecting to pod #{pod}")
98
+ kubectl_run(:wait, '--for=condition=Ready', '--timeout=5m', :pod, pod)
99
+ kubectl_run(:exec, '-it', pod, '--', *cmd)
100
+ rescue JSON::ParserError
101
+ fail_task('cannot get kubernetes resource')
102
+ ensure
103
+ ## delete Job
104
+ kubectl_run(:delete, :job, job) unless options[:keep]
105
+ end
106
+ end
107
+ end
108
+ end
@@ -16,6 +16,7 @@ module Stax
16
16
  ## pass through args to stern
17
17
  desc 'stern [STERN_ARGS]', 'use stern to show logs'
18
18
  def stern(*args)
19
+ trap('SIGINT', 'EXIT') # clean exit with ctrl-c
19
20
  stern_run('-l', helm_selector, *args)
20
21
  end
21
22
 
@@ -1,5 +1,5 @@
1
1
  module Stax
2
2
  module Helm
3
- VERSION = '0.0.4'
3
+ VERSION = '0.0.9'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stax-helm
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Lister
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-06-08 00:00:00.000000000 Z
11
+ date: 2020-12-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -67,11 +67,15 @@ files:
67
67
  - README.md
68
68
  - Rakefile
69
69
  - lib/stax/helm.rb
70
+ - lib/stax/helm/base.rb
70
71
  - lib/stax/helm/cmd.rb
72
+ - lib/stax/helm/cronjobs.rb
71
73
  - lib/stax/helm/deployment.rb
72
74
  - lib/stax/helm/ingress.rb
75
+ - lib/stax/helm/jobs.rb
73
76
  - lib/stax/helm/kubectl.rb
74
77
  - lib/stax/helm/pod.rb
78
+ - lib/stax/helm/runcmd.rb
75
79
  - lib/stax/helm/stern.rb
76
80
  - lib/stax/helm/version.rb
77
81
  - stax-helm.gemspec