kube_cluster 0.21.0 → 1.0.1
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/CHANGELOG.md +42 -0
- data/Gemfile.lock +3 -3
- data/kube_cluster.gemspec +1 -1
- data/lib/kube/cluster/standard/gateway_api/http_route.rb +55 -35
- data/lib/kube/cluster/standard.rb +13 -0
- data/lib/kube/cluster/version.rb +1 -1
- data/lib/kube/cluster.rb +138 -0
- metadata +5 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cff2cff26d95919ba88b763d17c91b4fd48b024e038bf5bcbaba269fbf549f6b
|
|
4
|
+
data.tar.gz: cb2b14a5cc86d623c2871517771f7b4e3ecfad529d8ac48093e573065fc80f9d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b6333f789ef8a88beaef674cc32752a42a885a300f5d6bb5ab09f14c2dcab973f111e5ccb20f360605177e24beb3eac69769cd2e85269e98907c162d217adf25
|
|
7
|
+
data.tar.gz: 2cf30bce0097d24f98a20691b99a3f47514581dde2642d4ec2d1dd04c0cf4daf5c660befdbf511976728e084a0083ec21eb283edd5b5c43b9f593946cbfb9204
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
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.1] - 2026-07-13
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- `require "kube/cluster/standard"` — an aggregator that loads the entire
|
|
12
|
+
Standard tree at once, for projects that use most of it. The tree remains
|
|
13
|
+
opt-in (`require "kube/cluster"` alone does not load it), so resolve overrides
|
|
14
|
+
still take effect. The core auto-require now also skips this aggregator file.
|
|
15
|
+
|
|
16
|
+
## [1.0.0] - 2026-07-13
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
- `Kube::Cluster.config` / `resolve` DSL backed by an internal resolve table
|
|
20
|
+
that `Kube::Cluster.[]` consults first, so a bare kind can be pinned to an
|
|
21
|
+
explicit `group/version/Kind` instead of whatever the schema registry lists
|
|
22
|
+
first.
|
|
23
|
+
- Resolve-table pins for every bare kind referenced under
|
|
24
|
+
`kube/cluster/standard` — Perses (`v1alpha2`), Gateway API (`v1`), built-in
|
|
25
|
+
Kubernetes kinds, and the Metacontroller, CloudNativePG, External Secrets,
|
|
26
|
+
KubeVirt, k3s HelmChart, and VictoriaMetrics CRDs.
|
|
27
|
+
- `config` warns when `Kube::Cluster::Standard` is already loaded, since those
|
|
28
|
+
classes have already bound their (now stale) superclasses.
|
|
29
|
+
- Test guarding that every bare kind used in the standard tree is pinned in the
|
|
30
|
+
resolve table.
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
- **Breaking:** the `kube/cluster/standard` tree is no longer auto-required by
|
|
34
|
+
`require "kube/cluster"`. Projects must require the specific standard classes
|
|
35
|
+
they use, so resolve overrides can be configured beforehand.
|
|
36
|
+
|
|
37
|
+
### Fixed
|
|
38
|
+
- `Standard::Perses::Perses` and `Standard::Perses::PersesDatasource` now resolve
|
|
39
|
+
to `perses.dev/v1alpha2` instead of the deprecated `v1alpha1` a bare-kind
|
|
40
|
+
lookup defaulted to.
|
|
41
|
+
|
|
42
|
+
[1.0.0]: https://github.com/general-intelligence-systems/kube_cluster/releases/tag/v1.0.0
|
data/Gemfile.lock
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
kube_cluster (0.
|
|
4
|
+
kube_cluster (1.0.1)
|
|
5
5
|
activesupport (~> 8.0)
|
|
6
6
|
kube_kubectl (~> 2.0)
|
|
7
|
-
kube_schema (~> 1.
|
|
7
|
+
kube_schema (~> 1.9.2)
|
|
8
8
|
|
|
9
9
|
GEM
|
|
10
10
|
remote: https://rubygems.org/
|
|
@@ -132,7 +132,7 @@ GEM
|
|
|
132
132
|
rubyshell (~> 1.5)
|
|
133
133
|
shellwords (~> 0.2.2)
|
|
134
134
|
string_builder (~> 1.2.2)
|
|
135
|
-
kube_schema (1.9.
|
|
135
|
+
kube_schema (1.9.2)
|
|
136
136
|
json_schemer (~> 2.5.0)
|
|
137
137
|
rubyshell (~> 1.5.0)
|
|
138
138
|
localhost (1.8.0)
|
data/kube_cluster.gemspec
CHANGED
|
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
|
31
31
|
spec.add_development_dependency "rake", "~> 13.0"
|
|
32
32
|
spec.add_development_dependency "scampi", "~> 1.0"
|
|
33
33
|
|
|
34
|
-
spec.add_dependency "kube_schema", "~> 1.9.
|
|
34
|
+
spec.add_dependency "kube_schema", "~> 1.9.2"
|
|
35
35
|
spec.add_dependency "kube_kubectl", "~> 2.0"
|
|
36
36
|
spec.add_dependency "activesupport", "~> 8.0"
|
|
37
37
|
end
|
|
@@ -22,16 +22,16 @@ module Kube
|
|
|
22
22
|
#
|
|
23
23
|
# Standard::GatewayApi::HTTPRoute.new(
|
|
24
24
|
# name: "sourcebot",
|
|
25
|
-
# gateway: "
|
|
26
|
-
# domains: ["sg.
|
|
25
|
+
# gateway: "example-com-https",
|
|
26
|
+
# domains: ["sg.example.com"],
|
|
27
27
|
# service: { namespace: "sourcebot", name: "sourcebot", port: 3000 },
|
|
28
|
-
# middleware: "forwardauth-oauth2-proxy-
|
|
28
|
+
# middleware: "forwardauth-oauth2-proxy-example",
|
|
29
29
|
# )
|
|
30
30
|
#
|
|
31
31
|
# Many matches -> one backend (forgejo git smart-HTTP):
|
|
32
32
|
#
|
|
33
33
|
# Standard::GatewayApi::HTTPRoute.new(
|
|
34
|
-
# name: "forgejo-git", gateway: "
|
|
34
|
+
# name: "forgejo-git", gateway: "example-net-https", domains: ["git.example.net"],
|
|
35
35
|
# regex: ["/.+/info/refs", "/.+/git-upload-pack", "/.+/git-receive-pack"],
|
|
36
36
|
# prefix: ["/api", "/v2"],
|
|
37
37
|
# service: { namespace: "default", name: "forgejo-http", port: 3000 },
|
|
@@ -41,8 +41,8 @@ module Kube
|
|
|
41
41
|
# Terminal http->https redirect (the `-http` sibling):
|
|
42
42
|
#
|
|
43
43
|
# Standard::GatewayApi::HTTPRoute.new(
|
|
44
|
-
# name: "sourcebot-http", gateway: "
|
|
45
|
-
# domains: ["sg.
|
|
44
|
+
# name: "sourcebot-http", gateway: "example-com-http",
|
|
45
|
+
# domains: ["sg.example.com"], prefix: ["/"], redirect: true,
|
|
46
46
|
# )
|
|
47
47
|
class HTTPRoute < Kube::Cluster["HTTPRoute"]
|
|
48
48
|
GATEWAY_GROUP = "gateway.networking.k8s.io"
|
|
@@ -86,7 +86,10 @@ module Kube
|
|
|
86
86
|
|
|
87
87
|
super() {
|
|
88
88
|
metadata.name = name
|
|
89
|
-
metadata.namespace
|
|
89
|
+
# A co-located route (namespace: nil) omits metadata.namespace so
|
|
90
|
+
# it lands in whatever namespace applies it; cross-namespace routes
|
|
91
|
+
# in kube-system set it explicitly.
|
|
92
|
+
metadata.namespace = namespace if namespace
|
|
90
93
|
|
|
91
94
|
spec.hostnames = hostnames
|
|
92
95
|
spec.parentRefs = [{
|
|
@@ -175,10 +178,21 @@ module Kube
|
|
|
175
178
|
# the backend (the cross-namespace model, which needs a ReferenceGrant
|
|
176
179
|
# the caller supplies). Omitting it yields the co-located short form.
|
|
177
180
|
def _backend(service)
|
|
178
|
-
ref = {
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
181
|
+
ref = {}
|
|
182
|
+
# Cross-namespace backends carry the explicit group/kind/namespace
|
|
183
|
+
# (and need a ReferenceGrant); a co-located Service uses the bare
|
|
184
|
+
# short form. Emitting group/kind only in the former keeps both
|
|
185
|
+
# shapes byte-identical to the hand-written routes they replace.
|
|
186
|
+
if service[:namespace]
|
|
187
|
+
ref[:group] = ""
|
|
188
|
+
ref[:kind] = "Service"
|
|
189
|
+
ref[:name] = service.fetch(:name)
|
|
190
|
+
ref[:namespace] = service[:namespace]
|
|
191
|
+
else
|
|
192
|
+
ref[:name] = service.fetch(:name)
|
|
193
|
+
end
|
|
194
|
+
ref[:port] = service.fetch(:port)
|
|
195
|
+
ref[:weight] = service.fetch(:weight, 1)
|
|
182
196
|
ref
|
|
183
197
|
end
|
|
184
198
|
end
|
|
@@ -195,8 +209,9 @@ describe "GatewayApi::HTTPRoute" do
|
|
|
195
209
|
it "initializes without error" do
|
|
196
210
|
route.(
|
|
197
211
|
name: "docuseal",
|
|
198
|
-
gateway: "
|
|
199
|
-
domains: ["docuseal.
|
|
212
|
+
gateway: "example-com-https",
|
|
213
|
+
domains: ["docuseal.example.com"],
|
|
214
|
+
prefix: ["/"],
|
|
200
215
|
service: { namespace: "ai", name: "docuseal", port: 3000 },
|
|
201
216
|
).to_yaml.is_a?(String).should == true
|
|
202
217
|
end
|
|
@@ -204,22 +219,23 @@ describe "GatewayApi::HTTPRoute" do
|
|
|
204
219
|
it "wires the fixed traefik-gateway parentRef with the given section" do
|
|
205
220
|
yaml = route.(
|
|
206
221
|
name: "docuseal",
|
|
207
|
-
gateway: "
|
|
208
|
-
domains: ["docuseal.
|
|
222
|
+
gateway: "example-com-https",
|
|
223
|
+
domains: ["docuseal.example.com"],
|
|
224
|
+
prefix: ["/"],
|
|
209
225
|
service: { namespace: "ai", name: "docuseal", port: 3000 },
|
|
210
226
|
).to_yaml
|
|
211
227
|
|
|
212
228
|
yaml.should.include "traefik-gateway"
|
|
213
|
-
yaml.should.include "
|
|
214
|
-
yaml.should.include "docuseal.
|
|
229
|
+
yaml.should.include "example-com-https"
|
|
230
|
+
yaml.should.include "docuseal.example.com"
|
|
215
231
|
yaml.should.include "PathPrefix"
|
|
216
232
|
end
|
|
217
233
|
|
|
218
234
|
it "renders many typed matches onto one backend with timeouts" do
|
|
219
235
|
yaml = route.(
|
|
220
236
|
name: "forgejo-git",
|
|
221
|
-
gateway: "
|
|
222
|
-
domains: ["git.
|
|
237
|
+
gateway: "example-net-https",
|
|
238
|
+
domains: ["git.example.net"],
|
|
223
239
|
regex: ["/.+/info/refs", "/.+/git-upload-pack", "/.+/git-receive-pack"],
|
|
224
240
|
prefix: ["/api", "/v2"],
|
|
225
241
|
service: { namespace: "default", name: "forgejo-http", port: 3000 },
|
|
@@ -236,8 +252,8 @@ describe "GatewayApi::HTTPRoute" do
|
|
|
236
252
|
it "renders a terminal https redirect with no backend" do
|
|
237
253
|
yaml = route.(
|
|
238
254
|
name: "sourcebot-http",
|
|
239
|
-
gateway: "
|
|
240
|
-
domains: ["sg.
|
|
255
|
+
gateway: "example-com-http",
|
|
256
|
+
domains: ["sg.example.com"],
|
|
241
257
|
prefix: ["/"],
|
|
242
258
|
redirect: true,
|
|
243
259
|
).to_yaml
|
|
@@ -250,8 +266,8 @@ describe "GatewayApi::HTTPRoute" do
|
|
|
250
266
|
it "renders a custom redirect with ReplaceFullPath and a 302" do
|
|
251
267
|
yaml = route.(
|
|
252
268
|
name: "forgejo-login",
|
|
253
|
-
gateway: "
|
|
254
|
-
domains: ["git.
|
|
269
|
+
gateway: "example-net-https",
|
|
270
|
+
domains: ["git.example.net"],
|
|
255
271
|
exact: ["/user/login"],
|
|
256
272
|
redirect: { path: "/user/oauth2/authelia", status: 302 },
|
|
257
273
|
).to_yaml
|
|
@@ -264,23 +280,25 @@ describe "GatewayApi::HTTPRoute" do
|
|
|
264
280
|
it "chains multiple middlewares as ExtensionRef filters" do
|
|
265
281
|
yaml = route.(
|
|
266
282
|
name: "docker-registry",
|
|
267
|
-
gateway: "
|
|
268
|
-
domains: ["registry.
|
|
283
|
+
gateway: "example-net-https",
|
|
284
|
+
domains: ["registry.example.net"],
|
|
285
|
+
prefix: ["/"],
|
|
269
286
|
service: { namespace: "docker-registry", name: "docker-registry", port: 80 },
|
|
270
|
-
middleware: ["clear-site-data-cookies", "forwardauth-oauth2-proxy-
|
|
287
|
+
middleware: ["clear-site-data-cookies", "forwardauth-oauth2-proxy-example"],
|
|
271
288
|
).to_yaml
|
|
272
289
|
|
|
273
290
|
yaml.scan(/ExtensionRef/).length.should == 2
|
|
274
291
|
yaml.should.include "clear-site-data-cookies"
|
|
275
|
-
yaml.should.include "forwardauth-oauth2-proxy-
|
|
292
|
+
yaml.should.include "forwardauth-oauth2-proxy-example"
|
|
276
293
|
end
|
|
277
294
|
|
|
278
295
|
it "renders a header modifier and a co-located short-form backend" do
|
|
279
296
|
yaml = route.(
|
|
280
297
|
name: "sogo",
|
|
281
298
|
namespace: "mail",
|
|
282
|
-
gateway: "
|
|
283
|
-
domains: ["sogo.
|
|
299
|
+
gateway: "example-com-https",
|
|
300
|
+
domains: ["sogo.example.com"],
|
|
301
|
+
prefix: ["/"],
|
|
284
302
|
service: { name: "sogo", port: 80 },
|
|
285
303
|
header_modifier: { remove: ["x-webobjects-remote-user"] },
|
|
286
304
|
).to_yaml
|
|
@@ -292,8 +310,9 @@ describe "GatewayApi::HTTPRoute" do
|
|
|
292
310
|
it "supports a websocket header match" do
|
|
293
311
|
yaml = route.(
|
|
294
312
|
name: "chrome-tool-ws",
|
|
295
|
-
gateway: "
|
|
296
|
-
domains: ["chrome-tool-ws.
|
|
313
|
+
gateway: "example-com-https",
|
|
314
|
+
domains: ["chrome-tool-ws.example.com"],
|
|
315
|
+
prefix: ["/"],
|
|
297
316
|
service: { namespace: "ai", name: "chrome-tool-ws", port: 8765 },
|
|
298
317
|
headers: { "Upgrade" => "websocket" },
|
|
299
318
|
).to_yaml
|
|
@@ -305,12 +324,13 @@ describe "GatewayApi::HTTPRoute" do
|
|
|
305
324
|
it "renders multiple hostnames on one route" do
|
|
306
325
|
yaml = route.(
|
|
307
326
|
name: "git",
|
|
308
|
-
gateway: "
|
|
309
|
-
domains: ["git.
|
|
327
|
+
gateway: "example-net-https",
|
|
328
|
+
domains: ["git.example.net", "git.example.com"],
|
|
329
|
+
prefix: ["/"],
|
|
310
330
|
service: { namespace: "default", name: "forgejo-http", port: 3000 },
|
|
311
331
|
).to_yaml
|
|
312
332
|
|
|
313
|
-
yaml.should.include "git.
|
|
314
|
-
yaml.should.include "git.
|
|
333
|
+
yaml.should.include "git.example.net"
|
|
334
|
+
yaml.should.include "git.example.com"
|
|
315
335
|
end
|
|
316
336
|
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
#
|
|
3
|
+
# Opt-in loader for the whole Standard tree.
|
|
4
|
+
#
|
|
5
|
+
# `require "kube/cluster"` deliberately does NOT auto-load the Standard classes
|
|
6
|
+
# (so resolve overrides can be configured before they bind their superclasses).
|
|
7
|
+
# Requiring this file pulls in every Standard class at once — the convenient
|
|
8
|
+
# "give me all of them" entry point for projects that use most of the tree.
|
|
9
|
+
require "kube/cluster"
|
|
10
|
+
|
|
11
|
+
Dir.glob("#{__dir__}/standard/**/*.rb").sort.each do |path|
|
|
12
|
+
require path
|
|
13
|
+
end
|
data/lib/kube/cluster/version.rb
CHANGED
data/lib/kube/cluster.rb
CHANGED
|
@@ -20,6 +20,42 @@ module Kube
|
|
|
20
20
|
Instance.new(kubeconfig: kubeconfig)
|
|
21
21
|
end
|
|
22
22
|
|
|
23
|
+
# Internal table mapping a bare kind to the group/version/Kind it should
|
|
24
|
+
# resolve to. Consulted first by Kube::Cluster.[] so a bare lookup lands on
|
|
25
|
+
# a pinned version instead of whatever the schema registry defaults to.
|
|
26
|
+
def self.resolve_table
|
|
27
|
+
@resolve_table ||= {}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Configure kind resolution:
|
|
31
|
+
#
|
|
32
|
+
# Kube::Cluster.config do
|
|
33
|
+
# resolve "Perses", to: "perses.dev/v1alpha2/Perses"
|
|
34
|
+
# end
|
|
35
|
+
#
|
|
36
|
+
# Ordering matters: Kube::Cluster.[] memoizes per kind, and the Standard
|
|
37
|
+
# classes bind their superclass at definition time (e.g.
|
|
38
|
+
# `class Perses < Kube::Cluster["Perses"]`). A resolve therefore only takes
|
|
39
|
+
# effect for kinds looked up afterwards — so configure before requiring any
|
|
40
|
+
# kube/cluster/standard class. If Standard is already loaded, warn: its
|
|
41
|
+
# classes have already bound their (now stale) superclasses.
|
|
42
|
+
def self.config(&block)
|
|
43
|
+
if const_defined?(:Standard, false)
|
|
44
|
+
warn "Kube::Cluster::Standard was loaded before Kube::Cluster.config — " \
|
|
45
|
+
"resolve overrides will not affect the already-bound Standard classes."
|
|
46
|
+
end
|
|
47
|
+
Config.instance_eval(&block) if block
|
|
48
|
+
Config
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
module Config
|
|
52
|
+
module_function
|
|
53
|
+
|
|
54
|
+
def resolve(kind, to:)
|
|
55
|
+
Kube::Cluster.resolve_table[kind] = to
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
23
59
|
# Returns an anonymous subclass of Kube::Cluster::Resource for the
|
|
24
60
|
# given Kubernetes kind, mirroring Kube::Schema[kind] but with
|
|
25
61
|
# dirty tracking, persistence, and resource helper methods.
|
|
@@ -27,6 +63,7 @@ module Kube
|
|
|
27
63
|
# Kube::Cluster["Deployment"].new { metadata.name = "web" }
|
|
28
64
|
#
|
|
29
65
|
def self.[](kind)
|
|
66
|
+
kind = resolve_table.fetch(kind, kind)
|
|
30
67
|
@resource_classes ||= {}
|
|
31
68
|
@resource_classes[kind] ||= begin
|
|
32
69
|
schema_class = Kube::Schema[kind]
|
|
@@ -48,7 +85,108 @@ require "kube/cluster/middleware"
|
|
|
48
85
|
require "kube/cluster/resource/dirty_tracking"
|
|
49
86
|
require "kube/cluster/resource/persistence"
|
|
50
87
|
|
|
88
|
+
# Kind resolution overrides. Registered here, at load time, so the pins are in
|
|
89
|
+
# place before a project requires any kube/cluster/standard class (those bind
|
|
90
|
+
# Kube::Cluster[kind] at definition time). The standard tree is deliberately not
|
|
91
|
+
# auto-required below — projects require the specific classes they use.
|
|
92
|
+
Kube::Cluster.config do
|
|
93
|
+
# Built-in Kubernetes kinds.
|
|
94
|
+
resolve "ConfigMap", to: "v1/ConfigMap"
|
|
95
|
+
resolve "PersistentVolumeClaim", to: "v1/PersistentVolumeClaim"
|
|
96
|
+
resolve "Secret", to: "v1/Secret"
|
|
97
|
+
resolve "Service", to: "v1/Service"
|
|
98
|
+
resolve "ServiceAccount", to: "v1/ServiceAccount"
|
|
99
|
+
resolve "DaemonSet", to: "apps/v1/DaemonSet"
|
|
100
|
+
resolve "Deployment", to: "apps/v1/Deployment"
|
|
101
|
+
resolve "CronJob", to: "batch/v1/CronJob"
|
|
102
|
+
resolve "Job", to: "batch/v1/Job"
|
|
103
|
+
resolve "Role", to: "rbac.authorization.k8s.io/v1/Role"
|
|
104
|
+
resolve "RoleBinding", to: "rbac.authorization.k8s.io/v1/RoleBinding"
|
|
105
|
+
resolve "CustomResourceDefinition", to: "apiextensions.k8s.io/v1/CustomResourceDefinition"
|
|
106
|
+
|
|
107
|
+
# Metacontroller.
|
|
108
|
+
resolve "CompositeController", to: "metacontroller.k8s.io/v1alpha1/CompositeController"
|
|
109
|
+
resolve "DecoratorController", to: "metacontroller.k8s.io/v1alpha1/DecoratorController"
|
|
110
|
+
|
|
111
|
+
# CloudNativePG.
|
|
112
|
+
resolve "Database", to: "postgresql.cnpg.io/v1/Database"
|
|
113
|
+
|
|
114
|
+
# External Secrets Operator.
|
|
115
|
+
resolve "ExternalSecret", to: "external-secrets.io/v1/ExternalSecret"
|
|
116
|
+
|
|
117
|
+
# KubeVirt.
|
|
118
|
+
resolve "VirtualMachine", to: "kubevirt.io/v1/VirtualMachine"
|
|
119
|
+
|
|
120
|
+
# k3s HelmChart.
|
|
121
|
+
resolve "HelmChart", to: "helm.cattle.io/v1/HelmChart"
|
|
122
|
+
|
|
123
|
+
# VictoriaMetrics operator.
|
|
124
|
+
resolve "VLAgent", to: "operator.victoriametrics.com/v1/VLAgent"
|
|
125
|
+
resolve "VLSingle", to: "operator.victoriametrics.com/v1/VLSingle"
|
|
126
|
+
resolve "VMAgent", to: "operator.victoriametrics.com/v1beta1/VMAgent"
|
|
127
|
+
resolve "VMNodeScrape", to: "operator.victoriametrics.com/v1beta1/VMNodeScrape"
|
|
128
|
+
resolve "VMServiceScrape", to: "operator.victoriametrics.com/v1beta1/VMServiceScrape"
|
|
129
|
+
resolve "VMSingle", to: "operator.victoriametrics.com/v1beta1/VMSingle"
|
|
130
|
+
|
|
131
|
+
# Gateway API — pin to the stable v1 group/version.
|
|
132
|
+
resolve "GatewayClass", to: "gateway.networking.k8s.io/v1/GatewayClass"
|
|
133
|
+
resolve "Gateway", to: "gateway.networking.k8s.io/v1/Gateway"
|
|
134
|
+
resolve "HTTPRoute", to: "gateway.networking.k8s.io/v1/HTTPRoute"
|
|
135
|
+
resolve "GRPCRoute", to: "gateway.networking.k8s.io/v1/GRPCRoute"
|
|
136
|
+
resolve "ReferenceGrant", to: "gateway.networking.k8s.io/v1/ReferenceGrant"
|
|
137
|
+
|
|
138
|
+
# Perses operator — pin to v1alpha2 (bare kind defaults to deprecated v1alpha1).
|
|
139
|
+
resolve "Perses", to: "perses.dev/v1alpha2/Perses"
|
|
140
|
+
resolve "PersesDashboard", to: "perses.dev/v1alpha2/PersesDashboard"
|
|
141
|
+
resolve "PersesDatasource", to: "perses.dev/v1alpha2/PersesDatasource"
|
|
142
|
+
resolve "PersesGlobalDatasource", to: "perses.dev/v1alpha2/PersesGlobalDatasource"
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
standard_root = "#{__dir__}/cluster/standard"
|
|
51
146
|
Dir.glob("#{__dir__}/cluster/**/*.rb").sort.each do |path|
|
|
147
|
+
# The standard/ tree is opt-in — via `require "kube/cluster/standard"` or a
|
|
148
|
+
# specific class — so that resolve overrides can be configured beforehand.
|
|
149
|
+
# Skip both the tree and its aggregator loader (cluster/standard.rb).
|
|
150
|
+
next if path == "#{standard_root}.rb" || path.start_with?("#{standard_root}/")
|
|
151
|
+
|
|
52
152
|
require path
|
|
53
153
|
end
|
|
54
154
|
|
|
155
|
+
__END__
|
|
156
|
+
|
|
157
|
+
# Every Standard class binds its superclass at load time with a bare kind, e.g.
|
|
158
|
+
# `class Perses < Kube::Cluster["Perses"]`. A bare kind resolves to whatever
|
|
159
|
+
# version the schema registry lists first — sometimes a deprecated one (Perses
|
|
160
|
+
# defaulted to v1alpha1) — so each such kind must be pinned in the resolve table
|
|
161
|
+
# above. This fails if any bare kind under kube/cluster/standard is unpinned.
|
|
162
|
+
describe "Kube::Cluster resolve table" do
|
|
163
|
+
it "pins every bare kind referenced under kube/cluster/standard" do
|
|
164
|
+
cluster_rb = Kube::Cluster.method(:[]).source_location.first
|
|
165
|
+
std_dir = File.join(File.dirname(cluster_rb), "cluster", "standard")
|
|
166
|
+
|
|
167
|
+
# kind => ["relative/file.rb:lineno", ...], scanning only real code (the
|
|
168
|
+
# section before each file's own __END__), skipping commented-out classes.
|
|
169
|
+
referenced = {}
|
|
170
|
+
Dir.glob("#{std_dir}/**/*.rb").sort.each do |file|
|
|
171
|
+
head = File.read(file).split(/^__END__$\n?/, 2).first
|
|
172
|
+
head.each_line.with_index(1) do |line, lineno|
|
|
173
|
+
next if line =~ /\A\s*#/
|
|
174
|
+
line.scan(/Kube::Cluster\[\s*['"]([^'"]+)['"]\s*\]/) do |(ref)|
|
|
175
|
+
next if ref.include?("/") # already a fully-qualified GVK
|
|
176
|
+
(referenced[ref] ||= []) << "#{file.sub("#{std_dir}/", "")}:#{lineno}"
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
table = Kube::Cluster.resolve_table
|
|
182
|
+
missing = referenced.reject { |kind, _| table.key?(kind) }
|
|
183
|
+
|
|
184
|
+
unless missing.empty?
|
|
185
|
+
report = missing.sort.map { |kind, locs| " #{kind} (#{locs.join(", ")})" }.join("\n")
|
|
186
|
+
raise "Bare kinds under kube/cluster/standard missing from the resolve table:\n#{report}"
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
missing.empty?.should == true
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kube_cluster
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 1.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nathan K
|
|
@@ -43,14 +43,14 @@ dependencies:
|
|
|
43
43
|
requirements:
|
|
44
44
|
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: 1.9.
|
|
46
|
+
version: 1.9.2
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
51
|
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: 1.9.
|
|
53
|
+
version: 1.9.2
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
55
|
name: kube_kubectl
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -96,6 +96,7 @@ files:
|
|
|
96
96
|
- ".github/workflows/test.yaml"
|
|
97
97
|
- ".gitignore"
|
|
98
98
|
- ".rubocop.yml"
|
|
99
|
+
- CHANGELOG.md
|
|
99
100
|
- Gemfile
|
|
100
101
|
- Gemfile.lock
|
|
101
102
|
- LICENSE
|
|
@@ -197,6 +198,7 @@ files:
|
|
|
197
198
|
- lib/kube/cluster/resource/extensions/custom_resource_definition.rb
|
|
198
199
|
- lib/kube/cluster/resource/persistence.rb
|
|
199
200
|
- lib/kube/cluster/script_command.rb
|
|
201
|
+
- lib/kube/cluster/standard.rb
|
|
200
202
|
- lib/kube/cluster/standard/cdi/data_volume.rb
|
|
201
203
|
- lib/kube/cluster/standard/cloud_native_pg/cluster.rb
|
|
202
204
|
- lib/kube/cluster/standard/cloud_native_pg/database_with_external_secret.rb
|