Skip to content

Commit 3d263ec

Browse files
committed
refactor(templates)!: secret now base64 encodes
Previously, the secret template only supported stringData. This commit refactors the secret to continue supporting stringData, but also support data. It forces all values to be base64 encoded, and adds a test to verify this functionality.
1 parent 0add60c commit 3d263ec

File tree

5 files changed

+165
-23
lines changed

5 files changed

+165
-23
lines changed

Gemfile.lock

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ PATH
22
remote: .
33
specs:
44
metatron (0.10.1)
5+
base64
56
json (~> 2.6)
67
rack (>= 2.2.8, < 4)
78

@@ -10,6 +11,7 @@ GEM
1011
specs:
1112
ast (2.4.2)
1213
backport (1.2.0)
14+
base64 (0.2.0)
1315
benchmark (0.4.0)
1416
byebug (11.1.3)
1517
diff-lcs (1.6.0)

lib/metatron.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
require "time"
77
require "logger"
88

9+
# external requirements
10+
require "base64"
11+
912
# The top-level module for Metatron
1013
module Metatron
1114
class Error < StandardError; end

lib/metatron/templates/secret.rb

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,38 @@ class Secret < Template
77
include Concerns::Annotated
88
include Concerns::Namespaced
99

10-
attr_accessor :additional_labels, :type, :data
10+
attr_accessor :additional_labels, :type, :data, :string_data
1111

12-
def initialize(name, data = {})
12+
alias stringData string_data
13+
14+
def initialize(name, provided_string_data = nil, string_data: nil, data: nil)
1315
super(name)
16+
@string_data = string_data || provided_string_data
1417
@data = data
1518
@additional_labels = {}
1619
@type = "Opaque"
1720
end
1821

22+
def formatted_data
23+
data_hash = {}
24+
25+
# Only include one of data or string_data, preferring data if both are present
26+
return data_hash unless data || string_data
27+
28+
# If string_data is provided, it should be a hash of string values
29+
# and will be base64 encoded
30+
if string_data
31+
data_hash[:data] = string_data.transform_values do |value|
32+
Base64.strict_encode64(value.to_s).gsub("\n", "")
33+
end
34+
end
35+
36+
# If data is provided, it should be a hash of base64 encoded values
37+
data_hash[:data] = data if data
38+
39+
data_hash
40+
end
41+
1942
def render
2043
{
2144
apiVersion:,
@@ -24,9 +47,8 @@ def render
2447
name:,
2548
labels: base_labels.merge(additional_labels)
2649
}.merge(formatted_annotations).merge(formatted_namespace).compact,
27-
type:,
28-
stringData: data
29-
}.compact
50+
type:
51+
}.compact.merge(formatted_data).compact
3052
end
3153
end
3254
end

metatron.gemspec

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
2727

2828
spec.required_ruby_version = "~> 3.1"
2929

30+
spec.add_dependency "base64"
3031
spec.add_dependency "json", "~> 2.6"
3132
spec.add_dependency "rack", ">= 2.2.8", "< 4"
3233

Lines changed: 132 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,142 @@
11
# frozen_string_literal: true
22

