Skip to content

Commit ebd4aed

Browse files
committed
Fix conversion Bundle->ClusterBundle
Signed-off-by: Erik Godding Boye <egboye@gmail.com>
1 parent 4e3ee86 commit ebd4aed

4 files changed

Lines changed: 100 additions & 16 deletions

File tree

pkg/apis/trust/v1alpha1/conversion.go

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package v1alpha1
1818

1919
import (
2020
"slices"
21+
"strings"
2122

2223
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2324
apimachineryconversion "k8s.io/apimachinery/pkg/conversion"
@@ -27,7 +28,7 @@ import (
2728
trustv1alpha2 "github.com/cert-manager/trust-manager/pkg/apis/trustmanager/v1alpha2"
2829
)
2930

30-
const annotationKeyJKSKey = "internal.trust-manager.io/jks-key"
31+
const AnnotationKeyJKSKey = "internal.trust-manager.io/jks-key"
3132

3233
func (src *Bundle) ConvertTo(dstRaw conversion.Hub) error {
3334
dst := dstRaw.(*trustv1alpha2.ClusterBundle)
@@ -53,6 +54,9 @@ func (src *Bundle) ConvertTo(dstRaw conversion.Hub) error {
5354
dst.Spec.Sources = slices.DeleteFunc(dst.Spec.Sources, func(bs trustv1alpha2.BundleSource) bool {
5455
return bs == trustv1alpha2.BundleSource{}
5556
})
57+
if len(dst.Spec.Sources) == 0 {
58+
dst.Spec.Sources = nil
59+
}
5660

5761
return nil
5862
}
@@ -78,7 +82,21 @@ func Convert_v1alpha1_BundleSource_To_v1alpha2_BundleSource(in *BundleSource, ou
7882

7983
if in.InLine != nil {
8084
obj := scope.Meta().Context.(*trustv1alpha2.ClusterBundle)
81-
obj.Spec.InLineCAs = in.InLine
85+
if obj.Spec.InLineCAs == nil {
86+
obj.Spec.InLineCAs = in.InLine
87+
} else {
88+
// The following logic is not pretty, but is required as we allow multiple inline sources
89+
// in the Bundle sources array.
90+
// It breaks the round-trippable conversion Bundle->ClusterBundle->Bundle,
91+
// but works for converting Bundle->ClusterBundle, and that's what we need for the migration.
92+
cas := *obj.Spec.InLineCAs
93+
if strings.HasSuffix(cas, "\n") {
94+
cas += *in.InLine
95+
} else {
96+
cas += "\n" + *in.InLine
97+
}
98+
obj.Spec.InLineCAs = &cas
99+
}
82100
}
83101
if in.UseDefaultCAs != nil {
84102
obj := scope.Meta().Context.(*trustv1alpha2.ClusterBundle)
@@ -122,7 +140,7 @@ func Convert_v1alpha1_BundleTarget_To_v1alpha2_BundleTarget(in *BundleTarget, ou
122140
if obj.Annotations == nil {
123141
obj.Annotations = map[string]string{}
124142
}
125-
obj.Annotations[annotationKeyJKSKey] = targetKV.Key
143+
obj.Annotations[AnnotationKeyJKSKey] = targetKV.Key
126144
}
127145
if in.AdditionalFormats.PKCS12 != nil {
128146
targetKV := trustv1alpha2.TargetKeyValue{
@@ -243,7 +261,7 @@ func Convert_v1alpha2_BundleTarget_To_v1alpha1_BundleTarget(in *trustv1alpha2.Bu
243261
var pkcs12 *PKCS12
244262
for _, tkv := range targetKeyValues {
245263
if tkv.Format == trustv1alpha2.BundleFormatPKCS12 {
246-
if k, ok := obj.Annotations[annotationKeyJKSKey]; ok && k == tkv.Key {
264+
if k, ok := obj.Annotations[AnnotationKeyJKSKey]; ok && k == tkv.Key {
247265
jks = &JKS{}
248266
jks.Key = tkv.Key
249267
jks.Password = tkv.PKCS12.Password
@@ -269,7 +287,7 @@ func Convert_v1alpha2_BundleTarget_To_v1alpha1_BundleTarget(in *trustv1alpha2.Bu
269287
}
270288
}
271289

272-
delete(obj.Annotations, annotationKeyJKSKey)
290+
delete(obj.Annotations, AnnotationKeyJKSKey)
273291
if len(obj.Annotations) == 0 {
274292
obj.Annotations = nil
275293
}

pkg/apis/trust/v1alpha1/conversion_test.go

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,52 @@ import (
2121
"slices"
2222
"testing"
2323

24+
"github.com/stretchr/testify/assert"
2425
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
2526
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
27+
"k8s.io/utils/ptr"
2628
"sigs.k8s.io/randfill"
2729

28-
trustv1alpha2 "github.com/cert-manager/trust-manager/pkg/apis/trustmanager/v1alpha2"
30+
trustmanagerapi "github.com/cert-manager/trust-manager/pkg/apis/trustmanager/v1alpha2"
2931
utilconversion "github.com/cert-manager/trust-manager/pkg/util/conversion"
32+
"github.com/cert-manager/trust-manager/test/dummy"
3033
)
3134

35+
func TestBundle_ConvertTo(t *testing.T) {
36+
tests := map[string]struct {
37+
src Bundle
38+
exp trustmanagerapi.ClusterBundle
39+
}{
40+
"multiple inline Bundle sources should be concatenated in ClusterBundle inLineCAs": {
41+
src: Bundle{
42+
Spec: BundleSpec{
43+
Sources: []BundleSource{
44+
{InLine: ptr.To(dummy.TestCertificate1)},
45+
{InLine: ptr.To(dummy.TestCertificate2)},
46+
},
47+
},
48+
},
49+
exp: trustmanagerapi.ClusterBundle{
50+
Spec: trustmanagerapi.BundleSpec{
51+
InLineCAs: ptr.To(dummy.JoinCerts(dummy.TestCertificate1, dummy.TestCertificate2)),
52+
},
53+
},
54+
},
55+
}
56+
57+
for name, tt := range tests {
58+
t.Run(name, func(t *testing.T) {
59+
dst := trustmanagerapi.ClusterBundle{}
60+
err := tt.src.ConvertTo(&dst)
61+
assert.NoError(t, err)
62+
assert.Equal(t, tt.exp, dst)
63+
})
64+
}
65+
}
66+
3267
func TestFuzzyConversion(t *testing.T) {
3368
t.Run("for Bundle", utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{
34-
Hub: &trustv1alpha2.ClusterBundle{},
69+
Hub: &trustmanagerapi.ClusterBundle{},
3570
Spoke: &Bundle{},
3671
FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzFuncs},
3772
}))
@@ -107,23 +142,23 @@ func spokeBundleTargetFuzzer(obj *BundleTarget, c randfill.Continue) {
107142
}
108143
}
109144

110-
func hubBundleSourceFuzzer(obj *trustv1alpha2.BundleSource, c randfill.Continue) {
145+
func hubBundleSourceFuzzer(obj *trustmanagerapi.BundleSource, c randfill.Continue) {
111146
c.FillNoCustom(obj)
112147

113148
// We only allow known kinds, so must normalize the source kind
114-
kindSet := []string{trustv1alpha2.ConfigMapKind, trustv1alpha2.SecretKind}
149+
kindSet := []string{trustmanagerapi.ConfigMapKind, trustmanagerapi.SecretKind}
115150
obj.Kind = kindSet[rand.Intn(len(kindSet))] //nolint:gosec
116151
}
117152

118-
func hubBundleTargetFuzzer(obj *trustv1alpha2.BundleTarget, c randfill.Continue) {
153+
func hubBundleTargetFuzzer(obj *trustmanagerapi.BundleTarget, c randfill.Continue) {
119154
c.FillNoCustom(obj)
120155

121-
normalizeTarget := func(target *trustv1alpha2.KeyValueTarget) *trustv1alpha2.KeyValueTarget {
156+
normalizeTarget := func(target *trustmanagerapi.KeyValueTarget) *trustmanagerapi.KeyValueTarget {
122157
if target == nil {
123158
return nil
124159
}
125160

126-
target.Data = slices.DeleteFunc(target.Data, func(tkv trustv1alpha2.TargetKeyValue) bool {
161+
target.Data = slices.DeleteFunc(target.Data, func(tkv trustmanagerapi.TargetKeyValue) bool {
127162
if tkv.Key == "" {
128163
// Key is a mandatory field
129164
return true
@@ -136,7 +171,7 @@ func hubBundleTargetFuzzer(obj *trustv1alpha2.BundleTarget, c randfill.Continue)
136171

137172
switch {
138173
case tkv.Password != nil:
139-
tkv.Format = trustv1alpha2.BundleFormatPKCS12
174+
tkv.Format = trustmanagerapi.BundleFormatPKCS12
140175
default:
141176
tkv.Format = ""
142177
tkv.Profile = ""

pkg/bundle/controller/bundle_controller.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ func (r *BundleReconciler) applyClusterBundle(ctx context.Context, bundle *trust
100100
return fmt.Errorf("failed to set ClusterBundle controller reference: %w", err)
101101
}
102102

103+
clusterBundle.APIVersion = "trust-manager.io/v1alpha2"
104+
clusterBundle.Kind = "ClusterBundle"
103105
encodedPatch, err := json.Marshal(clusterBundle)
104106
if err != nil {
105107
return fmt.Errorf("failed to marshal ClusterBundle patch: %w", err)
@@ -144,9 +146,10 @@ func convertBundleToClusterBundle(bundle *trustapi.Bundle) (*trustmanagerapi.Clu
144146
}
145147

146148
clusterBundle := &trustmanagerapi.ClusterBundle{}
147-
clusterBundle.APIVersion = "trust-manager.io/v1alpha2"
148-
clusterBundle.Kind = "ClusterBundle"
149-
clusterBundle.Name = bundle.Name
149+
clusterBundle.Name = cb.Name
150+
if jksKey, ok := cb.Annotations[trustapi.AnnotationKeyJKSKey]; ok {
151+
clusterBundle.Annotations = map[string]string{trustapi.AnnotationKeyJKSKey: jksKey}
152+
}
150153
clusterBundle.Spec = cb.Spec
151154
return clusterBundle, nil
152155
}

test/integration/clusterbundle/migration_test.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,18 @@ var _ = Describe("ClusterBundle Migration", func() {
5353
bundle = &trustapi.Bundle{}
5454
bundle.GenerateName = "migration-"
5555
bundle.Spec.Sources = []trustapi.BundleSource{{InLine: ptr.To(dummy.TestCertificate4)}}
56+
bundle.Spec.Target = trustapi.BundleTarget{
57+
ConfigMap: &trustapi.TargetTemplate{
58+
Key: "ca.crt",
59+
},
60+
AdditionalFormats: &trustapi.AdditionalFormats{
61+
JKS: &trustapi.JKS{
62+
KeySelector: trustapi.KeySelector{
63+
Key: "ca.jks",
64+
},
65+
},
66+
},
67+
}
5668

5769
clusterBundle = &trustmanagerapi.ClusterBundle{}
5870

@@ -72,6 +84,22 @@ var _ = Describe("ClusterBundle Migration", func() {
7284

7385
Expect(cl.Get(ctx, client.ObjectKeyFromObject(bundle), clusterBundle)).To(Succeed())
7486
Expect(clusterBundle.Spec.InLineCAs).To(Equal(ptr.To(dummy.TestCertificate4)))
87+
By("Ensuring additional JKS target is converted correctly with annotation", func() {
88+
Expect(clusterBundle.Spec.Target.ConfigMap).To(Not(BeNil()))
89+
Expect(clusterBundle.Spec.Target.ConfigMap.Data).To(ConsistOf(
90+
trustmanagerapi.TargetKeyValue{
91+
Key: "ca.crt",
92+
},
93+
trustmanagerapi.TargetKeyValue{
94+
Key: "ca.jks",
95+
Format: trustmanagerapi.BundleFormatPKCS12,
96+
PKCS12: trustmanagerapi.PKCS12{
97+
Password: ptr.To(trustapi.DefaultJKSPassword),
98+
},
99+
},
100+
))
101+
Expect(clusterBundle.Annotations).To(HaveKeyWithValue(trustapi.AnnotationKeyJKSKey, "ca.jks"))
102+
})
75103
Expect(clusterBundle.OwnerReferences).To(Equal([]metav1.OwnerReference{{
76104
APIVersion: "trust.cert-manager.io/v1alpha1",
77105
Kind: "Bundle",

0 commit comments

Comments
 (0)