kube_cluster 1.4.0 → 1.6.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: 161e8e4b158fcb49cbab16469213bb0a49fab8ff7d1669a1c974fa79b60e4d77
4
- data.tar.gz: 87da0f1d7a75f18803146f1dc23bbe23bf5c188a3106751ef1ff95edfe38c9a5
3
+ metadata.gz: c8a1a110a7fc51055c3b0b6c7bed9c90ef99a7f5d3270aada0f9b89b7fba5eb0
4
+ data.tar.gz: 07a7eb71bc8a0d9e9197fb24a76729764de4e237c68110fc1a486d0df38eec74
5
5
  SHA512:
6
- metadata.gz: d41568ed4346c1429eda172bb4021c38e72a1e4cb7994c8060991df077b6fb7eebc4a9f9c58689cf0839c97ad682d546aff7ab9360c57f8c14845d8626b07252
7
- data.tar.gz: 85f8c1da91dcacfedf71b19736edef620113d71d211c51aa0f303cef72d63d2110cd8a4d9adab7f2fc2ee99f2fbec55837141c49f904587fbbd07d90e101325c
6
+ metadata.gz: 8bc59ca6435b4f4b9096bb7925605211289ee6a337015fc3eba64d747d673adce333a391585b5235c961f5a681f23474588d8391d88c12e51af5c5d5026fed06
7
+ data.tar.gz: 73c07cf7c0c85c0f998dc2b406da0d385502d24e414194eeb5f2e2dfbecbef3bedcef8401678e73a0b53665bc1d62465a6cd9ef77b962e07c761ecdca09b8620
data/CHANGELOG.md CHANGED
@@ -5,6 +5,25 @@ All notable changes to this project are documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.6.0] - 2026-08-03
9
+
10
+ ### Added
11
+ - `Standard::JuiceFS::Sync` — a wrapper for the juicefs-operator's `Sync` CRD
12
+ (pinned to `juicefs.io/v1`). `from`/`to` are the CRD's sink hashes, passed
13
+ through as-is. Documents two operator behaviours worth knowing before use: the
14
+ unquoted metadata-URL export that breaks `juicefsCE` sinks whose metaurl
15
+ contains `&`, and the `ttlSecondsAfterFinished` deletion that makes a
16
+ reconciler-managed Sync re-run forever.
17
+ - `Standard::JuiceFS::PersistentVolume` — a statically-provisioned JuiceFS PV,
18
+ the only way to give a volume an exact, readable directory name (`subPath`)
19
+ rather than the `pvc-<uuid>` a StorageClass would assign.
20
+ - `PersistentVolume` pinned to `v1/PersistentVolume` in the resolve table.
21
+
22
+ ### Changed
23
+ - Requires kube_schema `~> 1.10.0`, which ships the `juicefs.io/v1` schemas.
24
+ These wrappers previously needed a local CRD-registration shim that downloaded
25
+ `dist/crd.yaml` at load time; that is no longer necessary.
26
+
8
27
  ## [1.4.0] - 2026-07-13
9
28
 
10
29
  ### Added
data/Gemfile.lock CHANGED
@@ -1,10 +1,10 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kube_cluster (1.4.0)
4
+ kube_cluster (1.6.0)
5
5
  activesupport (~> 8.0)
6
6
  kube_kubectl (~> 2.0)
7
- kube_schema (~> 1.9.2)
7
+ kube_schema (~> 1.10.0)
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.2)
135
+ kube_schema (1.10.0)
136
136
  json_schemer (~> 2.5.0)
137
137
  rubyshell (~> 1.5.0)
138
138
  lefthook (2.1.10)
data/kube_cluster.gemspec CHANGED
@@ -32,7 +32,7 @@ Gem::Specification.new do |spec|
32
32
  spec.add_development_dependency "scampi", "~> 1.0"
33
33
  spec.add_development_dependency "lefthook", "~> 2.1"
34
34
 
35
- spec.add_dependency "kube_schema", "~> 1.9.2"
35
+ spec.add_dependency "kube_schema", "~> 1.10.0"
36
36
  spec.add_dependency "kube_kubectl", "~> 2.0"
