Skip to content

Commit 5d9094f

Browse files
author
Drew Wells
authored
DEVOPS-30046 DEVOPS-30239 dsnexec conversion injects dbproxy (#381)
A bug in the conversion webhook added dbproxy mutating labels when only dsnexec was requested. This would cause issues if the pod could not handle dbproxy listening on port 5432.
1 parent a9d8783 commit 5d9094f

File tree

5 files changed

+95
-46
lines changed

5 files changed

+95
-46
lines changed

internal/webhook/conversion.go

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,13 @@ import (
1717
)
1818

1919
var (
20+
// DSNExec annotations
2021
DeprecatedAnnotationDSNExecConfig = "infoblox.com/dsnexec-config-secret"
2122
DeprecatedAnnotationRemoteDBDSN = "infoblox.com/remote-db-dsn-secret"
22-
DeprecatedAnnotationDBSecretPath = "infoblox.com/db-secret-path"
23-
DeprecatedAnnotationMessages = "persistance.atlas.infoblox.com/deprecation-messages"
23+
// DBProxy annotations
24+
DeprecatedAnnotationDBSecretPath = "infoblox.com/db-secret-path"
25+
26+
DeprecatedAnnotationMessages = "persistance.atlas.infoblox.com/deprecation-messages"
2427
)
2528

2629
// +kubebuilder:webhook:path=/convert-deprecated-pod,mutating=true,failurePolicy=fail,groups="",resources=pods,verbs=create;update,versions=v1,name=podconversion.persistance.atlas.infoblox.com,sideEffects=None,timeoutSeconds=10,admissionReviewVersions=v1
@@ -94,10 +97,18 @@ func (p *podConverter) Handle(ctx context.Context, req admission.Request) admiss
9497
}
9598

9699
// Check if any of the deprecated annotations are present
100+
// dsnexec
97101
dsnExecConfigSecret := pod.Annotations[DeprecatedAnnotationDSNExecConfig]
98102
remoteDBDSNSecret := pod.Annotations[DeprecatedAnnotationRemoteDBDSN]
103+
// dbproxy
99104
dbSecretPath := pod.Annotations[DeprecatedAnnotationDBSecretPath]
100105

106+
if pod.Labels[LabelCheckExec] == "enabled" || pod.Labels[LabelCheckProxy] == "enabled" {
107+
// This would log on every pod creation in the cluster
108+
// log.V(1).Info("Skipped conversion, already converted", "uid", req.UID)
109+
return admission.Allowed("Skipped conversion, already converted")
110+
}
111+
101112
if dsnExecConfigSecret == "" && remoteDBDSNSecret == "" && dbSecretPath == "" {
102113
// This would log on every pod creation in the cluster
103114
// log.V(1).Info("Skipped conversion, no deprecated annotations found", "uid", req.UID)
@@ -112,7 +123,7 @@ func (p *podConverter) Handle(ctx context.Context, req admission.Request) admiss
112123
if err != nil {
113124
return admission.Errored(http.StatusInternalServerError, err)
114125
}
115-
log.Info("converted_pod")
126+
log.Info("deprecated_pod_annotations_found")
116127
return admission.PatchResponseFromRaw(req.Object.Raw, bs)
117128
}
118129

@@ -139,41 +150,45 @@ func convertPod(ctx context.Context, reader client.Reader, class string, pod *co
139150
secretName = dbSecretPath
140151
}
141152

142-
log = log.WithValues("secret", secretName)
153+
log = log.WithValues("secret", secretName).WithValues("annotations", pod.Annotations).WithValues("labels", pod.Labels)
154+
155+
log.Info("converting_pod")
143156

144157
// db-secret-path has a key in it, so remove the key
145158
parts := strings.Split(secretName, "/")
146159
if len(parts) > 1 {
147160
secretName = parts[0]
148161
}
149162

