pfab 0.58.23 → 0.59.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3f1f5eda82b8146e9678f448de6fcd73e1d3eff2beae589631526054fbe8391c
4
- data.tar.gz: 97e88c622c126fd5607f77bbe0a73a08914ab3a91c516a75e5ebbc5d66be05b6
3
+ metadata.gz: 15668736ef7c25f6740964b891ed462e9525438cad02ac4a31f6675fa8a86d8a
4
+ data.tar.gz: cd649c6f885dff4abd50e56c14c20ec7541909e7938abcaf99eefdd46871d5dd
5
5
  SHA512:
6
- metadata.gz: 210e31b7c555d3703e73d25d236d9d616cbf6fbc0b7a397b3fdd62a32fc0d3cf9cbe00458ab0b35ce75b38713ef5a0ec9ca22a9146732795c8dea82bc5e04dba
7
- data.tar.gz: a2c6ee508f2dda1e8a0126f221813e8bff0f5f53a893aee748f5d9fbd97badee9df7feb71e3a84aae235b6467e771fb82e2495948fdf7acc67a00a375081ad65
6
+ metadata.gz: be5e0fc796dee5c98edf48277cc6869c7897e384b1a762743ac8c3845e9988f24d54596d5de64da2dac053c1ab221c83421bab5f6e8d51c43052ae63922e5273
7
+ data.tar.gz: d1c8b6dd4acf30cacd32704f37076da3fc1190be000b08d1718cc02306c1b3d784819ac9a9547393ee015033346c3bbbae99a16cbf08bb9565fbdf667d3fbf6b
@@ -26,9 +26,9 @@ module Pfab
26
26
  def get_command()
27
27
  cmd = get("command")
28
28
  if cmd.kind_of?(Array)
29
- return cmd
29
+ return clean_command_array(cmd)
30
30
  end
31
- return cmd.split(" ")
31
+ return clean_command_array(cmd.split(" "))
32
32
  end
33
33
 
34
34
  def cpu(req_type)
@@ -164,6 +164,156 @@ module Pfab
164
164
  return ports
165
165
  end
166
166
 
