kube_cluster 0.5.4 → 0.7.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: 8f08a431382eaf0cccfb51c9d2bfd46428eef571da2d21bb147fc04168cc12ee
4
- data.tar.gz: 98af3d4b4d90aeef68a38b59240a3d966c8ae421e8d73a3e191f957c9c34a42c
3
+ metadata.gz: 0f1c23db70574ae658780a8fcdcaefa84a23b917f206cce85749c84739ccd8c1
4
+ data.tar.gz: bd673c8ab74f4a2c6c046d27e40994cd7a819ad6e552b5a98e14fc1974f52bcc
5
5
  SHA512:
6
- metadata.gz: 9eeeda7bcf98afac44f299b99d14d688b622cbe759725d5a0142c6c19be88cee89900584e2210de87e66acfc521db88d4025f3722fc56ebd362ae0b46ecd648d
7
- data.tar.gz: 3c13178ef039b611ecddeded6a9ae35a9e3063299fe850e9d481a4ffe6c9f68fb7aa96b86d5749dd28cd4be32208b3575d9230cc4628840b191406656fd90597
6
+ metadata.gz: 49d328773bd999a1270386fec416f6a4afa0aa88d8fe6fe51e42af84e134154ac80b0220426c7be1b45e534ab2c164dc5ff22a9c0208f2d623c67aaba1be621e
7
+ data.tar.gz: fe000f50ed0f0b55a2b4efedc4fbedbf0bfcbf61039b64dd8584384cd0cf317d31e8b8db2d1bb79ae1b46dffcd6165ce27835d57cd5a9b86fbabdf976675dd21
data/.gitignore CHANGED
@@ -6,3 +6,5 @@
6
6
  /tmp/
7
7
  /vendor/bundle
8
8
  /kubeconfig.yaml
9
+ *.swo
10
+ *.swp
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- kube_cluster (0.5.3)
4
+ kube_cluster (0.7.0)
5
5
  kube_kubectl (~> 2.0)
6
6
  kube_schema (~> 1.5)
7
7
  scampi (~> 0.1)