150-
labelConfigExec := pod.Labels[LabelConfigExec]
151-
if labelConfigExec == "" && dsnExecConfigSecret != "" {
152-
pod.Labels[LabelConfigExec] = pod.Annotations[DeprecatedAnnotationDSNExecConfig]
153-
pod.Labels[LabelCheckExec] = "enabled"
154-
deprecationMsgs = append(deprecationMsgs, fmt.Sprintf(`Label "%s" replaces annotation "%s"`, LabelConfigExec, DeprecatedAnnotationDSNExecConfig))
163+
var claimName string
164+
var err error
165+
if claimName, err = getClaimName(ctx, reader, pod.GetNamespace(), secretName); err != nil {
166+
log.Error(err, "unable to find claim")
167+
return err
155168
}
156169

157-
// Process claims label
158-
if pod.Labels[LabelClaim] == "" {
170+
// dsnexec
171+
if dsnExecConfigSecret != "" && remoteDBDSNSecret != "" {
172+
pod.Labels[LabelClaim] = claimName
173+
pod.Labels[LabelClass] = class
174+
pod.Labels[LabelConfigExec] = dsnExecConfigSecret
175+
pod.Labels[LabelCheckExec] = "enabled"
159176

160-
if pod.Annotations[DeprecatedAnnotationRemoteDBDSN] != "" {
161-
deprecationMsgs = append(deprecationMsgs, fmt.Sprintf(`Label "%s" replaces annotation "%s"`, LabelClaim, DeprecatedAnnotationRemoteDBDSN))
162-
}
163-
if pod.Annotations[DeprecatedAnnotationDBSecretPath] != "" {
164-
deprecationMsgs = append(deprecationMsgs, fmt.Sprintf(`Label "%s" replaces annotation "%s"`, LabelClaim, DeprecatedAnnotationDBSecretPath))
165-
}
177+
deprecationMsgs = append(deprecationMsgs, fmt.Sprintf(`Use label "%s", annotation "%s" is deprecated`, LabelConfigExec, DeprecatedAnnotationDSNExecConfig))
166178

167-
var claimName string
168-
var err error
169-
if claimName, err = getClaimName(ctx, reader, pod.GetNamespace(), secretName); err != nil {
170-
log.Error(err, "unable to find claim")
171-
return err
179+
if pod.Annotations[DeprecatedAnnotationRemoteDBDSN] != "" {
180+
deprecationMsgs = append(deprecationMsgs, fmt.Sprintf(`Use label "%s", annotation "%s" is deprecated`, LabelClaim, DeprecatedAnnotationRemoteDBDSN))
172181
}
182+
}
173183

184+
// dbproxy
185+
if dbSecretPath != "" {
174186
pod.Labels[LabelClaim] = claimName
175187
pod.Labels[LabelClass] = class
176188
pod.Labels[LabelCheckProxy] = "enabled"
189+
190+
deprecationMsgs = append(deprecationMsgs, fmt.Sprintf(`Label "%s" replaces annotation "%s"`, LabelClaim, DeprecatedAnnotationDBSecretPath))
191+
177192
}
178193

179194
// Remove deprecated annotations

internal/webhook/conversion_test.go

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -96,30 +96,33 @@ var _ = Describe("annotation conversions", func() {
9696

9797
It("should convert deprecated pod", func() {
9898

99-
By("Check dbproxy pod is mutated")
99+
By("Check deprecated dbproxy annotations are converted to labels")
100100
name := "deprecated-dbproxy"
101101
pod := makeConvertedPod(name, class, dbcSecretName, "")
102102
Expect(pod.Annotations).To(HaveKey(DeprecatedAnnotationMessages))
103103
Expect(pod.Labels).To(HaveKeyWithValue(LabelClaim, dbcName))
104104
Expect(pod.Labels).To(HaveKeyWithValue(LabelCheckProxy, "enabled"))
105105
Expect(pod.Labels).To(HaveKeyWithValue(LabelClass, class))
106+
Expect(pod.Labels).ToNot(HaveKey(LabelConfigExec))
106107

107-
By("Check dsnexec pod is converted")
108+
By("Check dsnexec annotations are converted to labels")
108109
name = "deprecated-dsnexec"
109110
pod = makeConvertedPod(name, class, dbcSecretName, configSecretName)
110111
Expect(pod.Annotations).To(HaveKey(DeprecatedAnnotationMessages))
111112
Expect(pod.Labels).To(HaveKeyWithValue(LabelClaim, dbcName))
112113
Expect(pod.Labels).To(HaveKeyWithValue(LabelConfigExec, configSecretName))
113114
Expect(pod.Labels).To(HaveKeyWithValue(LabelCheckExec, "enabled"))
114115
Expect(pod.Labels).To(HaveKeyWithValue(LabelClass, class))
116+
Expect(pod.Labels).ToNot(HaveKey(LabelCheckProxy))
115117

116-
By("Check dbproxy dsnexec combo pod is converted")
118+
By("Check dbproxy dsnexec combo annotations are converted to labels")
117119
name = "deprecated-both"
118120
pod = makeConvertedPod(name, class, dbcSecretName, configSecretName)
119121
Expect(pod.Annotations).To(HaveKey(DeprecatedAnnotationMessages))
120122
Expect(pod.Labels).To(HaveKeyWithValue(LabelClaim, dbcName))
121123
Expect(pod.Labels).To(HaveKeyWithValue(LabelConfigExec, configSecretName))
122124
Expect(pod.Labels).To(HaveKeyWithValue(LabelCheckProxy, "enabled"))
125+
Expect(pod.Labels).To(HaveKeyWithValue(LabelCheckExec, "enabled"))
123126
Expect(pod.Labels).To(HaveKeyWithValue(LabelClass, class))
124127

125128
})
@@ -173,31 +176,28 @@ func makeDeprecatedPod(name, secretName, configSecret string) *corev1.Pod {
173176
},
174177
},
175178
}
179+
if pod.Annotations == nil {
180+
pod.Annotations = map[string]string{}
181+
}
182+
if pod.Labels == nil {
183+
pod.Labels = map[string]string{}
184+
}
176185
Expect(secretName).NotTo(BeEmpty())
177-
178186
switch name {
179187
case "deprecated-dbproxy":
180-
pod.Annotations = map[string]string{
181-
DeprecatedAnnotationDBSecretPath: secretName + "/" + "dsn.txt",
182-
}
188+
pod.Annotations[DeprecatedAnnotationDBSecretPath] = secretName + "/" + "dsn.txt"
189+
183190
case "deprecated-both":
184-
pod.Annotations = map[string]string{
185-
DeprecatedAnnotationDBSecretPath: secretName + "/" + "dsn.txt",
186-
}
191+
pod.Annotations[DeprecatedAnnotationDBSecretPath] = secretName + "/" + "dsn.txt"
187192
fallthrough
188193
case "deprecated-dsnexec":
189194
Expect(configSecret).NotTo(BeEmpty())
190-
pod.Annotations = map[string]string{
191-
DeprecatedAnnotationRemoteDBDSN: secretName,
192-
DeprecatedAnnotationDSNExecConfig: configSecret,
193-
}
195+
196+
pod.Annotations[DeprecatedAnnotationRemoteDBDSN] = secretName
197+
pod.Annotations[DeprecatedAnnotationDSNExecConfig] = configSecret
194198
case "deprecated-converted":
195-
pod.Annotations = map[string]string{
196-
DeprecatedAnnotationDBSecretPath: secretName + "/" + "dsn.txt",
197-
}
198-
pod.Labels = map[string]string{
199-
LabelConfigExec: "default-db",
200-
}
199+
pod.Annotations[DeprecatedAnnotationDBSecretPath] = secretName + "/" + "dsn.txt"
200+
pod.Labels[LabelConfigExec] = "default-db"
201201
case "deprecated-none":
202202
}
203203

internal/webhook/defaulter.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,12 +91,12 @@ func (p *podAnnotator) Default(ctx context.Context, obj runtime.Object) error {
9191
}
9292

9393
log := logf.FromContext(ctx).WithName("defaulter").WithValues("pod", nn)
94-
log.Info("processing")
9594

9695
if pod.Labels == nil || len(pod.Labels[LabelClaim]) == 0 {
9796
log.Info("Skipping Pod")
9897
return nil
9998
}
99+
log.Info("processing")
100100

101101
claimName := pod.Labels[LabelClaim]
102102

scripts/check-sidecars.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/bash -x
2+
3+
4+
# Optional namespace argument
5+
namespace_filter=${1:-}
6+
7+
# Determine the kubectl command based on whether a namespace filter is provided
8+
if [[ -n "$namespace_filter" ]]; then
9+
echo "Filtering by namespace: $namespace_filter"
10+
kubectl_command="kubectl -n $namespace_filter get pods -l persistance.atlas.infoblox.com/dbproxy -o=jsonpath='{range .items[*]}{.metadata.namespace} {.metadata.name}{\"\\n\"}{end}'"
11+
else
12+
echo "Checking all namespaces"
13+
kubectl_command="kubectl -A get pods -l persistance.atlas.infoblox.com/dbproxy -o=jsonpath='{range .items[*]}{.metadata.namespace} {.metadata.name}{\"\\n\"}{end}'"
14+
fi
15+
16+
# Get the pods
17+
pods=$(eval "$kubectl_command")
18+
19+
# Iterate over each pod and run the psql command
20+
while read -r namespace pod; do
21+
echo "Processing pod $pod in namespace $namespace"
22+
23+
# Execute the SELECT 1 command and capture output
24+
kubectl -n "$namespace" -c dbproxy exec "$pod" -- sh -c "psql \$(cat /dbproxy/uri_dsn.txt) -c 'SELECT 1'"
25+
kubectl -n "$namespace" -c dbproxy exec "$pod" -- sh -c "cat /run/dbproxy/pgbouncer.ini"
26+
kubectl -n "$namespace" -c dbproxy exec "$pod" -- sh -c "cat /run/dbproxy/userlist.txt"
27+
28+
done <<< "$pods"

scripts/psql-open.sh

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,14 @@ open_psql() {
1919
secret_name=$(kubectl get databaseclaim "$claim_name" -n "$namespace" -o jsonpath='{.spec.secretName}')
2020

2121
if [[ -z "$secret_name" ]]; then
22-
echo "Error: Unable to find secret name for $claim_name in namespace $namespace"
23-
return 1
22+
23+
secret_name=$(kubectl get dbroleclaim "$claim_name" -n "$namespace" -o jsonpath='{.spec.secretName}')
24+
if [[ -z "$secret_name" ]]; then
25+
echo "Error: Unable to find secret name for dbc: $claim_name in namespace $namespace"
26+
echo "Error: Unable to find secret name for dbroleclaim: $claim_name in namespace $namespace"
27+
return 1
28+
fi
29+
2430
fi
2531

2632
# Get the DSN from the secret
@@ -31,7 +37,7 @@ open_psql() {
3137
return 1
3238
fi
3339

34-
printf "DatabaseClaim: %s/%s\n" "$namespace" "$claim_name"
40+
printf "Claim: %s/%s\n" "$namespace" "$claim_name"
3541
# If a psql command is provided, execute it; otherwise, open a psql prompt
3642
if [[ -n "$psql_command" ]]; then
3743
kubectl exec deploy/db-controller -c manager -n db-controller -- psql "$dsn" -c "$psql_command"

0 commit comments

Comments
 (0)