Class: ManifestTest

Inherits:
Minitest::Test
  • Object
show all
Defined in:
lib/kube/cluster/manifest.rb

Constant Summary collapse

Middleware =
Kube::Cluster::Middleware

Instance Method Summary collapse

Instance Method Details

#test_bare_manifest_enumerates_resources_unchangedObject

── Bare manifest ────────────────────────────────────────────────────────



40
41
42
43
44
45
46
47
48
49
50
51
# File 'lib/kube/cluster/manifest.rb', line 40

def test_bare_manifest_enumerates_resources_unchanged
  m = Kube::Cluster::Manifest.new
  m << Kube::Cluster["ConfigMap"].new {
    .name = "test"
    self.data = { key: "value" }
  }

  resources = m.to_a
  assert_equal 1, resources.size
  assert_equal "ConfigMap", resources.first.to_h[:kind]
  assert_equal "test", resources.first.to_h.dig(:metadata, :name)
end

#test_chained_generative_middlewareObject

── Multi-generative: chained generation ────────────────────────────────



231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
# File 'lib/kube/cluster/manifest.rb', line 231

def test_chained_generative_middleware
  m = Kube::Cluster::Manifest.new
  m << Kube::Cluster["Deployment"].new {
    .name = "web"
    .namespace = "default"
    .labels = {
      "app.kubernetes.io/expose":    "app.example.com",
      "app.kubernetes.io/autoscale": "2-10",
    }
    spec.selector.matchLabels = { app: "web" }
    spec.template..labels = { app: "web" }
    spec.template.spec.containers = [
      { name: "web", image: "nginx", ports: [{ name: "http", containerPort: 8080 }] },
    ]
  }

  stack = Middleware::Stack.new do
    use Middleware::ServiceForDeployment   # Deployment → +Service
    use Middleware::IngressForService       # Service with expose label → +Ingress
    use Middleware::HPAForDeployment        # Deployment with autoscale label → +HPA
  end
  stack.call(m)

  kinds = m.map { |r| r.to_h[:kind] }

  assert_includes kinds, "Deployment"
  assert_includes kinds, "Service"
  assert_includes kinds, "Ingress"
  assert_includes kinds, "HorizontalPodAutoscaler"
  assert_equal 4, m.to_a.size
end

#test_each_without_block_returns_enumeratorObject

── each without block ──────────────────────────────────────────────────



131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/kube/cluster/manifest.rb', line 131

def test_each_without_block_returns_enumerator
  m = Kube::Cluster::Manifest.new
  m << Kube::Cluster["ConfigMap"].new { .name = "test" }

  Middleware::Namespace.new("production").call(m)

  enum = m.each
  assert_instance_of Enumerator, enum

  r = enum.first
  assert_equal "production", r.to_h.dig(:metadata, :namespace)
end

#test_enumerable_methods_workObject



82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/kube/cluster/manifest.rb', line 82

def test_enumerable_methods_work
  m = Kube::Cluster::Manifest.new
  m << Kube::Cluster["ConfigMap"].new { .name = "a" }
  m << Kube::Cluster["ConfigMap"].new { .name = "b" }

  Middleware::Namespace.new("production").call(m)

  names = m.map { |r| r.to_h.dig(:metadata, :name) }
  assert_equal %w[a b], names

  all_namespaced = m.all? { |r| r.to_h.dig(:metadata, :namespace) == "production" }
  assert all_namespaced
end

#test_generated_resources_flow_through_subsequent_stagesObject

── Generated resources flow through subsequent middleware stages ────────



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
# File 'lib/kube/cluster/manifest.rb', line 179

def test_generated_resources_flow_through_subsequent_stages
  m = Kube::Cluster::Manifest.new
  m << Kube::Cluster["Deployment"].new {
    .name = "web"
    spec.selector.matchLabels = { app: "web" }
    spec.template..labels = { app: "web" }
    spec.template.spec.containers = [
      { name: "web", image: "nginx", ports: [{ name: "http", containerPort: 8080 }] },
    ]
  }

  stack = Middleware::Stack.new do
    use Middleware::ServiceForDeployment           # generates Service
    use Middleware::Namespace, "production"         # namespaces everything
    use Middleware::Labels, managed_by: "middleware" # labels everything
  end
  stack.call(m)

  resources = m.to_a
  assert_equal 2, resources.size

  # Both the Deployment and the generated Service got namespaced and labeled
  resources.each do |r|
    h = r.to_h
    assert_equal "production", h.dig(:metadata, :namespace),
      "Expected #{h[:kind]} to be namespaced"
    assert_equal "middleware", h.dig(:metadata, :labels, :"app.kubernetes.io/managed-by"),
      "Expected #{h[:kind]} to be labeled"
  end
