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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +34 -0
- data/Gemfile.lock +5 -37
- data/flake.nix +2 -1
- data/kube_cluster.gemspec +2 -4
- data/lib/kube/cluster/container.rb +17 -17
- data/lib/kube/cluster/manifest.rb +158 -158
- data/lib/kube/cluster/middleware/annotations.rb +42 -42
- data/lib/kube/cluster/middleware/hpa_for_deployment.rb +134 -134
- data/lib/kube/cluster/middleware/ingress_for_service.rb +75 -75
- data/lib/kube/cluster/middleware/labels.rb +58 -58
- data/lib/kube/cluster/middleware/pod_anti_affinity.rb +104 -104
- data/lib/kube/cluster/middleware/resource_preset.rb +145 -145
- data/lib/kube/cluster/middleware/security_context.rb +127 -127
- data/lib/kube/cluster/middleware/service_for_deployment.rb +120 -120
- data/lib/kube/cluster/middleware.rb +219 -221
- data/lib/kube/cluster/resource/dirty_tracking.rb +388 -388
- data/lib/kube/cluster/resource.rb +16 -16
- data/lib/kube/cluster/standard/cdi/data_volume.rb +13 -13
- data/lib/kube/cluster/standard/cloud_native_pg/cluster.rb +11 -11
- data/lib/kube/cluster/standard/cloud_native_pg/database_with_external_secret.rb +11 -11
- data/lib/kube/cluster/standard/cloud_native_pg/external_secret.rb +11 -11
- data/lib/kube/cluster/standard/cloud_native_pg/helm.rb +26 -26
- data/lib/kube/cluster/standard/config_map.rb +11 -11
- data/lib/kube/cluster/standard/cron_job.rb +13 -13
- data/lib/kube/cluster/standard/cron_job_with_service_account.rb +12 -12
- data/lib/kube/cluster/standard/custom_resource_definition.rb +12 -12
- data/lib/kube/cluster/standard/daemon_set.rb +12 -12
- data/lib/kube/cluster/standard/deployment_with_service.rb +82 -82
- data/lib/kube/cluster/standard/env_processing.rb +15 -15
- data/lib/kube/cluster/standard/eso/external_secret.rb +13 -13
- data/lib/kube/cluster/standard/forgejo/helm.rb +11 -11
- data/lib/kube/cluster/standard/gateway_api/http_route.rb +322 -19
- data/lib/kube/cluster/standard/job.rb +12 -12
- data/lib/kube/cluster/standard/job_with_service_account.rb +11 -11
- data/lib/kube/cluster/standard/kube_virt/virtual_machine.rb +11 -11
- data/lib/kube/cluster/standard/meta_controller/composite_controller.rb +13 -13
- data/lib/kube/cluster/standard/meta_controller/decorator_controller.rb +13 -13
- data/lib/kube/cluster/standard/perses/perses.rb +9 -9
- data/lib/kube/cluster/standard/perses/perses_datasource.rb +13 -13
- data/lib/kube/cluster/standard/persistent_volume_claim.rb +12 -12
- data/lib/kube/cluster/standard/role.rb +12 -12
- data/lib/kube/cluster/standard/role_binding.rb +10 -10
- data/lib/kube/cluster/standard/secret.rb +11 -11
- data/lib/kube/cluster/standard/service.rb +12 -12
- data/lib/kube/cluster/standard/service_account.rb +9 -9
- data/lib/kube/cluster/standard/service_account_with_role.rb +10 -10
- data/lib/kube/cluster/standard/victoria_metrics/vl_agent.rb +9 -9
- data/lib/kube/cluster/standard/victoria_metrics/vl_single.rb +9 -9
- data/lib/kube/cluster/standard/victoria_metrics/vm_agent.rb +9 -9
- data/lib/kube/cluster/standard/victoria_metrics/vm_node_scrape.rb +9 -9
- data/lib/kube/cluster/standard/victoria_metrics/vm_service_scrape.rb +9 -9
- data/lib/kube/cluster/standard/victoria_metrics/vm_single.rb +9 -9
- data/lib/kube/cluster/standard/volume_processing.rb +3 -3
- data/lib/kube/cluster/version.rb +1 -1
- data/lib/kube/cluster.rb +137 -1
- data/lib/kube/helm/chart.rb +323 -323
- data/lib/kube/helm/endpoint.rb +58 -58
- data/lib/kube/helm/repo.rb +160 -160
- metadata +7 -20
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 462551e605fb3e1e675b9e6fbf15275b5e47e8d92182a1bb78e6a4bff5aa1ec2
|
|
4
|
+
data.tar.gz: 0cd151a210e51ffd9143b1a16686c7b4b01e865e5086d62492294f0f764cb1ba
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 16c8211e12773eb6ad277a73d9d3ff56c2111e82077a30dfa2ff527c4c2af9d1259bedef44c42f8528dc76c72f44d7c5aa6f6fa434984383f8ccf78d06551d2f
|
|
7
|
+
data.tar.gz: 10330e17dad9bf19a5e7f96d6dfb8fa007f6c584d21a53c2e4e143ea96e145911995c0be166c959d6007a23a9ca97642e82bc021868be802488ced36d7a3dc28
|
data/.gitignore
CHANGED
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2026-07-13
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `Kube::Cluster.config` / `resolve` DSL backed by an internal resolve table
|
|
12
|
+
that `Kube::Cluster.[]` consults first, so a bare kind can be pinned to an
|
|
13
|
+
explicit `group/version/Kind` instead of whatever the schema registry lists
|
|
14
|
+
first.
|
|
15
|
+
- Resolve-table pins for every bare kind referenced under
|
|
16
|
+
`kube/cluster/standard` — Perses (`v1alpha2`), Gateway API (`v1`), built-in
|
|
17
|
+
Kubernetes kinds, and the Metacontroller, CloudNativePG, External Secrets,
|
|
18
|
+
KubeVirt, k3s HelmChart, and VictoriaMetrics CRDs.
|
|
19
|
+
- `config` warns when `Kube::Cluster::Standard` is already loaded, since those
|
|
20
|
+
classes have already bound their (now stale) superclasses.
|
|
21
|
+
- Test guarding that every bare kind used in the standard tree is pinned in the
|
|
22
|
+
resolve table.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
- **Breaking:** the `kube/cluster/standard` tree is no longer auto-required by
|
|
26
|
+
`require "kube/cluster"`. Projects must require the specific standard classes
|
|
27
|
+
they use, so resolve overrides can be configured beforehand.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
- `Standard::Perses::Perses` and `Standard::Perses::PersesDatasource` now resolve
|
|
31
|
+
to `perses.dev/v1alpha2` instead of the deprecated `v1alpha1` a bare-kind
|
|
32
|
+
lookup defaulted to.
|
|
33
|
+
|
|
34
|
+
[1.0.0]: https://github.com/general-intelligence-systems/kube_cluster/releases/tag/v1.0.0
|
data/Gemfile.lock
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
kube_cluster (0.
|
|
4
|
+
kube_cluster (1.0.0)
|
|
5
5
|
activesupport (~> 8.0)
|
|
6
6
|
kube_kubectl (~> 2.0)
|
|
7
|
-
kube_schema (~> 1.
|
|
8
|
-
scampi (~> 0.1)
|
|
7
|
+
kube_schema (~> 1.9.2)
|
|
9
8
|
|
|
10
9
|
GEM
|
|
11
10
|
remote: https://rubygems.org/
|
|
@@ -23,7 +22,6 @@ GEM
|
|
|
23
22
|
securerandom (>= 0.3)
|
|
24
23
|
tzinfo (~> 2.0, >= 2.0.5)
|
|
25
24
|
uri (>= 0.13.1)
|
|
26
|
-
ast (2.4.3)
|
|
27
25
|
async (2.39.0)
|
|
28
26
|
console (~> 1.29)
|
|
29
27
|
fiber-annotation
|
|
@@ -77,9 +75,6 @@ GEM
|
|
|
77
75
|
base64 (0.3.0)
|
|
78
76
|
bigdecimal (4.1.2)
|
|
79
77
|
build-files (1.10.2)
|
|
80
|
-
colorize (1.1.0)
|
|
81
|
-
colorize-extended (0.1.0)
|
|
82
|
-
colorize (~> 1.1)
|
|
83
78
|
concurrent-ruby (1.3.6)
|
|
84
79
|
connection_pool (3.0.2)
|
|
85
80
|
console (1.34.3)
|
|
@@ -137,11 +132,9 @@ GEM
|
|
|
137
132
|
rubyshell (~> 1.5)
|
|
138
133
|
shellwords (~> 0.2.2)
|
|
139
134
|
string_builder (~> 1.2.2)
|
|
140
|
-
kube_schema (1.
|
|
135
|
+
kube_schema (1.9.2)
|
|
141
136
|
json_schemer (~> 2.5.0)
|
|
142
137
|
rubyshell (~> 1.5.0)
|
|
143
|
-
language_server-protocol (3.17.0.5)
|
|
144
|
-
lint_roller (1.1.0)
|
|
145
138
|
localhost (1.8.0)
|
|
146
139
|
bake
|
|
147
140
|
logger (1.7.0)
|
|
@@ -173,10 +166,6 @@ GEM
|
|
|
173
166
|
net-smtp (0.5.1)
|
|
174
167
|
net-protocol
|
|
175
168
|
openssl (4.0.2)
|
|
176
|
-
parallel (2.1.0)
|
|
177
|
-
parser (3.3.11.1)
|
|
178
|
-
ast (~> 2.4.1)
|
|
179
|
-
racc
|
|
180
169
|
pp (0.6.3)
|
|
181
170
|
prettyprint
|
|
182
171
|
prettyprint (0.2.0)
|
|
@@ -196,13 +185,11 @@ GEM
|
|
|
196
185
|
psych (5.3.1)
|
|
197
186
|
date
|
|
198
187
|
stringio
|
|
199
|
-
racc (1.8.1)
|
|
200
188
|
rack (3.2.6)
|
|
201
189
|
rackula (1.4.1)
|
|
202
190
|
falcon (~> 0.46)
|
|
203
191
|
samovar (~> 2.1)
|
|
204
192
|
variant
|
|
205
|
-
rainbow (3.1.1)
|
|
206
193
|
rake (13.4.2)
|
|
207
194
|
rbs (4.0.2)
|
|
208
195
|
logger
|
|
@@ -215,28 +202,12 @@ GEM
|
|
|
215
202
|
regexp_parser (2.12.0)
|
|
216
203
|
reline (0.6.3)
|
|
217
204
|
io-console (~> 0.5)
|
|
218
|
-
rubocop (1.86.2)
|
|
219
|
-
json (~> 2.3)
|
|
220
|
-
language_server-protocol (~> 3.17.0.2)
|
|
221
|
-
lint_roller (~> 1.1.0)
|
|
222
|
-
parallel (>= 1.10)
|
|
223
|
-
parser (>= 3.3.0.2)
|
|
224
|
-
rainbow (>= 2.2.2, < 4.0)
|
|
225
|
-
regexp_parser (>= 2.9.3, < 3.0)
|
|
226
|
-
rubocop-ast (>= 1.49.0, < 2.0)
|
|
227
|
-
ruby-progressbar (~> 1.7)
|
|
228
|
-
unicode-display_width (>= 2.4.0, < 4.0)
|
|
229
|
-
rubocop-ast (1.49.1)
|
|
230
|
-
parser (>= 3.3.7.2)
|
|
231
|
-
prism (~> 1.7)
|
|
232
|
-
ruby-progressbar (1.13.0)
|
|
233
205
|
rubyshell (1.5.0)
|
|
234
206
|
rugged (1.9.0)
|
|
235
207
|
samovar (2.4.1)
|
|
236
208
|
console (~> 1.0)
|
|
237
209
|
mapping (~> 1.0)
|
|
238
|
-
scampi (0.
|
|
239
|
-
colorize-extended
|
|
210
|
+
scampi (1.0.0)
|
|
240
211
|
securerandom (0.4.1)
|
|
241
212
|
shellwords (0.2.2)
|
|
242
213
|
simpleidn (0.2.3)
|
|
@@ -249,9 +220,6 @@ GEM
|
|
|
249
220
|
tsort (0.2.0)
|
|
250
221
|
tzinfo (2.0.6)
|
|
251
222
|
concurrent-ruby (~> 1.0)
|
|
252
|
-
unicode-display_width (3.2.0)
|
|
253
|
-
unicode-emoji (~> 4.1)
|
|
254
|
-
unicode-emoji (4.2.0)
|
|
255
223
|
uri (1.1.1)
|
|
256
224
|
utopia (2.32.1)
|
|
257
225
|
bake (~> 0.20)
|
|
@@ -290,7 +258,7 @@ DEPENDENCIES
|
|
|
290
258
|
bake-releases
|
|
291
259
|
kube_cluster!
|
|
292
260
|
rake (~> 13.0)
|
|
293
|
-
|
|
261
|
+
scampi (~> 1.0)
|
|
294
262
|
utopia-project
|
|
295
263
|
|
|
296
264
|
BUNDLED WITH
|
data/flake.nix
CHANGED
|
@@ -29,10 +29,11 @@
|
|
|
29
29
|
];
|
|
30
30
|
|
|
31
31
|
shellHook = ''
|
|
32
|
-
export GEM_HOME="$HOME/.gem"
|
|
32
|
+
export GEM_HOME="$HOME/.gem-${ruby.version}"
|
|
33
33
|
export GEM_PATH="$GEM_HOME"
|
|
34
34
|
export PATH="$GEM_HOME/bin:$PATH"
|
|
35
35
|
export BUNDLE_PATH="$GEM_HOME"
|
|
36
|
+
export BUNDLE_GEMFILE="$PWD/Gemfile"
|
|
36
37
|
export BUNDLE_BIN="$GEM_HOME/bin"
|
|
37
38
|
export KUBECONFIG="$PWD/kubeconfig.yaml"
|
|
38
39
|
'';
|
data/kube_cluster.gemspec
CHANGED
|
@@ -28,12 +28,10 @@ Gem::Specification.new do |spec|
|
|
|
28
28
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
29
29
|
spec.require_paths = ["lib"]
|
|
30
30
|
|
|
31
|
-
spec.add_dependency "scampi", "~> 0.1"
|
|
32
|
-
|
|
33
31
|
spec.add_development_dependency "rake", "~> 13.0"
|
|
34
|
-
spec.add_development_dependency "
|
|
32
|
+
spec.add_development_dependency "scampi", "~> 1.0"
|
|
35
33
|
|
|
36
|
-
spec.add_dependency "kube_schema", "~> 1.9.
|
|
34
|
+
spec.add_dependency "kube_schema", "~> 1.9.2"
|
|
37
35
|
spec.add_dependency "kube_kubectl", "~> 2.0"
|
|
38
36
|
spec.add_dependency "activesupport", "~> 8.0"
|
|
39
37
|
end
|
|
@@ -10,24 +10,24 @@ module Kube
|
|
|
10
10
|
end
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
__END__
|
|
14
|
+
|
|
15
|
+
it "creates a valid container" do
|
|
16
|
+
c = Kube::Cluster::Container.new(name: "app", image: "nginx:1.27")
|
|
17
|
+
c.valid?.should.be.true
|
|
18
|
+
c.name.should == "app"
|
|
19
|
+
end
|
|
19
20
|
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
it "auto-coerces inside a Deployment" do
|
|
22
|
+
c = Kube::Cluster::Container.new(name: "app", image: "nginx:1.27")
|
|
22
23
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
deploy = Kube::Cluster["Deployment"].new {
|
|
25
|
+
metadata.name = "web"
|
|
26
|
+
spec.replicas = 1
|
|
27
|
+
spec.selector.matchLabels = { app: "web" }
|
|
28
|
+
spec.template.metadata.labels = { app: "web" }
|
|
29
|
+
spec.template.spec.containers = [c]
|
|
30
|
+
}
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
end
|
|
32
|
+
deploy.to_h[:spec][:template][:spec][:containers].first[:name].should == "app"
|
|
33
33
|
end
|
|
@@ -52,204 +52,204 @@ module Kube
|
|
|
52
52
|
end
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
Middleware = Kube::Cluster::Middleware
|
|
55
|
+
__END__
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
Middleware = Kube::Cluster::Middleware
|
|
59
58
|
|
|
60
|
-
|
|
61
|
-
m = Kube::Cluster::Manifest.new
|
|
62
|
-
m << Kube::Cluster["ConfigMap"].new {
|
|
63
|
-
metadata.name = "test"
|
|
64
|
-
self.data = { key: "value" }
|
|
65
|
-
}
|
|
59
|
+
# ── Bare manifest ────────────────────────────────────────────────────────
|
|
66
60
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
61
|
+
it "bare_manifest_enumerates_resources_unchanged" do
|
|
62
|
+
m = Kube::Cluster::Manifest.new
|
|
63
|
+
m << Kube::Cluster["ConfigMap"].new {
|
|
64
|
+
metadata.name = "test"
|
|
65
|
+
self.data = { key: "value" }
|
|
66
|
+
}
|
|
70
67
|
|
|
71
|
-
|
|
68
|
+
resources = m.to_a
|
|
69
|
+
resources.size.should == 1
|
|
70
|
+
end
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
m = Kube::Cluster::Manifest.new
|
|
75
|
-
m << Kube::Cluster["ConfigMap"].new {
|
|
76
|
-
metadata.name = "test"
|
|
77
|
-
}
|
|
72
|
+
# ── Stack transforms resources ───────────────────────────────────────────
|
|
78
73
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
74
|
+
it "stack_transforms_resources" do
|
|
75
|
+
m = Kube::Cluster::Manifest.new
|
|
76
|
+
m << Kube::Cluster["ConfigMap"].new {
|
|
77
|
+
metadata.name = "test"
|
|
78
|
+
}
|
|
83
79
|
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
stack = Middleware::Stack.new do
|
|
81
|
+
use Middleware::SetNamespace, "production"
|
|
86
82
|
end
|
|
83
|
+
stack.call(m)
|
|
87
84
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
metadata.name = "test"
|
|
92
|
-
}
|
|
85
|
+
resources = m.to_a
|
|
86
|
+
resources.first.to_h.dig(:metadata, :namespace).should == "production"
|
|
87
|
+
end
|
|
93
88
|
|
|
94
|
-
|
|
89
|
+
it "to_yaml_reflects_middleware" do
|
|
90
|
+
m = Kube::Cluster::Manifest.new
|
|
91
|
+
m << Kube::Cluster["ConfigMap"].new {
|
|
92
|
+
metadata.name = "test"
|
|
93
|
+
}
|
|
95
94
|
|
|
96
|
-
|
|
97
|
-
yaml.should.include "namespace: production"
|
|
98
|
-
end
|
|
95
|
+
Middleware::SetNamespace.new("production").call(m)
|
|
99
96
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
m << Kube::Cluster["ConfigMap"].new { metadata.name = "b" }
|
|
97
|
+
yaml = m.to_yaml
|
|
98
|
+
yaml.should.include "namespace: production"
|
|
99
|
+
end
|
|
104
100
|
|
|
105
|
-
|
|
101
|
+
it "enumerable_methods_work" do
|
|
102
|
+
m = Kube::Cluster::Manifest.new
|
|
103
|
+
m << Kube::Cluster["ConfigMap"].new { metadata.name = "a" }
|
|
104
|
+
m << Kube::Cluster["ConfigMap"].new { metadata.name = "b" }
|
|
106
105
|
|
|
107
|
-
|
|
108
|
-
names.should == %w[a b]
|
|
109
|
-
end
|
|
106
|
+
Middleware::SetNamespace.new("production").call(m)
|
|
110
107
|
|
|
111
|
-
|
|
108
|
+
names = m.map { |r| r.to_h.dig(:metadata, :name) }
|
|
109
|
+
names.should == %w[a b]
|
|
110
|
+
end
|
|
112
111
|
|
|
113
|
-
|
|
114
|
-
m = Kube::Cluster::Manifest.new
|
|
115
|
-
m << Kube::Cluster["ConfigMap"].new {
|
|
116
|
-
metadata.name = "test"
|
|
117
|
-
}
|
|
112
|
+
# ── Multi-middleware stack ──────────────────────────────────────────────
|
|
118
113
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
114
|
+
it "multiple_middleware_compose_in_order" do
|
|
115
|
+
m = Kube::Cluster::Manifest.new
|
|
116
|
+
m << Kube::Cluster["ConfigMap"].new {
|
|
117
|
+
metadata.name = "test"
|
|
118
|
+
}
|
|
124
119
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
h.dig(:metadata, :namespace).should == "staging"
|
|
120
|
+
stack = Middleware::Stack.new do
|
|
121
|
+
use Middleware::SetNamespace, "staging"
|
|
122
|
+
use Middleware::Labels, app: "myapp", managed_by: "kube_cluster"
|
|
129
123
|
end
|
|
124
|
+
stack.call(m)
|
|
130
125
|
|
|
131
|
-
|
|
126
|
+
r = m.first
|
|
127
|
+
h = r.to_h
|
|
132
128
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
m << Kube::Cluster["ConfigMap"].new { metadata.name = "a" }
|
|
136
|
-
m << Kube::Cluster["ConfigMap"].new { metadata.name = "b" }
|
|
129
|
+
h.dig(:metadata, :namespace).should == "staging"
|
|
130
|
+
end
|
|
137
131
|
|
|
138
|
-
|
|
139
|
-
end
|
|
132
|
+
# ── size reflects resource count ─────────────────────────────────────────
|
|
140
133
|
|
|
141
|
-
|
|
134
|
+
it "size_reflects_resource_count" do
|
|
135
|
+
m = Kube::Cluster::Manifest.new
|
|
136
|
+
m << Kube::Cluster["ConfigMap"].new { metadata.name = "a" }
|
|
137
|
+
m << Kube::Cluster["ConfigMap"].new { metadata.name = "b" }
|
|
142
138
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
m << Kube::Cluster["ConfigMap"].new { metadata.name = "test" }
|
|
139
|
+
m.size.should == 2
|
|
140
|
+
end
|
|
146
141
|
|
|
147
|
-
|
|
142
|
+
# ── each without block ──────────────────────────────────────────────────
|
|
148
143
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
144
|
+
it "each_without_block_returns_enumerator" do
|
|
145
|
+
m = Kube::Cluster::Manifest.new
|
|
146
|
+
m << Kube::Cluster["ConfigMap"].new { metadata.name = "test" }
|
|
152
147
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
it "generative_middleware_adds_service" do
|
|
156
|
-
m = Kube::Cluster::Manifest.new
|
|
157
|
-
m << Kube::Cluster["Deployment"].new {
|
|
158
|
-
metadata.name = "web"
|
|
159
|
-
metadata.namespace = "default"
|
|
160
|
-
spec.selector.matchLabels = { app: "web" }
|
|
161
|
-
spec.template.metadata.labels = { app: "web" }
|
|
162
|
-
spec.template.spec.containers = [
|
|
163
|
-
{ name: "web", image: "nginx", ports: [{ name: "http", containerPort: 8080 }] },
|
|
164
|
-
]
|
|
165
|
-
}
|
|
148
|
+
Middleware::SetNamespace.new("production").call(m)
|
|
166
149
|
|
|
167
|
-
|
|
150
|
+
enum = m.each
|
|
151
|
+
enum.should.be.instance_of Enumerator
|
|
152
|
+
end
|
|
168
153
|
|
|
169
|
-
|
|
170
|
-
kinds.should == %w[Deployment Service]
|
|
171
|
-
end
|
|
154
|
+
# ── Generative middleware produces new resources ─────────────────────────
|
|
172
155
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
156
|
+
it "generative_middleware_adds_service" do
|
|
157
|
+
m = Kube::Cluster::Manifest.new
|
|
158
|
+
m << Kube::Cluster["Deployment"].new {
|
|
159
|
+
metadata.name = "web"
|
|
160
|
+
metadata.namespace = "default"
|
|
161
|
+
spec.selector.matchLabels = { app: "web" }
|
|
162
|
+
spec.template.metadata.labels = { app: "web" }
|
|
163
|
+
spec.template.spec.containers = [
|
|
164
|
+
{ name: "web", image: "nginx", ports: [{ name: "http", containerPort: 8080 }] },
|
|
165
|
+
]
|
|
166
|
+
}
|
|
178
167
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
resources = m.to_a
|
|
182
|
-
resources.size.should == 1
|
|
183
|
-
end
|
|
168
|
+
Middleware::ServiceForDeployment.new.call(m)
|
|
184
169
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
m = Kube::Cluster::Manifest.new
|
|
189
|
-
m << Kube::Cluster["Deployment"].new {
|
|
190
|
-
metadata.name = "web"
|
|
191
|
-
spec.selector.matchLabels = { app: "web" }
|
|
192
|
-
spec.template.metadata.labels = { app: "web" }
|
|
193
|
-
spec.template.spec.containers = [
|
|
194
|
-
{ name: "web", image: "nginx", ports: [{ name: "http", containerPort: 8080 }] },
|
|
195
|
-
]
|
|
196
|
-
}
|
|
170
|
+
kinds = m.map { |r| r.to_h[:kind] }
|
|
171
|
+
kinds.should == %w[Deployment Service]
|
|
172
|
+
end
|
|
197
173
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
stack.call(m)
|
|
174
|
+
it "generative_middleware_does_not_affect_non_matching_resources" do
|
|
175
|
+
m = Kube::Cluster::Manifest.new
|
|
176
|
+
m << Kube::Cluster["ConfigMap"].new {
|
|
177
|
+
metadata.name = "config"
|
|
178
|
+
}
|
|
204
179
|
|
|
205
|
-
|
|
206
|
-
resources.size.should == 2
|
|
207
|
-
end
|
|
180
|
+
Middleware::ServiceForDeployment.new.call(m)
|
|
208
181
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
m = Kube::Cluster::Manifest.new
|
|
213
|
-
m << Kube::Cluster["Deployment"].new {
|
|
214
|
-
metadata.name = "web"
|
|
215
|
-
spec.selector.matchLabels = { app: "web" }
|
|
216
|
-
spec.template.metadata.labels = { app: "web" }
|
|
217
|
-
spec.template.spec.containers = [
|
|
218
|
-
{ name: "web", image: "nginx", ports: [{ name: "http", containerPort: 8080 }] },
|
|
219
|
-
]
|
|
220
|
-
}
|
|
182
|
+
resources = m.to_a
|
|
183
|
+
resources.size.should == 1
|
|
184
|
+
end
|
|
221
185
|
|
|
222
|
-
|
|
223
|
-
|
|
186
|
+
# ── Generated resources flow through subsequent middleware stages ────────
|
|
187
|
+
|
|
188
|
+
it "generated_resources_flow_through_subsequent_stages" do
|
|
189
|
+
m = Kube::Cluster::Manifest.new
|
|
190
|
+
m << Kube::Cluster["Deployment"].new {
|
|
191
|
+
metadata.name = "web"
|
|
192
|
+
spec.selector.matchLabels = { app: "web" }
|
|
193
|
+
spec.template.metadata.labels = { app: "web" }
|
|
194
|
+
spec.template.spec.containers = [
|
|
195
|
+
{ name: "web", image: "nginx", ports: [{ name: "http", containerPort: 8080 }] },
|
|
196
|
+
]
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
stack = Middleware::Stack.new do
|
|
200
|
+
use Middleware::ServiceForDeployment # generates Service
|
|
201
|
+
use Middleware::SetNamespace, "production" # namespaces everything
|
|
202
|
+
use Middleware::Labels, managed_by: "middleware" # labels everything
|
|
224
203
|
end
|
|
204
|
+
stack.call(m)
|
|
225
205
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
m = Kube::Cluster::Manifest.new
|
|
230
|
-
m << Kube::Cluster["Deployment"].new {
|
|
231
|
-
metadata.name = "web"
|
|
232
|
-
metadata.namespace = "default"
|
|
233
|
-
metadata.labels = {
|
|
234
|
-
"app.kubernetes.io/expose": "app.example.com",
|
|
235
|
-
"app.kubernetes.io/autoscale": "2-10",
|
|
236
|
-
}
|
|
237
|
-
spec.selector.matchLabels = { app: "web" }
|
|
238
|
-
spec.template.metadata.labels = { app: "web" }
|
|
239
|
-
spec.template.spec.containers = [
|
|
240
|
-
{ name: "web", image: "nginx", ports: [{ name: "http", containerPort: 8080 }] },
|
|
241
|
-
]
|
|
242
|
-
}
|
|
206
|
+
resources = m.to_a
|
|
207
|
+
resources.size.should == 2
|
|
208
|
+
end
|
|
243
209
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
210
|
+
# ── YAML serializes integers correctly ──────────────────────────────────
|
|
211
|
+
|
|
212
|
+
it "to_yaml_serializes_integers_as_plain_values" do
|
|
213
|
+
m = Kube::Cluster::Manifest.new
|
|
214
|
+
m << Kube::Cluster["Deployment"].new {
|
|
215
|
+
metadata.name = "web"
|
|
216
|
+
spec.selector.matchLabels = { app: "web" }
|
|
217
|
+
spec.template.metadata.labels = { app: "web" }
|
|
218
|
+
spec.template.spec.containers = [
|
|
219
|
+
{ name: "web", image: "nginx", ports: [{ name: "http", containerPort: 8080 }] },
|
|
220
|
+
]
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
yaml = m.to_yaml
|
|
224
|
+
yaml.should.include "containerPort: 8080"
|
|
225
|
+
end
|
|
250
226
|
|
|
251
|
-
|
|
227
|
+
# ── Multi-generative: chained generation ────────────────────────────────
|
|
252
228
|
|
|
253
|
-
|
|
229
|
+
it "chained_generative_middleware" do
|
|
230
|
+
m = Kube::Cluster::Manifest.new
|
|
231
|
+
m << Kube::Cluster["Deployment"].new {
|
|
232
|
+
metadata.name = "web"
|
|
233
|
+
metadata.namespace = "default"
|
|
234
|
+
metadata.labels = {
|
|
235
|
+
"app.kubernetes.io/expose": "app.example.com",
|
|
236
|
+
"app.kubernetes.io/autoscale": "2-10",
|
|
237
|
+
}
|
|
238
|
+
spec.selector.matchLabels = { app: "web" }
|
|
239
|
+
spec.template.metadata.labels = { app: "web" }
|
|
240
|
+
spec.template.spec.containers = [
|
|
241
|
+
{ name: "web", image: "nginx", ports: [{ name: "http", containerPort: 8080 }] },
|
|
242
|
+
]
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
stack = Middleware::Stack.new do
|
|
246
|
+
use Middleware::ServiceForDeployment # Deployment → +Service
|
|
247
|
+
use Middleware::IngressForService # Service with expose label → +Ingress
|
|
248
|
+
use Middleware::HPAForDeployment # Deployment with autoscale label → +HPA
|
|
254
249
|
end
|
|
250
|
+
stack.call(m)
|
|
251
|
+
|
|
252
|
+
kinds = m.map { |r| r.to_h[:kind] }
|
|
253
|
+
|
|
254
|
+
m.to_a.size.should == 4
|
|
255
255
|
end
|