Skip to content

Commit fbdd0a6

Browse files
authored
Add guardian to whisker (#3793)
This commit adds guardian to the whisker deployment, and is only launched if the ManagementClusterConnection CR exists. This adds the ManagementClusterConnection CRD to open source. Guardian might not stay in this deployment (and likely won't), but it's a good temporary place for it alongside goldmane (where the service isn't exposed).
1 parent 3be21fa commit fbdd0a6

File tree

11 files changed

+301
-21
lines changed

11 files changed

+301
-21
lines changed

api/v1/managementclusterconnection_types.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2012,2015-2024 Tigera, Inc. All rights reserved.
1+
// Copyright (c) 2012,2015-2025 Tigera, Inc. All rights reserved.
22
/*
33
44
Licensed under the Apache License, Version 2.0 (the "License");
@@ -93,3 +93,12 @@ type ManagementClusterConnectionStatus struct {
9393
func init() {
9494
SchemeBuilder.Register(&ManagementClusterConnection{}, &ManagementClusterConnectionList{})
9595
}
96+
97+
func (cr *ManagementClusterConnection) FillDefaults() {
98+
if cr.Spec.TLS == nil {
99+
cr.Spec.TLS = &ManagementClusterTLS{}
100+
}
101+
if cr.Spec.TLS.CA == "" {
102+
cr.Spec.TLS.CA = CATypeTigera
103+
}
104+
}

config/calico_versions.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,6 @@ components:
3737
version: master
3838
calico/envoy-ratelimit:
3939
version: master
40+
calico/guardian:
41+
version: master
42+

hack/gen-versions/calico.go.tpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,5 +226,6 @@ var (
226226
ComponentCalicoEnvoyGateway,
227227
ComponentCalicoEnvoyProxy,
228228
ComponentCalicoEnvoyRatelimit,
229+
ComponentCalicoGuardian,
229230
}
230231
)

pkg/components/calico.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,11 @@ var (
166166
Registry: "",
167167
}
168168

169+
ComponentCalicoGuardian = Component{
170+
Version: "master",
171+
Image: "calico/guardian",
172+
Registry: "",
173+
}
169174
ComponentOperatorInit = Component{
170175
Version: version.VERSION,
171176
Image: "tigera/operator",
@@ -196,5 +201,6 @@ var (
196201
ComponentCalicoEnvoyGateway,
197202
ComponentCalicoEnvoyProxy,
198203
ComponentCalicoEnvoyRatelimit,
204+
ComponentCalicoGuardian,
199205
}
200206
)

pkg/components/references.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ func GetReference(c Component, registry, imagePath, imagePrefix string, is *oper
5959
ComponentCalicoCSIRegistrarFIPS,
6060
ComponentCalicoGoldmane,
6161
ComponentCalicoWhisker,
62-
ComponentCalicoWhiskerBackend:
62+
ComponentCalicoWhiskerBackend,
63+
ComponentCalicoGuardian:
64+
6365
registry = CalicoRegistry
6466
case ComponentOperatorInit:
6567
registry = InitRegistry

pkg/controller/installation/core_controller.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1201,6 +1201,14 @@ func (r *ReconcileInstallation) Reconcile(ctx context.Context, request reconcile
12011201
}
12021202

12031203
calicoVersion = components.EnterpriseRelease
1204+
} else {
1205+
cert, err := certificateManager.GetCertificate(r.client, render.VoltronLinseedPublicCert, common.OperatorNamespace())
1206+
if err != nil {
1207+
r.status.SetDegraded(operator.CertificateError, fmt.Sprintf("Failed to retrieve / validate %s", render.VoltronLinseedPublicCert), err, reqLogger)
1208+
return reconcile.Result{}, err
1209+
} else if cert != nil {
1210+
typhaNodeTLS.TrustedBundle.AddCertificates(cert)
1211+
}
12041212
}
12051213

12061214
kubeControllersMetricsPort, err := utils.GetKubeControllerMetricsPort(ctx, r.client)

pkg/controller/utils/utils.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,23 @@ func GetIfExists[E any, ClientObj ClientObjType[E]](ctx context.Context, key cli
474474
return obj, nil
475475
}
476476

477+
type Defaultable[E any, O ClientObjType[E]] interface {
478+
ClientObjType[E]
479+
client.Object
480+
FillDefaults()
481+
DeepCopy() O
482+
}
483+
484+
// ApplyDefaults sets any defaults that haven't been set on the given object and writes it to the k8s server.
485+
func ApplyDefaults[E any, O ClientObjType[E], D Defaultable[E, O]](ctx context.Context, c client.Client, obj D) error {
486+
preDefaultPatchFrom := client.MergeFrom(obj.DeepCopy())
487+
obj.FillDefaults()
488+
489+
// Write the discovered configuration back to the API. This is essentially a poor-man's defaulting, and
490+
// ensures that we don't surprise anyone by changing defaults in a future version of the operator.
491+
return c.Patch(ctx, obj, preDefaultPatchFrom)
492+
}
493+
477494
// GetNonClusterHost finds the NonClusterHost CR in your cluster.
478495
func GetNonClusterHost(ctx context.Context, cli client.Client) (*operatorv1.NonClusterHost, error) {
479496
nonclusterhost := &operatorv1.NonClusterHost{}

pkg/controller/whisker/controller.go

Lines changed: 57 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ import (
1818
"context"
1919
"fmt"
2020

21+
corev1 "k8s.io/api/core/v1"
2122
"k8s.io/apimachinery/pkg/runtime"
23+
"k8s.io/apimachinery/pkg/types"
2224
"sigs.k8s.io/controller-runtime/pkg/client"
2325
"sigs.k8s.io/controller-runtime/pkg/controller"
2426
"sigs.k8s.io/controller-runtime/pkg/handler"
@@ -28,6 +30,7 @@ import (
2830

2931
operatorv1 "github.com/tigera/operator/api/v1"
3032
"github.com/tigera/operator/pkg/common"
33+
"github.com/tigera/operator/pkg/controller/certificatemanager"
3134
"github.com/tigera/operator/pkg/controller/options"
3235
"github.com/tigera/operator/pkg/controller/status"
3336
"github.com/tigera/operator/pkg/controller/utils"
@@ -36,6 +39,7 @@ import (
3639
"github.com/tigera/operator/pkg/render"
3740
"github.com/tigera/operator/pkg/render/monitor"
3841
"github.com/tigera/operator/pkg/render/whisker"
42+
"github.com/tigera/operator/pkg/tls/certificatemanagement"
3943
)
4044

4145
const (
@@ -65,6 +69,7 @@ func Add(mgr manager.Manager, opts options.AddOptions) error {
6569
for _, secretName := range []string{
6670
monitor.PrometheusServerTLSSecretName,
6771
whisker.ManagedClusterConnectionSecretName,
72+
certificatemanagement.CASecretName,
6873
render.ProjectCalicoAPIServerTLSSecretName(operatorv1.TigeraSecureEnterprise),
6974
render.ProjectCalicoAPIServerTLSSecretName(operatorv1.Calico),
7075
} {
@@ -73,11 +78,20 @@ func Add(mgr manager.Manager, opts options.AddOptions) error {
7378
}
7479
}
7580

81+
if err = utils.AddConfigMapWatch(c, certificatemanagement.TrustedCertConfigMapName, common.OperatorNamespace(), &handler.EnqueueRequestForObject{}); err != nil {
82+
return fmt.Errorf("failed to add watch for config map %s/%s: %w", common.OperatorNamespace(), certificatemanagement.TrustedCertConfigMapName, err)
83+
}
84+
7685
err = c.WatchObject(&operatorv1.Whisker{}, &handler.EnqueueRequestForObject{})
7786
if err != nil {
7887
return fmt.Errorf("%s failed to watch primary resource: %w", controllerName, err)
7988
}
8089

90+
err = c.WatchObject(&operatorv1.ManagementClusterConnection{}, &handler.EnqueueRequestForObject{})
91+
if err != nil {
92+
return fmt.Errorf("%s failed to watch management cluster connection resource: %w", controllerName, err)
93+
}
94+
8195
if err = utils.AddInstallationWatch(c); err != nil {
8296
return fmt.Errorf("%s failed to watch Installation resource: %w", controllerName, err)
8397
}
@@ -136,20 +150,19 @@ type Reconciler struct {
136150
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
137151
reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
138152
reqLogger.Info("Reconciling Whisker")
139-
result := reconcile.Result{}
140153

141154
variant, installation, err := utils.GetInstallation(ctx, r.cli)
142155
if err != nil {
143-
return result, err
156+
return reconcile.Result{}, err
144157
}
145158

146159
whiskerCR, err := utils.GetIfExists[operatorv1.Whisker](ctx, utils.DefaultInstanceKey, r.cli)
147160
if err != nil {
148161
r.status.SetDegraded(operatorv1.ResourceReadError, "Error querying Whisker CR", err, reqLogger)
149-
return result, err
162+
return reconcile.Result{}, err
150163
} else if whiskerCR == nil {
151164
r.status.OnCRNotFound()
152-
return result, nil
165+
return reconcile.Result{}, nil
153166
}
154167
r.status.OnCRFound()
155168
// SetMetaData in the TigeraStatus such as observedGenerations.
@@ -158,14 +171,48 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
158171
pullSecrets, err := utils.GetNetworkingPullSecrets(installation, r.cli)
159172
if err != nil {
160173
r.status.SetDegraded(operatorv1.ResourceReadError, "Error retrieving pull secrets", err, reqLogger)
161-
return result, err
174+
return reconcile.Result{}, err
175+
}
176+
177+
var tunnelSecret *corev1.Secret
178+
managementClusterConnection, err := utils.GetIfExists[operatorv1.ManagementClusterConnection](ctx, utils.DefaultTSEEInstanceKey, r.cli)
179+
if err != nil {
180+
r.status.SetDegraded(operatorv1.ResourceReadError, "Error querying ManagementClusterConnection", err, reqLogger)
181+
return reconcile.Result{}, err
182+
} else if managementClusterConnection != nil {
183+
tunnelSecret, err = utils.GetIfExists[corev1.Secret](ctx, types.NamespacedName{Name: render.GuardianSecretName, Namespace: common.OperatorNamespace()}, r.cli)
184+
if err != nil {
185+
return reconcile.Result{}, err
186+
}
187+
188+
if err := utils.ApplyDefaults(ctx, r.cli, managementClusterConnection); err != nil {
189+
r.status.SetDegraded(operatorv1.ResourceUpdateError, err.Error(), err, reqLogger)
190+
return reconcile.Result{}, err
191+
}
192+
193+
log.V(2).Info("Loaded ManagementClusterConnection config", managementClusterConnection)
194+
}
195+
196+
certificateManager, err := certificatemanager.Create(r.cli, installation, r.clusterDomain, common.OperatorNamespace())
197+
if err != nil {
198+
r.status.SetDegraded(operatorv1.ResourceCreateError, "Unable to create the certificate manager", err, reqLogger)
199+
return reconcile.Result{}, err
200+
}
201+
202+
trustedCertBundle, err := certificateManager.LoadTrustedBundle(ctx, r.cli, whisker.WhiskerNamespace)
203+
if err != nil {
204+
r.status.SetDegraded(operatorv1.ResourceReadError, "Error loading trusted cert bundle", err, reqLogger)
205+
return reconcile.Result{}, err
162206
}
163207

164208
ch := utils.NewComponentHandler(log, r.cli, r.scheme, whiskerCR)
165209
cfg := &whisker.Configuration{
166-
PullSecrets: pullSecrets,
167-
OpenShift: r.provider.IsOpenShift(),
168-
Installation: installation,
210+
PullSecrets: pullSecrets,
211+
OpenShift: r.provider.IsOpenShift(),
212+
Installation: installation,
213+
TunnelSecret: tunnelSecret,
214+
TrustedCertBundle: trustedCertBundle,
215+
ManagementClusterConnection: managementClusterConnection,
169216
}
170217

171218
components := []render.Component{whisker.Whisker(cfg)}
@@ -177,12 +224,12 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
177224
for _, component := range components {
178225
if err := ch.CreateOrUpdateOrDelete(ctx, component, r.status); err != nil {
179226
r.status.SetDegraded(operatorv1.ResourceUpdateError, "Error creating / updating resource", err, reqLogger)
180-
return result, err
227+
return reconcile.Result{}, err
181228
}
182229
}
183230

184231
r.status.ReadyToMonitor()
185232
r.status.ClearDegraded()
186233

187-
return result, nil
234+
return reconcile.Result{}, nil
188235
}

pkg/crds/crds.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ var (
5353
func init() {
5454
yamlDelimRe = regexp.MustCompile(`\n---`)
5555

56-
calicoCRDNames := []string{"installation", "apiserver", "imageset", "tigerastatus", "whisker"}
56+
calicoCRDNames := []string{"installation", "apiserver", "imageset", "tigerastatus", "whisker", "managementclusterconnection"}
5757
calicoOprtrCRDsRe = regexp.MustCompile(fmt.Sprintf("(%s)", strings.Join(calicoCRDNames, "|")))
5858
}
5959

0 commit comments

Comments
 (0)