class Stax::Helm::Cmd

Public Instance Methods

containers() click to toggle source
# File lib/stax/helm/pod.rb, line 29
def containers
  columns = 'NAME:.metadata.name,CONTAINERS:.spec.containers[*].name'
  kubectl_run(:get, :pods, '-o', "custom-columns=#{columns}", '-l', helm_selector)
end
create() click to toggle source
# File lib/stax/helm/cmd.rb, line 50
def create
  debug("Creating helm release #{helm_release_name}")
  helm_run(:install, helm_release_name, helm_dir, helm_update_args)
end
cronjobs() click to toggle source
# File lib/stax/helm/cronjobs.rb, line 7
def cronjobs
  kubectl_run(:get, :cronjobs, '-l', helm_selector)
end
delete() click to toggle source
# File lib/stax/helm/cmd.rb, line 62
def delete
  debug("Deleting helm release #{helm_release_name}")
  helm_run(:delete, helm_release_name)
end
deployments() click to toggle source
# File lib/stax/helm/deployment.rb, line 28
def deployments
  kubectl_run(:get, :deployments, '-l', helm_selector)
end
dns() click to toggle source
# File lib/stax/helm/ingress.rb, line 12
def dns
  jsonpath = '{.items[].metadata.annotations.external-dns\.alpha\.kubernetes\.io/hostname}' + "\n"
  kubectl_run(:get, :ingresses, "-o=jsonpath='#{jsonpath}'", '-l', helm_selector)
end
exec(cmd = 'sh') click to toggle source
# File lib/stax/helm/pod.rb, line 42
def exec(cmd = 'sh')
  pod = helm_ask_pod('choose a pod')
  kubectl_run(:exec, '-it', pod, '--', cmd)
end
helm_ask_deployments(msg) click to toggle source

prompt user with a list of deployments to choose

# File lib/stax/helm/deployment.rb, line 13
def helm_ask_deployments(msg)
  deployments = helm_deployments
  if deployments.count > 1
    puts deployments.each_with_index.map { |d, i| "#{i}: #{d}" }
    resp = ask(msg, default: 'all')
    if resp != 'all'
      indices = resp.split.map(&:to_i)
      deployments = Array(deployments.slice(*indices))
    end
  end
  deployments
end
helm_ask_pod(msg) click to toggle source
# File lib/stax/helm/pod.rb, line 12
def helm_ask_pod(msg)
  pods = helm_pods
  index = 0
  if pods.count > 1
    puts pods.each_with_index.map { |p, i| "#{i}: #{p}" }
    index = ask(msg, default: index)
  end
  pods[index.to_i]
end
helm_bin() click to toggle source

location of helm binary

# File lib/stax/helm/cmd.rb, line 14
def helm_bin
  'helm'
