kube_cluster 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +4 -4
  3. data/examples/01-basic-redis-pod/manifest.rb +1 -1
  4. data/examples/02-manifest-with-middleware/manifest.rb +37 -0
  5. data/examples/02-manifest-with-middleware/middleware/labels.rb +4 -0
  6. data/examples/02-manifest-with-middleware/middleware/namespace.rb +4 -0
  7. data/examples/02-manifest-with-middleware/templates/config_map.rb +13 -0
  8. data/examples/02-manifest-with-middleware/templates/deployment.rb +59 -0
  9. data/examples/02-manifest-with-middleware/templates/horizontal_pod_autoscaler.rb +30 -0
  10. data/examples/02-manifest-with-middleware/templates/ingress.rb +38 -0
  11. data/examples/02-manifest-with-middleware/templates/service.rb +12 -0
  12. data/examples/{version2 → 03-app-with-database}/demo.rb +2 -2
  13. data/examples/{version2 → 03-app-with-database}/postgresql.rb +4 -4
  14. data/examples/{version2 → 03-app-with-database}/ruby_on_rails.rb +1 -1
  15. data/lib/kube/cluster/manifest.rb +13 -64
  16. data/lib/kube/cluster/middleware/annotations.rb +32 -0
  17. data/lib/kube/cluster/middleware/hpa_for_deployment.rb +111 -0
  18. data/lib/kube/cluster/{manifest/middleware → middleware}/ingress_for_service.rb +36 -34
  19. data/lib/kube/cluster/middleware/labels.rb +59 -0
  20. data/lib/kube/cluster/middleware/namespace.rb +31 -0
  21. data/lib/kube/cluster/middleware/pod_anti_affinity.rb +61 -0
  22. data/lib/kube/cluster/middleware/resource_preset.rb +64 -0
  23. data/lib/kube/cluster/middleware/security_context.rb +84 -0
  24. data/lib/kube/cluster/middleware/service_for_deployment.rb +71 -0
  25. data/lib/kube/cluster/middleware/stack.rb +43 -0
  26. data/lib/kube/cluster/middleware.rb +69 -0
  27. data/lib/kube/cluster/resource.rb +78 -0
  28. data/lib/kube/cluster/version.rb +1 -1
  29. data/lib/kube/cluster.rb +21 -0
  30. metadata +25 -19
  31. data/examples/database/manifest.rb +0 -238
  32. data/examples/web-app/manifest.rb +0 -215
  33. data/lib/kube/cluster/manifest/middleware/annotations.rb +0 -32
  34. data/lib/kube/cluster/manifest/middleware/hpa_for_deployment.rb +0 -109
  35. data/lib/kube/cluster/manifest/middleware/labels.rb +0 -59
  36. data/lib/kube/cluster/manifest/middleware/namespace.rb +0 -31
  37. data/lib/kube/cluster/manifest/middleware/pod_anti_affinity.rb +0 -61
  38. data/lib/kube/cluster/manifest/middleware/resource_preset.rb +0 -64
  39. data/lib/kube/cluster/manifest/middleware/security_context.rb +0 -84
  40. data/lib/kube/cluster/manifest/middleware/service_for_deployment.rb +0 -69
  41. data/lib/kube/cluster/manifest/middleware.rb +0 -178
  42. data/lib/kube/cluster/manifest/stack.rb +0 -56
  43. /data/examples/{version2 → 03-app-with-database}/helpers.rb +0 -0
  44. /data/examples/{version2 → 03-app-with-database}/my_app.rb +0 -0
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kube
4
+ module Cluster
5
+ class Middleware
6
+ # Merges labels into +metadata.labels+ on every resource.
7
+ # Existing labels are preserved; the supplied labels act as defaults
8
+ # that can be overridden per-resource.
9
+ #
10
+ # stack do
11
+ # use Middleware::Labels, app: "web-app", managed_by: "kube_cluster"
12
+ # end
13
+ #
14
+ # The keyword arguments are converted to standard label keys:
15
+ #
16
+ # app: -> "app.kubernetes.io/name"
17
+ # instance: -> "app.kubernetes.io/instance"
18
+ # version: -> "app.kubernetes.io/version"
19
+ # component: -> "app.kubernetes.io/component"
20
+ # part_of: -> "app.kubernetes.io/part-of"
21
+ # managed_by: -> "app.kubernetes.io/managed-by"
22
+ #
23
+ # Any unrecognized keys are passed through as-is (string or symbol).
24
+ #
25
+ class Labels < Middleware
26
+ STANDARD_KEYS = {
27
+ app: :"app.kubernetes.io/name",
28
+ instance: :"app.kubernetes.io/instance",
29
+ version: :"app.kubernetes.io/version",
30
+ component: :"app.kubernetes.io/component",
31
+ part_of: :"app.kubernetes.io/part-of",
32
+ managed_by: :"app.kubernetes.io/managed-by",
33
+ }.freeze
34
+
35
+ def initialize(**labels)
36
+ @labels = normalize(labels)
37
+ end
38
+
39
+ def call(manifest)
40
+ manifest.resources.map! do |resource|
41
+ h = resource.to_h
42
+ h[:metadata] ||= {}
43
+ h[:metadata][:labels] = @labels.merge(h[:metadata][:labels] || {})
44
+ resource.rebuild(h)
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ def normalize(labels)
51
+ labels.each_with_object({}) do |(key, value), result|
52
+ normalized_key = STANDARD_KEYS.fetch(key, key)
53
+ result[normalized_key] = value.to_s
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kube
4
+ module Cluster
5
+ class Middleware
6
+ # Sets +metadata.namespace+ on all namespace-scoped resources.
7
+ # Cluster-scoped kinds (Namespace, ClusterRole, etc.) are skipped.
8
+ #
9
+ # stack do
10
+ # use Middleware::Namespace, "production"
11
+ # end
12
+ #
13
+ class Namespace < Middleware
14
+ def initialize(namespace)
15
+ @namespace = namespace
16
+ end
17
+
18
+ def call(manifest)
19
+ manifest.resources.map! do |resource|
20
+ next resource if resource.cluster_scoped?
21
+
22
+ h = resource.to_h
23
+ h[:metadata] ||= {}
24
+ h[:metadata][:namespace] = @namespace
25
+ resource.rebuild(h)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kube
4
+ module Cluster
5
+ class Middleware
6
+ # Injects soft pod anti-affinity on pod-bearing resources so
7
+ # that pods prefer to spread across nodes.
8
+ #
9
+ # The anti-affinity uses the resource's own +matchLabels+ from
10
+ # +spec.selector.matchLabels+ as the label selector, and
11
+ # +kubernetes.io/hostname+ as the topology key.
12
+ #
13
+ # Resources that already have +spec.template.spec.affinity+
14
+ # set are left untouched.
15
+ #
16
+ # stack do
17
+ # use Middleware::PodAntiAffinity
18
+ # use Middleware::PodAntiAffinity, topology_key: "topology.kubernetes.io/zone"
19
+ # end
20
+ #
21
+ class PodAntiAffinity < Middleware
22
+ def initialize(topology_key: "kubernetes.io/hostname", weight: 1)
23
+ @topology_key = topology_key
24
+ @weight = weight
25
+ end
26
+
27
+ def call(manifest)
28
+ manifest.resources.map! do |resource|
29
+ next resource unless resource.pod_bearing?
30
+
31
+ h = resource.to_h
32
+ pod_spec = resource.pod_template(h)
33
+ next resource unless pod_spec
34
+
35
+ # Don't overwrite existing affinity configuration.
36
+ next resource if pod_spec[:affinity]
37
+
38
+ match_labels = h.dig(:spec, :selector, :matchLabels)
39
+ next resource unless match_labels && !match_labels.empty?
40
+
41
+ pod_spec[:affinity] = {
42
+ podAntiAffinity: {
43
+ preferredDuringSchedulingIgnoredDuringExecution: [
44
+ {
45
+ weight: @weight,
46
+ podAffinityTerm: {
47
+ labelSelector: { matchLabels: match_labels },
48
+ topologyKey: @topology_key,
49
+ },
50
+ },
51
+ ],
52
+ },
53
+ }
54
+
55
+ resource.rebuild(h)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,64 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kube
4
+ module Cluster
5
+ class Middleware
6
+ # Reads the +app.kubernetes.io/size+ label from pod-bearing
7
+ # resources and injects CPU/memory requests and limits into
8
+ # every container.
9
+ #
10
+ # The label on the resource is the input:
11
+ #
12
+ # Kube::Cluster["Deployment"].new {
13
+ # metadata.labels = { "app.kubernetes.io/size": "small" }
14
+ # ...
15
+ # }
16
+ #
17
+ # Register in the stack — no arguments needed:
18
+ #
19
+ # stack do
20
+ # use Middleware::ResourcePreset
21
+ # end
22
+ #
23
+ # Available sizes: nano, micro, small, medium, large, xlarge, 2xlarge.
24
+ # Limits are ~1.5x requests (following Bitnami conventions).
25
+ #
26
+ class ResourcePreset < Middleware
27
+ LABEL = :"app.kubernetes.io/size"
28
+
29
+ PRESETS = {
30
+ "nano" => { requests: { cpu: "100m", memory: "128Mi" }, limits: { cpu: "150m", memory: "192Mi" } },
31
+ "micro" => { requests: { cpu: "250m", memory: "256Mi" }, limits: { cpu: "375m", memory: "384Mi" } },
32
+ "small" => { requests: { cpu: "500m", memory: "512Mi" }, limits: { cpu: "750m", memory: "768Mi" } },
33
+ "medium" => { requests: { cpu: "500m", memory: "1024Mi" }, limits: { cpu: "750m", memory: "1536Mi" } },
34
+ "large" => { requests: { cpu: "1", memory: "2048Mi" }, limits: { cpu: "1.5", memory: "3072Mi" } },
35
+ "xlarge" => { requests: { cpu: "1", memory: "3072Mi" }, limits: { cpu: "3", memory: "6144Mi" } },
36
+ "2xlarge" => { requests: { cpu: "1", memory: "3072Mi" }, limits: { cpu: "6", memory: "12288Mi" } },
37
+ }.freeze
38
+
39
+ def call(manifest)
40
+ manifest.resources.map! do |resource|
41
+ size = resource.label(LABEL)
42
+ next resource unless size
43
+ next resource unless resource.pod_bearing?
44
+
45
+ preset = PRESETS.fetch(size.to_s) do
46
+ raise ArgumentError, "Unknown size preset: #{size.inspect}. " \
47
+ "Valid sizes: #{PRESETS.keys.join(', ')}"
48
+ end
49
+
50
+ h = resource.to_h
51
+ pod_spec = resource.pod_template(h)
52
+ next resource unless pod_spec
53
+
54
+ resource.each_container(pod_spec) do |container|
55
+ container[:resources] = deep_merge(preset, container[:resources] || {})
56
+ end
57
+
58
+ resource.rebuild(h)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kube
4
+ module Cluster
5
+ class Middleware
6
+ # Injects pod and container security contexts on pod-bearing resources.
7
+ #
8
+ # Reads the +app.kubernetes.io/security+ label. When the label
9
+ # is absent, the middleware applies the default profile.
10
+ #
11
+ # Kube::Cluster["Deployment"].new {
12
+ # metadata.labels = { "app.kubernetes.io/security": "restricted" }
13
+ # ...
14
+ # }
15
+ #
16
+ # Available profiles: +restricted+ (default), +baseline+.
17
+ #
18
+ # stack do
19
+ # use Middleware::SecurityContext # default: restricted
20
+ # use Middleware::SecurityContext, default: :baseline # change default
21
+ # end
22
+ #
23
+ class SecurityContext < Middleware
24
+ LABEL = :"app.kubernetes.io/security"
25
+
26
+ PROFILES = {
27
+ "restricted" => {
28
+ pod: {
29
+ runAsNonRoot: true,
30
+ runAsUser: 1000,
31
+ runAsGroup: 1000,
32
+ fsGroup: 1000,
33
+ seccompProfile: { type: "RuntimeDefault" },
34
+ },
35
+ container: {
36
+ allowPrivilegeEscalation: false,
37
+ readOnlyRootFilesystem: true,
38
+ capabilities: { drop: ["ALL"] },
39
+ },
40
+ },
41
+ "baseline" => {
42
+ pod: {
43
+ runAsNonRoot: true,
44
+ runAsUser: 1000,
45
+ runAsGroup: 1000,
46
+ fsGroup: 1000,
47
+ },
48
+ container: {
49
+ allowPrivilegeEscalation: false,
50
+ },
51
+ },
52
+ }.freeze
53
+
54
+ def initialize(default: :restricted)
55
+ @default = default.to_s
56
+ end
57
+
58
+ def call(manifest)
59
+ manifest.resources.map! do |resource|
60
+ next resource unless resource.pod_bearing?
61
+
62
+ profile_name = resource.label(LABEL) || @default
63
+ profile = PROFILES.fetch(profile_name.to_s) do
64
+ raise ArgumentError, "Unknown security profile: #{profile_name.inspect}. " \
65
+ "Valid profiles: #{PROFILES.keys.join(', ')}"
66
+ end
67
+
68
+ h = resource.to_h
69
+ pod_spec = resource.pod_template(h)
70
+ next resource unless pod_spec
71
+
72
+ pod_spec[:securityContext] = deep_merge(profile[:pod], pod_spec[:securityContext] || {})
73
+
74
+ resource.each_container(pod_spec) do |container|
75
+ container[:securityContext] = deep_merge(profile[:container], container[:securityContext] || {})
76
+ end
77
+
78
+ resource.rebuild(h)
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kube
4
+ module Cluster
5
+ class Middleware
6
+ # Generates a Service for every pod-bearing resource that has
7
+ # containers with named ports.
8
+ #
9
+ # The generated Service uses +spec.selector.matchLabels+ from
10
+ # the source resource and maps each named container port.
11
+ #
12
+ # Labels and namespace are copied from the source resource, so
13
+ # subsequent middleware (Labels, Namespace, etc.) will also
14
+ # apply to the generated Service.
15
+ #
16
+ # stack do
17
+ # use Middleware::ServiceForDeployment
18
+ # end
19
+ #
20
+ class ServiceForDeployment < Middleware
21
+ def call(manifest)
22
+ generated = []
23
+
24
+ manifest.resources.each do |resource|
25
+ next unless resource.pod_bearing?
26
+
27
+ h = resource.to_h
28
+ ports = extract_ports(resource, h)
29
+ next if ports.empty?
30
+
31
+ match_labels = h.dig(:spec, :selector, :matchLabels)
32
+ next unless match_labels && !match_labels.empty?
33
+
34
+ generated << Kube::Cluster["Service"].new {
35
+ metadata.name = h.dig(:metadata, :name)
36
+ metadata.namespace = h.dig(:metadata, :namespace) if h.dig(:metadata, :namespace)
37
+ metadata.labels = h.dig(:metadata, :labels) || {}
38
+
39
+ spec.selector = match_labels
40
+ spec.ports = ports.map { |p|
41
+ {
42
+ name: p[:name],
43
+ port: p[:containerPort],
44
+ targetPort: p[:name],
45
+ protocol: p.fetch(:protocol, "TCP"),
46
+ }
47
+ }
48
+ }
49
+ end
50
+
51
+ manifest.resources.concat(generated)
52
+ end
53
+
54
+ private
55
+
56
+ def extract_ports(resource, hash)
57
+ pod_spec = resource.pod_template(hash)
58
+ return [] unless pod_spec
59
+
60
+ ports = []
61
+ resource.each_container(pod_spec) do |container|
62
+ Array(container[:ports]).each do |port|
63
+ ports << port if port[:name]
64
+ end
65
+ end
66
+ ports
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Kube
4
+ module Cluster
5
+ class Middleware
6
+ # An ordered pipeline of middleware that processes a manifest.
7
+ # Each middleware receives the manifest and mutates it in place.
8
+ #
9
+ # stack = Kube::Cluster::Middleware::Stack.new do
10
+ # use Middleware::ServiceForDeployment
11
+ # use Middleware::Labels, app: "web"
12
+ # use Middleware::Namespace, "production"
13
+ # end
14
+ #
15
+ # stack.call(manifest)
16
+ #
17
+ class Stack
18
+ def initialize(&block)
19
+ @middleware = []
20
+ instance_eval(&block) if block
21
+ end
22
+
23
+ # Register a middleware class with optional positional and keyword arguments.
24
+ def use(klass, *args, **kwargs)
25
+ @middleware << [klass, args, kwargs]
26
+ end
27
+
28
+ # Run the manifest through every middleware in order.
29
+ # Each middleware mutates the manifest in place.
30
+ def call(manifest)
31
+ @middleware.each do |klass, args, kwargs|
32
+ klass.new(*args, **kwargs).call(manifest)
33
+ end
34
+ end
35
+
36
+ # True when no middleware has been registered.
37
+ def empty?
38
+ @middleware.empty?
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "middleware/stack"
4
+ require_relative "middleware/namespace"
5
+ require_relative "middleware/labels"
6
+ require_relative "middleware/annotations"
7
+ require_relative "middleware/resource_preset"
8
+ require_relative "middleware/security_context"
9
+ require_relative "middleware/pod_anti_affinity"
10
+ require_relative "middleware/service_for_deployment"
11
+ require_relative "middleware/ingress_for_service"
12
+ require_relative "middleware/hpa_for_deployment"
13
+
14
+ module Kube
15
+ module Cluster
16
+ # Base class for manifest middleware.
17
+ #
18
+ # Middleware receives the full manifest and mutates it in place.
19
+ # Each middleware is responsible for iterating resources as needed.
20
+ #
21
+ # Transform example:
22
+ #
23
+ # class AddTeamLabel < Middleware
24
+ # def call(manifest)
25
+ # manifest.resources.map! do |resource|
26
+ # h = resource.to_h
27
+ # h[:metadata][:labels][:"app.kubernetes.io/team"] = "platform"
28
+ # resource.rebuild(h)
29
+ # end
30
+ # end
31
+ # end
32
+ #
33
+ # Generative example:
34
+ #
35
+ # class ServiceForDeployment < Middleware
36
+ # def call(manifest)
37
+ # generated = []
38
+ # manifest.resources.each do |resource|
39
+ # next unless resource.pod_bearing?
40
+ # generated << build_service_from(resource)
41
+ # end
42
+ # manifest.resources.concat(generated)
43
+ # end
44
+ # end
45
+ #
46
+ class Middleware
47
+ def initialize(**opts)
48
+ @opts = opts
49
+ end
50
+
51
+ # Override in subclasses. Receives the full manifest,
52
+ # mutates it in place.
53
+ def call(manifest)
54
+ end
55
+
56
+ private
57
+
58
+ def deep_merge(base, overlay)
59
+ base.merge(overlay) do |_key, old_val, new_val|
60
+ if old_val.is_a?(Hash) && new_val.is_a?(Hash)
61
+ deep_merge(old_val, new_val)
62
+ else
63
+ new_val
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -11,11 +11,89 @@ module Kube
11
11
 