37
37
  spec.add_dependency "activesupport", "~> 8.0"
38
38
  end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # A statically-provisioned JuiceFS PersistentVolume.
4
+ #
5
+ # Dynamic provisioning (a `juicefs-sc` StorageClass) names each volume's
6
+ # directory `pvc-<uuid>` at the root of the filesystem. Static provisioning lets
7
+ # the directory be named explicitly via the `subPath` volume attribute — the
8
+ # only way to get an exact, readable folder name.
9
+ #
10
+ # `secret`/`secret_namespace` point at the JuiceFS "volume credentials" Secret
11
+ # (name / metaurl / storage / bucket / keys / encrypt_rsa_key). PersistentVolume
12
+ # is cluster-scoped and nodePublishSecretRef carries its own namespace, so the
13
+ # PV, its PVC, and that Secret may all live in different namespaces. The mount
14
+ # pod always runs in the CSI driver's namespace regardless.
15
+ #
16
+ # `storage` is a label only — JuiceFS enforces no quota through this field.
17
+
18
+ require "bundler/setup"
19
+ require "kube/cluster"
20
+
21
+ module Kube
22
+ module Cluster
23
+ module Standard
24
+ module JuiceFS
25
+ class PersistentVolume < Kube::Cluster["PersistentVolume"]
26
+ def initialize(name:, storage:, sub_path:, secret:, secret_namespace:,
27
+ access_modes: ["ReadWriteMany"], reclaim_policy: "Retain", &block)
28
+ super() {
29
+ metadata.name = name
30
+
31
+ spec.capacity = { storage: storage }
32
+ spec.accessModes = access_modes
33
+ spec.persistentVolumeReclaimPolicy = reclaim_policy
34
+ # Empty (not absent) so no StorageClass can claim this PV and the
35
+ # matching PVC binds by volumeName alone.
36
+ spec.storageClassName = ""
37
+ spec.csi = {
38
+ driver: "csi.juicefs.com",
39
+ volumeHandle: name,
40
+ fsType: "juicefs",
41
+ nodePublishSecretRef: { name: secret, namespace: secret_namespace },
42
+ volumeAttributes: { subPath: sub_path },
43
+ }
44
+
45
+ instance_exec(&block) if block
46
+ }
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ __END__
55
+
56
+ describe "JuiceFS::PersistentVolume" do
57
+ pv = Kube::Cluster::Standard::JuiceFS::PersistentVolume
58
+
59
+ volume = pv.new(
60
+ name: "media",
61
+ storage: "1Ti",
62
+ sub_path: "media",
63
+ secret: "juicefs-secret",
64
+ secret_namespace: "kube-system",
65
+ )
66
+
67
+ it "mounts the named subPath through the JuiceFS CSI driver" do
68
+ yaml = volume.to_yaml
69
+
70
+ yaml.include?("driver: csi.juicefs.com").should == true
71
+ yaml.include?("subPath: media").should == true
72
+ end
73
+
74
+ it "defaults to a retained, ReadWriteMany volume with no StorageClass" do
75
+ yaml = volume.to_yaml
76
+
77
+ yaml.include?("persistentVolumeReclaimPolicy: Retain").should == true
78
+ yaml.include?("ReadWriteMany").should == true
79
+ yaml.include?("storageClassName: ''").should == true
80
+ end
81
+ end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+ #
3
+ # juicefs.io/v1 Sync — a one-shot `juicefs sync` job run by the juicefs-operator
4
+ # (https://juicefs.com/docs/csi/guide/juicefs-operator/).
5
+ #
6
+ # The operator builds a manager pod (plus `replicas - 1` worker pods) from
7
+ # `image`, parses each sink into a URI, and runs
8
+ # `juicefs sync [--<options>] <from> <to>`.
9
+ #
10
+ # `from`/`to` are the CRD's sink hashes and are passed through as-is — they are
11
+ # the meaningful configuration, so wrapping them in a mini-DSL would only hide
12
+ # the CRD. Exactly one of these keys per sink:
13
+ #
14
+ # external: { uri:, accessKey:, secretKey:, extraVolumes: } any object store,
15
+ # a `file://` path, or a mounted PVC/hostPath
16
+ # juicefs: { volumeName:, token:, ... } enterprise edition
17
+ # juicefsCE: { metaURL:, metaPassWord:, path: } community edition
18
+ #
19
+ # NOTE ON juicefsCE: the operator emits its metadata-URL export UNQUOTED
20
+ # (pkg/utils/sync.go, `export %s=%s`). A metaurl containing a literal `&` (e.g.
21
+ # `?sslmode=require&search_path=juicefs`) is split by the pod's `sh -c`
22
+ # entrypoint — the export runs in a background subshell and the variable is
23
+ # empty in the shell that runs the sync. Use an `external` sink with a `pvc`
24
+ # extraVolume instead, and let the CSI mount pod do the JuiceFS work.
25
+ #
26
+ # NOTE ON ttlSecondsAfterFinished: DO NOT SET IT when the Sync is managed by a
27
+ # reconciler such as Flux or Argo CD. The controller DELETES the Sync object
28
+ # when the TTL expires (internal/controller/sync_controller.go); the reconciler
29
+ # then sees drift, recreates it, and the sync runs again — forever. Without a
30
+ # TTL the object simply stays `Completed`. To re-run, delete the object by hand
31
+ # or switch to a CronSync.
32
+
33
+ require "bundler/setup"
34
+ require "kube/cluster"
35
+
36
+ module Kube
37
+ module Cluster
38
+ module Standard
39
+ module JuiceFS
40
+ class Sync < Kube::Cluster["juicefs.io/v1/Sync"]
41
+ def initialize(name:, image:, from:, to:, replicas: 1, options: [], &block)
42
+ super() {
43
+ metadata.name = name
44
+ spec.image = image
45
+ spec.replicas = replicas
46
+ spec.options = options if options.any?
47
+ spec.from = from
48
+ spec.to = to
49
+
50
+ instance_exec(&block) if block
51
+ }
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ __END__
60
+
61
+ describe "JuiceFS::Sync" do
62
+ sync = Kube::Cluster::Standard::JuiceFS::Sync
63
+
64
+ it "emits the juicefs.io/v1 apiVersion" do
65
+ sync
66
+ .new(
67
+ name: "media-backup",
68
+ image: "juicedata/mount:latest",
69
+ from: { external: { uri: "file:///mnt/media/" } },
70
+ to: { external: { uri: "s3://backup.example.com/media/" } },
71
+ )
72
+ .to_yaml
73
+ .include?("apiVersion: juicefs.io/v1")
74
+ .should == true
75
+ end
76
+
77
+ it "omits options when none are given" do
78
+ sync
79
+ .new(
80
+ name: "plain",
81
+ image: "juicedata/mount:latest",
82
+ from: { external: { uri: "file:///a/" } },
83
+ to: { external: { uri: "file:///b/" } },
84
+ )
85
+ .to_yaml
86
+ .include?("options:")
87
+ .should == false
88
+ end
89
+
90
+ it "carries options and replicas through" do
91
+ yaml = sync.new(
92
+ name: "parallel",
93
+ image: "juicedata/mount:latest",
94
+ from: { external: { uri: "file:///a/" } },
95
+ to: { external: { uri: "file:///b/" } },
96
+ replicas: 3,
97
+ options: ["--update"],
98
+ ).to_yaml
99
+
100
+ yaml.include?("replicas: 3").should == true
101
+ yaml.include?("--update").should == true
102
+ end
103
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # HA/clustered VictoriaLogs: vlstorage + vlselect + vlinsert components
11
+ # (the horizontally-scalable alternative to VLSingle). Retention lives on
12
+ # the vlstorage component, so configure the components in the block.
13
+ class VLCluster < Kube::Cluster["VLCluster"]
14
+ def initialize(name:, &block)
15
+ super() {
16
+ metadata.name = name
17
+ instance_exec(&block) if block
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ __END__
27
+
28
+ describe "VictoriaMetrics::VLCluster" do
29
+ it "initializes without error" do
30
+ Kube::Cluster::Standard::VictoriaMetrics::VLCluster
31
+ .new(name: "vlcluster")
32
+ .to_yaml
33
+ .is_a?(String)
34
+ .should == true
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # Legacy VictoriaLogs kind (operator.victoriametrics.com/v1beta1). New
11
+ # deployments should prefer VLSingle (v1); this wrapper exists for
12
+ # completeness / migrating existing objects. Spec is configured in block.
13
+ class VLogs < Kube::Cluster["VLogs"]
14
+ def initialize(name:, &block)
15
+ super() {
16
+ metadata.name = name
17
+ instance_exec(&block) if block
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ __END__
27
+
28
+ describe "VictoriaMetrics::VLogs" do
29
+ it "initializes without error" do
30
+ Kube::Cluster::Standard::VictoriaMetrics::VLogs
31
+ .new(name: "vlogs")
32
+ .to_yaml
33
+ .is_a?(String)
34
+ .should == true
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # Managed Alertmanager instance. Notification routing/receivers can be
11
+ # supplied inline via spec.configRawYaml or selected from
12
+ # VMAlertmanagerConfig objects; configure that in the block.
13
+ class VMAlertmanager < Kube::Cluster["VMAlertmanager"]
14
+ def initialize(name:, replica_count: 1, &block)
15
+ super() {
16
+ metadata.name = name
17
+ spec.replicaCount = replica_count
18
+ instance_exec(&block) if block
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ __END__
28
+
29
+ describe "VictoriaMetrics::VMAlertmanager" do
30
+ it "initializes without error" do
31
+ Kube::Cluster::Standard::VictoriaMetrics::VMAlertmanager
32
+ .new(name: "vmalertmanager")
33
+ .to_yaml
34
+ .is_a?(String)
35
+ .should == true
36
+ end
37
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # Alertmanager routing tree and receivers, selected by a VMAlertmanager.
11
+ # Define spec.route and spec.receivers in the block.
12
+ class VMAlertmanagerConfig < Kube::Cluster["VMAlertmanagerConfig"]
13
+ def initialize(name:, &block)
14
+ super() {
15
+ metadata.name = name
16
+ instance_exec(&block) if block
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ __END__
26
+
27
+ describe "VictoriaMetrics::VMAlertmanagerConfig" do
28
+ it "initializes without error" do
29
+ Kube::Cluster::Standard::VictoriaMetrics::VMAlertmanagerConfig
30
+ .new(name: "vmalertmanagerconfig")
31
+ .to_yaml
32
+ .is_a?(String)
33
+ .should == true
34
+ end
35
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # VictoriaMetrics Anomaly Detection service (vmanomaly). Reads metrics,
11
+ # fits models, and writes anomaly scores back. Provide the model/reader/
12
+ # writer configuration via spec.configRawYaml in the block.
13
+ class VMAnomaly < Kube::Cluster["VMAnomaly"]
14
+ def initialize(name:, &block)
15
+ super() {
16
+ metadata.name = name
17
+ instance_exec(&block) if block
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ __END__
27
+
28
+ describe "VictoriaMetrics::VMAnomaly" do
29
+ it "initializes without error" do
30
+ Kube::Cluster::Standard::VictoriaMetrics::VMAnomaly
31
+ .new(name: "vmanomaly")
32
+ .to_yaml
33
+ .is_a?(String)
34
+ .should == true
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # Reusable configuration object referenced by a VMAnomaly instance.
11
+ # Define the models/schedulers in the block.
12
+ class VMAnomalyConfig < Kube::Cluster["VMAnomalyConfig"]
13
+ def initialize(name:, &block)
14
+ super() {
15
+ metadata.name = name
16
+ instance_exec(&block) if block
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ __END__
26
+
27
+ describe "VictoriaMetrics::VMAnomalyConfig" do
28
+ it "initializes without error" do
29
+ Kube::Cluster::Standard::VictoriaMetrics::VMAnomalyConfig
30
+ .new(name: "vmanomalyconfig") { spec.schedulers = {} }
31
+ .to_yaml
32
+ .is_a?(String)
33
+ .should == true
34
+ end
35
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # Auth proxy / router that sits in front of VictoriaMetrics components and
11
+ # dispatches requests according to the VMUser objects it selects. Configure
12
+ # user selection and unauthorized-access rules in the block.
13
+ class VMAuth < Kube::Cluster["VMAuth"]
14
+ def initialize(name:, &block)
15
+ super() {
16
+ metadata.name = name
17
+ instance_exec(&block) if block
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ __END__
27
+
28
+ describe "VictoriaMetrics::VMAuth" do
29
+ it "initializes without error" do
30
+ Kube::Cluster::Standard::VictoriaMetrics::VMAuth
31
+ .new(name: "vmauth")
32
+ .to_yaml
33
+ .is_a?(String)
34
+ .should == true
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # HA/clustered VictoriaMetrics: vmstorage + vmselect + vminsert
11
+ # components (the horizontally-scalable alternative to VMSingle).
12
+ # Configure the three components in the block.
13
+ class VMCluster < Kube::Cluster["VMCluster"]
14
+ def initialize(name:, retention_period: "30d", &block)
15
+ super() {
16
+ metadata.name = name
17
+ spec.retentionPeriod = retention_period
18
+ instance_exec(&block) if block
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ __END__
28
+
29
+ describe "VictoriaMetrics::VMCluster" do
30
+ it "initializes without error" do
31
+ Kube::Cluster::Standard::VictoriaMetrics::VMCluster
32
+ .new(name: "vmcluster")
33
+ .to_yaml
34
+ .is_a?(String)
35
+ .should == true
36
+ end
37
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # Multi-zone/distributed VictoriaMetrics topology. The full shape (zones,
11
+ # common settings) is configured in the block.
12
+ class VMDistributed < Kube::Cluster["VMDistributed"]
13
+ def initialize(name:, &block)
14
+ super() {
15
+ metadata.name = name
16
+ instance_exec(&block) if block
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ __END__
26
+
27
+ describe "VictoriaMetrics::VMDistributed" do
28
+ it "initializes without error" do
29
+ Kube::Cluster::Standard::VictoriaMetrics::VMDistributed
30
+ .new(name: "vmdistributed") { spec.retain = true }
31
+ .to_yaml
32
+ .is_a?(String)
33
+ .should == true
34
+ end
35
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # Declares how to scrape the pods selected by the app.kubernetes.io/name
11
+ # label (the pod-selector analogue of VMServiceScrape), relabelling the
12
+ # metrics onto a job.
13
+ class VMPodScrape < Kube::Cluster["VMPodScrape"]
14
+ def initialize(name:, job:, match_name:, port:, &block)
15
+ super() {
16
+ metadata.name = name
17
+ spec.selector = { matchLabels: { "app.kubernetes.io/name" => match_name } }
18
+ spec.podMetricsEndpoints = [{ port: port, relabelConfigs: [{ targetLabel: "job", replacement: job }] }]
19
+ instance_exec(&block) if block
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ __END__
29
+
30
+ describe "VictoriaMetrics::VMPodScrape" do
31
+ it "initializes without error" do
32
+ Kube::Cluster::Standard::VictoriaMetrics::VMPodScrape
33
+ .new(name: "opencost", job: "opencost", match_name: "opencost", port: "http")
34
+ .to_yaml
35
+ .is_a?(String)
36
+ .should == true
37
+ end
38
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # Blackbox/probe scraping: points a prober (e.g. blackbox_exporter) at a
11
+ # set of targets. Pass the prober URL here and the targets/module in the
12
+ # block via spec.targets and spec.module.
13
+ class VMProbe < Kube::Cluster["VMProbe"]
14
+ def initialize(name:, prober_url:, &block)
15
+ super() {
16
+ metadata.name = name
17
+ spec.vmProberSpec = { url: prober_url }
18
+ instance_exec(&block) if block
19
+ }
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ __END__
28
+
29
+ describe "VictoriaMetrics::VMProbe" do
30
+ it "initializes without error" do
31
+ Kube::Cluster::Standard::VictoriaMetrics::VMProbe
32
+ .new(name: "blackbox", prober_url: "http://blackbox-exporter.metrics.svc:9115")
33
+ .to_yaml
34
+ .is_a?(String)
35
+ .should == true
36
+ end
37
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # Generic scrape configuration supporting the full range of service-
11
+ # discovery mechanisms (static, kubernetes, http, ec2, consul, …). Declare
12
+ # the discovery configs and relabelling in the block.
13
+ class VMScrapeConfig < Kube::Cluster["VMScrapeConfig"]
14
+ def initialize(name:, &block)
15
+ super() {
16
+ metadata.name = name
17
+ instance_exec(&block) if block
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ __END__
27
+
28
+ describe "VictoriaMetrics::VMScrapeConfig" do
29
+ it "initializes without error" do
30
+ Kube::Cluster::Standard::VictoriaMetrics::VMScrapeConfig
31
+ .new(name: "vmscrapeconfig")
32
+ .to_yaml
33
+ .is_a?(String)
34
+ .should == true
35
+ end
36
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # Scrapes a fixed set of static targets (host:port) under a named job —
11
+ # for endpoints that have no Service/Pod to select. Extra per-endpoint
12
+ # settings (path, scheme, labels) can be added in the block.
13
+ class VMStaticScrape < Kube::Cluster["VMStaticScrape"]
14
+ def initialize(name:, job:, targets:, &block)
15
+ super() {
16
+ metadata.name = name
17
+ spec.jobName = job
18
+ spec.targetEndpoints = [{ targets: Array(targets) }]
19
+ instance_exec(&block) if block
20
+ }
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ __END__
29
+
30
+ describe "VictoriaMetrics::VMStaticScrape" do
31
+ it "initializes without error" do
32
+ Kube::Cluster::Standard::VictoriaMetrics::VMStaticScrape
33
+ .new(name: "external", job: "external", targets: ["10.0.0.1:9100"])
34
+ .to_yaml
35
+ .is_a?(String)
36
+ .should == true
37
+ end
38
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # A user/route definition consumed by VMAuth: maps credentials to a set of
11
+ # upstream target refs. Pass the routing in the block via spec.targetRefs.
12
+ class VMUser < Kube::Cluster["VMUser"]
13
+ def initialize(name:, username: nil, &block)
14
+ super() {
15
+ metadata.name = name
16
+ spec.username = username if username
17
+ instance_exec(&block) if block
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ __END__
27
+
28
+ describe "VictoriaMetrics::VMUser" do
29
+ it "initializes without error" do
30
+ Kube::Cluster::Standard::VictoriaMetrics::VMUser
31
+ .new(name: "vmuser", username: "reader") {
32
+ spec.targetRefs = [{ crd: { kind: "VMSingle", name: "vmsingle", namespace: "metrics" }, paths: ["/"] }]
33
+ }
34
+ .to_yaml
35
+ .is_a?(String)
36
+ .should == true
37
+ end
38
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # HA/clustered VictoriaTraces: storage + select + insert components
11
+ # (the horizontally-scalable alternative to VTSingle). Retention lives on
12
+ # the storage component, so configure the components in the block.
13
+ class VTCluster < Kube::Cluster["VTCluster"]
14
+ def initialize(name:, &block)
15
+ super() {
16
+ metadata.name = name
17
+ instance_exec(&block) if block
18
+ }
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ __END__
27
+
28
+ describe "VictoriaMetrics::VTCluster" do
29
+ it "initializes without error" do
30
+ Kube::Cluster::Standard::VictoriaMetrics::VTCluster
31
+ .new(name: "vtcluster")
32
+ .to_yaml
33
+ .is_a?(String)
34
+ .should == true
35
+ end
36
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/setup"
4
+ require "kube/cluster"
5
+
6
+ module Kube
7
+ module Cluster
8
+ module Standard
9
+ module VictoriaMetrics
10
+ # Single-node VictoriaTraces store.
11
+ class VTSingle < Kube::Cluster["VTSingle"]
12
+ def initialize(name:, retention_period: "30d", &block)
13
+ super() {
14
+ metadata.name = name
15
+ spec.retentionPeriod = retention_period
16
+ instance_exec(&block) if block
17
+ }
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+
25
+ __END__
26
+
27
+ describe "VictoriaMetrics::VTSingle" do
28
+ it "initializes without error" do
29
+ Kube::Cluster::Standard::VictoriaMetrics::VTSingle
30
+ .new(name: "vtsingle")
31
+ .to_yaml
32
+ .is_a?(String)
33
+ .should == true
34
+ end
35
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Kube
4
4
  module Cluster
5
- VERSION = "1.4.0"
5
+ VERSION = "1.6.0"
6
6
  end
7
7
  end
data/lib/kube/cluster.rb CHANGED
@@ -92,6 +92,7 @@ require "kube/cluster/resource/persistence"
92
92
  Kube::Cluster.config do
93
93
  # Built-in Kubernetes kinds.
94
94
  resolve "ConfigMap", to: "v1/ConfigMap"
95
+ resolve "PersistentVolume", to: "v1/PersistentVolume"
95
96
  resolve "PersistentVolumeClaim", to: "v1/PersistentVolumeClaim"
96
97
  resolve "Secret", to: "v1/Secret"
97
98
  resolve "Service", to: "v1/Service"
@@ -126,13 +127,29 @@ Kube::Cluster.config do
126
127
 
127
128
  # VictoriaMetrics operator.
128
129
  resolve "VLAgent", to: "operator.victoriametrics.com/v1/VLAgent"
130
+ resolve "VLCluster", to: "operator.victoriametrics.com/v1/VLCluster"
131
+ resolve "VLogs", to: "operator.victoriametrics.com/v1beta1/VLogs"
129
132
  resolve "VLSingle", to: "operator.victoriametrics.com/v1/VLSingle"
130
133
  resolve "VMAgent", to: "operator.victoriametrics.com/v1beta1/VMAgent"
131
134
  resolve "VMAlert", to: "operator.victoriametrics.com/v1beta1/VMAlert"
135
+ resolve "VMAlertmanager", to: "operator.victoriametrics.com/v1beta1/VMAlertmanager"
136
+ resolve "VMAlertmanagerConfig", to: "operator.victoriametrics.com/v1beta1/VMAlertmanagerConfig"
137
+ resolve "VMAnomaly", to: "operator.victoriametrics.com/v1/VMAnomaly"
138
+ resolve "VMAnomalyConfig", to: "operator.victoriametrics.com/v1/VMAnomalyConfig"
139
+ resolve "VMAuth", to: "operator.victoriametrics.com/v1beta1/VMAuth"
140
+ resolve "VMCluster", to: "operator.victoriametrics.com/v1beta1/VMCluster"
141
+ resolve "VMDistributed", to: "operator.victoriametrics.com/v1alpha1/VMDistributed"
132
142
  resolve "VMNodeScrape", to: "operator.victoriametrics.com/v1beta1/VMNodeScrape"
143
+ resolve "VMPodScrape", to: "operator.victoriametrics.com/v1beta1/VMPodScrape"
144
+ resolve "VMProbe", to: "operator.victoriametrics.com/v1beta1/VMProbe"
133
145
  resolve "VMRule", to: "operator.victoriametrics.com/v1beta1/VMRule"
146
+ resolve "VMScrapeConfig", to: "operator.victoriametrics.com/v1beta1/VMScrapeConfig"
134
147
  resolve "VMServiceScrape", to: "operator.victoriametrics.com/v1beta1/VMServiceScrape"
135
148
  resolve "VMSingle", to: "operator.victoriametrics.com/v1beta1/VMSingle"
149
+ resolve "VMStaticScrape", to: "operator.victoriametrics.com/v1beta1/VMStaticScrape"
150
+ resolve "VMUser", to: "operator.victoriametrics.com/v1beta1/VMUser"
151
+ resolve "VTCluster", to: "operator.victoriametrics.com/v1/VTCluster"
152
+ resolve "VTSingle", to: "operator.victoriametrics.com/v1/VTSingle"
136
153
 
137
154
  # Gateway API — pin to the stable v1 group/version.
138
155
  resolve "GatewayClass", to: "gateway.networking.k8s.io/v1/GatewayClass"
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: 1.4.0
4
+ version: 1.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan K
@@ -57,14 +57,14 @@ dependencies:
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: 1.9.2
60
+ version: 1.10.0
61
61
  type: :runtime
62
62
  prerelease: false
63
63
  version_requirements: !ruby/object:Gem::Requirement
64
64
  requirements:
65
65
  - - "~>"
66
66
  - !ruby/object:Gem::Version
67
- version: 1.9.2
67
+ version: 1.10.0
68
68
  - !ruby/object:Gem::Dependency
69
69
  name: kube_kubectl
70
70
  requirement: !ruby/object:Gem::Requirement
@@ -231,6 +231,8 @@ files:
231
231
  - lib/kube/cluster/standard/gateway_api/http_route.rb
232
232
  - lib/kube/cluster/standard/job.rb
233
233
  - lib/kube/cluster/standard/job_with_service_account.rb
234
+ - lib/kube/cluster/standard/juice_fs/persistent_volume.rb
235
+ - lib/kube/cluster/standard/juice_fs/sync.rb
234
236
  - lib/kube/cluster/standard/kube_virt/virtual_machine.rb
235
237
  - lib/kube/cluster/standard/meta_controller/composite_controller.rb
236
238
  - lib/kube/cluster/standard/meta_controller/decorator_controller.rb
@@ -244,13 +246,29 @@ files:
244
246
  - lib/kube/cluster/standard/service_account.rb
245
247
  - lib/kube/cluster/standard/service_account_with_role.rb
246
248
  - lib/kube/cluster/standard/victoria_metrics/vl_agent.rb
249
+ - lib/kube/cluster/standard/victoria_metrics/vl_cluster.rb
247
250
  - lib/kube/cluster/standard/victoria_metrics/vl_single.rb
251
+ - lib/kube/cluster/standard/victoria_metrics/vlogs.rb
248
252
  - lib/kube/cluster/standard/victoria_metrics/vm_agent.rb
249
253
  - lib/kube/cluster/standard/victoria_metrics/vm_alert.rb
254
+ - lib/kube/cluster/standard/victoria_metrics/vm_alertmanager.rb
255
+ - lib/kube/cluster/standard/victoria_metrics/vm_alertmanager_config.rb
256
+ - lib/kube/cluster/standard/victoria_metrics/vm_anomaly.rb
257
+ - lib/kube/cluster/standard/victoria_metrics/vm_anomaly_config.rb
258
+ - lib/kube/cluster/standard/victoria_metrics/vm_auth.rb
259
+ - lib/kube/cluster/standard/victoria_metrics/vm_cluster.rb
260
+ - lib/kube/cluster/standard/victoria_metrics/vm_distributed.rb
250
261
  - lib/kube/cluster/standard/victoria_metrics/vm_node_scrape.rb
262
+ - lib/kube/cluster/standard/victoria_metrics/vm_pod_scrape.rb
263
+ - lib/kube/cluster/standard/victoria_metrics/vm_probe.rb
251
264
  - lib/kube/cluster/standard/victoria_metrics/vm_rule.rb
265
+ - lib/kube/cluster/standard/victoria_metrics/vm_scrape_config.rb
252
266
  - lib/kube/cluster/standard/victoria_metrics/vm_service_scrape.rb
253
267
  - lib/kube/cluster/standard/victoria_metrics/vm_single.rb
268
+ - lib/kube/cluster/standard/victoria_metrics/vm_static_scrape.rb
269
+ - lib/kube/cluster/standard/victoria_metrics/vm_user.rb
270
+ - lib/kube/cluster/standard/victoria_metrics/vt_cluster.rb
271
+ - lib/kube/cluster/standard/victoria_metrics/vt_single.rb
254
272
  - lib/kube/cluster/standard/volume_processing.rb
255
273
  - lib/kube/cluster/version.rb
256
274
  - lib/kube/cluster/version.rb.erb