@@ -0,0 +1,97 @@
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 CloudNativePg
10
+ module Helm
11
+ class Operator < Kube::Cluster["HelmChart"]
12
+ def initialize(&block)
13
+ super {
14
+ metadata.name = "cloudnative-pg"
15
+ metadata.namespace = "kube-system"
16
+ spec.chart = "cloudnative-pg"
17
+ spec.version = "0.28.2"
18
+ spec.repo = "https://cloudnative-pg.github.io/charts"
19
+ spec.targetNamespace = "cnpg-system"
20
+ spec.createNamespace = true
21
+
22
+ instance_exec(&block) if block
23
+ }
24
+ end
25
+ end
26
+
27
+ # You shouldn't really need this... it's a dependency of
28
+ # the Operator chart...
29
+ #
30
+ # class Cluster < Kube::Cluster["HelmChart"]
31
+ # def initialize(&block)
32
+ # super {
33
+ # metadata.name = "cloudnative-pg--cluster"
34
+ # metadata.namespace = "kube-system"
35
+ # spec.chart = "cluster"
36
+ # spec.version = "0.6.1"
37
+ # spec.repo = "https://cloudnative-pg.github.io/charts"
38
+ # spec.targetNamespace = "cnpg-system"
39
+ # spec.createNamespace = true
40
+
41
+ # instance_exec(&block) if block
42
+ # }
43
+ # end
44
+ # end
45
+
46
+ class Barman < Kube::Cluster["HelmChart"]
47
+ def initialize(&block)
48
+ super {
49
+ metadata.name = "plugin-barman-cloud"
50
+ metadata.namespace = "kube-system"
51
+ spec.chart = "plugin-barman-cloud"
52
+ spec.version = "0.6.0"
53
+ spec.repo = "https://cloudnative-pg.github.io/charts"
54
+ spec.targetNamespace = "cnpg-system"
55
+ spec.createNamespace = true
56
+
57
+ instance_exec(&block) if block
58
+ }
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ test do
68
+ describe "Operator" do
69
+ it "initializes without error" do
70
+ Kube::Cluster::Standard::CloudNativePg::Helm::Operator
71
+ .new()
72
+ .to_yaml
73
+ .is_a?(String)
74
+ .should == true
75
+ end
76
+ end
77
+
78
+ #describe "Cluster" do
79
+ # it "initializes without error" do
80
+ # Kube::Cluster::Standard::CloudNativePg::Helm::Cluster
81
+ # .new()
82
+ # .to_yaml
83
+ # .is_a?(String)
84
+ # .should == true
85
+ # end
86
+ #end
87
+
88
+ describe "Barman" do
89
+ it "initializes without error" do
90
+ Kube::Cluster::Standard::CloudNativePg::Helm::Barman
91
+ .new()
92
+ .to_yaml
93
+ .is_a?(String)
94
+ .should == true
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,17 @@
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 CloudNativePg
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ test do
16
+ # no op
17
+ end
@@ -0,0 +1,152 @@
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
+ class DeploymentWithService < Kube::Cluster::Manifest
10
+ def initialize(
11
+ name:,
12
+ image:,
13
+ port:,
14
+ namespace: 'default',
15
+ env: {},
16
+ security_context: nil,
17
+ pod_security_context: nil,
18
+ volume_mounts: {},
19
+ service_port: nil,
20
+ &block
21
+ )
22
+ @_limits = {}
23
+ @_probes = {}
24
+
25
+ processed_env = EnvProcessing.process(env)
26
+ processed_volumes = VolumeProcessing.process(volume_mounts)
27
+
28
+ service_ports = Array(service_port || port)
29
+
30
+ service = Kube::Cluster::Standard::Service.new(
31
+ name: name,
32
+ namespace: namespace,
33
+ ports: service_ports
34
+ )
35
+
36
+ deployment = Kube::Cluster['Deployment'].new do
37
+ metadata.name = name
38
+ metadata.namespace = namespace
39
+ metadata.labels = { 'app' => name }
40
+
41
+ spec.replicas = 1
42
+ spec.selector.matchLabels = { 'app' => name }
43
+
44
+ spec.template.metadata.labels = { 'app' => name }
45
+ spec.template.spec.securityContext = pod_security_context if pod_security_context
46
+
47
+ container = {
48
+ name: name,
49
+ image: image,
50
+ ports: [{ name: 'http', containerPort: port, protocol: 'TCP' }],
51
+ env: processed_env
52
+ }
53
+ container[:securityContext] = security_context if security_context
54
+ container[:volumeMounts] = processed_volumes[:volume_mounts] unless processed_volumes[:volume_mounts].empty?
55
+
56
+ spec.template.spec.containers = [container]
57
+ spec.template.spec.volumes = processed_volumes[:volumes] unless processed_volumes[:volumes].empty?
58
+ end
59
+
60
+ super(deployment, service)
61
+
62
+ instance_exec(&block) if block
63
+
64
+ _apply_limits(deployment)
65
+ _apply_probes(deployment)
66
+ end
67
+
68
+ def limits
69
+ @_limits
70
+ end
71
+
72
+ def probes
73
+ @_probes
74
+ end
75
+
76
+ private
77
+
78
+ def _apply_limits(deployment)
79
+ return if @_limits.empty?
80
+
81
+ container = deployment.to_h[:spec][:template][:spec][:containers][0]
82
+ resources = {}
83
+
84
+ @_limits.each do |resource_type, mapping|
85
+ mapping.each do |request, limit|
86
+ resources[:requests] ||= {}
87
+ resources[:requests][resource_type] = request.to_s
88
+
89
+ if limit != Float::INFINITY
90
+ resources[:limits] ||= {}
91
+ resources[:limits][resource_type] = limit.to_s
92
+ end
93
+ end
94
+ end
95
+
96
+ container[:resources] = resources
97
+ h = deployment.to_h
98
+ h[:spec][:template][:spec][:containers][0] = container
99
+ deployment.rebuild(h)
100
+ end
101
+
102
+ def _apply_probes(deployment)
103
+ return if @_probes.empty?
104
+ return unless @_probes[:url]
105
+
106
+ container = deployment.to_h[:spec][:template][:spec][:containers][0]
107
+ url = @_probes[:url]
108
+
109
+ if @_probes[:liveness]
110
+ delay, period = @_probes[:liveness].first
111
+ container[:livenessProbe] = {
112
+ httpGet: url,
113
+ initialDelaySeconds: delay,
114
+ periodSeconds: period,
115
+ timeoutSeconds: 5
116
+ }
117
+ end
118
+
119
+ if @_probes[:readiness]
120
+ delay, period = @_probes[:readiness].first
121
+ container[:readinessProbe] = {
122
+ httpGet: url,
123
+ initialDelaySeconds: delay,
124
+ periodSeconds: period,
125
+ timeoutSeconds: 5
126
+ }
127
+ end
128
+
129
+ h = deployment.to_h
130
+ h[:spec][:template][:spec][:containers][0] = container
131
+ deployment.rebuild(h)
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+
138
+ test do
139
+ describe "DeploymentWithService" do
140
+ it "initializes without error" do
141
+ Kube::Cluster::Standard::DeploymentWithService
142
+ .new(
143
+ name: "pointless-ruby-container",
144
+ image: "ruby/ruby",
145
+ port: 3000,
146
+ )
147
+ .to_yaml
148
+ .is_a?(String)
149
+ .should == true
150
+ end
151
+ end
152
+ end
@@ -0,0 +1,42 @@
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 EnvProcessing
10
+ # Convert an env hash into a Kubernetes env array.
11
+ #
12
+ # String/numeric values become plain env vars:
13
+ # "FOO" => "bar" => { name: "FOO", value: "bar" }
14
+ #
15
+ # ExternalSecret::TemplateRef values become secretKeyRef env vars
16
+ # and register the template entry on the ExternalSecret:
17
+ # "FOO" => secret.template("{{ .bar }}")
18
+ # => { name: "FOO", valueFrom: { secretKeyRef: { name: "secret-name", key: "FOO" } } }
19
+ #
20
+ def self.process(env)
21
+ return env if env.is_a?(Array)
22
+ return [] if env.nil?
23
+
24
+ env.map do |key, value|
25
+ key = key.to_s
26
+
27
+ if value.is_a?(ExternalSecret::TemplateRef)
28
+ value.secret.register_template!(key, value.template_value)
29
+ { name: key, valueFrom: { secretKeyRef: { name: value.secret.secret_name, key: key } } }
30
+ else
31
+ { name: key, value: value.to_s }
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ test do
41
+ # no op
42
+ end
@@ -0,0 +1,34 @@
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
+ class Secret < Kube::Cluster["Secret"]
10
+ def initialize(name:, **data, &block)
11
+ super() {
12
+ metadata.name = name
13
+ data.each { |k, v| stringData[k.to_s] = v }
14
+ instance_exec(&block) if block_given?
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ test do
23
+ describe "Secret" do
24
+ it "initializes without error" do
25
+ Kube::Cluster::Standard::Secret
26
+ .new(
27
+ name: "my-secret"
28
+ )
29
+ .to_yaml
30
+ .is_a?(String)
31
+ .should == true
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,41 @@
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
+ class Service < Kube::Cluster["Service"]
10
+ def initialize(name:, ports:, namespace: "default", **options, &block)
11
+ super() {
12
+ metadata.name = name
13
+ metadata.namespace = namespace
14
+ metadata.labels = { "app" => name }
15
+ spec.selector = { "app" => name }
16
+ spec.ports = ports.map do |port|
17
+ { name: "http-#{port}", port: port, targetPort: port, protocol: "TCP" }
18
+ end
19
+
20
+ instance_exec(&block) if block_given?
21
+ }
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+ test do
29
+ describe "Service" do
30
+ it "initializes without error" do
31
+ Kube::Cluster::Standard::Service
32
+ .new(
33
+ name: "my-secret",
34
+ ports: [],
35
+ )
36
+ .to_yaml
37
+ .is_a?(String)
38
+ .should == true
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,88 @@
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 VolumeProcessing
10
+ # Convert a volume_mounts hash into Kubernetes volumes and volumeMounts arrays.
11
+ #
12
+ # Hash values (mount path => source ref):
13
+ # ExternalSecret::KeyRef => secret volume with items, mount with subPath + readOnly
14
+ # ExternalSecret => secret volume, directory mount
15
+ # PersistentVolumeClaim => persistentVolumeClaim volume, plain mount
16
+ #
17
+ # Legacy: if input is an Array, it is returned as-is for backwards compat.
18
+ #
19
+ def self.process(input)
20
+ return { volumes: [], volume_mounts: input } if input.is_a?(Array)
21
+ return { volumes: [], volume_mounts: [] } if input.nil? || input.empty?
22
+
23
+ volumes = []
24
+ mounts = []
25
+
26
+ input.each do |mount_path, source|
27
+ case source
28
+ when ExternalSecret::KeyRef
29
+ name = source.secret.secret_name
30
+ key = source.key_name
31
+ volumes << {
32
+ name: name,
33
+ secret: {
34
+ secretName: name,
35
+ items: [{ key: key, path: key }]
36
+ }
37
+ }
38
+ mounts << {
39
+ name: name,
40
+ mountPath: mount_path,
41
+ subPath: key,
42
+ readOnly: true
43
+ }
44
+
45
+ when ExternalSecret
46
+ name = source.secret_name
47
+ volumes << { name: name, secret: { secretName: name } }
48
+ mounts << { name: name, mountPath: mount_path }
49
+
50
+ when PersistentVolumeClaim
51
+ name = source.to_h.dig(:metadata, :name)
52
+ volumes << { name: name, persistentVolumeClaim: { claimName: name } }
53
+ mounts << { name: name, mountPath: mount_path }
54
+
55
+ when ConfigMap::KeyRef
56
+ name = source.config_map.config_map_name
57
+ key = source.key_name
58
+ volumes << {
59
+ name: name,
60
+ configMap: {
61
+ name: name,
62
+ items: [{ key: key, path: key }]
63
+ }
64
+ }
65
+ mounts << {
66
+ name: name,
67
+ mountPath: mount_path,
68
+ subPath: key,
69
+ readOnly: true
70
+ }
71
+
72
+ when ConfigMap
73
+ name = source.to_h.dig(:metadata, :name)
74
+ volumes << { name: name, configMap: { name: name } }
75
+ mounts << { name: name, mountPath: mount_path, readOnly: true }
76
+ end
77
+ end
78
+
79
+ { volumes: volumes, volume_mounts: mounts }
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+
86
+ test do
87
+ # no op
88
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Kube
4
4
  module Cluster
5
- VERSION = "0.5.4"
5
+ VERSION = "0.7.0"
6
6
  end
7
7
  end
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.5.4
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan K
@@ -195,6 +195,13 @@ files:
195
195
  - lib/kube/cluster/resource/extensions/custom_resource_definition.rb
196
196
  - lib/kube/cluster/resource/persistence.rb
197
197
  - lib/kube/cluster/script_command.rb
198
+ - lib/kube/cluster/standard/cloud_native_pg.rb
199
+ - lib/kube/cluster/standard/cloud_native_pg/helm.rb
200
+ - lib/kube/cluster/standard/deployment_with_service.rb
201
+ - lib/kube/cluster/standard/env_processing.rb
202
+ - lib/kube/cluster/standard/secret.rb
203
+ - lib/kube/cluster/standard/service.rb
204
+ - lib/kube/cluster/standard/volume_processing.rb
198
205
  - lib/kube/cluster/version.rb
199
206
  - lib/kube/cluster/version.rb.erb
200
207
  - lib/kube/errors.rb