12
12
  attr_accessor :cluster
13
13
 
14
+ POD_BEARING_KINDS = %w[
15
+ Deployment
16
+ StatefulSet
17
+ DaemonSet
18
+ Job
19
+ CronJob
20
+ ReplicaSet
21
+ ].freeze
22
+
23
+ CLUSTER_SCOPED_KINDS = %w[
24
+ Namespace
25
+ ClusterRole
26
+ ClusterRoleBinding
27
+ PersistentVolume
28
+ StorageClass
29
+ IngressClass
30
+ CustomResourceDefinition
31
+ PriorityClass
32
+ RuntimeClass
33
+ VolumeAttachment
34
+ CSIDriver
35
+ CSINode
36
+ ].freeze
37
+
14
38
  def initialize(hash = {}, &block)
15
39
  @cluster = hash.delete(:cluster)
16
40
  super
17
41
  snapshot!
18
42
  end
43
+
44
+ # Build a new resource of the same schema subclass from a hash.
45
+ def rebuild(hash)
46
+ self.class.new(hash)
47
+ end
48
+
49
+ # Read a label value from the resource.
50
+ def label(key)
51
+ labels = to_h.dig(:metadata, :labels) || {}
52
+ labels[key.to_sym] || labels[key.to_s]
53
+ end
54
+
55
+ # Read an annotation value from the resource.
56
+ def annotation(key)
57
+ annotations = to_h.dig(:metadata, :annotations) || {}
58
+ annotations[key.to_sym] || annotations[key.to_s]
59
+ end
60
+
61
+ # The resource kind as a String (e.g. "Deployment").
62
+ def kind
63
+ h = to_h
64
+ (h[:kind] || h["kind"]).to_s
65
+ end
66
+
67
+ # Is this a resource that contains a pod template?
68
+ def pod_bearing?
69
+ POD_BEARING_KINDS.include?(kind)
70
+ end
71
+
72
+ # Is this a cluster-scoped resource (no namespace)?
73
+ def cluster_scoped?
74
+ CLUSTER_SCOPED_KINDS.include?(kind)
75
+ end
76
+
77
+ # Returns the pod template spec path from a resource hash,
78
+ # accounting for CronJob's extra nesting.
79
+ def pod_template(hash)
80
+ if (hash[:kind] || hash["kind"]).to_s == "CronJob"
81
+ hash.dig(:spec, :jobTemplate, :spec, :template, :spec)
82
+ else
83
+ hash.dig(:spec, :template, :spec)
84
+ end
85
+ end
86
+
87
+ # Walk every container list in a pod spec (containers,
88
+ # initContainers) and yield each container hash.
89
+ def each_container(pod_spec, &block)
90
+ return unless pod_spec
91
+
92
+ [:containers, :initContainers].each do |key|
93
+ Array(pod_spec[key]).each(&block)
94
+ end
95
+ end
96
+
19
97
  end
