kitchen-kubernetes 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.travis.yml +50 -0
- data/Gemfile +21 -0
- data/LICENSE +201 -0
- data/README.md +191 -0
- data/Rakefile +17 -0
- data/kitchen-kubernetes.gemspec +50 -0
- data/lib/kitchen-kubernetes/helper.rb +45 -0
- data/lib/kitchen-kubernetes/version.rb +20 -0
- data/lib/kitchen/driver/kubernetes.rb +216 -0
- data/lib/kitchen/driver/pod.yaml.erb +96 -0
- data/lib/kitchen/transport/kubernetes.rb +84 -0
- data/lib/kitchen/verifier/train_kubernetes_hack.rb +90 -0
- data/rsync/Dockerfile +21 -0
- data/test/.kitchen.yml +57 -0
- data/test/cookbooks/test/metadata.rb +17 -0
- data/test/cookbooks/test/recipes/default.rb +30 -0
- data/test/cookbooks/test/recipes/service.rb +28 -0
- data/test/cookbooks/test/templates/template.erb +1 -0
- data/test/gemfiles/master.gemfile +22 -0
- data/test/gemfiles/train-new.gemfile +19 -0
- data/test/gemfiles/train-old.gemfile +19 -0
- data/test/integration/default/serverspec/default_spec.rb +32 -0
- data/test/integration/inspec/default_spec.rb +29 -0
- data/test/integration/service/serverspec/service_spec.rb +23 -0
- metadata +212 -0
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2017, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'bundler/gem_tasks'
|
@@ -0,0 +1,50 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2017, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
lib = File.expand_path('../lib', __FILE__)
|
18
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
19
|
+
require 'kitchen-kubernetes/version'
|
20
|
+
|
21
|
+
Gem::Specification.new do |spec|
|
22
|
+
spec.name = 'kitchen-kubernetes'
|
23
|
+
spec.version = KitchenKubernetes::VERSION
|
24
|
+
spec.authors = ['Noah Kantrowitz']
|
25
|
+
spec.email = ['noah@coderanger.net']
|
26
|
+
spec.description = %q{A Kubernetes Driver for Test Kitchen}
|
27
|
+
spec.summary = spec.description
|
28
|
+
spec.homepage = 'https://github.com/coderanger/kitchen-kubernetes'
|
29
|
+
spec.license = 'Apache 2.0'
|
30
|
+
|
31
|
+
spec.files = `git ls-files`.split($/)
|
32
|
+
spec.executables = []
|
33
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
34
|
+
spec.require_paths = ['lib']
|
35
|
+
|
36
|
+
spec.add_dependency 'test-kitchen', '~> 1.18'
|
37
|
+
|
38
|
+
spec.add_development_dependency 'bundler'
|
39
|
+
spec.add_development_dependency 'rake'
|
40
|
+
|
41
|
+
# Unit testing gems.
|
42
|
+
spec.add_development_dependency 'rspec', '~> 3.2'
|
43
|
+
spec.add_development_dependency 'rspec-its', '~> 1.2'
|
44
|
+
spec.add_development_dependency 'fuubar', '~> 2.0'
|
45
|
+
spec.add_development_dependency 'simplecov', '~> 0.9'
|
46
|
+
spec.add_development_dependency 'codecov', '~> 0.0', '>= 0.0.2'
|
47
|
+
|
48
|
+
# Integration testing.
|
49
|
+
spec.add_development_dependency 'kitchen-inspec', '~> 0.20'
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2017, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
|
18
|
+
module KitchenKubernetes
|
19
|
+
# Utility mixin for other classes in this plugin.
|
20
|
+
#
|
21
|
+
# @since 1.0
|
22
|
+
# @api private
|
23
|
+
module Helper
|
24
|
+
# Because plugins and connections have different APIs.
|
25
|
+
def kube_options
|
26
|
+
if defined?(config)
|
27
|
+
config
|
28
|
+
elsif defined?(options)
|
29
|
+
options
|
30
|
+
else
|
31
|
+
raise "Something went wrong, please file a bug"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def kubectl_command(*cmd)
|
36
|
+
out = [kube_options[:kubectl_command]]
|
37
|
+
if kube_options[:context]
|
38
|
+
out << '--context'
|
39
|
+
out << kube_options[:context]
|
40
|
+
end
|
41
|
+
out.concat(cmd)
|
42
|
+
out
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2017, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
|
18
|
+
module KitchenKubernetes
|
19
|
+
VERSION = "1.0.0"
|
20
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2017, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
require 'erb'
|
18
|
+
require 'json'
|
19
|
+
|
20
|
+
require 'kitchen/driver/base'
|
21
|
+
require 'kitchen/provisioner/chef_base'
|
22
|
+
require 'kitchen/shell_out'
|
23
|
+
require 'kitchen/verifier/busser'
|
24
|
+
|
25
|
+
require 'kitchen/transport/kubernetes'
|
26
|
+
require 'kitchen-kubernetes/helper'
|
27
|
+
|
28
|
+
|
29
|
+
module Kitchen
|
30
|
+
module Driver
|
31
|
+
|
32
|
+
# Kubernetes driver for Kitchen.
|
33
|
+
#
|
34
|
+
# @author Noah Kantrowitz <noah@coderanger>
|
35
|
+
# @since 1.0
|
36
|
+
# @see Kitchen::Transport::Kubernetes
|
37
|
+
class Kubernetes < Kitchen::Driver::Base
|
38
|
+
include ShellOut
|
39
|
+
include KitchenKubernetes::Helper
|
40
|
+
|
41
|
+
default_config :cache_path, '/data/chef/%{chef_version}'
|
42
|
+
default_config :chef_image, 'chef/chef'
|
43
|
+
default_config :chef_version, 'latest'
|
44
|
+
default_config :context, nil
|
45
|
+
default_config :image_pull_policy, nil
|
46
|
+
default_config :image_pull_secrets, nil
|
47
|
+
default_config :init_system, nil
|
48
|
+
default_config :kubectl_command, 'kubectl'
|
49
|
+
default_config :pod_template, File.expand_path('../pod.yaml.erb', __FILE__)
|
50
|
+
default_config :rsync_command, 'rsync'
|
51
|
+
default_config :rsync_image, 'kitchenkubernetes/rsync:3.1.2-r5'
|
52
|
+
default_config :rsync_rsh, "#{RbConfig.ruby} -e \"exec('kubectl', 'exec', '--stdin', '--container=rsync', ARGV[0], '--', *ARGV[1..-1])\""
|
53
|
+
|
54
|
+
default_config :cache_volume do |driver|
|
55
|
+
if driver[:cache_path]
|
56
|
+
path = driver[:cache_path] % {chef_version: driver[:chef_version]}
|
57
|
+
{hostPath: {path: path, type: 'DirectoryOrCreate'}}
|
58
|
+
else
|
59
|
+
{emptyDir: {}}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
default_config :image do |driver|
|
64
|
+
driver.default_image
|
65
|
+
end
|
66
|
+
|
67
|
+
default_config :pod_name do |driver|
|
68
|
+
# Borrowed from kitchen-rackspace.
|
69
|
+
[
|
70
|
+
driver.instance.name.gsub(/\W/, ''),
|
71
|
+
(Etc.getlogin || 'nologin').gsub(/\W/, ''),
|
72
|
+
Socket.gethostname.gsub(/\W/, '')[0..20],
|
73
|
+
Array.new(8) { rand(36).to_s(36) }.join
|
74
|
+
].join('-')
|
75
|
+
end
|
76
|
+
|
77
|
+
# Don't expand path on commands that don't look like a path, otherwise
|
78
|
+
# it turns kubectl in to /path/to/cookbook/kubectl.
|
79
|
+
expand_path_for :kubectl_command do |driver|
|
80
|
+
driver[:kubectl_command] =~ %r{/|\\}
|
81
|
+
end
|
82
|
+
expand_path_for :pod_template
|
83
|
+
expand_path_for :rsync_command do |driver|
|
84
|
+
driver[:rsync_command] =~ %r{/|\\}
|
85
|
+
end
|
86
|
+
|
87
|
+
# Work out the default primary container image to use for this instance.
|
88
|
+
# Can be overridden by subclasses. Must return a string compatible with
|
89
|
+
# a Kubernetes container image specification.
|
90
|
+
#
|
91
|
+
# @return [String]
|
92
|
+
def default_image
|
93
|
+
if instance.platform.name =~ /^(.*)-([^-]*)$/
|
94
|
+
"#{$1}:#{$2}"
|
95
|
+
else
|
96
|
+
instance.platform.name
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Muck with some other plugins to make the UX easier. Haxxxx.
|
101
|
+
#
|
102
|
+
# @api private
|
103
|
+
def finalize_config!(instance)
|
104
|
+
super.tap do
|
105
|
+
# Force the use of the Kubernetes transport since it isn't much use
|
106
|
+
# without that.
|
107
|
+
instance.transport = Kitchen::Transport::Kubernetes.new(config)
|
108
|
+
# Leave room for the possibility of other provisioners in the future,
|
109
|
+
# but force some options we need.
|
110
|
+
if instance.provisioner.is_a?(Kitchen::Provisioner::ChefBase)
|
111
|
+
instance.provisioner.send(:config).update(
|
112
|
+
require_chef_omnibus: false,
|
113
|
+
product_name: nil,
|
114
|
+
chef_omnibus_root: '/opt/chef',
|
115
|
+
sudo: false,
|
116
|
+
)
|
117
|
+
end
|
118
|
+
# Ditto to the above, other verifiers will need their own hacks, but
|
119
|
+
# this is a start at least.
|
120
|
+
if instance.verifier.is_a?(Kitchen::Verifier::Busser)
|
121
|
+
instance.verifier.send(:config).update(
|
122
|
+
root_path: '/tmp/kitchen/verifier',
|
123
|
+
sudo: false,
|
124
|
+
)
|
125
|
+
elsif defined?(Kitchen::Verifier::Inspec) && instance.verifier.is_a?(Kitchen::Verifier::Inspec)
|
126
|
+
# Monkeypatch kitchen-inspec to use my copy of the kubernetes train transport.
|
127
|
+
# Pending https://github.com/chef/train/pull/205 and https://github.com/chef/kitchen-inspec/pull/148
|
128
|
+
# or https://github.com/chef/kitchen-inspec/pull/149.
|
129
|
+
require 'kitchen/verifier/train_kubernetes_hack'
|
130
|
+
_config = config # Because closure madness.
|
131
|
+
old_runner_options = instance.verifier.method(:runner_options)
|
132
|
+
instance.verifier.send(:define_singleton_method, :runner_options) do |transport, state = {}, platform = nil, suite = nil|
|
133
|
+
if transport.is_a?(Kitchen::Transport::Kubernetes)
|
134
|
+
# Initiate 1337 ha><0rz.
|
135
|
+
{
|
136
|
+
"backend" => "kubernetes_hack",
|
137
|
+
"logger" => logger,
|
138
|
+
"pod" => state[:pod_id],
|
139
|
+
"container" => "default",
|
140
|
+
"kubectl_path" => _config[:kubectl_path],
|
141
|
+
"context" => _config[:context],
|
142
|
+
}.tap do |runner_options|
|
143
|
+
# Copied directly from kitchen-inspec because there is no way not to. Sigh.
|
144
|
+
runner_options["color"] = (config[:color].nil? ? true : config[:color])
|
145
|
+
runner_options["format"] = config[:format] unless config[:format].nil?
|
146
|
+
runner_options["output"] = config[:output] % { platform: platform, suite: suite } unless config[:output].nil?
|
147
|
+
runner_options["profiles_path"] = config[:profiles_path] unless config[:profiles_path].nil?
|
148
|
+
runner_options[:controls] = config[:controls]
|
149
|
+
end
|
150
|
+
else
|
151
|
+
old_runner_options.call(transport, state, platform, suite)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# (see Base#create)
|
159
|
+
def create(state)
|
160
|
+
# Already created, we're good.
|
161
|
+
return if state[:pod_id]
|
162
|
+
# Lock in our name with randomness and whatever.
|
163
|
+
pod_id = config[:pod_name]
|
164
|
+
# Render the pod YAML and feed it to kubectl.
|
165
|
+
tpl = ERB.new(IO.read(config[:pod_template]), 0, '-')
|
166
|
+
tpl.filename = config[:pod_template]
|
167
|
+
pod_yaml = tpl.result(binding)
|
168
|
+
debug("Creating pod with YAML:\n#{pod_yaml}\n")
|
169
|
+
run_command(kubectl_command('create', '--filename', '-'), input: pod_yaml)
|
170
|
+
# Wait until the pod reaches Running status.
|
171
|
+
status = nil
|
172
|
+
start_time = Time.now
|
173
|
+
while status != 'Running'
|
174
|
+
if Time.now - start_time > 20
|
175
|
+
# More than 20 seconds, start giving user feedback. 20 second threshold
|
176
|
+
# was 100% pulled from my ass based on how long it takes to launch
|
177
|
+
# on my local minikube, may need changing for reality.
|
178
|
+
info("Waiting for pod #{pod_id} to be running, currently #{status}")
|
179
|
+
end
|
180
|
+
sleep(1)
|
181
|
+
# Can't use run_command here because error! is unwanted and logging is a bit much.
|
182
|
+
status_cmd = Mixlib::ShellOut.new(kubectl_command('get', 'pod', pod_id, '--output=json'))
|
183
|
+
status_cmd.run_command
|
184
|
+
unless status_cmd.error? || status_cmd.stdout.empty?
|
185
|
+
status = JSON.parse(status_cmd.stdout)['status']['phase']
|
186
|
+
end
|
187
|
+
end
|
188
|
+
# Save the pod ID.
|
189
|
+
state[:pod_id] = pod_id
|
190
|
+
rescue Exception => ex
|
191
|
+
# If something goes wrong, try to clean up.
|
192
|
+
if pod_id
|
193
|
+
begin
|
194
|
+
debug("Failure during create, trying to clean up pod #{pod_id}")
|
195
|
+
run_command(kubectl_command('delete', 'pod', pod_id, '--now'))
|
196
|
+
rescue ShellCommandFailed => cleanup_ex
|
197
|
+
# Welp, we tried.
|
198
|
+
debug("Cleanup failed, continuing anyway: #{cleanup_ex}")
|
199
|
+
end
|
200
|
+
end
|
201
|
+
raise ex
|
202
|
+
end
|
203
|
+
|
204
|
+
# (see Base#destroy)
|
205
|
+
def destroy(state)
|
206
|
+
return unless state[:pod_id]
|
207
|
+
run_command(kubectl_command('delete', 'pod', state[:pod_id], '--now'))
|
208
|
+
# Explicitly not waiting for the delete to finish, if k8s has problems
|
209
|
+
# with deletes in the future, I can add a wait here.
|
210
|
+
rescue ShellCommandFailed => ex
|
211
|
+
raise unless ex.to_s.include?('(NotFound)')
|
212
|
+
end
|
213
|
+
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
#
|
2
|
+
# Copyright 2017, Noah Kantrowitz
|
3
|
+
#
|
4
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
# you may not use this file except in compliance with the License.
|
6
|
+
# You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
# Unless required by applicable law or agreed to in writing, software
|
11
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
# See the License for the specific language governing permissions and
|
14
|
+
# limitations under the License.
|
15
|
+
#
|
16
|
+
|
17
|
+
apiVersion: v1
|
18
|
+
kind: Pod
|
19
|
+
metadata:
|
20
|
+
name: <%= pod_id %>
|
21
|
+
labels:
|
22
|
+
heritage: kitchen-kubernetes
|
23
|
+
annotations:
|
24
|
+
coderanger.net/kitchen-instance: <%= instance.name %>
|
25
|
+
coderanger.net/kitchen-platform: <%= instance.platform.name %>
|
26
|
+
coderanger.net/kitchen-created-by: <%= Etc.getlogin || 'unknown' %>
|
27
|
+
coderanger.net/kitchen-created-on: <%= Socket.gethostname %>
|
28
|
+
spec:
|
29
|
+
initContainers:
|
30
|
+
- name: chef
|
31
|
+
image: <%= config[:chef_image] %>:<%= config[:chef_version] %>
|
32
|
+
<%- if config[:chef_version] == 'latest' -%>
|
33
|
+
command: ["/bin/cp", "-a", "-u", "/opt/chef", "/mnt"]
|
34
|
+
<%- else -%>
|
35
|
+
command: ["/bin/sh", "-c", "if [ ! -d /mnt/chef/bin ]; then cp -a /opt/chef /mnt; fi"]
|
36
|
+
<%- end -%>
|
37
|
+
volumeMounts:
|
38
|
+
- mountPath: /mnt/chef
|
39
|
+
name: chef
|
40
|
+
containers:
|
41
|
+
- name: default
|
42
|
+
image: <%= config[:image] %>
|
43
|
+
<%- if config[:image_pull_policy] %>
|
44
|
+
imagePullPolicy: <%= config[:image_pull_policy] %>
|
45
|
+
<%- end -%>
|
46
|
+
<%- if config[:init_system] == 'systemd' -%>
|
47
|
+
env:
|
48
|
+
- name: container
|
49
|
+
value: docker
|
50
|
+
command: ["/sbin/init"]
|
51
|
+
<%- else -%>
|
52
|
+
command: ["/bin/sh", "-c", "trap 'exit 0' TERM; sleep 2147483647 & wait"]
|
53
|
+
<%- end -%>
|
54
|
+
volumeMounts:
|
55
|
+
- mountPath: /opt/chef
|
56
|
+
name: chef
|
57
|
+
- mountPath: /tmp/kitchen
|
58
|
+
name: kitchen
|
59
|
+
<%- if config[:init_system] == 'systemd' -%>
|
60
|
+
- mountPath: /tmp
|
61
|
+
name: systemd-tmp
|
62
|
+
- mountPath: /run
|
63
|
+
name: systemd-run
|
64
|
+
- mountPath: /run/lock
|
65
|
+
name: systemd-lock
|
66
|
+
- mountPath: /sys/fs/cgroup
|
67
|
+
name: systemd-cgroup
|
68
|
+
readOnly: true
|
69
|
+
<%- end -%>
|
70
|
+
- name: rsync
|
71
|
+
image: <%= config[:rsync_image] %>
|
72
|
+
volumeMounts:
|
73
|
+
- mountPath: /tmp/kitchen
|
74
|
+
name: kitchen
|
75
|
+
volumes:
|
76
|
+
- <%= {name: 'chef'}.merge(config[:cache_volume]).to_json %>
|
77
|
+
- name: kitchen
|
78
|
+
emptyDir: {}
|
79
|
+
<%- if config[:init_system] == 'systemd' -%>
|
80
|
+
- name: systemd-tmp
|
81
|
+
emptyDir:
|
82
|
+
medium: Memory
|
83
|
+
- name: systemd-run
|
84
|
+
emptyDir:
|
85
|
+
medium:
|
86
|
+
- name: systemd-lock
|
87
|
+
emptyDir:
|
88
|
+
medium: Memory
|
89
|
+
- name: systemd-cgroup
|
90
|
+
hostPath:
|
91
|
+
path: /sys/fs/cgroup
|
92
|
+
type: Directory
|
93
|
+
<%- end -%>
|
94
|
+
<%- if config[:image_pull_secrets] -%>
|
95
|
+
imagePullSecrets: <%= Array(config[:image_pull_secrets]).map {|n| {name: n} }.to_json %>
|
96
|
+
<%- end -%>
|