Repository navigation
Expand file tree
/
Copy pathextension.go
More file actions
131 lines (113 loc) · 4.26 KB
/
Copy pathextension.go
File metadata and controls
131 lines (113 loc) · 4.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package proxy
import (
"context"
"maps"
"strings"
"github.com/go-logr/logr"
"github.com/operator-framework/helm-operator-plugins/pkg/extensions"
"github.com/pkg/errors"
commonLabels "github.com/stackrox/rox/operator/internal/common/labels"
"github.com/stackrox/rox/operator/internal/utils"
"github.com/stackrox/rox/pkg/k8sutil"
corev1 "k8s.io/api/core/v1"
apiErrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
ctrlClient "sigs.k8s.io/controller-runtime/pkg/client"
)
// ReconcileProxySecretExtension returns a reconcile extension that ensures that a proxy secret exists.
func ReconcileProxySecretExtension(client ctrlClient.Client, direct ctrlClient.Reader, proxyEnv map[string]string) extensions.ReconcileExtension {
return func(ctx context.Context, obj *unstructured.Unstructured, statusUpdater func(statusFunc extensions.UpdateStatusFunc), _ logr.Logger) error {
if obj.GetDeletionTimestamp() != nil {
return deleteProxyEnvSecret(ctx, obj, client, direct)
}
return reconcileProxySecret(ctx, obj, proxyEnv, statusUpdater, client, direct)
}
}
func getProxyEnvSecretName(obj k8sutil.Object) string {
return strings.ToLower(obj.GetObjectKind().GroupVersionKind().Kind + "-" + obj.GetName() + "-proxy-env")
}
func reconcileProxySecret(ctx context.Context, obj k8sutil.Object, proxyEnvVars map[string]string, statusUpdater func(extensions.UpdateStatusFunc), client ctrlClient.Client, direct ctrlClient.Reader) error {
var err error
if len(proxyEnvVars) == 0 {
err = deleteProxyEnvSecret(ctx, obj, client, direct)
} else {
err = updateProxyEnvSecret(ctx, obj, client, direct, proxyEnvVars)
}
if err != nil {
statusUpdater(utils.UpdateStatusCondition(
ProxyConfigFailedStatusType,
metav1.ConditionTrue,
SecretReconcileErrorReason,
err.Error()))
return nil // do not block reconciliation because of the proxy config
}
var reason, msg string
if len(proxyEnvVars) == 0 {
reason = NoProxyConfigReason
msg = "No proxy configuration is desired"
} else {
reason = ProxyConfigAppliedReason
msg = "Proxy configuration has been applied successfully"
}
statusUpdater(utils.UpdateStatusCondition(
ProxyConfigFailedStatusType,
metav1.ConditionFalse,
reason,
msg))
return nil
}
func deleteProxyEnvSecret(ctx context.Context, obj k8sutil.Object, client ctrlClient.Client, direct ctrlClient.Reader) error {
existingSecret := &corev1.Secret{}
key := ctrlClient.ObjectKey{Namespace: obj.GetNamespace(), Name: getProxyEnvSecretName(obj)}
if err := utils.GetWithFallbackToUncached(ctx, client, direct, key, existingSecret); err != nil {
if apiErrors.IsNotFound(err) {
return nil
}
return errors.Wrap(err, "error checking for proxy env secret")
}
if !metav1.IsControlledBy(existingSecret, obj) {
return nil // don't touch a secret we don't own
}
return utils.DeleteExact(ctx, client, existingSecret)
}
func updateProxyEnvSecret(ctx context.Context, obj k8sutil.Object, client ctrlClient.Client, direct ctrlClient.Reader, proxyEnvVars map[string]string) error {
secretName := getProxyEnvSecretName(obj)
secret := &corev1.Secret{}
key := ctrlClient.ObjectKey{Namespace: obj.GetNamespace(), Name: secretName}
if err := utils.GetWithFallbackToUncached(ctx, client, direct, key, secret); err != nil {
if !apiErrors.IsNotFound(err) {
return err
}
secret = &corev1.Secret{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "Secret",
},
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: obj.GetNamespace(),
Labels: commonLabels.DefaultLabels(),
OwnerReferences: []metav1.OwnerReference{
*metav1.NewControllerRef(obj, obj.GetObjectKind().GroupVersionKind()),
},
},
}
} else if !metav1.IsControlledBy(secret, obj) {
return errors.Errorf("secret %s exists, but is not controlled by %s", secretName, obj.GetName())
}
strData := make(map[string]string, len(secret.Data))
for k, v := range secret.Data {
strData[k] = string(v)
}
if maps.Equal(strData, proxyEnvVars) {
return nil
}
secret.Data = nil
secret.StringData = proxyEnvVars
if secret.ResourceVersion == "" {
return client.Create(ctx, secret)
}
secret.Labels, _ = commonLabels.WithDefaults(secret.Labels)
return client.Update(ctx, secret)
}