20
98
  end
21
99
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Kube
4
4
  module Cluster
5
- VERSION = "0.2.1"
5
+ VERSION = "0.3.0"
6
6
  end
7
7
  end
data/lib/kube/cluster.rb CHANGED
@@ -7,6 +7,7 @@ require_relative "cluster/connection"
7
7
  require_relative "cluster/instance"
8
8
  require_relative "cluster/resource"
9
9
  require_relative "cluster/manifest"
10
+ require_relative "cluster/middleware"
10
11
  require 'kube/ctl'
11
12
 
12
13
  module Kube
@@ -18,5 +19,25 @@ module Kube
18
19
  def self.connect(kubeconfig:)
19
20
  Instance.new(kubeconfig: kubeconfig)
20
21
  end
22
+
23
+ # Returns an anonymous subclass of Kube::Cluster::Resource for the
24
+ # given Kubernetes kind, mirroring Kube::Schema[kind] but with
25
+ # dirty tracking, persistence, and resource helper methods.
26
+ #
27
+ # Kube::Cluster["Deployment"].new { metadata.name = "web" }
28
+ #
29
+ def self.[](kind)
30
+ @resource_classes ||= {}
31
+ @resource_classes[kind] ||= begin
32
+ schema_class = Kube::Schema[kind]
33
+ Class.new(Resource) do
34
+ @schema = schema_class.schema
35
+ @defaults = schema_class.defaults
36
+
37
+ def self.schema = @schema || superclass.schema
38
+ def self.defaults = @defaults || superclass.defaults
39
+ end
40
+ end
41
+ end
21
42
  end
