ood_core 0.14.0 → 0.17.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.
@@ -1,18 +1,17 @@
1
1
  class OodCore::Job::Adapters::Kubernetes::Helper
2
2
 
3
- require 'ood_core/job/adapters/kubernetes/resources'
3
+ require_relative 'resources'
4
+ require_relative 'k8s_job_info'
4
5
  require 'resolv'
5
6
  require 'base64'
7
+ require 'active_support/core_ext/hash'
6
8
 
7
9
  class K8sDataError < StandardError; end
8
10
 
9
- Resources = OodCore::Job::Adapters::Kubernetes::Resources
10
-
11
11
  # Extract info from json data. The data is expected to be from the kubectl
12
12
  # command and conform to kubernetes' datatype structures.
13
13
  #
14
- # Returns { native: {host: localhost, port:80, password: sshhh }} in the info
15
- # object field in lieu of writing a connection.yml
14
+ # Returns K8sJobInfo in the in lieu of writing a connection.yml
16
15
  #
17
16
  # @param pod_json [#to_h]
18
17
  # the pod data returned from 'kubectl get pod abc-123'
@@ -20,16 +19,17 @@ class OodCore::Job::Adapters::Kubernetes::Helper
20
19
  # the service data returned from 'kubectl get service abc-123-service'
21
20
  # @param secret_json [#to_h]
22
21
  # the secret data returned from 'kubectl get secret abc-123-secret'
23
- # @return [OodCore::Job::Info]
24
- def info_from_json(pod_json: nil, service_json: nil, secret_json: nil)
25
- pod_hash = pod_info_from_json(pod_json)
22
+ # @param ns_prefix [#to_s]
23
+ # the namespace prefix so that namespaces can be converted back to usernames
24
+ # @return [OodCore::Job::Adapters::Kubernetes::K8sJobInfo]
25
+ def info_from_json(pod_json: nil, service_json: nil, secret_json: nil, ns_prefix: nil)
26
+ pod_hash = pod_info_from_json(pod_json, ns_prefix: ns_prefix)
26
27
  service_hash = service_info_from_json(service_json)
27
28
  secret_hash = secret_info_from_json(secret_json)
28
29
 
29
- # can't just use deep_merge bc we don't depend *directly* on rails
30
- pod_hash[:native] = pod_hash[:native].merge(service_hash[:native])
31
- pod_hash[:native] = pod_hash[:native].merge(secret_hash[:native])
32
- OodCore::Job::Info.new(pod_hash)
30
+ pod_hash.deep_merge!(service_hash)
31
+ pod_hash.deep_merge!(secret_hash)
32
+ OodCore::Job::Adapters::Kubernetes::K8sJobInfo.new(pod_hash)
33
33
  rescue NoMethodError
34
34
  raise K8sDataError, "unable to read data correctly from json"
35
35
  end
@@ -38,18 +38,23 @@ class OodCore::Job::Adapters::Kubernetes::Helper
38
38
  #
39
39
  # @param container [#to_h]
40
40
  # the input container hash
41
+ # @param default_env [#to_h]
42
+ # Default env to merge with defined env
41
43
  # @return [OodCore::Job::Adapters::Kubernetes::Resources::Container]