33
RSpec.describe Metatron::Templates::Secret do
4-
let(:secret) { described_class.new("test", { "some secret" => "value" }) }
5-
6-
let(:rendered_secret) do
7-
{
8-
apiVersion: "v1",
9-
kind: "Secret",
10-
metadata: {
11-
name: "test",
12-
labels: { "metatron.therubyist.org/name": "test" }
13-
},
14-
type: "Opaque",
15-
stringData: {
16-
"some secret" => "value"
4+
describe "using legacy unnamed constructor with string_data" do
5+
let(:secret) { described_class.new("test", { "some secret" => "value" }) }
6+
7+
let(:rendered_secret) do
8+
{
9+
apiVersion: "v1",
10+
kind: "Secret",
11+
metadata: {
12+
name: "test",
13+
labels: { "metatron.therubyist.org/name": "test" }
14+
},
15+
type: "Opaque",
16+
data: { "some secret" => "dmFsdWU=" } # Base64 encoded "value"
1717
}
18-
}
18+
end
19+
20+
it "produces a hash" do
21+
expect(secret.render).to be_a(Hash)
22+
end
23+
24+
it "renders properly" do
25+
expect(secret.render).to eq(rendered_secret)
26+
end
1927
end
2028

21-
it "produces a hash" do
22-
expect(secret.render).to be_a(Hash)
29+
describe "using named constructor with string_data" do
30+
let(:secret) do
31+
described_class.new("test", string_data: { "some secret" => "value" })
32+
end
33+
34+
let(:rendered_secret) do
35+
{
36+
apiVersion: "v1",
37+
kind: "Secret",
38+
metadata: {
39+
name: "test",
40+
labels: { "metatron.therubyist.org/name": "test" }
41+
},
42+
type: "Opaque",
43+
data: { "some secret" => "dmFsdWU=" } # Base64 encoded "value"
44+
}
45+
end
46+
47+
it "produces a hash" do
48+
expect(secret.render).to be_a(Hash)
49+
end
50+
51+
it "renders properly" do
52+
expect(secret.render).to eq(rendered_secret)
53+
end
2354
end
2455

25-
it "renders properly" do
26-
expect(secret.render).to eq(rendered_secret)
56+
describe "using named constructor with data" do
57+
let(:secret) do
58+
described_class.new("test", data: { "some secret" => "b3RoZXIgdmFsdWU=" })
59+
end
60+
61+
let(:rendered_secret) do
62+
{
63+
apiVersion: "v1",
64+
kind: "Secret",
65+
metadata: {
66+
name: "test",
67+
labels: { "metatron.therubyist.org/name": "test" }
68+
},
69+
type: "Opaque",
70+
data: { "some secret" => "b3RoZXIgdmFsdWU=" } # Base64 encoded "other value"
71+
}
72+
end
73+
74+
it "produces a hash" do
75+
expect(secret.render).to be_a(Hash)
76+
end
77+
78+
it "renders properly" do
79+
expect(secret.render).to eq(rendered_secret)
80+
end
81+
end
82+
83+
describe "using named constructor with both string_data and data" do
84+
let(:secret) do
85+
described_class.new(
86+
"test",
87+
data: { "some secret" => "b3RoZXIgdmFsdWU=" }, # should prefer this
88+
string_data: { "some secret" => "value" }
89+
)
90+
end
91+
92+
let(:rendered_secret) do
93+
{
94+
apiVersion: "v1",
95+
kind: "Secret",
96+
metadata: {
97+
name: "test",
98+
labels: { "metatron.therubyist.org/name": "test" }
99+
},
100+
type: "Opaque",
101+
data: { "some secret" => "b3RoZXIgdmFsdWU=" } # Base64 encoded "other value"
102+
}
103+
end
104+
105+
it "produces a hash" do
106+
expect(secret.render).to be_a(Hash)
107+
end
108+
109+
it "renders properly" do
110+
expect(secret.render).to eq(rendered_secret)
111+
end
112+
end
113+
114+
describe "using no data or string_data in constructor, applying string_data later" do
115+
let(:secret) do
116+
r = described_class.new("test")
117+
r.string_data = { "some secret" => "value" }
118+
r
119+
end
120+
121+
let(:rendered_secret) do
122+
{
123+
apiVersion: "v1",
124+
kind: "Secret",
125+
metadata: {
126+
name: "test",
127+
labels: { "metatron.therubyist.org/name": "test" }
128+
},
129+
type: "Opaque",
130+
data: { "some secret" => "dmFsdWU=" } # Base64 encoded "value"
131+
}
132+
end
133+
134+
it "produces a hash" do
135+
expect(secret.render).to be_a(Hash)
136+
end
137+
138+
it "renders properly" do
139+
expect(secret.render).to eq(rendered_secret)
140+
end
27141
end
28142
end

0 commit comments

Comments
 (0)