22
43
  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.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nathan K
@@ -121,13 +121,19 @@ files:
121
121
  - bin/test
122
122
  - docker-compose.yml
123
123
  - examples/01-basic-redis-pod/manifest.rb
124
- - examples/database/manifest.rb
125
- - examples/version2/demo.rb
126
- - examples/version2/helpers.rb
127
- - examples/version2/my_app.rb
128
- - examples/version2/postgresql.rb
129
- - examples/version2/ruby_on_rails.rb
130
- - examples/web-app/manifest.rb
124
+ - examples/02-manifest-with-middleware/manifest.rb
125
+ - examples/02-manifest-with-middleware/middleware/labels.rb
126
+ - examples/02-manifest-with-middleware/middleware/namespace.rb
127
+ - examples/02-manifest-with-middleware/templates/config_map.rb
128
+ - examples/02-manifest-with-middleware/templates/deployment.rb
129
+ - examples/02-manifest-with-middleware/templates/horizontal_pod_autoscaler.rb
130
+ - examples/02-manifest-with-middleware/templates/ingress.rb
131
+ - examples/02-manifest-with-middleware/templates/service.rb
132
+ - examples/03-app-with-database/demo.rb
133
+ - examples/03-app-with-database/helpers.rb
134
+ - examples/03-app-with-database/my_app.rb
135
+ - examples/03-app-with-database/postgresql.rb
136
+ - examples/03-app-with-database/ruby_on_rails.rb
131
137
  - flake.lock
