kube_cluster 0.20.1 → 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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +34 -0
  4. data/Gemfile.lock +5 -37
  5. data/flake.nix +2 -1
  6. data/kube_cluster.gemspec +2 -4
  7. data/lib/kube/cluster/container.rb +17 -17
  8. data/lib/kube/cluster/manifest.rb +158 -158
  9. data/lib/kube/cluster/middleware/annotations.rb +42 -42
  10. data/lib/kube/cluster/middleware/hpa_for_deployment.rb +134 -134
  11. data/lib/kube/cluster/middleware/ingress_for_service.rb +75 -75
  12. data/lib/kube/cluster/middleware/labels.rb +58 -58
  13. data/lib/kube/cluster/middleware/pod_anti_affinity.rb +104 -104
  14. data/lib/kube/cluster/middleware/resource_preset.rb +145 -145
  15. data/lib/kube/cluster/middleware/security_context.rb +127 -127
  16. data/lib/kube/cluster/middleware/service_for_deployment.rb +120 -120
  17. data/lib/kube/cluster/middleware.rb +219 -221
  18. data/lib/kube/cluster/resource/dirty_tracking.rb +388 -388
  19. data/lib/kube/cluster/resource.rb +16 -16
  20. data/lib/kube/cluster/standard/cdi/data_volume.rb +13 -13
  21. data/lib/kube/cluster/standard/cloud_native_pg/cluster.rb +11 -11
  22. data/lib/kube/cluster/standard/cloud_native_pg/database_with_external_secret.rb +11 -11
  23. data/lib/kube/cluster/standard/cloud_native_pg/external_secret.rb +11 -11
  24. data/lib/kube/cluster/standard/cloud_native_pg/helm.rb +26 -26
  25. data/lib/kube/cluster/standard/config_map.rb +11 -11
  26. data/lib/kube/cluster/standard/cron_job.rb +13 -13
  27. data/lib/kube/cluster/standard/cron_job_with_service_account.rb +12 -12
  28. data/lib/kube/cluster/standard/custom_resource_definition.rb +12 -12
  29. data/lib/kube/cluster/standard/daemon_set.rb +12 -12
  30. data/lib/kube/cluster/standard/deployment_with_service.rb +82 -82
  31. data/lib/kube/cluster/standard/env_processing.rb +15 -15
  32. data/lib/kube/cluster/standard/eso/external_secret.rb +13 -13
  33. data/lib/kube/cluster/standard/forgejo/helm.rb +11 -11
  34. data/lib/kube/cluster/standard/gateway_api/http_route.rb +322 -19
  35. data/lib/kube/cluster/standard/job.rb +12 -12
  36. data/lib/kube/cluster/standard/job_with_service_account.rb +11 -11
  37. data/lib/kube/cluster/standard/kube_virt/virtual_machine.rb +11 -11
  38. data/lib/kube/cluster/standard/meta_controller/composite_controller.rb +13 -13
  39. data/lib/kube/cluster/standard/meta_controller/decorator_controller.rb +13 -13
  40. data/lib/kube/cluster/standard/perses/perses.rb +9 -9
  41. data/lib/kube/cluster/standard/perses/perses_datasource.rb +13 -13
  42. data/lib/kube/cluster/standard/persistent_volume_claim.rb +12 -12
  43. data/lib/kube/cluster/standard/role.rb +12 -12
  44. data/lib/kube/cluster/standard/role_binding.rb +10 -10
  45. data/lib/kube/cluster/standard/secret.rb +11 -11
  46. data/lib/kube/cluster/standard/service.rb +12 -12
  47. data/lib/kube/cluster/standard/service_account.rb +9 -9
  48. data/lib/kube/cluster/standard/service_account_with_role.rb +10 -10
  49. data/lib/kube/cluster/standard/victoria_metrics/vl_agent.rb +9 -9
  50. data/lib/kube/cluster/standard/victoria_metrics/vl_single.rb +9 -9
  51. data/lib/kube/cluster/standard/victoria_metrics/vm_agent.rb +9 -9
  52. data/lib/kube/cluster/standard/victoria_metrics/vm_node_scrape.rb +9 -9
  53. data/lib/kube/cluster/standard/victoria_metrics/vm_service_scrape.rb +9 -9
  54. data/lib/kube/cluster/standard/victoria_metrics/vm_single.rb +9 -9
  55. data/lib/kube/cluster/standard/volume_processing.rb +3 -3
  56. data/lib/kube/cluster/version.rb +1 -1
  57. data/lib/kube/cluster.rb +137 -1
  58. data/lib/kube/helm/chart.rb +323 -323
  59. data/lib/kube/helm/endpoint.rb +58 -58
  60. data/lib/kube/helm/repo.rb +160 -160
  61. metadata +7 -20
