Skip to content

Commit b969ce6

Browse files
committed
feat(templates): add volume snapshot and content
Adds templates for volume snapshots and volume snapshot contents.
1 parent d8aaa49 commit b969ce6

File tree

5 files changed

+301
-0
lines changed

5 files changed

+301
-0
lines changed

lib/metatron.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class ConfigError < Error; end
4747
require "metatron/templates/service"
4848
require "metatron/templates/service_account"
4949
require "metatron/templates/stateful_set"
50+
require "metatron/templates/volume_snapshot"
51+
require "metatron/templates/volume_snapshot_content"
5052
require "metatron/controller"
5153
require "metatron/composite_controller"
5254
require "metatron/controllers/ping"
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# frozen_string_literal: true
2+
3+
module Metatron
4+
module Templates
5+
# The VolumeSnapshot Kubernetes resource
6+
class VolumeSnapshot < Template
7+
include Concerns::Annotated
8+
include Concerns::Namespaced
9+
10+
attr_accessor :source, :volume_snapshot_class_name
11+
12+
alias volumeSnapshotClassName volume_snapshot_class_name
13+
14+
def initialize(name, source: {}, volume_snapshot_class_name: nil)
15+
super(name)
16+
@source = source
17+
@volume_snapshot_class_name = volume_snapshot_class_name
18+
@api_version = "snapshot.storage.k8s.io/v1"
19+
end
20+
21+
def render
22+
{
23+
apiVersion:,
24+
kind:,
25+
metadata: {
26+
name:,
27+
labels: base_labels.merge(additional_labels)
28+
}.merge(formatted_annotations).merge(formatted_namespace).compact,
29+
spec: {}.merge(formatted_source).merge(formatted_volume_snapshot_class_name).compact
30+
}.compact
31+
end
32+
33+
def formatted_source
34+
case source
35+
when Hash
36+
{ source: }
37+
when Metatron::Templates::VolumeSnapshotContent
38+
{ source: { volumeSnapshotContentName: source.name } }
39+
when Metatron::Templates::PersistentVolumeClaim
40+
{ source: { persistentVolumeClaimName: source.name } }
41+
when nil
42+
{}
43+
else
44+
raise ArgumentError,
45+
"Invalid source type: #{source.class}. " \
46+
"Expected Hash, VolumeSnapshotContent, or PersistentVolumeClaim."
47+
end
48+
end
49+
50+
def formatted_volume_snapshot_class_name
51+
return {} unless volume_snapshot_class_name
52+
53+
if volume_snapshot_class_name.is_a?(String)
54+
{ volumeSnapshotClassName: }
55+
elsif volume_snapshot_class_name.respond_to?(:name)
56+
{ volumeSnapshotClassName: volume_snapshot_class_name.name }
57+
else
58+
raise ArgumentError,
59+
"Invalid volume_snapshot_class_name type: #{volume_snapshot_class_name.class}."
60+
end
61+
end
62+
end
63+
end
64+
end
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
# frozen_string_literal: true
2+
3+
module Metatron
4+
module Templates
5+
# The VolumeSnapshotContent Kubernetes resource
6+
class VolumeSnapshotContent < Template
7+
include Concerns::Annotated
8+
include Concerns::Namespaced
9+
10+
attr_accessor :source, :deletion_policy, :driver, :source_volume_mode, :volume_snapshot_ref
11+
12+
alias deletionPolicy deletion_policy
13+
alias sourceVolumeMode source_volume_mode
14+
alias volumeSnapshotRef volume_snapshot_ref
15+
16+
def initialize(name, driver:, source: {}, deletion_policy: "Delete",
17+
volume_snapshot_ref: nil, source_volume_mode: "Filesystem")
18+
super(name)
19+
@api_version = "snapshot.storage.k8s.io/v1"
20+
@driver = driver
21+
@source = source
22+
@source_volume_mode = source_volume_mode
23+
@deletion_policy = deletion_policy
24+
@volume_snapshot_ref = volume_snapshot_ref
25+
end
26+
27+
def render
28+
{
29+
apiVersion:,
30+
kind:,
31+
metadata: {
32+
name:,
33+
labels: base_labels.merge(additional_labels)
34+
}.merge(formatted_annotations).merge(formatted_namespace).compact,
35+
spec: {
36+
driver:,
37+
deletionPolicy:,
38+
sourceVolumeMode:
39+
}.merge(formatted_source).merge(formatted_volume_snapshot_ref).compact
40+
}.compact
41+
end
42+
43+
def formatted_source
44+
return {} unless source
45+
raise ArgumentError, "Invalid source type: #{source.class}." unless source.is_a?(Hash)
46+
47+
{ source: }
48+
end
49+
50+
def formatted_volume_snapshot_ref
51+
return {} unless volume_snapshot_ref
52+
53+
if volume_snapshot_ref.is_a?(Hash)
54+
{ volumeSnapshotRef: }
55+
elsif volume_snapshot_ref.is_a?(VolumeSnapshot)
56+
{
57+
volumeSnapshotRef: {
58+
name: volume_snapshot_ref.name,
59+
namespace: volume_snapshot_ref.namespace
60+
}.compact
61+
}
62+
else
63+
raise ArgumentError,
64+
"Invalid volume_snapshot_ref type: #{volume_snapshot_ref.class}."
65+
end
66+
end
67+
end
68+
end
69+
end
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe Metatron::Templates::VolumeSnapshotContent do
4+
describe "for simple volume snapshot contents" do
5+
let(:volume_snapshot_content) do
6+
described_class.new(
7+
"new-snapshot-content-test",
8+
source: { snapshotHandle: "7bdd0de3-aaeb-11e8-9aae-0242ac110002" },
9+
driver: "hostpath.csi.k8s.io",
10+
volume_snapshot_ref: {
11+
name: "new-snapshot-test",
12+
namespace: "foo"
13+
}
14+
)
15+
end
16+
17+
let(:rendered_volume_snapshot_content) do
18+
{
19+
apiVersion: "snapshot.storage.k8s.io/v1",
20+
kind: "VolumeSnapshotContent",
21+
metadata: {
22+
name: "new-snapshot-content-test",
23+
labels: { "metatron.therubyist.org/name": "new-snapshot-content-test" }
24+
},
25+
spec: {
26+
deletionPolicy: "Delete",
27+
driver: "hostpath.csi.k8s.io",
28+
source: {
29+
snapshotHandle: "7bdd0de3-aaeb-11e8-9aae-0242ac110002"
30+
},
31+
sourceVolumeMode: "Filesystem",
32+
volumeSnapshotRef: {
33+
name: "new-snapshot-test",
34+
namespace: "foo"
35+
}
36+
}
37+
}
38+
end
39+
40+
it "produces a hash" do
41+
expect(volume_snapshot_content.render).to be_a(Hash)
42+
end
43+
44+
it "renders properly" do
45+
expect(volume_snapshot_content.render).to eq(rendered_volume_snapshot_content)
46+
end
47+
end
48+
49+
describe "for volume snapshot contents provided a volume snapshot" do
50+
let(:volume_snapshot) do
51+
snapshot = Metatron::Templates::VolumeSnapshot.new(
52+
"new-snapshot-test",
53+
source: { persistentVolumeClaimName: "hello" },
54+
volume_snapshot_class_name: "testClass"
55+
)
56+
snapshot.namespace = "foo"
57+
snapshot
58+
end
59+
60+
let(:volume_snapshot_content) do
61+
described_class.new(
62+
"new-snapshot-content-test",
63+
source: { snapshotHandle: "7bdd0de3-aaeb-11e8-9aae-0242ac110003" },
64+
driver: "hostpath.csi.k8s.io",
65+
volume_snapshot_ref: volume_snapshot
66+
)
67+
end
68+
69+
let(:rendered_volume_snapshot_content) do
70+
{
71+
apiVersion: "snapshot.storage.k8s.io/v1",
72+
kind: "VolumeSnapshotContent",
73+
metadata: {
74+
name: "new-snapshot-content-test",
75+
labels: { "metatron.therubyist.org/name": "new-snapshot-content-test" }
76+
},
77+
spec: {
78+
deletionPolicy: "Delete",
79+
driver: "hostpath.csi.k8s.io",
80+
source: {
81+
snapshotHandle: "7bdd0de3-aaeb-11e8-9aae-0242ac110003"
82+
},
83+
sourceVolumeMode: "Filesystem",
84+
volumeSnapshotRef: {
85+
name: "new-snapshot-test",
86+
namespace: "foo"
87+
}
88+
}
89+
}
90+
end
91+
92+
it "produces a hash" do
93+
expect(volume_snapshot_content.render).to be_a(Hash)
94+
end
95+
96+
it "renders properly" do
97+
expect(volume_snapshot_content.render).to eq(rendered_volume_snapshot_content)
98+
end
99+
end
100+
end
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# frozen_string_literal: true
2+
3+
RSpec.describe Metatron::Templates::VolumeSnapshot do
4+
describe "for simple volume snapshots" do
5+
let(:volume_snapshot) do
6+
described_class.new("hello", source: { persistentVolumeClaimName: "hello" })
7+
end
8+
9+
let(:rendered_volume_snapshot) do
10+
{
11+
apiVersion: "snapshot.storage.k8s.io/v1",
12+
kind: "VolumeSnapshot",
13+
metadata: { labels: { "metatron.therubyist.org/name": "hello" }, name: "hello" },
14+
spec: {
15+
source: {
16+
persistentVolumeClaimName: "hello"
17+
}
18+
}
19+
}
20+
end
21+
22+
it "produces a hash" do
23+
expect(volume_snapshot.render).to be_a(Hash)
24+
end
25+
26+
it "renders properly" do
27+
expect(volume_snapshot.render).to eq(rendered_volume_snapshot)
28+
end
29+
end
30+
31+
describe "for volume snapshots from a persistent volume claim" do
32+
let(:volume_snapshot) do
33+
described_class.new(
34+
"hello",
35+
source: Metatron::Templates::PersistentVolumeClaim.new(
36+
"hello",
37+
storage_class: "test",
38+
storage: "1Gi"
39+
),
40+
volume_snapshot_class_name: "testClass"
41+
)
42+
end
43+
44+
let(:rendered_volume_snapshot) do
45+
{
46+
apiVersion: "snapshot.storage.k8s.io/v1",
47+
kind: "VolumeSnapshot",
48+
metadata: { labels: { "metatron.therubyist.org/name": "hello" }, name: "hello" },
49+
spec: {
50+
source: {
51+
persistentVolumeClaimName: "hello"
52+
},
53+
volumeSnapshotClassName: "testClass"
54+
}
55+
}
56+
end
57+
58+
it "produces a hash" do
59+
expect(volume_snapshot.render).to be_a(Hash)
60+
end
61+
62+
it "renders properly" do
63+
expect(volume_snapshot.render).to eq(rendered_volume_snapshot)
64+
end
65+
end
66+
end

0 commit comments

Comments
 (0)