Skip to content

Commit

Permalink
Add guardian to whisker
Browse files Browse the repository at this point in the history
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).
  • Loading branch information
Brian-McM committed Feb 28, 2025
1 parent 3be21fa commit 5d95cd4
Show file tree
Hide file tree
Showing 11 changed files with 301 additions and 21 deletions.
11 changes: 10 additions & 1 deletion api/v1/managementclusterconnection_types.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2012,2015-2024 Tigera, Inc. All rights reserved.
// Copyright (c) 2012,2015-2025 Tigera, Inc. All rights reserved.
/*
Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -93,3 +93,12 @@ type ManagementClusterConnectionStatus struct {
func init() {
SchemeBuilder.Register(&ManagementClusterConnection{}, &ManagementClusterConnectionList{})
}

func (cr *ManagementClusterConnection) FillDefaults() {
if cr.Spec.TLS == nil {
cr.Spec.TLS = &ManagementClusterTLS{}
}
if cr.Spec.TLS.CA == "" {
cr.Spec.TLS.CA = CATypeTigera
}
}
3 changes: 3 additions & 0 deletions config/calico_versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ components:
version: master
calico/envoy-ratelimit:
version: master
calico/guardian:
version: master

1 change: 1 addition & 0 deletions hack/gen-versions/calico.go.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -226,5 +226,6 @@ var (
ComponentCalicoEnvoyGateway,
ComponentCalicoEnvoyProxy,
ComponentCalicoEnvoyRatelimit,
ComponentCalicoGuardian,
}
)
6 changes: 6 additions & 0 deletions pkg/components/calico.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ var (
Registry: "",
}

ComponentCalicoGuardian = Component{
Version: "master",
Image: "calico/guardian",
Registry: "",
}
ComponentOperatorInit = Component{
Version: version.VERSION,
Image: "tigera/operator",
Expand Down Expand Up @@ -196,5 +201,6 @@ var (
ComponentCalicoEnvoyGateway,
ComponentCalicoEnvoyProxy,
ComponentCalicoEnvoyRatelimit,
ComponentCalicoGuardian,
}
)
4 changes: 3 additions & 1 deletion pkg/components/references.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,9 @@ func GetReference(c Component, registry, imagePath, imagePrefix string, is *oper
ComponentCalicoCSIRegistrarFIPS,
ComponentCalicoGoldmane,
ComponentCalicoWhisker,
ComponentCalicoWhiskerBackend:
ComponentCalicoWhiskerBackend,
ComponentCalicoGuardian:

registry = CalicoRegistry
case ComponentOperatorInit:
registry = InitRegistry
Expand Down
8 changes: 8 additions & 0 deletions pkg/controller/installation/core_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,14 @@ func (r *ReconcileInstallation) Reconcile(ctx context.Context, request reconcile
}

calicoVersion = components.EnterpriseRelease
} else {
cert, err := certificateManager.GetCertificate(r.client, render.VoltronLinseedPublicCert, common.OperatorNamespace())
if err != nil {
r.status.SetDegraded(operator.CertificateError, fmt.Sprintf("Failed to retrieve / validate %s", render.VoltronLinseedPublicCert), err, reqLogger)
return reconcile.Result{}, err
} else if cert != nil {
typhaNodeTLS.TrustedBundle.AddCertificates(cert)
}
}

kubeControllersMetricsPort, err := utils.GetKubeControllerMetricsPort(ctx, r.client)
Expand Down
17 changes: 17 additions & 0 deletions pkg/controller/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,23 @@ func GetIfExists[E any, ClientObj ClientObjType[E]](ctx context.Context, key cli
return obj, nil
}

type Defaultable[E any, O ClientObjType[E]] interface {
ClientObjType[E]
client.Object
FillDefaults()
DeepCopy() O
}

// ApplyDefaults sets any defaults that haven't been set on the given object and writes it to the k8s server.
func ApplyDefaults[E any, O ClientObjType[E], D Defaultable[E, O]](ctx context.Context, c client.Client, obj D) error {
preDefaultPatchFrom := client.MergeFrom(obj.DeepCopy())
obj.FillDefaults()

// Write the discovered configuration back to the API. This is essentially a poor-man's defaulting, and
// ensures that we don't surprise anyone by changing defaults in a future version of the operator.
return c.Patch(ctx, obj, preDefaultPatchFrom)
}

// GetNonClusterHost finds the NonClusterHost CR in your cluster.
func GetNonClusterHost(ctx context.Context, cli client.Client) (*operatorv1.NonClusterHost, error) {
nonclusterhost := &operatorv1.NonClusterHost{}
Expand Down
67 changes: 57 additions & 10 deletions pkg/controller/whisker/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ import (
"context"
"fmt"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
"sigs.k8s.io/controller-runtime/pkg/handler"
Expand All @@ -28,6 +30,7 @@ import (

operatorv1 "github.com/tigera/operator/api/v1"
"github.com/tigera/operator/pkg/common"
"github.com/tigera/operator/pkg/controller/certificatemanager"
"github.com/tigera/operator/pkg/controller/options"
"github.com/tigera/operator/pkg/controller/status"
"github.com/tigera/operator/pkg/controller/utils"
Expand All @@ -36,6 +39,7 @@ import (
"github.com/tigera/operator/pkg/render"
"github.com/tigera/operator/pkg/render/monitor"
"github.com/tigera/operator/pkg/render/whisker"
"github.com/tigera/operator/pkg/tls/certificatemanagement"
)

const (
Expand Down Expand Up @@ -65,6 +69,7 @@ func Add(mgr manager.Manager, opts options.AddOptions) error {
for _, secretName := range []string{
monitor.PrometheusServerTLSSecretName,
whisker.ManagedClusterConnectionSecretName,
certificatemanagement.CASecretName,
render.ProjectCalicoAPIServerTLSSecretName(operatorv1.TigeraSecureEnterprise),
render.ProjectCalicoAPIServerTLSSecretName(operatorv1.Calico),
} {
Expand All @@ -73,11 +78,20 @@ func Add(mgr manager.Manager, opts options.AddOptions) error {
}
}

if err = utils.AddConfigMapWatch(c, certificatemanagement.TrustedCertConfigMapName, common.OperatorNamespace(), &handler.EnqueueRequestForObject{}); err != nil {
return fmt.Errorf("failed to add watch for config map %s/%s: %w", common.OperatorNamespace(), certificatemanagement.TrustedCertConfigMapName, err)
}

err = c.WatchObject(&operatorv1.Whisker{}, &handler.EnqueueRequestForObject{})
if err != nil {
return fmt.Errorf("%s failed to watch primary resource: %w", controllerName, err)
}

err = c.WatchObject(&operatorv1.ManagementClusterConnection{}, &handler.EnqueueRequestForObject{})
if err != nil {
return fmt.Errorf("%s failed to watch management cluster connection resource: %w", controllerName, err)
}

if err = utils.AddInstallationWatch(c); err != nil {
return fmt.Errorf("%s failed to watch Installation resource: %w", controllerName, err)
}
Expand Down Expand Up @@ -136,20 +150,19 @@ type Reconciler struct {
func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
reqLogger.Info("Reconciling Whisker")
result := reconcile.Result{}

variant, installation, err := utils.GetInstallation(ctx, r.cli)
if err != nil {
return result, err
return reconcile.Result{}, err
}

whiskerCR, err := utils.GetIfExists[operatorv1.Whisker](ctx, utils.DefaultInstanceKey, r.cli)
if err != nil {
r.status.SetDegraded(operatorv1.ResourceReadError, "Error querying Whisker CR", err, reqLogger)
return result, err
return reconcile.Result{}, err
} else if whiskerCR == nil {
r.status.OnCRNotFound()
return result, nil
return reconcile.Result{}, nil
}
r.status.OnCRFound()
// SetMetaData in the TigeraStatus such as observedGenerations.
Expand All @@ -158,14 +171,48 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) (
pullSecrets, err := utils.GetNetworkingPullSecrets(installation, r.cli)
if err != nil {
r.status.SetDegraded(operatorv1.ResourceReadError, "Error retrieving pull secrets", err, reqLogger)
return result, err
return reconcile.Result{}, err
}

var tunnelSecret *corev1.Secret
managementClusterConnection, err := utils.GetIfExists[operatorv1.ManagementClusterConnection](ctx, utils.DefaultTSEEInstanceKey, r.cli)
if err != nil {
r.status.SetDegraded(operatorv1.ResourceReadError, "Error querying ManagementClusterConnection", err, reqLogger)
return reconcile.Result{}, err
} else if managementClusterConnection != nil {
tunnelSecret, err = utils.GetIfExists[corev1.Secret](ctx, types.NamespacedName{Name: render.GuardianSecretName, Namespace: common.OperatorNamespace()}, r.cli)
if err != nil {
return reconcile.Result{}, err
}

if err := utils.ApplyDefaults(ctx, r.cli, managementClusterConnection); err != nil {
r.status.SetDegraded(operatorv1.ResourceUpdateError, err.Error(), err, reqLogger)
return reconcile.Result{}, err
}

log.V(2).Info("Loaded ManagementClusterConnection config", managementClusterConnection)
}

certificateManager, err := certificatemanager.Create(r.cli, installation, r.clusterDomain, common.OperatorNamespace())
if err != nil {
r.status.SetDegraded(operatorv1.ResourceCreateError, "Unable to create the certificate manager", err, reqLogger)
return reconcile.Result{}, err
}

trustedCertBundle, err := certificateManager.LoadTrustedBundle(ctx, r.cli, whisker.WhiskerNamespace)
if err != nil {
r.status.SetDegraded(operatorv1.ResourceReadError, "Error loading trusted cert bundle", err, reqLogger)
return reconcile.Result{}, err
}

ch := utils.NewComponentHandler(log, r.cli, r.scheme, whiskerCR)
cfg := &whisker.Configuration{
PullSecrets: pullSecrets,
OpenShift: r.provider.IsOpenShift(),
Installation: installation,
PullSecrets: pullSecrets,
OpenShift: r.provider.IsOpenShift(),
Installation: installation,
TunnelSecret: tunnelSecret,
TrustedCertBundle: trustedCertBundle,
ManagementClusterConnection: managementClusterConnection,
}

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

r.status.ReadyToMonitor()
r.status.ClearDegraded()

return result, nil
return reconcile.Result{}, nil
}
2 changes: 1 addition & 1 deletion pkg/crds/crds.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ var (
func init() {
yamlDelimRe = regexp.MustCompile(`\n---`)

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

Expand Down
Loading

0 comments on commit 5d95cd4

Please sign in to comment.