@@ -68,163 +68,163 @@ module Kube
68
68
  end
69
69
  end
70
70
 
71
- test do
72
- Middleware = Kube::Cluster::Middleware
73
-
74
- it "injects_small_preset_into_deployment" do
75
- m = manifest(Kube::Cluster["Deployment"].new {
76
- metadata.name = "web"
77
- metadata.labels = { "app.kubernetes.io/size": "small" }
78
- spec.selector.matchLabels = { app: "web" }
79
- spec.template.metadata.labels = { app: "web" }
80
- spec.template.spec.containers = [
81
- { name: "web", image: "nginx:latest" },
82
- ]
83
- })
84
-
85
- Middleware::ResourcePreset.new.call(m)
86
- container = m.resources.first.to_h.dig(:spec, :template, :spec, :containers, 0)
87
-
88
- container.dig(:resources, :requests, :cpu).should == "500m"
89
- end
71
+ __END__
90
72
 
91
- it "injects_nano_preset" do
92
- m = manifest(Kube::Cluster["Deployment"].new {
93
- metadata.name = "tiny"
94
- metadata.labels = { "app.kubernetes.io/size": "nano" }
95
- spec.selector.matchLabels = { app: "tiny" }
96
- spec.template.metadata.labels = { app: "tiny" }
97
- spec.template.spec.containers = [
98
- { name: "app", image: "app:latest" },
99
- ]
100
- })
101
-
102
- Middleware::ResourcePreset.new.call(m)
103
- container = m.resources.first.to_h.dig(:spec, :template, :spec, :containers, 0)
104
-
105
- container.dig(:resources, :requests, :cpu).should == "100m"
106
- end
73
+ Middleware = Kube::Cluster::Middleware
107
74
 
108
- it "injects_xlarge_preset" do
109
- m = manifest(Kube::Cluster["Deployment"].new {
110
- metadata.name = "big"
111
- metadata.labels = { "app.kubernetes.io/size": "xlarge" }
112
- spec.selector.matchLabels = { app: "big" }
113
- spec.template.metadata.labels = { app: "big" }
114
- spec.template.spec.containers = [
115
- { name: "app", image: "app:latest" },
116
- ]
117
- })
118
-
119
- Middleware::ResourcePreset.new.call(m)
120
- container = m.resources.first.to_h.dig(:spec, :template, :spec, :containers, 0)
121
-
122
- container.dig(:resources, :limits, :cpu).should == "3"
123
- end
75
+ it "injects_small_preset_into_deployment" do
76
+ m = manifest(Kube::Cluster["Deployment"].new {
77
+ metadata.name = "web"
78
+ metadata.labels = { "app.kubernetes.io/size": "small" }
79
+ spec.selector.matchLabels = { app: "web" }
80
+ spec.template.metadata.labels = { app: "web" }
81
+ spec.template.spec.containers = [
82
+ { name: "web", image: "nginx:latest" },
83
+ ]
84
+ })
124
85
 
125
- it "applies_to_all_containers" do
126
- m = manifest(Kube::Cluster["Deployment"].new {
127
- metadata.name = "multi"
128
- metadata.labels = { "app.kubernetes.io/size": "micro" }
129
- spec.selector.matchLabels = { app: "multi" }
130
- spec.template.metadata.labels = { app: "multi" }
131
- spec.template.spec.containers = [
132
- { name: "app", image: "app:latest" },
133
- { name: "sidecar", image: "sidecar:latest" },
134
- ]
135
- })
136
-
137
- Middleware::ResourcePreset.new.call(m)
138
- containers = m.resources.first.to_h.dig(:spec, :template, :spec, :containers)
139
-
140
- containers.last.dig(:resources, :requests, :cpu).should == "250m"
141
- end
86
+ Middleware::ResourcePreset.new.call(m)
87
+ container = m.resources.first.to_h.dig(:spec, :template, :spec, :containers, 0)
142
88
 