end
helm_deployments() click to toggle source
# File lib/stax/helm/deployment.rb, line 7
def helm_deployments
  jsonpath = '{.items[*].metadata.name}'
  %x[kubectl get deployments -o=jsonpath='#{jsonpath}' -l #{helm_selector}].split
end
helm_description() click to toggle source

description added to release

# File lib/stax/helm/cmd.rb, line 25
def helm_description
  Git.sha
end
helm_dir() click to toggle source

location of helm chart

# File lib/stax/helm/cmd.rb, line 9
def helm_dir
  File.join(Stax.root_path, 'helm')
end
helm_pods() click to toggle source
# File lib/stax/helm/pod.rb, line 7
def helm_pods
  jsonpath = '{.items[*].metadata.name}'
  %x[kubectl get pods -o=jsonpath='#{jsonpath}' -l #{helm_selector}].split
end
helm_run(*args) click to toggle source

run helm with args

# File lib/stax/helm/cmd.rb, line 19
def helm_run(*args)
  cmd = [helm_bin, *args].join(' ')
  options[:recon] ? puts(cmd) : system(cmd)
end
helm_run_cmd() click to toggle source

default command to run

# File lib/stax/helm/runcmd.rb, line 45
def helm_run_cmd
  'bash'
end
helm_run_container() click to toggle source

name of container to clone from Deployment

# File lib/stax/helm/runcmd.rb, line 35
def helm_run_container
  'web'
end
helm_run_deployment() click to toggle source

Deployment to clone for container

# File lib/stax/helm/runcmd.rb, line 30
def helm_run_deployment
  "#{helm_release_name}-web"
end
helm_run_job() click to toggle source

name for Job to create based on container

# File lib/stax/helm/runcmd.rb, line 40
def helm_run_job
  "#{helm_release_name}-run-#{SecureRandom.hex(4)}"
end
helm_run_template(name) click to toggle source

construct a Job template

# File lib/stax/helm/runcmd.rb, line 9
def helm_run_template(name)
  {
    apiVersion: 'batch/v1',
    kind: :Job,
    metadata: {
      name: name,
      labels: {
        'app.kubernetes.io/managed-by' => :stax
      }
    },
    spec: {
      template: {
        spec: {
          restartPolicy: :Never
        }
      }
    }
  }
end
helm_selector() click to toggle source

override this to match all objects in your helm release

# File lib/stax/helm/kubectl.rb, line 22
def helm_selector
  "app.kubernetes.io/instance=#{helm_release_name}"
end
helm_update_args() click to toggle source

construct args for install and upgrade commands

# File lib/stax/helm/cmd.rb, line 40
def helm_update_args
  [].tap do |args|
    args.push("--description #{helm_description}") if helm_description
    args.push("-f #{helm_values_file}") if helm_values_file
    args.push(helm_values&.map { |k,v| "--set #{k}=#{v}" })
  end.flatten
end
helm_values() click to toggle source

override with hash of extra values to set

# File lib/stax/helm/cmd.rb, line 35
def helm_values
  {}
end
helm_values_file() click to toggle source

override with full path to a values.yaml file

# File lib/stax/helm/cmd.rb, line 30
def helm_values_file
  nil
end
history() click to toggle source
# File lib/stax/helm/cmd.rb, line 83
def history
  helm_run(:history, helm_release_name)
end
ingresses() click to toggle source
# File lib/stax/helm/ingress.rb, line 7
def ingresses
  kubectl_run(:get, :ingresses, '-l', helm_selector)
end
jobs() click to toggle source
# File lib/stax/helm/jobs.rb, line 7
def jobs
  kubectl_run(:get, :jobs, '-l', helm_selector)
end
kubectl_bin() click to toggle source
# File lib/stax/helm/kubectl.rb, line 6
def kubectl_bin
  'kubectl'
end
kubectl_json(*args) click to toggle source
# File lib/stax/helm/kubectl.rb, line 15
def kubectl_json(*args)
  args.push('-o=json')
  cmd = [kubectl_bin, *args].join(' ')
  options[:recon] ? puts(cmd) : JSON.parse(%x(#{cmd}))
end
kubectl_run(*args) click to toggle source
# File lib/stax/helm/kubectl.rb, line 10
def kubectl_run(*args)
  cmd = [kubectl_bin, *args].join(' ')
  options[:recon] ? puts(cmd) : system(cmd)
end
logs(*args) click to toggle source
# File lib/stax/helm/pod.rb, line 35
def logs(*args)
  trap('SIGINT', 'EXIT')    # clean exit with ctrl-c
  args = [ '--all-containers', '--prefix', '--follow' ] if args.empty? # helpful default args
  kubectl_run(:logs, '-l', helm_selector, *args)
end
ls() click to toggle source
# File lib/stax/helm/cmd.rb, line 93
def ls
  helm_run(:ls, "--filter '^#{helm_release_name}$'")
end
pods() click to toggle source
# File lib/stax/helm/pod.rb, line 24
def pods
  kubectl_run(:get, :pods, '-l', helm_selector)
end
restart() click to toggle source
# File lib/stax/helm/deployment.rb, line 33
def restart
  helm_ask_deployments('choose deployments').each do |deployment|
    kubectl_run(:rollout, :restart, :deployment, deployment)
  end
end
rollback(revision = nil) click to toggle source
# File lib/stax/helm/cmd.rb, line 88
def rollback(revision = nil)
  helm_run(:rollback, helm_release_name, revision)
end
runcmd(*cmd) click to toggle source
# File lib/stax/helm/runcmd.rb, line 57
def runcmd(*cmd)
  ## use default if not set
  cmd = Array(helm_run_cmd) if cmd.empty?

  ## name of k8s Job to create, and basic template
  job = helm_run_job
  template = helm_run_template(job)

  ## get deployment and extract container spec
  deployment = kubectl_json(:get, :deployment, helm_run_deployment)
  spec = deployment.dig('spec', 'template', 'spec', 'containers').find do |c|
    c['name'] == helm_run_container
  end

  ## cleanup the container spec so we can use it in a Job
  spec.delete('livenessProbe')
  spec.delete('readinessProbe')
  spec.delete('startupProbe')
  spec.delete('volumeMounts')
  spec['name'] = 'run'
  spec['args'] = ['sleep', options[:sleep]]

  ## add container to Job template
  template[:spec][:template][:spec][:containers] = [ spec ]

  ## get service account and add to template
  service_account = deployment.dig('spec', 'template', 'spec', 'serviceAccountName')
  template[:spec][:template][:spec][:serviceAccountName] = service_account if service_account

  ## create new unique Job based on the container spec
  debug("Creating job #{job}")
  Open3.popen2('kubectl create -f -') { |stdin, stdout, _|
    stdin.print(template.to_json)
    stdin.close
    puts stdout.gets
  }

  ## get name of the Pod created by the Job
  pod = kubectl_json(:get, :pod, '-l', "job-name=#{job}")['items'].first['metadata']['name']

  ## exec into the pod and run interactive command
  debug("Connecting to pod #{pod}")
  kubectl_run(:wait, '--for=condition=Ready', '--timeout=5m', :pod, pod)
  kubectl_run(:exec, '-it', pod, '--', *cmd)
rescue JSON::ParserError
  fail_task('cannot get kubernetes resource')
ensure
  ## delete Job
  kubectl_run(:delete, :job, job) unless options[:keep]
end
scale() click to toggle source
# File lib/stax/helm/deployment.rb, line 41
def scale
  if options[:replicas]
    deployments = helm_ask_deployments('choose deployments').join(' ')
    kubectl_run(:scale, :deployment, deployments, '--replicas', options[:replicas])
  else
    debug("Deployment replicas for #{helm_release_name}")
    deployments = kubectl_json(:get, :deployments, '-l', helm_selector)
    print_table deployments['items'].map { |i|
      [ i['metadata']['name'], i['status']['replicas'] || 0 ]
    }
  end
end
services() click to toggle source
# File lib/stax/helm/kubectl.rb, line 28
def services
  kubectl_run(:get, :services, '-l', helm_selector)
end
status() click to toggle source
# File lib/stax/helm/cmd.rb, line 68
def status
  helm_run(:status, helm_release_name)
end
stern(*args) click to toggle source
# File lib/stax/helm/stern.rb, line 18
def stern(*args)
  trap('SIGINT', 'EXIT')    # clean exit with ctrl-c
  stern_run('-l', helm_selector, *args)
end
stern_bin() click to toggle source
# File lib/stax/helm/stern.rb, line 6
def stern_bin
  'stern'
end
stern_run(*args) click to toggle source
# File lib/stax/helm/stern.rb, line 10
def stern_run(*args)
  cmd = [stern_bin, *args].join(' ')
  options[:dry_run] ? puts(cmd) : system(cmd)
end
template() click to toggle source
# File lib/stax/helm/cmd.rb, line 73
def template
  helm_run(:get, :all, helm_release_name)
end
update() click to toggle source
# File lib/stax/helm/cmd.rb, line 56
def update
  debug("Updating helm release #{helm_release_name}")
  helm_run(:upgrade, '-i', helm_release_name, helm_dir, helm_update_args)
end
values() click to toggle source
# File lib/stax/helm/cmd.rb, line 78
def values
  helm_run(:get, :values, helm_release_name)
end