class Kitchen::Driver::Kubernetes
Kubernetes
driver for Kitchen
.
@author Noah Kantrowitz <noah@coderanger> @since 1.0 @see Kitchen::Transport::Kubernetes
Public Instance Methods
create(state)
click to toggle source
(see Base#create)
# File lib/kitchen/driver/kubernetes.rb, line 159 def create(state) # Already created, we're good. return if state[:pod_id] # Lock in our name with randomness and whatever. pod_id = config[:pod_name] # Render the pod YAML and feed it to kubectl. tpl = ERB.new(IO.read(config[:pod_template]), 0, '-') tpl.filename = config[:pod_template] pod_yaml = tpl.result(binding) debug("Creating pod with YAML:\n#{pod_yaml}\n") run_command(kubectl_command('create', '--filename', '-'), input: pod_yaml) # Wait until the pod reaches Running status. status = nil start_time = Time.now while status != 'Running' if Time.now - start_time > 20 # More than 20 seconds, start giving user feedback. 20 second threshold # was 100% pulled from my ass based on how long it takes to launch # on my local minikube, may need changing for reality. info("Waiting for pod #{pod_id} to be running, currently #{status}") end sleep(1) # Can't use run_command here because error! is unwanted and logging is a bit much. status_cmd = Mixlib::ShellOut.new(kubectl_command('get', 'pod', pod_id, '--output=json')) status_cmd.run_command unless status_cmd.error? || status_cmd.stdout.empty? status = JSON.parse(status_cmd.stdout)['status']['phase'] end end # Save the pod ID. state[:pod_id] = pod_id rescue Exception => ex # If something goes wrong, try to clean up. if pod_id begin debug("Failure during create, trying to clean up pod #{pod_id}") run_command(kubectl_command('delete', 'pod', pod_id, '--now')) rescue ShellCommandFailed => cleanup_ex # Welp, we tried. debug("Cleanup failed, continuing anyway: #{cleanup_ex}") end end raise ex end
default_image()
click to toggle source
Work out the default primary container image to use for this instance. Can be overridden by subclasses. Must return a string compatible with a Kubernetes
container image specification.
@return [String]
# File lib/kitchen/driver/kubernetes.rb, line 92 def default_image if instance.platform.name =~ /^(.*)-([^-]*)$/ "#{$1}:#{$2}" else instance.platform.name end end
destroy(state)
click to toggle source
(see Base#destroy)
# File lib/kitchen/driver/kubernetes.rb, line 205 def destroy(state) return unless state[:pod_id] run_command(kubectl_command('delete', 'pod', state[:pod_id], '--now')) # Explicitly not waiting for the delete to finish, if k8s has problems # with deletes in the future, I can add a wait here. rescue ShellCommandFailed => ex raise unless ex.to_s.include?('(NotFound)') end
finalize_config!(instance)
click to toggle source
Muck with some other plugins to make the UX easier. Haxxxx.
@api private
Calls superclass method
# File lib/kitchen/driver/kubernetes.rb, line 103 def finalize_config!(instance) super.tap do # Force the use of the Kubernetes transport since it isn't much use # without that. instance.transport = Kitchen::Transport::Kubernetes.new(config) # Leave room for the possibility of other provisioners in the future, # but force some options we need. if instance.provisioner.is_a?(Kitchen::Provisioner::ChefBase) instance.provisioner.send(:config).update( require_chef_omnibus: false, product_name: nil, chef_omnibus_root: '/opt/chef', sudo: false, ) end # Ditto to the above, other verifiers will need their own hacks, but # this is a start at least. if instance.verifier.is_a?(Kitchen::Verifier::Busser) instance.verifier.send(:config).update( root_path: '/tmp/kitchen/verifier', sudo: false, ) elsif defined?(Kitchen::Verifier::Inspec) && instance.verifier.is_a?(Kitchen::Verifier::Inspec) # Monkeypatch kitchen-inspec to use my copy of the kubernetes train transport. # Pending https://github.com/chef/train/pull/205 and https://github.com/chef/kitchen-inspec/pull/148 # or https://github.com/chef/kitchen-inspec/pull/149. require 'kitchen/verifier/train_kubernetes_hack' _config = config # Because closure madness. old_runner_options = instance.verifier.method(:runner_options) instance.verifier.send(:define_singleton_method, :runner_options) do |transport, state = {}, platform = nil, suite = nil| if transport.is_a?(Kitchen::Transport::Kubernetes) # Initiate 1337 ha><0rz. { "backend" => "kubernetes_hack", "logger" => logger, "pod" => state[:pod_id], "container" => "default", "kubectl_path" => _config[:kubectl_path], "context" => _config[:context], }.tap do |runner_options| # Copied directly from kitchen-inspec because there is no way not to. Sigh. runner_options["color"] = (config[:color].nil? ? true : config[:color]) runner_options["format"] = config[:format] unless config[:format].nil? runner_options["output"] = config[:output] % { platform: platform, suite: suite } unless config[:output].nil? runner_options["profiles_path"] = config[:profiles_path] unless config[:profiles_path].nil? runner_options[:controls] = config[:controls] end else old_runner_options.call(transport, state, platform, suite) end end end end end