143
- it "skips_non_pod_bearing_resources" do
144
- resource = Kube::Cluster["ConfigMap"].new {
145
- metadata.name = "config"
146
- metadata.labels = { "app.kubernetes.io/size": "small" }
147
- }
148
- m = manifest(resource)
89
+ container.dig(:resources, :requests, :cpu).should == "500m"
90
+ end
149
91
 
150
- Middleware::ResourcePreset.new.call(m)
92
+ it "injects_nano_preset" do
93
+ m = manifest(Kube::Cluster["Deployment"].new {
94
+ metadata.name = "tiny"
95
+ metadata.labels = { "app.kubernetes.io/size": "nano" }
96
+ spec.selector.matchLabels = { app: "tiny" }
97
+ spec.template.metadata.labels = { app: "tiny" }
98
+ spec.template.spec.containers = [
99
+ { name: "app", image: "app:latest" },
100
+ ]
101
+ })
102
+
103
+ Middleware::ResourcePreset.new.call(m)
104
+ container = m.resources.first.to_h.dig(:spec, :template, :spec, :containers, 0)
105
+
106
+ container.dig(:resources, :requests, :cpu).should == "100m"
107
+ end
151
108
 
152
- m.resources.first.to_h.should == resource.to_h
153
- end
109
+ it "injects_xlarge_preset" do
110
+ m = manifest(Kube::Cluster["Deployment"].new {
111
+ metadata.name = "big"
112
+ metadata.labels = { "app.kubernetes.io/size": "xlarge" }
113
+ spec.selector.matchLabels = { app: "big" }
114
+ spec.template.metadata.labels = { app: "big" }
115
+ spec.template.spec.containers = [
116
+ { name: "app", image: "app:latest" },
117
+ ]
118
+ })
119
+
120
+ Middleware::ResourcePreset.new.call(m)
121
+ container = m.resources.first.to_h.dig(:spec, :template, :spec, :containers, 0)
122
+
123
+ container.dig(:resources, :limits, :cpu).should == "3"
124
+ end
154
125
 
155
- it "skips_resources_without_size_label" do
156
- m = manifest(Kube::Cluster["Deployment"].new {
157
- metadata.name = "web"
158
- spec.selector.matchLabels = { app: "web" }
159
- spec.template.metadata.labels = { app: "web" }
160
- spec.template.spec.containers = [
161
- { name: "web", image: "nginx:latest" },
162
- ]
163
- })
126
+ it "applies_to_all_containers" do
127
+ m = manifest(Kube::Cluster["Deployment"].new {
128
+ metadata.name = "multi"
129
+ metadata.labels = { "app.kubernetes.io/size": "micro" }
130
+ spec.selector.matchLabels = { app: "multi" }
131
+ spec.template.metadata.labels = { app: "multi" }
132
+ spec.template.spec.containers = [
133
+ { name: "app", image: "app:latest" },
134
+ { name: "sidecar", image: "sidecar:latest" },
135
+ ]
136
+ })
137
+
138
+ Middleware::ResourcePreset.new.call(m)
139
+ containers = m.resources.first.to_h.dig(:spec, :template, :spec, :containers)
140
+
141
+ containers.last.dig(:resources, :requests, :cpu).should == "250m"
142
+ end
164
143
 
165
- Middleware::ResourcePreset.new.call(m)
166
- container = m.resources.first.to_h.dig(:spec, :template, :spec, :containers, 0)
144
+ it "skips_non_pod_bearing_resources" do
145
+ resource = Kube::Cluster["ConfigMap"].new {
146
+ metadata.name = "config"
147
+ metadata.labels = { "app.kubernetes.io/size": "small" }
148
+ }
149
+ m = manifest(resource)
167
150
 
168
- container[:resources].should.be.nil
169
- end
151
+ Middleware::ResourcePreset.new.call(m)
170
152
 