167
+ def sidecars
168
+ get("sidecars") || []
169
+ end
170
+
171
+ def build_sidecar_resources(sidecar)
172
+ return nil unless sidecar["resources"]
173
+
174
+ resources = {}
175
+ if sidecar["resources"]["requests"]
176
+ resources[:requests] = {}
177
+ resources[:requests][:cpu] = sidecar["resources"]["requests"]["cpu"] if sidecar["resources"]["requests"]["cpu"]
178
+ resources[:requests][:memory] = sidecar["resources"]["requests"]["memory"] if sidecar["resources"]["requests"]["memory"]
179
+ end
180
+ if sidecar["resources"]["limits"]
181
+ resources[:limits] = {}
182
+ resources[:limits][:cpu] = sidecar["resources"]["limits"]["cpu"] if sidecar["resources"]["limits"]["cpu"]
183
+ resources[:limits][:memory] = sidecar["resources"]["limits"]["memory"] if sidecar["resources"]["limits"]["memory"]
184
+ end
185
+
186
+ resources.empty? ? nil : resources
187
+ end
188
+
189
+ def build_sidecar_env(sidecar)
190
+ # Start with base environment variables that all containers get
191
+ base_env = env_vars.dup
192
+
193
+ # If sidecar has additional env vars, merge them in (allowing overrides)
194
+ if sidecar["env"]
195
+ sidecar_env = sidecar["env"].map do |env_var|
196
+ if env_var.is_a?(Hash)
197
+ env_var.transform_keys(&:to_sym)
198
+ elsif env_var.is_a?(String)
199
+ # Handle simple string format like "KEY=value" or just "KEY"
200
+ if env_var.include?("=")
201
+ key, value = env_var.split("=", 2)
202
+ { name: key, value: value }
203
+ else
204
+ { name: env_var }
205
+ end
206
+ end
207
+ end.compact
208
+
209
+ # Merge sidecar env vars, allowing them to override base vars
210
+ env_hash = {}
211
+ base_env.each { |e| env_hash[e[:name]] = e }
212
+ sidecar_env.each { |e| env_hash[e[:name]] = e }
213
+ env_hash.values
214
+ else
215
+ base_env
216
+ end
217
+ end
218
+
219
+ def build_sidecar_ports(sidecar)
220
+ return nil unless sidecar["ports"]
221
+
222
+ sidecar["ports"].map do |port|
223
+ if port.is_a?(Hash)
224
+ result = {}
225
+ result[:name] = port["name"] if port["name"]
226
+ result[:containerPort] = port["containerPort"] if port["containerPort"]
227
+ result[:protocol] = port["protocol"] if port["protocol"]
228
+ result
229
+ elsif port.is_a?(Integer)
230
+ { containerPort: port }
231
+ end
232
+ end.compact
233
+ end
234
+
235
+ def build_sidecar_volume_mounts(sidecar)
236
+ return nil unless sidecar["volumeMounts"]
237
+
238
+ sidecar["volumeMounts"].map do |mount|
239
+ result = {}
240
+ result[:name] = mount["name"] if mount["name"]
241
+ result[:mountPath] = mount["mountPath"] if mount["mountPath"]
242
+ result[:readOnly] = mount["readOnly"] if mount.key?("readOnly")
243
+ result[:subPath] = mount["subPath"] if mount["subPath"]
244
+ result
245
+ end
246
+ end
247
+
248
+ def build_env_hash_for_expansion
249
+ # Build hash of all environment variables with same precedence as env_vars
250
+ env_hash = {}
251
+
252
+ # Load in order of precedence (later values override earlier)
253
+ [
254
+ @data.dig("application_yaml", :environment),
255
+ @data.dig("application_yaml", @data["env"], :environment),
256
+ app_vars[:environment],
257
+ app_vars.dig(@data["env"], :environment)
258
+ ].each do |env_vars|
259
+ next unless env_vars
260
+ env_vars.each do |key, value|
261
+ # Skip special field/ and configmap/ references
262
+ unless value.to_s.start_with?("field/", "configmap/")
263
+ env_hash[key.to_s] = value.to_s
264
+ end
265
+ end
266
+ end
267
+
268
+ env_hash
269
+ end
270
+
271
+ def expand_variables(str)
272
+ return str unless str.is_a?(String)
273
+
274
+ env_hash = build_env_hash_for_expansion
275
+
276
+ # Support both $(VAR) and ${VAR} syntax
277
+ str.gsub(/\$\{([^}]+)\}|\$\(([^)]+)\)/) do
278
+ var_name = $1 || $2
279
+ env_hash[var_name] || "$#{$1 ? "{#{var_name}}" : "(#{var_name})"}"
280
+ end
281
+ end
282
+
283
+ def clean_command_array(array)
284
+ return nil unless array
285
+
286
+ array.map do |item|
287
+ if item.is_a?(String)
288
+ expand_variables(item.strip)
289
+ else
290
+ item
291
+ end
292
+ end
293
+ end
294
+
295
+ def sidecar_containers
296
+ sidecars.map do |sidecar|
297
+ container = {
298
+ name: sidecar["name"],
299
+ image: sidecar["image"],
300
+ restartPolicy: "Always" # Native sidecar support (K8s 1.28+)
301
+ }
302
+
303
+ container[:command] = clean_command_array(sidecar["command"])
304
+ container[:args] = clean_command_array(sidecar["args"])
305
+ container[:env] = build_sidecar_env(sidecar)
306
+ container[:envFrom] = env_from # Inherit ConfigMap/Secret references
307
+ container[:resources] = build_sidecar_resources(sidecar)
308
+ container[:ports] = build_sidecar_ports(sidecar)
309
+ container[:volumeMounts] = build_sidecar_volume_mounts(sidecar)
310
+ container[:imagePullPolicy] = sidecar["imagePullPolicy"] if sidecar["imagePullPolicy"]
311
+ container[:securityContext] = sidecar["securityContext"].transform_keys(&:to_sym) if sidecar["securityContext"]
312
+
313
+ container.compact
314
+ end
315
+ end
316
+
167
317
  def base_labels
168
318
  {
169
319
  application: @data['application'],
@@ -36,6 +36,7 @@ module Pfab
36
36
  },
37
37
  spec: {
38
38
  serviceAccountName: get('serviceAccountName'),
39
+ initContainers: sidecar_containers.empty? ? nil : sidecar_containers,
39
40
  containers: [
40
41
  {
41
42
  image: image_name,
@@ -33,6 +33,7 @@ module Pfab
33
33
  },
34
34
  spec: {
35
35
  serviceAccountName: get('serviceAccountName'),
36
+ initContainers: sidecar_containers.empty? ? nil : sidecar_containers,
36
37
  containers: [
37
38
  {
38
39
  image: image_name,
@@ -30,6 +30,7 @@ module Pfab
30
30
  },
31
31
  spec: {
32
32
  serviceAccountName: get('serviceAccountName'),
33
+ initContainers: sidecar_containers.empty? ? nil : sidecar_containers,
33
34
  containers: [
34
35
  {
35
36
  image: image_name,
@@ -282,6 +282,7 @@ module Pfab
282
282
  spec: {
283
283
  serviceAccountName: get('serviceAccountName'),
284
284
  terminationGracePeriodSeconds: get("terminationGracePeriodSeconds") || 30,
285
+ initContainers: sidecar_containers.empty? ? nil : sidecar_containers,
285
286
  containers: [
286
287
  {
287
288
  image: image_name,
data/lib/pfab/version.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module Pfab
2
2
  module Version
3
3
  MAJOR = 0
4
- MINOR = 58
5
- PATCH = 23
4
+ MINOR = 59
5
+ PATCH = 0
6
6
  BUILD = nil
7
7
 
8
8
  STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
data/pfab.gemspec CHANGED
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: pfab 0.58.23 ruby lib
5
+ # stub: pfab 0.59.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "pfab".freeze
9
- s.version = "0.58.23".freeze
9
+ s.version = "0.59.0".freeze
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib".freeze]
13
13
  s.authors = ["Jeff Dwyer".freeze]
14
- s.date = "2025-09-08"
14
+ s.date = "2025-10-28"
15
15
  s.description = "k8s helper".freeze
16
16
  s.email = "jdwyer@prefab.cloud".freeze
17
17
  s.executables = ["pfab".freeze]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pfab
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.58.23
4
+ version: 0.59.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeff Dwyer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-09-09 00:00:00.000000000 Z
11
+ date: 2025-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: commander