Class: Kitchen::Driver::Kubernetes
- Inherits:
-
Base
- Object
- Base
- Kitchen::Driver::Kubernetes
- Includes:
- KitchenKubernetes::Helper, ShellOut
- Defined in:
- lib/kitchen/driver/kubernetes.rb
Overview
Kubernetes driver for Kitchen.
Instance Method Summary collapse
- #create(state) ⇒ Object
-
#default_image ⇒ String
Work out the default primary container image to use for this instance.
- #destroy(state) ⇒ Object
-
#finalize_config!(instance) ⇒ Object
private
Muck with some other plugins to make the UX easier.
Methods included from KitchenKubernetes::Helper
#kube_options, #kubectl_command
Instance Method Details
#create(state) ⇒ Object
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
# 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 ⇒ String
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.
92 93 94 95 96 97 98 |
# 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) ⇒ Object
205 206 207 208 209 210 211 212 |
# 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) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Muck with some other plugins to make the UX easier. Haxxxx.
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 |
# 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. = 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 || # Copied directly from kitchen-inspec because there is no way not to. Sigh. ["color"] = (config[:color].nil? ? true : config[:color]) ["format"] = config[:format] unless config[:format].nil? ["output"] = config[:output] % { platform: platform, suite: suite } unless config[:output].nil? ["profiles_path"] = config[:profiles_path] unless config[:profiles_path].nil? [:controls] = config[:controls] end else .call(transport, state, platform, suite) end end end end end |