171
- it "raises_on_unknown_size" do
172
- m = manifest(Kube::Cluster["Deployment"].new {
173
- metadata.name = "web"
174
- metadata.labels = { "app.kubernetes.io/size": "potato" }
175
- spec.selector.matchLabels = { app: "web" }
176
- spec.template.metadata.labels = { app: "web" }
177
- spec.template.spec.containers = [
178
- { name: "web", image: "nginx:latest" },
179
- ]
180
- })
181
-
182
- lambda { Middleware::ResourcePreset.new.call(m) }.should.raise ArgumentError
183
- end
153
+ m.resources.first.to_h.should == resource.to_h
154
+ end
184
155
 
185
- it "applies_to_statefulset" do
186
- m = manifest(Kube::Cluster["StatefulSet"].new {
187
- metadata.name = "db"
188
- metadata.labels = { "app.kubernetes.io/size": "medium" }
189
- spec.selector.matchLabels = { app: "db" }
190
- spec.template.metadata.labels = { app: "db" }
191
- spec.template.spec.containers = [
192
- { name: "postgres", image: "postgres:16" },
193
- ]
194
- })
195
-
196
- Middleware::ResourcePreset.new.call(m)
197
- container = m.resources.first.to_h.dig(:spec, :template, :spec, :containers, 0)
198
-
199
- container.dig(:resources, :requests, :cpu).should == "500m"
200
- end
156
+ it "skips_resources_without_size_label" do
157
+ m = manifest(Kube::Cluster["Deployment"].new {
158
+ metadata.name = "web"
159
+ spec.selector.matchLabels = { app: "web" }
160
+ spec.template.metadata.labels = { app: "web" }
161
+ spec.template.spec.containers = [
162
+ { name: "web", image: "nginx:latest" },
163
+ ]
164
+ })
201
165
 
202
- it "preserves_existing_container_resources_via_deep_merge" do
203
- m = manifest(Kube::Cluster["Deployment"].new {
204
- metadata.name = "web"
205
- metadata.labels = { "app.kubernetes.io/size": "small" }
206
- spec.selector.matchLabels = { app: "web" }
207
- spec.template.metadata.labels = { app: "web" }
208
- spec.template.spec.containers = [
209
- {
210
- name: "web", image: "nginx:latest",
211
- resources: { requests: { cpu: "999m" } },
212
- },
213
- ]
214
- })
215
-
216
- Middleware::ResourcePreset.new.call(m)
217
- container = m.resources.first.to_h.dig(:spec, :template, :spec, :containers, 0)
218
-
219
- # The container's explicit value wins over the preset
220
- container.dig(:resources, :requests, :cpu).should == "999m"
221
- end
166
+ Middleware::ResourcePreset.new.call(m)
167
+ container = m.resources.first.to_h.dig(:spec, :template, :spec, :containers, 0)
168
+
169
+ container[:resources].should.be.nil
170
+ end
222
171
 
223
- private
172
+ it "raises_on_unknown_size" do
173
+ m = manifest(Kube::Cluster["Deployment"].new {
174
+ metadata.name = "web"
175
+ metadata.labels = { "app.kubernetes.io/size": "potato" }
176
+ spec.selector.matchLabels = { app: "web" }
177
+ spec.template.metadata.labels = { app: "web" }
178
+ spec.template.spec.containers = [
179
+ { name: "web", image: "nginx:latest" },
180
+ ]
181
+ })
182
+
183
+ lambda { Middleware::ResourcePreset.new.call(m) }.should.raise ArgumentError
184
+ end
224
185
 
225
- def manifest(*resources)
226
- m = Kube::Cluster::Manifest.new
227
- resources.each { |r| m << r }
228
- m
229
- end
186
+ it "applies_to_statefulset" do
187
+ m = manifest(Kube::Cluster["StatefulSet"].new {
188
+ metadata.name = "db"
189
+ metadata.labels = { "app.kubernetes.io/size": "medium" }
190
+ spec.selector.matchLabels = { app: "db" }
191
+ spec.template.metadata.labels = { app: "db" }
192
+ spec.template.spec.containers = [
193
+ { name: "postgres", image: "postgres:16" },
194
+ ]
195
+ })
196
+
197
+ Middleware::ResourcePreset.new.call(m)
198
+ container = m.resources.first.to_h.dig(:spec, :template, :spec, :containers, 0)
199
+
200
+ container.dig(:resources, :requests, :cpu).should == "500m"
230
201
  end