132
138
  - flake.nix
133
139
  - kube_cluster.gemspec
@@ -136,17 +142,17 @@ files:
136
142
  - lib/kube/cluster/connection.rb
137
143
  - lib/kube/cluster/instance.rb
138
144
  - lib/kube/cluster/manifest.rb
139
- - lib/kube/cluster/manifest/middleware.rb
140
- - lib/kube/cluster/manifest/middleware/annotations.rb
141
- - lib/kube/cluster/manifest/middleware/hpa_for_deployment.rb
142
- - lib/kube/cluster/manifest/middleware/ingress_for_service.rb
143
- - lib/kube/cluster/manifest/middleware/labels.rb
144
- - lib/kube/cluster/manifest/middleware/namespace.rb
145
- - lib/kube/cluster/manifest/middleware/pod_anti_affinity.rb
146
- - lib/kube/cluster/manifest/middleware/resource_preset.rb
147
- - lib/kube/cluster/manifest/middleware/security_context.rb
148
- - lib/kube/cluster/manifest/middleware/service_for_deployment.rb
149
- - lib/kube/cluster/manifest/stack.rb
145
+ - lib/kube/cluster/middleware.rb
146
+ - lib/kube/cluster/middleware/annotations.rb
147
+ - lib/kube/cluster/middleware/hpa_for_deployment.rb
148
+ - lib/kube/cluster/middleware/ingress_for_service.rb
149
+ - lib/kube/cluster/middleware/labels.rb
150
+ - lib/kube/cluster/middleware/namespace.rb
151
+ - lib/kube/cluster/middleware/pod_anti_affinity.rb
152
+ - lib/kube/cluster/middleware/resource_preset.rb
153
+ - lib/kube/cluster/middleware/security_context.rb
154
+ - lib/kube/cluster/middleware/service_for_deployment.rb
155
+ - lib/kube/cluster/middleware/stack.rb
150
156
  - lib/kube/cluster/resource.rb
151
157
  - lib/kube/cluster/resource/dirty_tracking.rb
152
158
  - lib/kube/cluster/resource/persistence.rb