Skip to content

Commit 7d04196

Browse files
authored
Drop mappings (vmware-tanzu#134)
The functionality enabled by mappings can/will be replaced with dedicated resources that can decorate a secret exposing the ProvisionedService duck-type which can be consumed by a ServiceBinding. Custom type and provider fields are now managed with projected volumes and field path env vars. Refs servicebinding/spec#154 Signed-off-by: Scott Andrews <[email protected]>
1 parent b600cd1 commit 7d04196

25 files changed

+939
-1294
lines changed

config/300-servicebinding.yaml

-20
Original file line numberDiff line numberDiff line change
@@ -142,26 +142,6 @@ spec:
142142
- name
143143
type: object
144144
type: array
145-
mappings:
146-
description: Mappings is the collection of mappings from existing
147-
Secret entries to new Secret entries
148-
items:
149-
description: ServiceBindingMapping defines a mapping from the existing
150-
collection of Secret values to a new Secret entry.
151-
properties:
152-
name:
153-
description: Name is the name of the mapped Secret entry
154-
type: string
155-
value:
156-
description: Value is the value of the new Secret entry. Contents
157-
may be a Go template and refer to the other secret entries
158-
by name.
159-
type: string
160-
required:
161-
- name
162-
- value
163-
type: object
164-
type: array
165145
name:
166146
description: Name is the name of the service as projected into the
167147
application container. Defaults to .metadata.name.

config/300-servicebindingprojection.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ spec:
107107
type: array
108108
name:
109109
type: string
110+
provider:
111+
type: string
112+
type:
113+
type: string
110114
required:
111115
- application
112116
- binding

pkg/apis/labsinternal/v1alpha1/servicebindingprojection_lifecycle.go

+100-10
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"context"
1010
"crypto/sha1"
1111
"fmt"
12+
"regexp"
1213
"sort"
1314
"strings"
1415

@@ -57,19 +58,64 @@ func (b *ServiceBindingProjection) Do(ctx context.Context, ps *duckv1.WithPod) {
5758
b.Undo(ctx, ps)
5859

5960
injectedSecrets, injectedVolumes := b.injectedValues(ps)
61+
key := b.annotationKey()
6062

6163
sb := b.Spec.Binding
6264

6365
volume := corev1.Volume{
6466
Name: fmt.Sprintf("%s%x", bindingVolumePrefix, sha1.Sum([]byte(sb.Name))),
6567
VolumeSource: corev1.VolumeSource{
66-
Secret: &corev1.SecretVolumeSource{
67-
SecretName: sb.Name,
68+
Projected: &corev1.ProjectedVolumeSource{
69+
Sources: []corev1.VolumeProjection{
70+
{
71+
Secret: &corev1.SecretProjection{
72+
LocalObjectReference: corev1.LocalObjectReference{
73+
Name: sb.Name,
74+
},
75+
},
76+
},
77+
},
6878
},
6979
},
7080
}
81+
if b.Spec.Type != "" {
82+
typeAnnotation := fmt.Sprintf("%s-type", key)
83+
ps.Spec.Template.Annotations[typeAnnotation] = b.Spec.Type
84+
volume.VolumeSource.Projected.Sources = append(volume.VolumeSource.Projected.Sources,
85+
corev1.VolumeProjection{
86+
DownwardAPI: &corev1.DownwardAPIProjection{
87+
Items: []corev1.DownwardAPIVolumeFile{
88+
{
89+
FieldRef: &corev1.ObjectFieldSelector{
90+
FieldPath: fmt.Sprintf("metadata.annotations['%s']", typeAnnotation),
91+
},
92+
Path: "type",
93+
},
94+
},
95+
},
96+
},
97+
)
98+
}
99+
if b.Spec.Provider != "" {
100+
providerAnnotation := fmt.Sprintf("%s-provider", key)
101+
ps.Spec.Template.Annotations[providerAnnotation] = b.Spec.Provider
102+
volume.VolumeSource.Projected.Sources = append(volume.VolumeSource.Projected.Sources,
103+
corev1.VolumeProjection{
104+
DownwardAPI: &corev1.DownwardAPIProjection{
105+
Items: []corev1.DownwardAPIVolumeFile{
106+
{
107+
FieldRef: &corev1.ObjectFieldSelector{
108+
FieldPath: fmt.Sprintf("metadata.annotations['%s']", providerAnnotation),
109+
},
110+
Path: "provider",
111+
},
112+
},
113+
},
114+
},
115+
)
116+
}
71117
ps.Spec.Template.Spec.Volumes = append(ps.Spec.Template.Spec.Volumes, volume)
72-
injectedSecrets.Insert(volume.Secret.SecretName)
118+
injectedSecrets.Insert(sb.Name)
73119
injectedVolumes.Insert(volume.Name)
74120
sort.SliceStable(ps.Spec.Template.Spec.Volumes, func(i, j int) bool {
75121
iname := ps.Spec.Template.Spec.Volumes[i].Name
@@ -81,7 +127,7 @@ func (b *ServiceBindingProjection) Do(ctx context.Context, ps *duckv1.WithPod) {
81127
return iname < jname
82128
})
83129
// track which secret is injected, so it can be removed when no longer used
84-
ps.Annotations[b.annotationKey()] = volume.Secret.SecretName
130+
ps.Annotations[key] = sb.Name
85131

86132
for i := range ps.Spec.Template.Spec.InitContainers {
87133
c := &ps.Spec.Template.Spec.InitContainers[i]
@@ -98,6 +144,7 @@ func (b *ServiceBindingProjection) Do(ctx context.Context, ps *duckv1.WithPod) {
98144
}
99145

100146
func (b *ServiceBindingProjection) doContainer(ctx context.Context, ps *duckv1.WithPod, c *corev1.Container, bindingVolume, secretName string, allInjectedVolumes, allInjectedSecrets sets.String) {
147+
key := b.annotationKey()
101148
mountPath := ""
102149
// lookup predefined mount path
103150
for _, e := range c.Env {
@@ -133,6 +180,30 @@ func (b *ServiceBindingProjection) doContainer(ctx context.Context, ps *duckv1.W
133180

134181
if len(b.Spec.Env) != 0 {
135182
for _, e := range b.Spec.Env {
183+
if e.Key == "type" && b.Spec.Type != "" {
184+
typeAnnotation := fmt.Sprintf("%s-type", key)
185+
c.Env = append(c.Env, corev1.EnvVar{
186+
Name: e.Name,
187+
ValueFrom: &corev1.EnvVarSource{
188+
FieldRef: &corev1.ObjectFieldSelector{
189+
FieldPath: fmt.Sprintf("metadata.annotations['%s']", typeAnnotation),
190+
},
191+
},
192+
})
193+
continue
194+
}
195+
if e.Key == "provider" && b.Spec.Provider != "" {
196+
providerAnnotation := fmt.Sprintf("%s-provider", key)
197+
c.Env = append(c.Env, corev1.EnvVar{
198+
Name: e.Name,
199+
ValueFrom: &corev1.EnvVarSource{
200+
FieldRef: &corev1.ObjectFieldSelector{
201+
FieldPath: fmt.Sprintf("metadata.annotations['%s']", providerAnnotation),
202+
},
203+
},
204+
})
205+
continue
206+
}
136207
c.Env = append(c.Env, corev1.EnvVar{
137208
Name: e.Name,
138209
ValueFrom: &corev1.EnvVarSource{
@@ -149,9 +220,7 @@ func (b *ServiceBindingProjection) doContainer(ctx context.Context, ps *duckv1.W
149220
iv := c.Env[i]
150221
jv := c.Env[j]
151222
// only sort injected env
152-
if iv.ValueFrom == nil || iv.ValueFrom.SecretKeyRef == nil ||
153-
jv.ValueFrom == nil || jv.ValueFrom.SecretKeyRef == nil ||
154-
!allInjectedSecrets.HasAll(iv.ValueFrom.SecretKeyRef.Name, jv.ValueFrom.SecretKeyRef.Name) {
223+
if !b.isInjectedEnv(iv, allInjectedSecrets) || !b.isInjectedEnv(jv, allInjectedSecrets) {
155224
return false
156225
}
157226
return iv.Name < jv.Name
@@ -183,15 +252,22 @@ func (b *ServiceBindingProjection) Undo(ctx context.Context, ps *duckv1.WithPod)
183252
if ps.Annotations == nil {
184253
ps.Annotations = map[string]string{}
185254
}
255+
if ps.Spec.Template.Annotations == nil {
256+
ps.Spec.Template.Annotations = map[string]string{}
257+
}
186258

187259
key := b.annotationKey()
188260
removeSecrets := sets.NewString(ps.Annotations[key], b.Spec.Binding.Name)
189261
removeVolumes := sets.NewString()
190262
delete(ps.Annotations, key)
263+
delete(ps.Spec.Template.Annotations, fmt.Sprintf("%s-type", key))
264+
delete(ps.Spec.Template.Annotations, fmt.Sprintf("%s-provider", key))
191265

192266
preservedVolumes := []corev1.Volume{}
193267
for _, v := range ps.Spec.Template.Spec.Volumes {
194-
if v.Secret != nil && removeSecrets.Has(v.Secret.SecretName) {
268+
if v.Projected != nil && len(v.Projected.Sources) > 0 &&
269+
v.Projected.Sources[0].Secret != nil &&
270+
removeSecrets.Has(v.Projected.Sources[0].Secret.Name) {
195271
removeVolumes.Insert(v.Name)
196272
continue
197273
}
@@ -218,7 +294,7 @@ func (b *ServiceBindingProjection) undoContainer(ctx context.Context, ps *duckv1
218294

219295
preservedEnv := []corev1.EnvVar{}
220296
for _, e := range c.Env {
221-
if e.ValueFrom == nil || e.ValueFrom.SecretKeyRef == nil || !removeSecrets.Has(e.ValueFrom.SecretKeyRef.Name) {
297+
if !b.isInjectedEnv(e, removeSecrets) {
222298
preservedEnv = append(preservedEnv, e)
223299
}
224300
}
@@ -238,13 +314,27 @@ func (b *ServiceBindingProjection) injectedValues(ps *duckv1.WithPod) (sets.Stri
238314
}
239315
}
240316
for _, v := range ps.Spec.Template.Spec.Volumes {
241-
if v.Secret != nil && secrets.Has(v.Secret.SecretName) {
317+
if v.Projected != nil && len(v.Projected.Sources) > 0 &&
318+
v.Projected.Sources[0].Secret != nil &&
319+
secrets.Has(v.Projected.Sources[0].Secret.Name) {
242320
volumes.Insert(v.Name)
243321
}
244322
}
245323
return secrets, volumes
246324
}
247325

326+
var fieldPathAnnotationRe = regexp.MustCompile(fmt.Sprintf(`^%s[0-9a-f]+%s(type|provider)%s$`, regexp.QuoteMeta(fmt.Sprintf("metadata.annotations['%s-", ServiceBindingProjectionAnnotationKey)), "-", "']"))
327+
328+
func (b *ServiceBindingProjection) isInjectedEnv(e corev1.EnvVar, allInjectedSecrets sets.String) bool {
329+
if e.ValueFrom != nil && e.ValueFrom.SecretKeyRef != nil && allInjectedSecrets.Has(e.ValueFrom.SecretKeyRef.Name) {
330+
return true
331+
}
332+
if e.ValueFrom != nil && e.ValueFrom.FieldRef != nil && fieldPathAnnotationRe.MatchString(e.ValueFrom.FieldRef.FieldPath) {
333+
return true
334+
}
335+
return false
336+
}
337+
248338
func (bs *ServiceBindingProjectionStatus) InitializeConditions() {
249339
sbpCondSet.Manage(bs).InitializeConditions()
250340
}

0 commit comments

Comments
 (0)