202
+
203
+ it "preserves_existing_container_resources_via_deep_merge" do
204
+ m = manifest(Kube::Cluster["Deployment"].new {
205
+ metadata.name = "web"
206
+ metadata.labels = { "app.kubernetes.io/size": "small" }
207
+ spec.selector.matchLabels = { app: "web" }
208
+ spec.template.metadata.labels = { app: "web" }
209
+ spec.template.spec.containers = [
210
+ {
211
+ name: "web", image: "nginx:latest",
212
+ resources: { requests: { cpu: "999m" } },
213
+ },
214
+ ]
215
+ })
216
+
217
+ Middleware::ResourcePreset.new.call(m)
218
+ container = m.resources.first.to_h.dig(:spec, :template, :spec, :containers, 0)
219
+
220
+ # The container's explicit value wins over the preset
221
+ container.dig(:resources, :requests, :cpu).should == "999m"
222
+ end
223
+
224
+ private
225
+
226
+ def manifest(*resources)
227
+ m = Kube::Cluster::Manifest.new
228
+ resources.each { |r| m << r }
229
+ m
230
+ end
@@ -86,142 +86,142 @@ module Kube
86
86
  end
87
87
  end
88
88
 
89
- test do
90
- Middleware = Kube::Cluster::Middleware
91
-
92
- it "applies_restricted_profile_by_default" do
93
- m = manifest(Kube::Cluster["Deployment"].new {
94
- metadata.name = "web"
95
- spec.selector.matchLabels = { app: "web" }
96
- spec.template.metadata.labels = { app: "web" }
97
- spec.template.spec.containers = [
98
- { name: "web", image: "nginx:latest" },
99
- ]
100
- })
101
-
102
- Middleware::SecurityContext.new.call(m)
103
- h = m.resources.first.to_h
104
- pod_sc = h.dig(:spec, :template, :spec, :securityContext)
105
-
106
- pod_sc[:runAsNonRoot].should == true
107
- end
89
+ __END__
108
90
 
109
- it "applies_baseline_profile_via_label" do
110
- m = manifest(Kube::Cluster["Deployment"].new {
111
- metadata.name = "web"
112
- metadata.labels = { "app.kubernetes.io/security": "baseline" }
113
- spec.selector.matchLabels = { app: "web" }
114
- spec.template.metadata.labels = { app: "web" }
115
- spec.template.spec.containers = [
116
- { name: "web", image: "nginx:latest" },
117
- ]
118
- })
119
-
120
- Middleware::SecurityContext.new.call(m)
121
- h = m.resources.first.to_h
122
- pod_sc = h.dig(:spec, :template, :spec, :securityContext)
123
-
124
- pod_sc[:runAsNonRoot].should == true
125
- end
91
+ Middleware = Kube::Cluster::Middleware
126
92
 
127
- it "applies_baseline_profile_via_constructor_default" do
128
- m = manifest(Kube::Cluster["Deployment"].new {
129
- metadata.name = "web"
130
- spec.selector.matchLabels = { app: "web" }
131
- spec.template.metadata.labels = { app: "web" }
132
- spec.template.spec.containers = [
133
- { name: "web", image: "nginx:latest" },
134
- ]
135
- })
136
-
137
- Middleware::SecurityContext.new(default: :baseline).call(m)
138
- h = m.resources.first.to_h
139
- pod_sc = h.dig(:spec, :template, :spec, :securityContext)
140
-
141
- pod_sc[:seccompProfile].should.be.nil
142
- end
93
+ it "applies_restricted_profile_by_default" do
94
+ m = manifest(Kube::Cluster["Deployment"].new {
95
+ metadata.name = "web"
96
+ spec.selector.matchLabels = { app: "web" }
97
+ spec.template.metadata.labels = { app: "web" }
98
+ spec.template.spec.containers = [
99
+ { name: "web", image: "nginx:latest" },
100
+ ]
101
+ })
143
102
 
