From 91e923e842450b11ae96c8a5988163641801b6d6 Mon Sep 17 00:00:00 2001 From: chaosinthecrd Date: Tue, 22 Apr 2025 18:19:09 +0100 Subject: [PATCH] k8s-operator: use iota-based enums (#14323) Signed-off-by: chaosinthecrd --- cmd/k8s-operator/dnsrecords.go | 12 +++--- cmd/k8s-operator/dnsrecords_test.go | 4 +- cmd/k8s-operator/egress-eps_test.go | 14 +++---- cmd/k8s-operator/egress-services-readiness.go | 2 +- .../egress-services-readiness_test.go | 4 +- cmd/k8s-operator/egress-services.go | 21 +++++----- cmd/k8s-operator/egress-services_test.go | 4 +- cmd/k8s-operator/ingress-for-pg.go | 35 +++++++---------- cmd/k8s-operator/ingress-for-pg_test.go | 8 ++-- cmd/k8s-operator/ingress.go | 8 ++-- cmd/k8s-operator/ingress_test.go | 16 ++++---- cmd/k8s-operator/operator.go | 12 +++--- cmd/k8s-operator/operator_test.go | 39 ++++++++++--------- cmd/k8s-operator/proxygroup.go | 4 +- cmd/k8s-operator/proxygroup_test.go | 2 +- cmd/k8s-operator/sts_test.go | 18 ++++----- cmd/k8s-operator/svc.go | 34 +++++++++------- cmd/k8s-operator/testutils_test.go | 2 +- 18 files changed, 121 insertions(+), 118 deletions(-) diff --git a/cmd/k8s-operator/dnsrecords.go b/cmd/k8s-operator/dnsrecords.go index f91dd49ec..7d40fb466 100644 --- a/cmd/k8s-operator/dnsrecords.go +++ b/cmd/k8s-operator/dnsrecords.go @@ -30,7 +30,6 @@ import ( const ( dnsRecordsRecocilerFinalizer = "tailscale.com/dns-records-reconciler" - annotationTSMagicDNSName = "tailscale.com/magic-dnsname" ) // dnsRecordsReconciler knows how to update dnsrecords ConfigMap with DNS @@ -159,7 +158,7 @@ func (dnsRR *dnsRecordsReconciler) maybeProvision(ctx context.Context, headlessS // Ensure that headless Service is annotated with the current MagicDNS // name to help with records cleanup when proxy resources are deleted or // MagicDNS name changes. - oldFqdn := headlessSvc.Annotations[annotationTSMagicDNSName] + oldFqdn := AnnotationMagicDNSName.GetValue(headlessSvc) if oldFqdn != "" && oldFqdn != fqdn { // i.e user has changed the value of tailscale.com/tailnet-fqdn annotation logger.Debugf("MagicDNS name has changed, remvoving record for %s", oldFqdn) updateFunc := func(rec *operatorutils.Records) { @@ -169,7 +168,7 @@ func (dnsRR *dnsRecordsReconciler) maybeProvision(ctx context.Context, headlessS return fmt.Errorf("error removing record for %s: %w", oldFqdn, err) } } - mak.Set(&headlessSvc.Annotations, annotationTSMagicDNSName, fqdn) + mak.Set(&headlessSvc.Annotations, AnnotationMagicDNSName.String(), fqdn) if !apiequality.Semantic.DeepEqual(oldHeadlessSvc, headlessSvc) { logger.Infof("provisioning DNS record for MagicDNS name: %s", fqdn) // this will be printed exactly once if err := dnsRR.Update(ctx, headlessSvc); err != nil { @@ -267,7 +266,7 @@ func (h *dnsRecordsReconciler) maybeCleanup(ctx context.Context, headlessSvc *co logger.Debug("'dnsrecords' ConfigMap contains no records") return h.removeHeadlessSvcFinalizer(ctx, headlessSvc) } - fqdn, _ := headlessSvc.GetAnnotations()[annotationTSMagicDNSName] + fqdn := AnnotationMagicDNSName.GetValue(headlessSvc) if fqdn == "" { return h.removeHeadlessSvcFinalizer(ctx, headlessSvc) } @@ -316,7 +315,7 @@ func (dnsRR *dnsRecordsReconciler) fqdnForDNSRecord(ctx context.Context, headles } else if err != nil { return "", err } - return svc.Annotations[AnnotationTailnetTargetFQDN], nil + return AnnotationTailnetTargetFQDN.GetValue(svc), nil } return "", nil } @@ -363,6 +362,5 @@ func (dnsRR *dnsRecordsReconciler) isSvcForFQDNEgressProxy(ctx context.Context, } else if err != nil { return false, err } - annots := parentSvc.Annotations - return annots != nil && annots[AnnotationTailnetTargetFQDN] != "", nil + return AnnotationTailnetTargetFQDN.GetValue(parentSvc) != "", nil } diff --git a/cmd/k8s-operator/dnsrecords_test.go b/cmd/k8s-operator/dnsrecords_test.go index 4e73e6c9e..79012e55a 100644 --- a/cmd/k8s-operator/dnsrecords_test.go +++ b/cmd/k8s-operator/dnsrecords_test.go @@ -81,7 +81,7 @@ func TestDNSRecordsReconciler(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "egress-fqdn", Namespace: "test", - Annotations: map[string]string{"tailscale.com/tailnet-fqdn": "foo.bar.ts.net"}, + Annotations: map[string]string{AnnotationTailnetTargetFQDN.String(): "foo.bar.ts.net"}, }, Spec: corev1.ServiceSpec{ ExternalName: "unused", @@ -104,7 +104,7 @@ func TestDNSRecordsReconciler(t *testing.T) { // 2. DNS record is updated if tailscale.com/tailnet-fqdn annotation's // value changes mustUpdate(t, fc, "test", "egress-fqdn", func(svc *corev1.Service) { - svc.Annotations["tailscale.com/tailnet-fqdn"] = "baz.bar.ts.net" + svc.Annotations[AnnotationTailnetTargetFQDN.String()] = "baz.bar.ts.net" }) expectReconciled(t, dnsRR, "tailscale", "egress-fqdn") // dns-records-reconciler reconcile the headless Service wantHosts = map[string][]string{"baz.bar.ts.net": {"10.9.8.7"}} diff --git a/cmd/k8s-operator/egress-eps_test.go b/cmd/k8s-operator/egress-eps_test.go index bd81071cb..510aec60c 100644 --- a/cmd/k8s-operator/egress-eps_test.go +++ b/cmd/k8s-operator/egress-eps_test.go @@ -32,8 +32,8 @@ func TestTailscaleEgressEndpointSlices(t *testing.T) { Namespace: "default", UID: types.UID("1234-UID"), Annotations: map[string]string{ - AnnotationTailnetTargetFQDN: "foo.bar.ts.net", - AnnotationProxyGroup: "foo", + AnnotationTailnetTargetFQDN.String(): "foo.bar.ts.net", + AnnotationProxyGroup.String(): "foo", }, }, Spec: corev1.ServiceSpec{ @@ -135,10 +135,10 @@ func configMapForSvc(t *testing.T, svc *corev1.Service, p uint16) *corev1.Config cfg := egressservices.Config{ Ports: ports, } - if fqdn := svc.Annotations[AnnotationTailnetTargetFQDN]; fqdn != "" { + if fqdn := AnnotationTailnetTargetFQDN.GetValue(svc); fqdn != "" { cfg.TailnetTarget = egressservices.TailnetTarget{FQDN: fqdn} } - if ip := svc.Annotations[AnnotationTailnetTargetIP]; ip != "" { + if ip := AnnotationTailnetTargetIP.GetValue(svc); ip != "" { cfg.TailnetTarget = egressservices.TailnetTarget{IP: ip} } name := tailnetSvcName(svc) @@ -149,7 +149,7 @@ func configMapForSvc(t *testing.T, svc *corev1.Service, p uint16) *corev1.Config } cm := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: pgEgressCMName(svc.Annotations[AnnotationProxyGroup]), + Name: pgEgressCMName(AnnotationProxyGroup.GetValue(svc)), Namespace: "operator-ns", }, BinaryData: map[string][]byte{egressservices.KeyEgressServices: bs}, @@ -164,10 +164,10 @@ func serviceStatusForPodIP(t *testing.T, svc *corev1.Service, ip string, p uint1 ports[egressservices.PortMap{Protocol: string(port.Protocol), MatchPort: p, TargetPort: uint16(port.Port)}] = struct{}{} } svcSt := egressservices.ServiceStatus{Ports: ports} - if fqdn := svc.Annotations[AnnotationTailnetTargetFQDN]; fqdn != "" { + if fqdn := AnnotationTailnetTargetFQDN.GetValue(svc); fqdn != "" { svcSt.TailnetTarget = egressservices.TailnetTarget{FQDN: fqdn} } - if ip := svc.Annotations[AnnotationTailnetTargetIP]; ip != "" { + if ip := AnnotationTailnetTargetIP.GetValue(svc); ip != "" { svcSt.TailnetTarget = egressservices.TailnetTarget{IP: ip} } svcName := tailnetSvcName(svc) diff --git a/cmd/k8s-operator/egress-services-readiness.go b/cmd/k8s-operator/egress-services-readiness.go index 5e95a5279..cc689cc6c 100644 --- a/cmd/k8s-operator/egress-services-readiness.go +++ b/cmd/k8s-operator/egress-services-readiness.go @@ -86,7 +86,7 @@ func (esrr *egressSvcsReadinessReconciler) Reconcile(ctx context.Context, req re } pg := &tsapi.ProxyGroup{ ObjectMeta: metav1.ObjectMeta{ - Name: svc.Annotations[AnnotationProxyGroup], + Name: AnnotationProxyGroup.GetValue(svc), }, } err = esrr.Get(ctx, client.ObjectKeyFromObject(pg), pg) diff --git a/cmd/k8s-operator/egress-services-readiness_test.go b/cmd/k8s-operator/egress-services-readiness_test.go index ce947329d..e3d57837e 100644 --- a/cmd/k8s-operator/egress-services-readiness_test.go +++ b/cmd/k8s-operator/egress-services-readiness_test.go @@ -43,8 +43,8 @@ func TestEgressServiceReadiness(t *testing.T) { Name: "my-app", Namespace: "dev", Annotations: map[string]string{ - AnnotationProxyGroup: "dev", - AnnotationTailnetTargetFQDN: tailnetFQDN, + AnnotationProxyGroup.String(): "dev", + AnnotationTailnetTargetFQDN.String(): tailnetFQDN, }, }, } diff --git a/cmd/k8s-operator/egress-services.go b/cmd/k8s-operator/egress-services.go index 7103205ac..a4e857f35 100644 --- a/cmd/k8s-operator/egress-services.go +++ b/cmd/k8s-operator/egress-services.go @@ -192,7 +192,7 @@ func (esr *egressSvcsReconciler) maybeProvision(ctx context.Context, svc *corev1 upToDate := svcConfigurationUpToDate(svc, l) provisioned := true if !upToDate { - if clusterIPSvc, provisioned, err = esr.provision(ctx, svc.Annotations[AnnotationProxyGroup], svc, clusterIPSvc, l); err != nil { + if clusterIPSvc, provisioned, err = esr.provision(ctx, AnnotationProxyGroup.GetValue(svc), svc, clusterIPSvc, l); err != nil { return err } } @@ -403,7 +403,7 @@ func (esr *egressSvcsReconciler) maybeCleanup(ctx context.Context, svc *corev1.S } func (esr *egressSvcsReconciler) maybeCleanupProxyGroupConfig(ctx context.Context, svc *corev1.Service, l *zap.SugaredLogger) error { - wantsProxyGroup := svc.Annotations[AnnotationProxyGroup] + wantsProxyGroup := AnnotationProxyGroup.GetValue(svc) cond := tsoperator.GetServiceCondition(svc, tsapi.EgressSvcConfigured) if cond == nil { return nil @@ -506,7 +506,7 @@ func (esr *egressSvcsReconciler) ensureEgressSvcCfgDeleted(ctx context.Context, } func (esr *egressSvcsReconciler) validateClusterResources(ctx context.Context, svc *corev1.Service, l *zap.SugaredLogger) (bool, error) { - proxyGroupName := svc.Annotations[AnnotationProxyGroup] + proxyGroupName := AnnotationProxyGroup.GetValue(svc) pg := &tsapi.ProxyGroup{ ObjectMeta: metav1.ObjectMeta{ Name: proxyGroupName, @@ -563,7 +563,7 @@ func validateEgressService(svc *corev1.Service, pg *tsapi.ProxyGroup) []string { violations := validateService(svc) // We check that only one of these two is set in the earlier validateService function. - if svc.Annotations[AnnotationTailnetTargetFQDN] == "" && svc.Annotations[AnnotationTailnetTargetIP] == "" { + if AnnotationTailnetTargetFQDN.GetValue(svc) == "" && AnnotationTailnetTargetIP.GetValue(svc) == "" { violations = append(violations, fmt.Sprintf("egress Service for ProxyGroup must have one of %s, %s annotations set", AnnotationTailnetTargetFQDN, AnnotationTailnetTargetIP)) } if len(svc.Spec.Ports) == 0 { @@ -618,13 +618,13 @@ func unusedPort(usedPorts sets.Set[int32]) int32 { // Service must contain exactly one of tailscale.com/tailnet-ip, // tailscale.com/tailnet-fqdn annotations. func tailnetTargetFromSvc(svc *corev1.Service) egressservices.TailnetTarget { - if fqdn := svc.Annotations[AnnotationTailnetTargetFQDN]; fqdn != "" { + if fqdn := AnnotationTailnetTargetFQDN.GetValue(svc); fqdn != "" { return egressservices.TailnetTarget{ FQDN: fqdn, } } return egressservices.TailnetTarget{ - IP: svc.Annotations[AnnotationTailnetTargetIP], + IP: AnnotationTailnetTargetIP.GetValue(svc), } } @@ -642,8 +642,7 @@ func isEgressSvcForProxyGroup(obj client.Object) bool { if !ok { return false } - annots := s.ObjectMeta.Annotations - return annots[AnnotationProxyGroup] != "" && (annots[AnnotationTailnetTargetFQDN] != "" || annots[AnnotationTailnetTargetIP] != "") + return AnnotationProxyGroup.GetValue(s) != "" && (AnnotationTailnetTargetFQDN.GetValue(s) != "" || AnnotationTailnetTargetIP.GetValue(s) != "") } // egressSvcConfig returns a ConfigMap that contains egress services configuration for the provided ProxyGroup as well @@ -684,7 +683,7 @@ func egressSvcChildResourceLabels(svc *corev1.Service) map[string]string { LabelParentType: "svc", LabelParentName: svc.Name, LabelParentNamespace: svc.Namespace, - labelProxyGroup: svc.Annotations[AnnotationProxyGroup], + labelProxyGroup: AnnotationProxyGroup.GetValue(svc), labelSvcType: typeEgress, } } @@ -743,12 +742,12 @@ func svcConfiguredReason(svc *corev1.Service, configured bool, l *zap.SugaredLog } else { r = fmt.Sprintf("ConfigurationFailed:%s", r) } - r += fmt.Sprintf("ProxyGroup:%s", svc.Annotations[AnnotationProxyGroup]) + r += fmt.Sprintf("ProxyGroup:%s", AnnotationProxyGroup.GetValue(svc)) tt := tailnetTargetFromSvc(svc) s := cfg{ Ports: svc.Spec.Ports, TailnetTarget: tt, - ProxyGroup: svc.Annotations[AnnotationProxyGroup], + ProxyGroup: AnnotationProxyGroup.GetValue(svc), } r += fmt.Sprintf(":Config:%s", cfgHash(s, l)) return r diff --git a/cmd/k8s-operator/egress-services_test.go b/cmd/k8s-operator/egress-services_test.go index d8a5dfd32..46375813c 100644 --- a/cmd/k8s-operator/egress-services_test.go +++ b/cmd/k8s-operator/egress-services_test.go @@ -69,8 +69,8 @@ func TestTailscaleEgressServices(t *testing.T) { Namespace: "default", UID: types.UID("1234-UID"), Annotations: map[string]string{ - AnnotationTailnetTargetFQDN: tailnetTargetFQDN, - AnnotationProxyGroup: "foo", + AnnotationTailnetTargetFQDN.String(): tailnetTargetFQDN, + AnnotationProxyGroup.String(): "foo", }, }, Spec: corev1.ServiceSpec{ diff --git a/cmd/k8s-operator/ingress-for-pg.go b/cmd/k8s-operator/ingress-for-pg.go index 3df5a07ee..a48b645ca 100644 --- a/cmd/k8s-operator/ingress-for-pg.go +++ b/cmd/k8s-operator/ingress-for-pg.go @@ -50,9 +50,6 @@ const ( FinalizerNamePG = "tailscale.com/ingress-pg-finalizer" indexIngressProxyGroup = ".metadata.annotations.ingress-proxy-group" - // annotationHTTPEndpoint can be used to configure the Ingress to expose an HTTP endpoint to tailnet (as - // well as the default HTTPS endpoint). - annotationHTTPEndpoint = "tailscale.com/http-endpoint" labelDomain = "tailscale.com/domain" ) @@ -147,7 +144,7 @@ func (r *HAIngressReconciler) maybeProvision(ctx context.Context, hostname strin return false, nil } // Get and validate ProxyGroup readiness - pgName := ing.Annotations[AnnotationProxyGroup] + pgName := ing.Annotations[AnnotationProxyGroup.String()] if pgName == "" { logger.Infof("[unexpected] no ProxyGroup annotation, skipping VIPService provisioning") return false, nil @@ -305,7 +302,7 @@ func (r *HAIngressReconciler) maybeProvision(ctx context.Context, hostname strin // 4. Ensure that the VIPService exists and is up to date. tags := r.defaultTags - if tstr, ok := ing.Annotations[AnnotationTags]; ok { + if tstr, ok := ing.Annotations[AnnotationTags.String()]; ok { tags = strings.Split(tstr, ",") } @@ -498,7 +495,7 @@ func (r *HAIngressReconciler) maybeCleanup(ctx context.Context, hostname string, }() // 1. Check if there is a VIPService associated with this Ingress. - pg := ing.Annotations[AnnotationProxyGroup] + pg := ing.Annotations[AnnotationProxyGroup.String()] cm, cfg, err := r.proxyGroupServeConfig(ctx, pg) if err != nil { return false, fmt.Errorf("error getting ProxyGroup serve config: %w", err) @@ -610,7 +607,7 @@ func (r *HAIngressReconciler) shouldExpose(ing *networkingv1.Ingress) bool { isTSIngress := ing != nil && ing.Spec.IngressClassName != nil && *ing.Spec.IngressClassName == tailscaleIngressClassName - pgAnnot := ing.Annotations[AnnotationProxyGroup] + pgAnnot := ing.Annotations[AnnotationProxyGroup.String()] return isTSIngress && pgAnnot != "" } @@ -624,7 +621,7 @@ func (r *HAIngressReconciler) validateIngress(ctx context.Context, ing *networki var errs []error // Validate tags if present - if tstr, ok := ing.Annotations[AnnotationTags]; ok { + if tstr, ok := ing.Annotations[AnnotationTags.String()]; ok { tags := strings.Split(tstr, ",") for _, tag := range tags { tag = strings.TrimSpace(tag) @@ -714,7 +711,7 @@ func (r *HAIngressReconciler) cleanupVIPService(ctx context.Context, name tailcf if err != nil { return false, fmt.Errorf("error marshalling updated VIPService owner reference: %w", err) } - svc.Annotations[ownerAnnotation] = string(json) + svc.Annotations[AnnotationOwnerReferences.String()] = string(json) return true, r.tsClient.CreateOrUpdateVIPService(ctx, svc) } @@ -723,7 +720,7 @@ func isHTTPEndpointEnabled(ing *networkingv1.Ingress) bool { if ing == nil { return false } - return ing.Annotations[annotationHTTPEndpoint] == "enabled" + return AnnotationHTTPEndpoint.GetValue(ing) == "enabled" } // serviceAdvertisementMode describes the desired state of a VIPService. @@ -824,8 +821,6 @@ func (a *HAIngressReconciler) numberPodsAdvertising(ctx context.Context, pgName return count, nil } -const ownerAnnotation = "tailscale.com/owner-references" - // ownerAnnotationValue is the content of the VIPService.Annotation[ownerAnnotation] field. type ownerAnnotationValue struct { // OwnerRefs is a list of owner references that identify all operator @@ -856,7 +851,7 @@ func (r *HAIngressReconciler) ownerAnnotations(svc *tailscale.VIPService) (map[s return nil, fmt.Errorf("[unexpected] unable to marshal VIPService owner annotation contents: %w, please report this", err) } return map[string]string{ - ownerAnnotation: string(json), + AnnotationOwnerReferences.String(): string(json), }, nil } o, err := parseOwnerAnnotation(svc) @@ -879,18 +874,18 @@ func (r *HAIngressReconciler) ownerAnnotations(svc *tailscale.VIPService) (map[s for k, v := range svc.Annotations { newAnnots[k] = v } - newAnnots[ownerAnnotation] = string(json) + newAnnots[AnnotationOwnerReferences.String()] = string(json) return newAnnots, nil } // parseOwnerAnnotation returns nil if no valid owner found. func parseOwnerAnnotation(vipSvc *tailscale.VIPService) (*ownerAnnotationValue, error) { - if vipSvc.Annotations == nil || vipSvc.Annotations[ownerAnnotation] == "" { + if vipSvc.Annotations == nil || vipSvc.Annotations[AnnotationOwnerReferences.String()] == "" { return nil, nil } o := &ownerAnnotationValue{} - if err := json.Unmarshal([]byte(vipSvc.Annotations[ownerAnnotation]), o); err != nil { - return nil, fmt.Errorf("error parsing VIPService %s annotation %q: %w", ownerAnnotation, vipSvc.Annotations[ownerAnnotation], err) + if err := json.Unmarshal([]byte(vipSvc.Annotations[AnnotationOwnerReferences.String()]), o); err != nil { + return nil, fmt.Errorf("error parsing VIPService %s annotation %q: %w", AnnotationOwnerReferences.String(), vipSvc.Annotations[AnnotationOwnerReferences.String()], err) } return o, nil } @@ -898,9 +893,9 @@ func parseOwnerAnnotation(vipSvc *tailscale.VIPService) (*ownerAnnotationValue, func ownersAreSetAndEqual(a, b *tailscale.VIPService) bool { return a != nil && b != nil && a.Annotations != nil && b.Annotations != nil && - a.Annotations[ownerAnnotation] != "" && - b.Annotations[ownerAnnotation] != "" && - strings.EqualFold(a.Annotations[ownerAnnotation], b.Annotations[ownerAnnotation]) + a.Annotations[AnnotationOwnerReferences.String()] != "" && + b.Annotations[AnnotationOwnerReferences.String()] != "" && + strings.EqualFold(a.Annotations[AnnotationOwnerReferences.String()], b.Annotations[AnnotationOwnerReferences.String()]) } // ensureCertResources ensures that the TLS Secret for an HA Ingress and RBAC diff --git a/cmd/k8s-operator/ingress-for-pg_test.go b/cmd/k8s-operator/ingress-for-pg_test.go index 0ad424bd6..5288ffe58 100644 --- a/cmd/k8s-operator/ingress-for-pg_test.go +++ b/cmd/k8s-operator/ingress-for-pg_test.go @@ -277,7 +277,7 @@ func TestValidateIngress(t *testing.T) { Name: "test-ingress", Namespace: "default", Annotations: map[string]string{ - AnnotationProxyGroup: "test-pg", + AnnotationProxyGroup.String(): "test-pg", }, }, Spec: networkingv1.IngressSpec{ @@ -338,7 +338,7 @@ func TestValidateIngress(t *testing.T) { Name: baseIngress.Name, Namespace: baseIngress.Namespace, Annotations: map[string]string{ - AnnotationTags: "tag:invalid!", + AnnotationTags.String(): "tag:invalid!", }, }, }, @@ -411,7 +411,7 @@ func TestValidateIngress(t *testing.T) { Name: "existing-ingress", Namespace: "default", Annotations: map[string]string{ - AnnotationProxyGroup: "test-pg", + AnnotationProxyGroup.String(): "test-pg", }, }, Spec: networkingv1.IngressSpec{ @@ -759,7 +759,7 @@ func TestIngressPGReconciler_MultiCluster(t *testing.T) { existingVIPSvc := &tailscale.VIPService{ Name: "svc:my-svc", Annotations: map[string]string{ - ownerAnnotation: `{"ownerrefs":[{"operatorID":"operator-2"}]}`, + AnnotationOwnerReferences.String(): `{"ownerrefs":[{"operatorID":"operator-2"}]}`, }, } ft.vipServices = map[tailcfg.ServiceName]*tailscale.VIPService{ diff --git a/cmd/k8s-operator/ingress.go b/cmd/k8s-operator/ingress.go index 6c50e10b2..3a4d23a35 100644 --- a/cmd/k8s-operator/ingress.go +++ b/cmd/k8s-operator/ingress.go @@ -179,7 +179,7 @@ func (a *IngressReconciler) maybeProvision(ctx context.Context, logger *zap.Suga }, }, } - if opt.Bool(ing.Annotations[AnnotationFunnel]).EqualBool(true) { + if opt.Bool(ing.Annotations[AnnotationFunnel.String()]).EqualBool(true) { sc.AllowFunnel = map[ipn.HostPort]bool{ magic443: true, } @@ -204,7 +204,7 @@ func (a *IngressReconciler) maybeProvision(ctx context.Context, logger *zap.Suga crl := childResourceLabels(ing.Name, ing.Namespace, "ingress") var tags []string - if tstr, ok := ing.Annotations[AnnotationTags]; ok { + if tstr, ok := ing.Annotations[AnnotationTags.String()]; ok { tags = strings.Split(tstr, ",") } hostname := hostnameForIngress(ing) @@ -220,7 +220,7 @@ func (a *IngressReconciler) maybeProvision(ctx context.Context, logger *zap.Suga proxyType: proxyTypeIngressResource, } - if val := ing.GetAnnotations()[AnnotationExperimentalForwardClusterTrafficViaL7IngresProxy]; val == "true" { + if val := ing.GetAnnotations()[AnnotationExperimentalForwardClusterTrafficViaL7IngresProxy.String()]; val == "true" { sts.ForwardClusterTrafficViaL7IngressProxy = true } @@ -264,7 +264,7 @@ func (a *IngressReconciler) shouldExpose(ing *networkingv1.Ingress) bool { return ing != nil && ing.Spec.IngressClassName != nil && *ing.Spec.IngressClassName == tailscaleIngressClassName && - ing.Annotations[AnnotationProxyGroup] == "" + ing.Annotations[AnnotationProxyGroup.String()] == "" } // validateIngressClass attempts to validate that 'tailscale' IngressClass diff --git a/cmd/k8s-operator/ingress_test.go b/cmd/k8s-operator/ingress_test.go index a975fec7a..6d4ee55ee 100644 --- a/cmd/k8s-operator/ingress_test.go +++ b/cmd/k8s-operator/ingress_test.go @@ -94,7 +94,7 @@ func TestTailscaleIngress(t *testing.T) { // 3. Resources get created for Ingress that should allow forwarding // cluster traffic mustUpdate(t, fc, "default", "test", func(ing *networkingv1.Ingress) { - mak.Set(&ing.ObjectMeta.Annotations, AnnotationExperimentalForwardClusterTrafficViaL7IngresProxy, "true") + mak.Set(&ing.ObjectMeta.Annotations, AnnotationExperimentalForwardClusterTrafficViaL7IngresProxy.String(), "true") }) opts.shouldEnableForwardingClusterTrafficViaIngress = true expectReconciled(t, ingR, "default", "test") @@ -230,7 +230,8 @@ func TestTailscaleIngressWithProxyClass(t *testing.T) { Spec: tsapi.ProxyClassSpec{StatefulSet: &tsapi.StatefulSet{ Labels: tsapi.Labels{"foo": "bar"}, Annotations: map[string]string{"bar.io/foo": "some-val"}, - Pod: &tsapi.Pod{Annotations: map[string]string{"foo.io/bar": "some-val"}}}}, + Pod: &tsapi.Pod{Annotations: map[string]string{"foo.io/bar": "some-val"}}, + }}, } fc := fake.NewClientBuilder(). WithScheme(tsapi.GlobalScheme). @@ -285,7 +286,7 @@ func TestTailscaleIngressWithProxyClass(t *testing.T) { // 2. Ingress is updated to specify a ProxyClass, ProxyClass is not yet // ready, so proxy resource configuration does not change. mustUpdate(t, fc, "default", "test", func(ing *networkingv1.Ingress) { - mak.Set(&ing.ObjectMeta.Labels, LabelProxyClass, "custom-metadata") + mak.Set(&ing.ObjectMeta.Labels, LabelAnnotationProxyClass, "custom-metadata") }) expectReconciled(t, ingR, "default", "test") expectEqual(t, fc, expectedSTSUserspace(t, fc, opts), removeHashAnnotation, removeResourceReqs) @@ -309,7 +310,7 @@ func TestTailscaleIngressWithProxyClass(t *testing.T) { // Ingress gets reconciled and the custom ProxyClass configuration is // removed from the proxy resources. mustUpdate(t, fc, "default", "test", func(ing *networkingv1.Ingress) { - delete(ing.ObjectMeta.Labels, LabelProxyClass) + delete(ing.ObjectMeta.Labels, LabelAnnotationProxyClass) }) expectReconciled(t, ingR, "default", "test") opts.proxyClass = "" @@ -325,14 +326,15 @@ func TestTailscaleIngressWithServiceMonitor(t *testing.T) { Status: metav1.ConditionTrue, Type: string(tsapi.ProxyClassReady), ObservedGeneration: 1, - }}}, + }}, + }, } crd := &apiextensionsv1.CustomResourceDefinition{ObjectMeta: metav1.ObjectMeta{Name: serviceMonitorCRD}} // Create fake client with ProxyClass, IngressClass, Ingress with metrics ProxyClass, and Service ing := ingress() ing.Labels = map[string]string{ - LabelProxyClass: "metrics", + LabelAnnotationProxyClass: "metrics", } fc := fake.NewClientBuilder(). WithScheme(tsapi.GlobalScheme). @@ -452,7 +454,7 @@ func TestIngressLetsEncryptStaging(t *testing.T) { ing := ingress() if tt.proxyClassPerResource != "" { ing.Labels = map[string]string{ - LabelProxyClass: tt.proxyClassPerResource, + LabelAnnotationProxyClass: tt.proxyClassPerResource, } } mustCreate(t, fc, ing) diff --git a/cmd/k8s-operator/operator.go b/cmd/k8s-operator/operator.go index 1f637927b..4b4a9e958 100644 --- a/cmd/k8s-operator/operator.go +++ b/cmd/k8s-operator/operator.go @@ -753,7 +753,7 @@ func proxyClassHandlerForSvc(cl client.Client, logger *zap.SugaredLogger) handle return func(ctx context.Context, o client.Object) []reconcile.Request { svcList := new(corev1.ServiceList) labels := map[string]string{ - LabelProxyClass: o.GetName(), + LabelAnnotationProxyClass: o.GetName(), } if err := cl.List(ctx, svcList, client.MatchingLabels(labels)); err != nil { logger.Debugf("error listing Services for ProxyClass: %v", err) @@ -774,7 +774,7 @@ func proxyClassHandlerForIngress(cl client.Client, logger *zap.SugaredLogger) ha return func(ctx context.Context, o client.Object) []reconcile.Request { ingList := new(networkingv1.IngressList) labels := map[string]string{ - LabelProxyClass: o.GetName(), + LabelAnnotationProxyClass: o.GetName(), } if err := cl.List(ctx, ingList, client.MatchingLabels(labels)); err != nil { logger.Debugf("error listing Ingresses for ProxyClass: %v", err) @@ -875,7 +875,7 @@ func serviceHandlerForIngress(cl client.Client, logger *zap.SugaredLogger) handl } func serviceHandler(_ context.Context, o client.Object) []reconcile.Request { - if _, ok := o.GetAnnotations()[AnnotationProxyGroup]; ok { + if _, ok := o.GetAnnotations()[AnnotationProxyGroup.String()]; ok { // Do not reconcile Services for ProxyGroup. return nil } @@ -1275,7 +1275,7 @@ func indexEgressServices(o client.Object) []string { if !isEgressSvcForProxyGroup(o) { return nil } - return []string{o.GetAnnotations()[AnnotationProxyGroup]} + return []string{o.GetAnnotations()[AnnotationProxyGroup.String()]} } // indexPGIngresses adds a local index to a cached Tailscale Ingresses meant to be exposed on a ProxyGroup. The index is @@ -1284,7 +1284,7 @@ func indexPGIngresses(o client.Object) []string { if !hasProxyGroupAnnotation(o) { return nil } - return []string{o.GetAnnotations()[AnnotationProxyGroup]} + return []string{o.GetAnnotations()[AnnotationProxyGroup.String()]} } // serviceHandlerForIngressPG returns a handler for Service events that ensures that if the Service @@ -1325,7 +1325,7 @@ func serviceHandlerForIngressPG(cl client.Client, logger *zap.SugaredLogger) han func hasProxyGroupAnnotation(obj client.Object) bool { ing := obj.(*networkingv1.Ingress) - return ing.Annotations[AnnotationProxyGroup] != "" + return ing.Annotations[AnnotationProxyGroup.String()] != "" } func id(ctx context.Context, lc *local.Client) (string, error) { diff --git a/cmd/k8s-operator/operator_test.go b/cmd/k8s-operator/operator_test.go index 175003ac7..2c0c2ba04 100644 --- a/cmd/k8s-operator/operator_test.go +++ b/cmd/k8s-operator/operator_test.go @@ -65,7 +65,7 @@ func TestLoadBalancerClass(t *testing.T) { // on it being set. UID: types.UID("1234-UID"), Annotations: map[string]string{ - AnnotationTailnetTargetFQDN: "invalid.example.com", + AnnotationTailnetTargetFQDN.String(): "invalid.example.com", }, }, Spec: corev1.ServiceSpec{ @@ -88,7 +88,7 @@ func TestLoadBalancerClass(t *testing.T) { Namespace: "default", UID: types.UID("1234-UID"), Annotations: map[string]string{ - AnnotationTailnetTargetFQDN: "invalid.example.com", + AnnotationTailnetTargetFQDN.String(): "invalid.example.com", }, }, Spec: corev1.ServiceSpec{ @@ -242,7 +242,7 @@ func TestTailnetTargetFQDNAnnotation(t *testing.T) { // on it being set. UID: types.UID("1234-UID"), Annotations: map[string]string{ - AnnotationTailnetTargetFQDN: tailnetTargetFQDN, + AnnotationTailnetTargetFQDN.String(): tailnetTargetFQDN, }, }, Spec: corev1.ServiceSpec{ @@ -276,7 +276,7 @@ func TestTailnetTargetFQDNAnnotation(t *testing.T) { Finalizers: []string{"tailscale.com/finalizer"}, UID: types.UID("1234-UID"), Annotations: map[string]string{ - AnnotationTailnetTargetFQDN: tailnetTargetFQDN, + AnnotationTailnetTargetFQDN.String(): tailnetTargetFQDN, }, }, Spec: corev1.ServiceSpec{ @@ -298,7 +298,7 @@ func TestTailnetTargetFQDNAnnotation(t *testing.T) { tailnetTargetFQDN = "bar.baz.ts.net" mustUpdate(t, fc, "default", "test", func(s *corev1.Service) { s.ObjectMeta.Annotations = map[string]string{ - AnnotationTailnetTargetFQDN: tailnetTargetFQDN, + AnnotationTailnetTargetFQDN.String(): tailnetTargetFQDN, } }) @@ -354,7 +354,7 @@ func TestTailnetTargetIPAnnotation(t *testing.T) { // on it being set. UID: types.UID("1234-UID"), Annotations: map[string]string{ - AnnotationTailnetTargetIP: tailnetTargetIP, + AnnotationTailnetTargetIP.String(): tailnetTargetIP, }, }, Spec: corev1.ServiceSpec{ @@ -388,7 +388,7 @@ func TestTailnetTargetIPAnnotation(t *testing.T) { Finalizers: []string{"tailscale.com/finalizer"}, UID: types.UID("1234-UID"), Annotations: map[string]string{ - AnnotationTailnetTargetIP: tailnetTargetIP, + AnnotationTailnetTargetIP.String(): tailnetTargetIP, }, }, Spec: corev1.ServiceSpec{ @@ -410,7 +410,7 @@ func TestTailnetTargetIPAnnotation(t *testing.T) { tailnetTargetIP = "100.77.77.77" mustUpdate(t, fc, "default", "test", func(s *corev1.Service) { s.ObjectMeta.Annotations = map[string]string{ - AnnotationTailnetTargetIP: tailnetTargetIP, + AnnotationTailnetTargetIP.String(): tailnetTargetIP, } }) @@ -462,7 +462,7 @@ func TestTailnetTargetIPAnnotation_IPCouldNotBeParsed(t *testing.T) { UID: types.UID("1234-UID"), Annotations: map[string]string{ - AnnotationTailnetTargetIP: tailnetTargetIP, + AnnotationTailnetTargetIP.String(): tailnetTargetIP, }, }, Spec: corev1.ServiceSpec{ @@ -482,7 +482,7 @@ func TestTailnetTargetIPAnnotation_IPCouldNotBeParsed(t *testing.T) { Namespace: "default", UID: types.UID("1234-UID"), Annotations: map[string]string{ - AnnotationTailnetTargetIP: tailnetTargetIP, + AnnotationTailnetTargetIP.String(): tailnetTargetIP, }, }, Spec: corev1.ServiceSpec{ @@ -533,7 +533,7 @@ func TestTailnetTargetIPAnnotation_InvalidIP(t *testing.T) { UID: types.UID("1234-UID"), Annotations: map[string]string{ - AnnotationTailnetTargetIP: tailnetTargetIP, + AnnotationTailnetTargetIP.String(): tailnetTargetIP, }, }, Spec: corev1.ServiceSpec{ @@ -553,7 +553,7 @@ func TestTailnetTargetIPAnnotation_InvalidIP(t *testing.T) { Namespace: "default", UID: types.UID("1234-UID"), Annotations: map[string]string{ - AnnotationTailnetTargetIP: tailnetTargetIP, + AnnotationTailnetTargetIP.String(): tailnetTargetIP, }, }, Spec: corev1.ServiceSpec{ @@ -1132,7 +1132,9 @@ func TestProxyClassForService(t *testing.T) { StatefulSet: &tsapi.StatefulSet{ Labels: tsapi.Labels{"foo": "bar"}, Annotations: map[string]string{"bar.io/foo": "some-val"}, - Pod: &tsapi.Pod{Annotations: map[string]string{"foo.io/bar": "some-val"}}}}, + Pod: &tsapi.Pod{Annotations: map[string]string{"foo.io/bar": "some-val"}}, + }, + }, } fc := fake.NewClientBuilder(). WithScheme(tsapi.GlobalScheme). @@ -1194,7 +1196,7 @@ func TestProxyClassForService(t *testing.T) { // pointing at the 'custom-metadata' ProxyClass. The ProxyClass is not // yet ready, so no changes are actually applied to the proxy resources. mustUpdate(t, fc, "default", "test", func(svc *corev1.Service) { - mak.Set(&svc.Labels, LabelProxyClass, "custom-metadata") + mak.Set(&svc.Labels, LabelAnnotationProxyClass, "custom-metadata") }) expectReconciled(t, sr, "default", "test") expectEqual(t, fc, expectedSTS(t, fc, opts), removeHashAnnotation, removeResourceReqs) @@ -1220,7 +1222,7 @@ func TestProxyClassForService(t *testing.T) { // configuration from the ProxyClass is removed from the cluster // resources. mustUpdate(t, fc, "default", "test", func(svc *corev1.Service) { - delete(svc.Labels, LabelProxyClass) + delete(svc.Labels, LabelAnnotationProxyClass) }) opts.proxyClass = "" expectReconciled(t, sr, "default", "test") @@ -1667,7 +1669,7 @@ func Test_externalNameService(t *testing.T) { // on it being set. UID: types.UID("1234-UID"), Annotations: map[string]string{ - AnnotationExpose: "true", + AnnotationExpose.String(): "true", }, }, Spec: corev1.ServiceSpec{ @@ -1711,14 +1713,15 @@ func Test_metricsResourceCreation(t *testing.T) { Status: metav1.ConditionTrue, Type: string(tsapi.ProxyClassReady), ObservedGeneration: 1, - }}}, + }}, + }, } svc := &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ Name: "test", Namespace: "default", UID: types.UID("1234-UID"), - Labels: map[string]string{LabelProxyClass: "metrics"}, + Labels: map[string]string{LabelAnnotationProxyClass: "metrics"}, }, Spec: corev1.ServiceSpec{ ClusterIP: "10.20.30.40", diff --git a/cmd/k8s-operator/proxygroup.go b/cmd/k8s-operator/proxygroup.go index f263829d7..74ebaabf3 100644 --- a/cmd/k8s-operator/proxygroup.go +++ b/cmd/k8s-operator/proxygroup.go @@ -327,11 +327,11 @@ func (r *ProxyGroupReconciler) maybeProvision(ctx context.Context, pg *tsapi.Pro // TODO(irbekrm): remove this in 1.84. hash := cfgHash if capver >= 110 { - hash = s.Spec.Template.GetAnnotations()[podAnnotationLastSetConfigFileHash] + hash = PodAnnotationLastSetConfigFileHash.GetValue(s) } s.Spec = ss.Spec if hash != "" && pg.Spec.Type == tsapi.ProxyGroupTypeEgress { - mak.Set(&s.Spec.Template.Annotations, podAnnotationLastSetConfigFileHash, hash) + mak.Set(&s.Spec.Template.Annotations, PodAnnotationLastSetConfigFileHash.String(), hash) } s.ObjectMeta.Labels = ss.ObjectMeta.Labels diff --git a/cmd/k8s-operator/proxygroup_test.go b/cmd/k8s-operator/proxygroup_test.go index 159329eda..659bec05f 100644 --- a/cmd/k8s-operator/proxygroup_test.go +++ b/cmd/k8s-operator/proxygroup_test.go @@ -617,7 +617,7 @@ func expectProxyGroupResources(t *testing.T, fc client.WithWatch, pg *tsapi.Prox } statefulSet.Annotations = defaultProxyClassAnnotations if cfgHash != "" { - mak.Set(&statefulSet.Spec.Template.Annotations, podAnnotationLastSetConfigFileHash, cfgHash) + mak.Set(&statefulSet.Spec.Template.Annotations, PodAnnotationLastSetConfigFileHash.String(), cfgHash) } if shouldExist { diff --git a/cmd/k8s-operator/sts_test.go b/cmd/k8s-operator/sts_test.go index 35c512c8c..9833f4d9c 100644 --- a/cmd/k8s-operator/sts_test.go +++ b/cmd/k8s-operator/sts_test.go @@ -161,7 +161,7 @@ func Test_applyProxyClassToStatefulSet(t *testing.T) { LabelParentName: "foo", } annots := map[string]string{ - podAnnotationLastSetClusterIP: "1.2.3.4", + PodAnnotationLastSetClusterIP.String(): "1.2.3.4", } env := []corev1.EnvVar{{Name: "TS_HOSTNAME", Value: "nginx"}} userspaceProxySS.Labels = labels @@ -341,28 +341,28 @@ func Test_mergeStatefulSetLabelsOrAnnots(t *testing.T) { }, { name: "no custom annots specified and none present in current annots, return current annots", - current: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"}, - want: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"}, + current: map[string]string{PodAnnotationLastSetClusterIP.String(): "1.2.3.4"}, + want: map[string]string{PodAnnotationLastSetClusterIP.String(): "1.2.3.4"}, managed: tailscaleManagedAnnotations, }, { name: "no custom annots specified, but some present in current annots, return tailscale managed annots only from the current annots", - current: map[string]string{"foo": "bar", "something.io/foo": "bar", podAnnotationLastSetClusterIP: "1.2.3.4"}, - want: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"}, + current: map[string]string{"foo": "bar", "something.io/foo": "bar", PodAnnotationLastSetClusterIP.String(): "1.2.3.4"}, + want: map[string]string{PodAnnotationLastSetClusterIP.String(): "1.2.3.4"}, managed: tailscaleManagedAnnotations, }, { name: "custom annots specified, current annots only contain tailscale managed annots, return a union of both", - current: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"}, + current: map[string]string{PodAnnotationLastSetClusterIP.String(): "1.2.3.4"}, custom: map[string]string{"foo": "bar", "something.io/foo": "bar"}, - want: map[string]string{"foo": "bar", "something.io/foo": "bar", podAnnotationLastSetClusterIP: "1.2.3.4"}, + want: map[string]string{"foo": "bar", "something.io/foo": "bar", PodAnnotationLastSetClusterIP.String(): "1.2.3.4"}, managed: tailscaleManagedAnnotations, }, { name: "custom annots specified, current annots contain tailscale managed annots and custom annots, some of which are not present in the new custom annots, return a union of managed annots and the desired custom annots", - current: map[string]string{"foo": "bar", "something.io/foo": "bar", podAnnotationLastSetClusterIP: "1.2.3.4"}, + current: map[string]string{"foo": "bar", "something.io/foo": "bar", PodAnnotationLastSetClusterIP.String(): "1.2.3.4"}, custom: map[string]string{"something.io/foo": "bar"}, - want: map[string]string{"something.io/foo": "bar", podAnnotationLastSetClusterIP: "1.2.3.4"}, + want: map[string]string{"something.io/foo": "bar", PodAnnotationLastSetClusterIP.String(): "1.2.3.4"}, managed: tailscaleManagedAnnotations, }, { diff --git a/cmd/k8s-operator/svc.go b/cmd/k8s-operator/svc.go index d6a6f440f..13bef8b71 100644 --- a/cmd/k8s-operator/svc.go +++ b/cmd/k8s-operator/svc.go @@ -93,7 +93,7 @@ func childResourceLabels(name, ns, typ string) map[string]string { func (a *ServiceReconciler) isTailscaleService(svc *corev1.Service) bool { targetIP := tailnetTargetAnnotation(svc) - targetFQDN := svc.Annotations[AnnotationTailnetTargetFQDN] + targetFQDN := AnnotationTailnetTargetFQDN.GetValue(svc) return a.shouldExpose(svc) || targetIP != "" || targetFQDN != "" } @@ -112,7 +112,7 @@ func (a *ServiceReconciler) Reconcile(ctx context.Context, req reconcile.Request return reconcile.Result{}, fmt.Errorf("failed to get svc: %w", err) } - if _, ok := svc.Annotations[AnnotationProxyGroup]; ok { + if AnnotationProxyGroup.GetValue(svc) != "" { return reconcile.Result{}, nil // this reconciler should not look at Services for ProxyGroup } @@ -257,7 +257,7 @@ func (a *ServiceReconciler) maybeProvision(ctx context.Context, logger *zap.Suga } crl := childResourceLabels(svc.Name, svc.Namespace, "svc") var tags []string - if tstr, ok := svc.Annotations[AnnotationTags]; ok { + if tstr := AnnotationTags.GetValue(svc); tstr != "" { tags = strings.Split(tstr, ",") } @@ -287,8 +287,9 @@ func (a *ServiceReconciler) maybeProvision(ctx context.Context, logger *zap.Suga sts.TailnetTargetIP = ip a.managedEgressProxies.Add(svc.UID) gaugeEgressProxies.Set(int64(a.managedEgressProxies.Len())) - } else if fqdn := svc.Annotations[AnnotationTailnetTargetFQDN]; fqdn != "" { - fqdn := svc.Annotations[AnnotationTailnetTargetFQDN] + } else if fqdn := AnnotationTailnetTargetFQDN.GetValue(svc); fqdn != "" { + // NOTE (TOM): Do we need this? fqdn should already be set... + fqdn := AnnotationTailnetTargetFQDN.GetValue(svc) if !strings.HasSuffix(fqdn, ".") { fqdn = fqdn + "." } @@ -367,15 +368,15 @@ func (a *ServiceReconciler) maybeProvision(ctx context.Context, logger *zap.Suga func validateService(svc *corev1.Service) []string { violations := make([]string, 0) - if svc.Annotations[AnnotationTailnetTargetFQDN] != "" && svc.Annotations[AnnotationTailnetTargetIP] != "" { + if AnnotationTailnetTargetFQDN.GetValue(svc) != "" && AnnotationTailnetTargetIP.GetValue(svc) != "" { violations = append(violations, fmt.Sprintf("only one of annotations %s and %s can be set", AnnotationTailnetTargetIP, AnnotationTailnetTargetFQDN)) } - if fqdn := svc.Annotations[AnnotationTailnetTargetFQDN]; fqdn != "" { + if fqdn := AnnotationTailnetTargetFQDN.GetValue(svc); fqdn != "" { if !isMagicDNSName(fqdn) { violations = append(violations, fmt.Sprintf("invalid value of annotation %s: %q does not appear to be a valid MagicDNS name", AnnotationTailnetTargetFQDN, fqdn)) } } - if ipStr := svc.Annotations[AnnotationTailnetTargetIP]; ipStr != "" { + if ipStr := AnnotationTailnetTargetIP.GetValue(svc); ipStr != "" { ip, err := netip.ParseAddr(ipStr) if err != nil { violations = append(violations, fmt.Sprintf("invalid value of annotation %s: %q could not be parsed as a valid IP Address, error: %s", AnnotationTailnetTargetIP, ipStr, err)) @@ -386,7 +387,7 @@ func validateService(svc *corev1.Service) []string { svcName := nameForService(svc) if err := dnsname.ValidLabel(svcName); err != nil { - if _, ok := svc.Annotations[AnnotationHostname]; ok { + if AnnotationHostname.GetValue(svc) != "" { violations = append(violations, fmt.Sprintf("invalid Tailscale hostname specified %q: %s", svcName, err)) } else { violations = append(violations, fmt.Sprintf("invalid Tailscale hostname %q, use %q annotation to override: %s", svcName, AnnotationHostname, err)) @@ -420,7 +421,7 @@ func isTailscaleLoadBalancerService(svc *corev1.Service, isDefaultLoadBalancer b // hasExposeAnnotation reports whether Service has the tailscale.com/expose // annotation set func hasExposeAnnotation(svc *corev1.Service) bool { - return svc != nil && svc.Annotations[AnnotationExpose] == "true" + return svc != nil && AnnotationExpose.GetValue(svc) == "true" } // tailnetTargetAnnotation returns the value of tailscale.com/tailnet-ip @@ -431,19 +432,24 @@ func tailnetTargetAnnotation(svc *corev1.Service) string { if svc == nil { return "" } - if ip := svc.Annotations[AnnotationTailnetTargetIP]; ip != "" { + if ip := AnnotationTailnetTargetIP.GetValue(svc); ip != "" { return ip } - return svc.Annotations[annotationTailnetTargetIPOld] + + return AnnotationTailnetTargetIPOld.GetValue(svc) } // proxyClassForObject returns the proxy class for the given object. If the // object does not have a proxy class label, it returns the default proxy class func proxyClassForObject(o client.Object, proxyDefaultClass string) string { - proxyClass, exists := o.GetLabels()[LabelProxyClass] + proxyClass, exists := o.GetLabels()[LabelAnnotationProxyClass] if !exists { - proxyClass = proxyDefaultClass + proxyClass, exists = o.GetAnnotations()[LabelAnnotationProxyClass] + if !exists { + proxyClass = proxyDefaultClass + } } + return proxyClass } diff --git a/cmd/k8s-operator/testutils_test.go b/cmd/k8s-operator/testutils_test.go index f47f96e44..5491a68c9 100644 --- a/cmd/k8s-operator/testutils_test.go +++ b/cmd/k8s-operator/testutils_test.go @@ -826,7 +826,7 @@ func (c *fakeTSClient) Deleted() []string { // that we don't have to change the annotation in each test case after any // change to the configfile contents). func removeHashAnnotation(sts *appsv1.StatefulSet) { - delete(sts.Spec.Template.Annotations, podAnnotationLastSetConfigFileHash) + delete(sts.Spec.Template.Annotations, PodAnnotationLastSetConfigFileHash.String()) if len(sts.Spec.Template.Annotations) == 0 { sts.Spec.Template.Annotations = nil }