42
- def container_from_native(container)
43
- Resources::Container.new(
44
+ def container_from_native(container, default_env)
45
+ env = container.fetch(:env, {}).to_h.symbolize_keys
46
+ OodCore::Job::Adapters::Kubernetes::Resources::Container.new(
44
47
  container[:name],
45
48
  container[:image],
46
49
  command: parse_command(container[:command]),
47
50
  port: container[:port],
48
- env: container.fetch(:env, []),
51
+ env: default_env.merge(env),
49
52
  memory: container[:memory],
50
53
  cpu: container[:cpu],
51
54
  working_dir: container[:working_dir],
52
- restart_policy: container[:restart_policy]
55
+ restart_policy: container[:restart_policy],
56
+ image_pull_policy: container[:image_pull_policy],
57
+ image_pull_secret: container[:image_pull_secret]
53
58
  )
54
59
  end
55
60
 
@@ -76,15 +81,22 @@ class OodCore::Job::Adapters::Kubernetes::Helper
76
81
  # the input configmap hash
77
82
  # @param id [#to_s]
78
83
  # the id to use for giving the configmap a name
84
+ # @param script_content [#to_s]
85
+ # the batch script content
79
86
  # @return [OodCore::Job::Adapters::Kubernetes::Resources::ConfigMap]
80
- def configmap_from_native(native, id)
81
- configmap = native.fetch(:configmap, nil)
82
- return nil if configmap.nil?
83
-
84
- Resources::ConfigMap.new(
87
+ def configmap_from_native(native, id, script_content)
88
+ configmap = native.fetch(:configmap, {})
89
+ configmap[:files] ||= []
90
+ configmap[:files] << {
91
+ filename: 'script.sh',
92
+ data: script_content,
93
+ mount_path: '/ood/script.sh',
94
+ sub_path: 'script.sh',
95
+ } unless configmap[:files].any? { |f| f[:filename] == 'script.sh' }
96
+
97
+ OodCore::Job::Adapters::Kubernetes::Resources::ConfigMap.new(
85
98
  configmap_name(id),
86
- configmap[:filename],
87
- configmap[:data]
99
+ (configmap[:files] || [])
88
100
  )
89
101
  end
90
102
 
@@ -93,13 +105,15 @@ class OodCore::Job::Adapters::Kubernetes::Helper
93
105
  # @param native_data [#to_h]
94
106
  # the native data to parse. Expected key init_ctrs and for that
95
107
  # key to be an array of hashes.
108
+ # @param default_env [#to_h]
109
+ # Default env to merge with defined env
96
110
  # @return [Array<OodCore::Job::Adapters::Kubernetes::Resources::Container>]
97
111
  # the array of init containers
98
- def init_ctrs_from_native(ctrs)
112
+ def init_ctrs_from_native(ctrs, default_env)
99
113
  init_ctrs = []
100
114
 
101
115
  ctrs&.each do |ctr_raw|
102
- ctr = container_from_native(ctr_raw)
116
+ ctr = container_from_native(ctr_raw, default_env)
103
117
  init_ctrs.push(ctr)
104
118
  end
105
119
 
@@ -118,25 +132,29 @@ class OodCore::Job::Adapters::Kubernetes::Helper
118
132
  id + '-configmap'
119
133
  end
120
134
 
135
+ def seconds_to_duration(s)
136
+ "%02dh%02dm%02ds" % [s / 3600, s / 60 % 60, s % 60]
137
+ end
138
+
121
139
  # Extract pod info from json data. The data is expected to be from the kubectl
122
140
  # command and conform to kubernetes' datatype structures.
123
141
  #
124
142
  # @param json_data [#to_h]
125
143
  # the pod data returned from 'kubectl get pod abc-123'
144
+ # @param ns_prefix [#to_s]
145
+ # the namespace prefix so that namespaces can be converted back to usernames
126
146
  # @return [#to_h]
127
147
  # the hash of info expected from adapters
128
- def pod_info_from_json(json_data)
148
+ def pod_info_from_json(json_data, ns_prefix: nil)
129
149
  {
130
150
  id: json_data.dig(:metadata, :name).to_s,
131
151
  job_name: name_from_metadata(json_data.dig(:metadata)),
132
152
  status: pod_status_from_json(json_data),
133
- job_owner: json_data.dig(:metadata, :namespace).to_s,
153
+ job_owner: job_owner_from_json(json_data, ns_prefix),
134
154
  submission_time: submission_time(json_data),
135
155
  dispatch_time: dispatch_time(json_data),
136
156
  wallclock_time: wallclock_time(json_data),
137
- native: {
138
- host: get_host(json_data.dig(:status, :hostIP))
139
- },
157
+ ood_connection_info: { host: get_host(json_data.dig(:status, :hostIP)) },
140
158
  procs: procs_from_json(json_data)
141
159
  }
142
160
  rescue NoMethodError
@@ -162,39 +180,24 @@ class OodCore::Job::Adapters::Kubernetes::Helper
162
180
  def service_info_from_json(json_data)
163
181
  # all we need is the port - .spec.ports[0].nodePort
164
182
  ports = json_data.dig(:spec, :ports)
165
- {
166
- native:
167
- {
168
- port: ports[0].dig(:nodePort)
169
- }
170
- }
183
+ { ood_connection_info: { port: ports[0].dig(:nodePort) } }
171
184
  rescue
172
- empty_native
185
+ {}
173
186
  end
174
187
 
175
188
  def secret_info_from_json(json_data)
176
189
  raw = json_data.dig(:data, :password)
177
- {
178
- native:
179
- {
180
- password: Base64.decode64(raw)
181
- }
182
- }
190
+ { ood_connection_info: { password: Base64.decode64(raw) } }
183
191
  rescue
184
- empty_native
185
- end
186
-
187
- def empty_native
188
- {
189
- native: {}
190
- }
192
+ {}
191
193
  end
192
194
 
193
195
  def dispatch_time(json_data)
194
196
  status = pod_status_from_json(json_data)
195
- return nil if status == 'undetermined'
197
+ container_statuses = json_data.dig(:status, :containerStatuses)
198
+ return nil if container_statuses.nil?
196
199
 
197
- state_data = json_data.dig(:status, :containerStatuses)[0].dig(:state)
200
+ state_data = container_statuses[0].dig(:state)
198
201
  date_string = nil
199
202
 
200
203
  if status == 'completed'
@@ -208,9 +211,10 @@ class OodCore::Job::Adapters::Kubernetes::Helper
208
211
 
209
212
  def wallclock_time(json_data)
210
213
  status = pod_status_from_json(json_data)
211
- return nil if status == 'undetermined'
214
+ container_statuses = json_data.dig(:status, :containerStatuses)
215
+ return nil if container_statuses.nil?
212
216
 
213
- state_data = json_data.dig(:status, :containerStatuses)[0].dig(:state)
217
+ state_data = container_statuses[0].dig(:state)
214
218
  start_time = dispatch_time(json_data)
215
219
  return nil if start_time.nil?
216
220
 
@@ -250,20 +254,21 @@ class OodCore::Job::Adapters::Kubernetes::Helper
250
254
  end
251
255
 
252
256
  def pod_status_from_json(json_data)
253
- state = 'undetermined'
254
- status = json_data.dig(:status)
255
- container_statuses = status.dig(:containerStatuses)
256
-
257
- if container_statuses.nil?
258
- # if you're here, it means you're pending, probably unschedulable
259
- return OodCore::Job::Status.new(state: state)
260
- end
261
-
262
- # only support 1 container/pod
263
- json_state = container_statuses[0].dig(:state)
264
- state = 'running' unless json_state.dig(:running).nil?
265
- state = terminated_state(json_state) unless json_state.dig(:terminated).nil?
266
- state = 'queued' unless json_state.dig(:waiting).nil?
257
+ phase = json_data.dig(:status, :phase)
258
+ state = case phase
259
+ when "Running"
260
+ "running"
261
+ when "Pending"
262
+ "queued"
263
+ when "Failed"
264
+ "suspended"
265
+ when "Succeeded"
266
+ "completed"
267
+ when "Unknown"
268
+ "undetermined"
269
+ else
270
+ "undetermined"
271
+ end
267
272
 
268
273
  OodCore::Job::Status.new(state: state)
269
274
  end
@@ -295,4 +300,9 @@ class OodCore::Job::Adapters::Kubernetes::Helper
295
300
  cpu
296
301
  end
297
302
  end
298
- end
303
+
304
+ def job_owner_from_json(json_data = {}, ns_prefix = nil)
305
+ namespace = json_data.dig(:metadata, :namespace).to_s
306
+ namespace.delete_prefix(ns_prefix.to_s)
307
+ end
308
+ end
@@ -0,0 +1,9 @@
1
+ # An object that describes a submitted kubernetes job with extended information
2
+ class OodCore::Job::Adapters::Kubernetes::K8sJobInfo < OodCore::Job::Info
3
+ attr_reader :ood_connection_info
4
+
5
+ def initialize(ood_connection_info: {}, **options)
6
+ super(options)
7
+ @ood_connection_info = ood_connection_info
8
+ end
9
+ end
@@ -1,22 +1,45 @@
1
1
  module OodCore::Job::Adapters::Kubernetes::Resources
2
2
 
3
3
  class ConfigMap
4
- attr_accessor :name, :filename, :data
4
+ attr_accessor :name, :files
5
5
 
6
- def initialize(name, filename, data)
6
+ def initialize(name, files)
7
7
  @name = name
8
- @filename = filename
9
- @data = data
8
+ @files = []
9
+ files.each do |f|
10
+ @files << ConfigMapFile.new(f)
11
+ end
12
+ end
13
+
14
+ def mounts?
15
+ @files.any? { |f| f.mount_path }
16
+ end
17
+
18
+ def init_mounts?
19
+ @files.any? { |f| f.init_mount_path }
20
+ end
21
+ end
22
+
23
+ class ConfigMapFile
24
+ attr_accessor :filename, :data, :mount_path, :sub_path, :init_mount_path, :init_sub_path
25
+
26
+ def initialize(data)
27
+ @filename = data[:filename]
28
+ @data = data[:data]
29
+ @mount_path = data[:mount_path]
30
+ @sub_path = data[:sub_path]
31
+ @init_mount_path = data[:init_mount_path]
32
+ @init_sub_path = data[:init_sub_path]
10
33
  end
11
34
  end
12
35
 
13
36
  class Container
14
37
  attr_accessor :name, :image, :command, :port, :env, :memory, :cpu, :working_dir,
15
- :restart_policy
38
+ :restart_policy, :image_pull_policy, :image_pull_secret, :supplemental_groups
16
39
 
17
40
  def initialize(
18
- name, image, command: [], port: nil, env: [], memory: "4Gi", cpu: "1",
19
- working_dir: "", restart_policy: "Never"
41
+ name, image, command: [], port: nil, env: {}, memory: "4Gi", cpu: "1",
42
+ working_dir: "", restart_policy: "Never", image_pull_policy: nil, image_pull_secret: nil, supplemental_groups: []
20
43
  )
21
44
  raise ArgumentError, "containers need valid names and images" unless name && image
22
45
 
@@ -24,11 +47,14 @@ module OodCore::Job::Adapters::Kubernetes::Resources
24
47
  @image = image
25
48
  @command = command.nil? ? [] : command
26
49
  @port = port&.to_i
27
- @env = env.nil? ? [] : env
50
+ @env = env.nil? ? {} : env
28
51
  @memory = memory.nil? ? "4Gi" : memory
29
52
  @cpu = cpu.nil? ? "1" : cpu
30
53
  @working_dir = working_dir.nil? ? "" : working_dir
31
54
  @restart_policy = restart_policy.nil? ? "Never" : restart_policy
55
+ @image_pull_policy = image_pull_policy.nil? ? "IfNotPresent" : image_pull_policy
56
+ @image_pull_secret = image_pull_secret
57
+ @supplemental_groups = supplemental_groups.nil? ? [] : supplemental_groups
32
58
  end
33
59
 
34
60
  def ==(other)
@@ -40,9 +66,11 @@ module OodCore::Job::Adapters::Kubernetes::Resources
40
66
  memory == other.memory &&
41
67
  cpu == other.cpu &&
42
68
  working_dir == other.working_dir &&
43
- restart_policy == other.restart_policy
69
+ restart_policy == other.restart_policy &&
70
+ image_pull_policy == other.image_pull_policy &&
71
+ image_pull_secret == other.image_pull_secret &&
72
+ supplemental_groups == other.supplemental_groups
44
73
  end
45
-
46
74
  end
47
75
 
48
76
  class PodSpec
@@ -7,100 +7,187 @@ metadata:
7
7
  job: <%= id %>
8
8
  app.kubernetes.io/name: <%= container.name %>
9
9
  app.kubernetes.io/managed-by: open-ondemand
10
+ <%- if !script.accounting_id.nil? && script.accounting_id != "" -%>
11
+ account: <%= script.accounting_id %>
12
+ <%- end -%>
13
+ annotations:
14
+ <%- unless script.wall_time.nil? -%>
15
+ pod.kubernetes.io/lifetime: <%= helper.seconds_to_duration(script.wall_time) %>
16
+ <%- end -%>
10
17
  spec:
11
18
  restartPolicy: <%= spec.container.restart_policy %>
12
19
  securityContext:
13
20
  runAsUser: <%= run_as_user %>
14
21
  runAsGroup: <%= run_as_group %>
22
+ runAsNonRoot: true
23
+ <%- if spec.container.supplemental_groups.empty? -%>
24
+ supplementalGroups: []
25
+ <%- else -%>
26
+ supplementalGroups:
27
+ <%- spec.container.supplemental_groups.each do |supplemental_group| -%>
28
+ - "<%= supplemental_group %>"
29
+ <%- end -%>
30
+ <%- end -%>
15
31
  fsGroup: <%= fs_group %>
32
+ hostNetwork: false
33
+ hostIPC: false
34
+ hostPID: false
35
+ <%- unless spec.container.image_pull_secret.nil? -%>
36
+ imagePullSecrets:
37
+ - name: <%= spec.container.image_pull_secret %>
38
+ <%- end -%>
16
39
  containers:
17
40
  - name: "<%= spec.container.name %>"
18
41
  image: <%= spec.container.image %>
19
- imagePullPolicy: IfNotPresent
20
- <% unless spec.container.working_dir.empty? %>
42
+ imagePullPolicy: <%= spec.container.image_pull_policy %>
43
+ <%- unless spec.container.working_dir.empty? -%>
21
44
  workingDir: "<%= spec.container.working_dir %>"
22
- <% end %>
23
- <% unless spec.container.env.empty? %>
45
+ <%- end -%>
24
46
  env:
25
- <% spec.container.env.each do |env| %>
26
- - name: <%= env[:name] %>
27
- value: "<%= env[:value] %>"
28
- <% end %> <%# for each env %>
29
- <% end %> <%# unless env is nil %>
30
- <% unless spec.container.command.empty? %>
47
+ - name: POD_NAME
48
+ valueFrom:
49
+ fieldRef:
50
+ fieldPath: metadata.name
51
+ - name: POD_NAMESPACE
52
+ valueFrom:
53
+ fieldRef:
54
+ fieldPath: metadata.namespace
55
+ <%- spec.container.env.each_pair do |name, value| -%>
56
+ - name: <%= name %>
57
+ value: "<%= value %>"
58
+ <%- end # for each env -%>
59
+ <%- unless spec.container.command.empty? -%>
31
60
  command:
32
- <% spec.container.command.each do |cmd| %>
61
+ <%- spec.container.command.each do |cmd| -%>
33
62
  - "<%= cmd %>"
34
- <% end %> <%# for each command %>
35
- <% end %> <%# unless command is nil %>
36
- <% unless spec.container.port.nil? %>
63
+ <%- end # for each command -%>
64
+ <%- end # unless command is nil -%>
65
+ <%- unless spec.container.port.nil? -%>
37
66
  ports:
38
67
  - containerPort: <%= spec.container.port %>
39
- <% end %>
68
+ <%- end -%>
69
+ <%- if !all_mounts.empty? || (!configmap.nil? && configmap.mounts?) -%>
40
70
  volumeMounts:
41
- <% unless configmap.nil? %>
71
+ <%- unless configmap.nil? -%>
72
+ <%- configmap.files.each do |file| -%>
73
+ <%- next if file.mount_path.nil? -%>
42
74
  - name: configmap-volume
43
- mountPath: <%= configmap_mount_path %>
44
- <% end %>
45
- <% all_mounts.each do |mount| %>
75
+ mountPath: <%= file.mount_path %>
76
+ <%- unless file.sub_path.nil? -%>
77
+ subPath: <%= file.sub_path %>
78
+ <%- end # end unless file.sub_path.nil? -%>
79
+ <%- end # end configmap.files.each -%>
80
+ <%- end # unless configmap.nil? -%>
81
+ <%- all_mounts.each do |mount| -%>
46
82
  - name: <%= mount[:name] %>
47
83
  mountPath: <%= mount[:destination_path] %>
48
- <% end %> <%# for each mount %>
84
+ <%- end # for each mount -%>
85
+ <%- end # configmap mounts? and all_mounts not empty -%>
49
86
  resources:
50
87
  limits:
51
88
  memory: "<%= spec.container.memory %>"
52
89
  cpu: "<%= spec.container.cpu %>"
90
+ <%- unless script.gpus_per_node.nil? -%>
91
+ <%= gpu_type %>: <%= script.gpus_per_node %>
92
+ <%- end -%>
53
93
  requests:
54
94
  memory: "<%= spec.container.memory %>"
55
95
  cpu: "<%= spec.container.cpu %>"
56
- <% unless spec.init_containers.nil? %>
96
+ <%- unless script.gpus_per_node.nil? -%>
97
+ <%= gpu_type %>: <%= script.gpus_per_node %>
98
+ <%- end -%>
99
+ securityContext:
100
+ allowPrivilegeEscalation: false
101
+ capabilities:
102
+ drop:
103
+ - all
104
+ privileged: false
105
+ <%- unless spec.init_containers.empty? -%>
57
106
  initContainers:
58
- <% spec.init_containers.each do |ctr| %>
107
+ <%- spec.init_containers.each do |ctr| -%>
59
108
  - name: "<%= ctr.name %>"
60
109
  image: "<%= ctr.image %>"
110
+ imagePullPolicy: <%= ctr.image_pull_policy %>
111
+ env:
112
+ - name: POD_NAME
113
+ valueFrom:
114
+ fieldRef:
115
+ fieldPath: metadata.name
116
+ - name: POD_NAMESPACE
117
+ valueFrom:
118
+ fieldRef:
119
+ fieldPath: metadata.namespace
120
+ <%- ctr.env.each_pair do |name, value| -%>
121
+ - name: <%= name %>
122
+ value: "<%= value %>"
123
+ <%- end # for each env -%>
61
124
  command:
62
- <% ctr.command.each do |cmd| %>
125
+ <%- ctr.command.each do |cmd| -%>
63
126
  - "<%= cmd %>"
64
- <% end %> <%# command loop %>
127
+ <%- end # command loop -%>
128
+ <%- if !all_mounts.empty? || (!configmap.nil? && configmap.init_mounts?) -%>
65
129
  volumeMounts:
66
- <% unless configmap.nil? %>
130
+ <%- unless configmap.nil? -%>
131
+ <%- configmap.files.each do |file| -%>
132
+ <%- next if file.init_mount_path.nil? -%>
67
133
  - name: configmap-volume
68
- mountPath: <%= configmap_mount_path %>
69
- <% end %>
70
- <% all_mounts.each do |mount| %>
134
+ mountPath: <%= file.init_mount_path %>
135
+ <%- unless file.init_sub_path.nil? -%>
136
+ subPath: <%= file.init_sub_path %>
137
+ <%- end # end unless file.sub_path.nil? -%>
138
+ <%- end # end configmap.files.each -%>
139
+ <%- end # unless configmap.nil? -%>
140
+ <%- all_mounts.each do |mount| -%>
71
141
  - name: <%= mount[:name] %>
72
142
  mountPath: <%= mount[:destination_path] %>
73
- <% end %> <%# for each mount %>
74
- <% end %> <%# init container loop %>
75
- <% end %> <%# if init containers %>
76
- <% unless configmap.nil? || all_mounts.empty? %>
143
+ <%- end # for each mount -%>
144
+ <%- end # if config_map init mounts and all_mounts not empty -%>
145
+ securityContext:
146
+ allowPrivilegeEscalation: false
147
+ capabilities:
148
+ drop:
149
+ - all
150
+ privileged: false
151
+ <%- end # init container loop -%>
152
+ <%- end # if init containers -%>
153
+ <%- unless (configmap.to_s.empty? && all_mounts.empty?) -%>
77
154
  volumes:
78
- <% end %> <%# configmap.nil? || all_mounts.empty? %>
79
- <% unless configmap.nil? %>
155
+ <%- unless configmap.to_s.empty? -%>
80
156
  - name: configmap-volume
81
157
  configMap:
82
158
  name: <%= configmap_name(id) %>
83
- <% end %>
84
- <% all_mounts.each do |mount| %>
85
- <% if mount[:type] == 'nfs' %>
159
+ <%- end -%>
160
+ <%- all_mounts.each do |mount| -%>
161
+ <%- if mount[:type] == 'nfs' -%>
86
162
  - name: <%= mount[:name] %>
87
163
  nfs:
88
164
  server: <%= mount[:host] %>
89
165
  path: <%= mount[:path] %>
90
- <% elsif mount[:type] == 'host' %>
166
+ <%- elsif mount[:type] == 'host' -%>
91
167
  - name: <%= mount[:name] %>
92
168
  hostPath:
93
169
  path: <%= mount[:path] %>
94
170
  type: <%= mount[:host_type] %>
95
- <% end %> <%# if mount is [host,nfs] %>
96
- <% end %> <%# for each mount %>
171
+ <%- end # if mount is [host,nfs] -%>
172
+ <%- end # for each mount -%>
173
+ <%- end # (configmap.to_s.empty? || all_mounts.empty?) -%>
174
+ <%- unless node_selector.empty? -%>
175
+ nodeSelector:
176
+ <%- node_selector.each_pair do |key, value| -%>
177
+ <%= key %>: "<%= value %>"
178
+ <%- end # node_selector.each_pair -%>
179
+ <%- end #unless node_selector.empty? -%>
97
180
  ---
98
- <% unless spec.container.port.nil? %>
181
+ <%- unless spec.container.port.nil? -%>
99
182
  apiVersion: v1
100
183
  kind: Service
101
184
  metadata:
102
185
  name: <%= service_name(id) %>
103
186
  namespace: <%= namespace %>
187
+ labels:
188
+ job: <%= id %>
189
+ app.kubernetes.io/name: <%= container.name %>
190
+ app.kubernetes.io/managed-by: open-ondemand
104
191
  spec:
105
192
  selector:
106
193
  job: <%= id %>
@@ -109,15 +196,22 @@ spec:
109
196
  port: 80
110
197
  targetPort: <%= spec.container.port %>
111
198
  type: NodePort
112
- <% end %> <%# end for service %>
199
+ <%- end # end for service -%>
200
+ <%- unless configmap.nil? -%>
113
201
  ---
114
- <% unless configmap.nil? %>
115
202
  apiVersion: v1
116
203
  kind: ConfigMap
117
204
  metadata:
118
205
  name: <%= configmap_name(id) %>
119
206
  namespace: <%= namespace %>
207
+ labels:
208
+ job: <%= id %>
209
+ app.kubernetes.io/name: <%= container.name %>
210
+ app.kubernetes.io/managed-by: open-ondemand
120
211
  data:
121
- <%= configmap.filename %>: |
122
- <% config_data_lines(configmap.data).each do |line| %><%= line %><% end %>
123
- <% end %> <%# end for configmap %>
212
+ <%- configmap.files.each do |file| -%>
213
+ <%- next if file.data.nil? || file.filename.nil? -%>
214
+ <%= file.filename %>: |
215
+ <% config_data_lines(file.data).each do |line| %><%= line %><% end %>
216
+ <%- end # end for configmap files -%>
217
+ <%- end # end configmap.nil? %>