144
- it "label_overrides_constructor_default" do
145
- m = manifest(Kube::Cluster["Deployment"].new {
146
- metadata.name = "web"
147
- metadata.labels = { "app.kubernetes.io/security": "restricted" }
148
- spec.selector.matchLabels = { app: "web" }
149
- spec.template.metadata.labels = { app: "web" }
150
- spec.template.spec.containers = [
151
- { name: "web", image: "nginx:latest" },
152
- ]
153
- })
154
-
155
- Middleware::SecurityContext.new(default: :baseline).call(m)
156
- h = m.resources.first.to_h
157
- pod_sc = h.dig(:spec, :template, :spec, :securityContext)
158
-
159
- pod_sc[:seccompProfile].should == { type: "RuntimeDefault" }
160
- end
103
+ Middleware::SecurityContext.new.call(m)
104
+ h = m.resources.first.to_h
105
+ pod_sc = h.dig(:spec, :template, :spec, :securityContext)
161
106
 
162
- it "applies_to_all_containers" do
163
- m = manifest(Kube::Cluster["Deployment"].new {
164
- metadata.name = "web"
165
- spec.selector.matchLabels = { app: "web" }
166
- spec.template.metadata.labels = { app: "web" }
167
- spec.template.spec.containers = [
168
- { name: "app", image: "app:latest" },
169
- { name: "sidecar", image: "sidecar:latest" },
170
- ]
171
- })
172
-
173
- Middleware::SecurityContext.new.call(m)
174
- containers = m.resources.first.to_h.dig(:spec, :template, :spec, :containers)
175
-
176
- containers.last.dig(:securityContext, :allowPrivilegeEscalation).should == false
177
- end
107
+ pod_sc[:runAsNonRoot].should == true
108
+ end
178
109
 
179
- it "skips_non_pod_bearing_resources" do
180
- resource = Kube::Cluster["ConfigMap"].new { metadata.name = "config" }
181
- m = manifest(resource)
110
+ it "applies_baseline_profile_via_label" do
111
+ m = manifest(Kube::Cluster["Deployment"].new {
112
+ metadata.name = "web"
113
+ metadata.labels = { "app.kubernetes.io/security": "baseline" }
114
+ spec.selector.matchLabels = { app: "web" }
115
+ spec.template.metadata.labels = { app: "web" }
116
+ spec.template.spec.containers = [
117
+ { name: "web", image: "nginx:latest" },
118
+ ]
119
+ })
120
+
121
+ Middleware::SecurityContext.new.call(m)
122
+ h = m.resources.first.to_h
123
+ pod_sc = h.dig(:spec, :template, :spec, :securityContext)
124
+
125
+ pod_sc[:runAsNonRoot].should == true
126
+ end
182
127
 
183
- Middleware::SecurityContext.new.call(m)
128
+ it "applies_baseline_profile_via_constructor_default" do
129
+ m = manifest(Kube::Cluster["Deployment"].new {
130
+ metadata.name = "web"
131
+ spec.selector.matchLabels = { app: "web" }
132
+ spec.template.metadata.labels = { app: "web" }
133
+ spec.template.spec.containers = [
134
+ { name: "web", image: "nginx:latest" },
135
+ ]
136
+ })
137
+
138
+ Middleware::SecurityContext.new(default: :baseline).call(m)
139
+ h = m.resources.first.to_h
140
+ pod_sc = h.dig(:spec, :template, :spec, :securityContext)
141
+
142
+ pod_sc[:seccompProfile].should.be.nil
143
+ end
184
144
 
185
- m.resources.first.to_h.should == resource.to_h
186
- end
145
+ it "label_overrides_constructor_default" do
146
+ m = manifest(Kube::Cluster["Deployment"].new {
147
+ metadata.name = "web"
148
+ metadata.labels = { "app.kubernetes.io/security": "restricted" }
149
+ spec.selector.matchLabels = { app: "web" }
150
+ spec.template.metadata.labels = { app: "web" }
151
+ spec.template.spec.containers = [
152
+ { name: "web", image: "nginx:latest" },
153
+ ]
154
+ })
155
+
156
+ Middleware::SecurityContext.new(default: :baseline).call(m)
157
+ h = m.resources.first.to_h
158
+ pod_sc = h.dig(:spec, :template, :spec, :securityContext)
159
+
160
+ pod_sc[:seccompProfile].should == { type: "RuntimeDefault" }
161
+ end
187
162
 
