|
#!/usr/bin/env ruby |
|
# frozen_string_literal: true |
|
|
|
require 'optparse' |
|
require 'active_support/core_ext/object/blank' |
|
require 'active_support/core_ext/hash/keys' |
|
require 'yaml' |
|
require 'tempfile' |
|
require 'awesome_print' |
|
|
|
class Deploy |
|
CLUSTER_CONFIG = 'clusters.yaml'.freeze |
|
DEPLOYMENT = 'kubernetes-sentry'.freeze |
|
|
|
def initialize(args) |
|
options = {} |
|
option_parser = init_option_parser(options) |
|
# Parse the command-line. Remember there are two forms |
|
# of the parse method. The 'parse' method simply parses |
|
# args, while the 'parse!' method parses args and removes |
|
# any options found there, as well as any parameters for |
|
# the options. |
|
option_parser.parse!(args) |
|
process(options) |
|
end |
|
|
|
def process(options) |
|
if options[:all] |
|
# deploy to all clusters |
|
deploy_all |
|
else |
|
# deploy to single context |
|
context = options[:context] |
|
# select current-context if no context is passed |
|
context = `kubectl config current-context`.strip if context.blank? |
|
deploy(context) |
|
end |
|
end |
|
|
|
private |
|
|
|
def deploy_all |
|
clusters = YAML.load_file(CLUSTER_CONFIG) |
|
clusters.deep_symbolize_keys! |
|
clusters[:clusters].each do |config| |
|
if config[:enabled] |
|
deploy(config[:context]) |
|
else |
|
delete(config[:context]) |
|
end |
|
end |
|
end |
|
|
|
def deploy(context) |
|
scope = "--context=#{context}" |
|
puts "Deploying #{DEPLOYMENT} on context: #{context}" |
|
|
|
# check for `phpa-service-account` |
|
# NOTE: we need phpa-service-account, if not found create it using |
|
# 'kubectl apply -f setup-access.yaml' |
|
exec("kubectl get serviceaccount kubernetes-sentry-service-account #{scope}") |
|
|
|
deployment_file = build_yaml(context) |
|
# deleting old deployment and apply |
|
exec("kubectl delete -f #{deployment_file} #{scope}", exit_on_nonzero: false) |
|
exec("kubectl apply -f #{deployment_file} #{scope}") |
|
# check deployment status |
|
exec("kubectl rollout status deployment #{DEPLOYMENT} #{scope}") |
|
end |
|
|
|
def delete(context) |
|
scope = "--context=#{context}" |
|
puts "Cleanup #{DEPLOYMENT} on context: #{context}" |
|
|
|
exec("kubectl delete -f #{DEPLOYMENT}.yaml #{scope} || true") |
|
end |
|
|
|
def build_yaml(context) |
|
deployment = YAML.load_file("#{DEPLOYMENT}.yaml") |
|
cluster = { "name" => "CLUSTER_NAME", "value" => context } |
|
deployment['spec']['template']['spec']['containers'].first['env'] << cluster |
|
file = Tempfile.new(["#{context}-", ".yaml"]) |
|
file.write(deployment.to_yaml) |
|
file.rewind |
|
return file.path |
|
end |
|
|
|
def exec(command, exit_on_nonzero: true) |
|
system(command) |
|
result = $? |
|
return if result.exitstatus.zero? |
|
|
|
# fail if command exits with non-zero exit code |
|
puts result |
|
puts "Exit status code: #{result.exitstatus}" |
|
raise "Failed to run command: '#{command}'" if exit_on_nonzero |
|
end |
|
|
|
# ============= CLI Option Parsing ============== |
|
|
|
def init_option_parser(options) |
|
option_parser = OptionParser.new do |parser| |
|
# Set a banner displayed at top of help screen |
|
parser.banner = 'USAGE: deploy.rb [options]' |
|
parser.separator 'example: ./deploy.rb -c context' |
|
parser.separator "If context is not passed it will deploy in current context" |
|
|
|
context_option(parser, options) |
|
all_option(parser, options) |
|
help_option(parser) |
|
end |
|
return option_parser |
|
end |
|
|
|
|
|
# option definition |
|
def help_option(parser) |
|
parser.on('-h', '--help', 'Display this screen') do |
|
puts parser |
|
exit |
|
end |
|
end |
|
|
|
def all_option(parser, options) |
|
options[:all] = false |
|
help = "Deploy on all clusters defined in #{CLUSTER_CONFIG}" |
|
parser.on('--all', help) do |
|
options[:all] = true |
|
end |
|
end |
|
|
|
def context_option(parser, options) |
|
help = 'Deploy in a specific context' |
|
parser.on('-c', '--context CONTEXT', help) do |context| |
|
options[:context] = context |
|
end |
|
end |
|
end |
|
|
|
Deploy.new(ARGV) |