end

#test_generative_middleware_adds_serviceObject

── Generative middleware produces new resources ─────────────────────────



146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/kube/cluster/manifest.rb', line 146

def test_generative_middleware_adds_service
  m = Kube::Cluster::Manifest.new
  m << Kube::Cluster["Deployment"].new {
    .name = "web"
    .namespace = "default"
    spec.selector.matchLabels = { app: "web" }
    spec.template..labels = { app: "web" }
    spec.template.spec.containers = [
      { name: "web", image: "nginx", ports: [{ name: "http", containerPort: 8080 }] },
    ]
  }

  Middleware::ServiceForDeployment.new.call(m)

  kinds = m.map { |r| r.to_h[:kind] }
  assert_equal %w[Deployment Service], kinds
end

#test_generative_middleware_does_not_affect_non_matching_resourcesObject



164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/kube/cluster/manifest.rb', line 164

def test_generative_middleware_does_not_affect_non_matching_resources
  m = Kube::Cluster::Manifest.new
  m << Kube::Cluster["ConfigMap"].new {
    .name = "config"
  }

  Middleware::ServiceForDeployment.new.call(m)

  resources = m.to_a
  assert_equal 1, resources.size
  assert_equal "ConfigMap", resources.first.to_h[:kind]
end

#test_multiple_middleware_compose_in_orderObject

── Multi-middleware stack ──────────────────────────────────────────────



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/kube/cluster/manifest.rb', line 98

def test_multiple_middleware_compose_in_order
  m = Kube::Cluster::Manifest.new
  m << Kube::Cluster["ConfigMap"].new {
    .name = "test"
  }

  stack = Middleware::Stack.new do
    use Middleware::Namespace, "staging"
    use Middleware::Labels, app: "myapp", managed_by: "kube_cluster"
  end
  stack.call(m)

  r = m.first
  h = r.to_h

  assert_equal "staging", h.dig(:metadata, :namespace)
  assert_equal "myapp", h.dig(:metadata, :labels, :"app.kubernetes.io/name")
  assert_equal "kube_cluster", h.dig(:metadata, :labels, :"app.kubernetes.io/managed-by")
end

#test_size_reflects_resource_countObject

── size reflects resource count ─────────────────────────────────────────



120
121
122
123
124
125
126
127
# File 'lib/kube/cluster/manifest.rb', line 120

def test_size_reflects_resource_count
  m = Kube::Cluster::Manifest.new
  m << Kube::Cluster["ConfigMap"].new { .name = "a" }
  m << Kube::Cluster["ConfigMap"].new { .name = "b" }

  assert_equal 2, m.size
  assert_equal 2, m.length
end

#test_stack_transforms_resourcesObject

── Stack transforms resources ───────────────────────────────────────────



55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/kube/cluster/manifest.rb', line 55

def test_stack_transforms_resources
  m = Kube::Cluster::Manifest.new
  m << Kube::Cluster["ConfigMap"].new {
    .name = "test"
  }

  stack = Middleware::Stack.new do
    use Middleware::Namespace, "production"
  end
  stack.call(m)

  resources = m.to_a
  assert_equal "production", resources.first.to_h.dig(:metadata, :namespace)
end

#test_to_yaml_reflects_middlewareObject



70
71
72
73
74
75
76
77
78
79
80
# File 'lib/kube/cluster/manifest.rb', line 70

def test_to_yaml_reflects_middleware
  m = Kube::Cluster::Manifest.new
  m << Kube::Cluster["ConfigMap"].new {
    .name = "test"
  }

  Middleware::Namespace.new("production").call(m)

  yaml = m.to_yaml
  assert_includes yaml, "namespace: production"
end

#test_to_yaml_serializes_integers_as_plain_valuesObject

── YAML serializes integers correctly ──────────────────────────────────



212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# File 'lib/kube/cluster/manifest.rb', line 212

def test_to_yaml_serializes_integers_as_plain_values
  m = Kube::Cluster::Manifest.new
  m << Kube::Cluster["Deployment"].new {
    .name = "web"
    spec.selector.matchLabels = { app: "web" }
    spec.template..labels = { app: "web" }
    spec.template.spec.containers = [
      { name: "web", image: "nginx", ports: [{ name: "http", containerPort: 8080 }] },
    ]
  }

  yaml = m.to_yaml
  refute_includes yaml, "!ruby/object:Integer",
    "Integer values must serialize as plain YAML numbers, not !ruby/object:Integer"
  assert_includes yaml, "containerPort: 8080"
end