188
- it "raises_on_unknown_profile" do
189
- m = manifest(Kube::Cluster["Deployment"].new {
190
- metadata.name = "web"
191
- metadata.labels = { "app.kubernetes.io/security": "yolo" }
192
- spec.selector.matchLabels = { app: "web" }
193
- spec.template.metadata.labels = { app: "web" }
194
- spec.template.spec.containers = [
195
- { name: "web", image: "nginx:latest" },
196
- ]
197
- })
198
-
199
- lambda { Middleware::SecurityContext.new.call(m) }.should.raise ArgumentError
200
- end
163
+ it "applies_to_all_containers" do
164
+ m = manifest(Kube::Cluster["Deployment"].new {
165
+ metadata.name = "web"
166
+ spec.selector.matchLabels = { app: "web" }
167
+ spec.template.metadata.labels = { app: "web" }
168
+ spec.template.spec.containers = [
169
+ { name: "app", image: "app:latest" },
170
+ { name: "sidecar", image: "sidecar:latest" },
171
+ ]
172
+ })
173
+
174
+ Middleware::SecurityContext.new.call(m)
175
+ containers = m.resources.first.to_h.dig(:spec, :template, :spec, :containers)
176
+
177
+ containers.last.dig(:securityContext, :allowPrivilegeEscalation).should == false
178
+ end
201
179
 
202
- it "preserves_existing_pod_security_context" do
203
- m = manifest(Kube::Cluster["Deployment"].new {
204
- metadata.name = "web"
205
- spec.selector.matchLabels = { app: "web" }
206
- spec.template.metadata.labels = { app: "web" }
207
- spec.template.spec.securityContext = { runAsUser: 9999 }
208
- spec.template.spec.containers = [
209
- { name: "web", image: "nginx:latest" },
210
- ]
211
- })
212
-
213
- Middleware::SecurityContext.new.call(m)
214
- pod_sc = m.resources.first.to_h.dig(:spec, :template, :spec, :securityContext)
215
-
216
- # Existing value wins
217
- pod_sc[:runAsUser].should == 9999
218
- end
180
+ it "skips_non_pod_bearing_resources" do
181
+ resource = Kube::Cluster["ConfigMap"].new { metadata.name = "config" }
182
+ m = manifest(resource)
219
183
 
220
- private
184
+ Middleware::SecurityContext.new.call(m)
221
185
 
222
- def manifest(*resources)
223
- m = Kube::Cluster::Manifest.new
224
- resources.each { |r| m << r }
225
- m
226
- end
186
+ m.resources.first.to_h.should == resource.to_h
187
+ end
188
+
189
+ it "raises_on_unknown_profile" do
190
+ m = manifest(Kube::Cluster["Deployment"].new {
191
+ metadata.name = "web"
192
+ metadata.labels = { "app.kubernetes.io/security": "yolo" }
193
+ spec.selector.matchLabels = { app: "web" }
194
+ spec.template.metadata.labels = { app: "web" }
195
+ spec.template.spec.containers = [
196
+ { name: "web", image: "nginx:latest" },
197
+ ]
198
+ })
199
+
200
+ lambda { Middleware::SecurityContext.new.call(m) }.should.raise ArgumentError
227
201
  end
202
+
203
+ it "preserves_existing_pod_security_context" do
204
+ m = manifest(Kube::Cluster["Deployment"].new {
205
+ metadata.name = "web"
206
+ spec.selector.matchLabels = { app: "web" }
207
+ spec.template.metadata.labels = { app: "web" }
208
+ spec.template.spec.securityContext = { runAsUser: 9999 }
209
+ spec.template.spec.containers = [
210
+ { name: "web", image: "nginx:latest" },
211
+ ]
212
+ })
213
+
214
+ Middleware::SecurityContext.new.call(m)
215
+ pod_sc = m.resources.first.to_h.dig(:spec, :template, :spec, :securityContext)
216
+
217
+ # Existing value wins
218
+ pod_sc[:runAsUser].should == 9999
219
+ end
220
+
221
+ private
222
+
223
+ def manifest(*resources)
224
+ m = Kube::Cluster::Manifest.new
225
+ resources.each { |r| m << r }
226
+ m
227
+ end