mirror of
https://github.com/tailscale/tailscale.git
synced 2025-07-29 15:23:45 +00:00
k8s-operator: use iota-based enums (#14323)
Signed-off-by: chaosinthecrd <tom@tmlabs.co.uk>
This commit is contained in:
parent
e2e5914d57
commit
91e923e842
@ -30,7 +30,6 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
dnsRecordsRecocilerFinalizer = "tailscale.com/dns-records-reconciler"
|
dnsRecordsRecocilerFinalizer = "tailscale.com/dns-records-reconciler"
|
||||||
annotationTSMagicDNSName = "tailscale.com/magic-dnsname"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// dnsRecordsReconciler knows how to update dnsrecords ConfigMap with DNS
|
// 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
|
// Ensure that headless Service is annotated with the current MagicDNS
|
||||||
// name to help with records cleanup when proxy resources are deleted or
|
// name to help with records cleanup when proxy resources are deleted or
|
||||||
// MagicDNS name changes.
|
// 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
|
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)
|
logger.Debugf("MagicDNS name has changed, remvoving record for %s", oldFqdn)
|
||||||
updateFunc := func(rec *operatorutils.Records) {
|
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)
|
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) {
|
if !apiequality.Semantic.DeepEqual(oldHeadlessSvc, headlessSvc) {
|
||||||
logger.Infof("provisioning DNS record for MagicDNS name: %s", fqdn) // this will be printed exactly once
|
logger.Infof("provisioning DNS record for MagicDNS name: %s", fqdn) // this will be printed exactly once
|
||||||
if err := dnsRR.Update(ctx, headlessSvc); err != nil {
|
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")
|
logger.Debug("'dnsrecords' ConfigMap contains no records")
|
||||||
return h.removeHeadlessSvcFinalizer(ctx, headlessSvc)
|
return h.removeHeadlessSvcFinalizer(ctx, headlessSvc)
|
||||||
}
|
}
|
||||||
fqdn, _ := headlessSvc.GetAnnotations()[annotationTSMagicDNSName]
|
fqdn := AnnotationMagicDNSName.GetValue(headlessSvc)
|
||||||
if fqdn == "" {
|
if fqdn == "" {
|
||||||
return h.removeHeadlessSvcFinalizer(ctx, headlessSvc)
|
return h.removeHeadlessSvcFinalizer(ctx, headlessSvc)
|
||||||
}
|
}
|
||||||
@ -316,7 +315,7 @@ func (dnsRR *dnsRecordsReconciler) fqdnForDNSRecord(ctx context.Context, headles
|
|||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return svc.Annotations[AnnotationTailnetTargetFQDN], nil
|
return AnnotationTailnetTargetFQDN.GetValue(svc), nil
|
||||||
}
|
}
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
@ -363,6 +362,5 @@ func (dnsRR *dnsRecordsReconciler) isSvcForFQDNEgressProxy(ctx context.Context,
|
|||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
annots := parentSvc.Annotations
|
return AnnotationTailnetTargetFQDN.GetValue(parentSvc) != "", nil
|
||||||
return annots != nil && annots[AnnotationTailnetTargetFQDN] != "", nil
|
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ func TestDNSRecordsReconciler(t *testing.T) {
|
|||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "egress-fqdn",
|
Name: "egress-fqdn",
|
||||||
Namespace: "test",
|
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{
|
Spec: corev1.ServiceSpec{
|
||||||
ExternalName: "unused",
|
ExternalName: "unused",
|
||||||
@ -104,7 +104,7 @@ func TestDNSRecordsReconciler(t *testing.T) {
|
|||||||
// 2. DNS record is updated if tailscale.com/tailnet-fqdn annotation's
|
// 2. DNS record is updated if tailscale.com/tailnet-fqdn annotation's
|
||||||
// value changes
|
// value changes
|
||||||
mustUpdate(t, fc, "test", "egress-fqdn", func(svc *corev1.Service) {
|
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
|
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"}}
|
wantHosts = map[string][]string{"baz.bar.ts.net": {"10.9.8.7"}}
|
||||||
|
@ -32,8 +32,8 @@ func TestTailscaleEgressEndpointSlices(t *testing.T) {
|
|||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
UID: types.UID("1234-UID"),
|
UID: types.UID("1234-UID"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationTailnetTargetFQDN: "foo.bar.ts.net",
|
AnnotationTailnetTargetFQDN.String(): "foo.bar.ts.net",
|
||||||
AnnotationProxyGroup: "foo",
|
AnnotationProxyGroup.String(): "foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
@ -135,10 +135,10 @@ func configMapForSvc(t *testing.T, svc *corev1.Service, p uint16) *corev1.Config
|
|||||||
cfg := egressservices.Config{
|
cfg := egressservices.Config{
|
||||||
Ports: ports,
|
Ports: ports,
|
||||||
}
|
}
|
||||||
if fqdn := svc.Annotations[AnnotationTailnetTargetFQDN]; fqdn != "" {
|
if fqdn := AnnotationTailnetTargetFQDN.GetValue(svc); fqdn != "" {
|
||||||
cfg.TailnetTarget = egressservices.TailnetTarget{FQDN: 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}
|
cfg.TailnetTarget = egressservices.TailnetTarget{IP: ip}
|
||||||
}
|
}
|
||||||
name := tailnetSvcName(svc)
|
name := tailnetSvcName(svc)
|
||||||
@ -149,7 +149,7 @@ func configMapForSvc(t *testing.T, svc *corev1.Service, p uint16) *corev1.Config
|
|||||||
}
|
}
|
||||||
cm := &corev1.ConfigMap{
|
cm := &corev1.ConfigMap{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: pgEgressCMName(svc.Annotations[AnnotationProxyGroup]),
|
Name: pgEgressCMName(AnnotationProxyGroup.GetValue(svc)),
|
||||||
Namespace: "operator-ns",
|
Namespace: "operator-ns",
|
||||||
},
|
},
|
||||||
BinaryData: map[string][]byte{egressservices.KeyEgressServices: bs},
|
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{}{}
|
ports[egressservices.PortMap{Protocol: string(port.Protocol), MatchPort: p, TargetPort: uint16(port.Port)}] = struct{}{}
|
||||||
}
|
}
|
||||||
svcSt := egressservices.ServiceStatus{Ports: ports}
|
svcSt := egressservices.ServiceStatus{Ports: ports}
|
||||||
if fqdn := svc.Annotations[AnnotationTailnetTargetFQDN]; fqdn != "" {
|
if fqdn := AnnotationTailnetTargetFQDN.GetValue(svc); fqdn != "" {
|
||||||
svcSt.TailnetTarget = egressservices.TailnetTarget{FQDN: 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}
|
svcSt.TailnetTarget = egressservices.TailnetTarget{IP: ip}
|
||||||
}
|
}
|
||||||
svcName := tailnetSvcName(svc)
|
svcName := tailnetSvcName(svc)
|
||||||
|
@ -86,7 +86,7 @@ func (esrr *egressSvcsReadinessReconciler) Reconcile(ctx context.Context, req re
|
|||||||
}
|
}
|
||||||
pg := &tsapi.ProxyGroup{
|
pg := &tsapi.ProxyGroup{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: svc.Annotations[AnnotationProxyGroup],
|
Name: AnnotationProxyGroup.GetValue(svc),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err = esrr.Get(ctx, client.ObjectKeyFromObject(pg), pg)
|
err = esrr.Get(ctx, client.ObjectKeyFromObject(pg), pg)
|
||||||
|
@ -43,8 +43,8 @@ func TestEgressServiceReadiness(t *testing.T) {
|
|||||||
Name: "my-app",
|
Name: "my-app",
|
||||||
Namespace: "dev",
|
Namespace: "dev",
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationProxyGroup: "dev",
|
AnnotationProxyGroup.String(): "dev",
|
||||||
AnnotationTailnetTargetFQDN: tailnetFQDN,
|
AnnotationTailnetTargetFQDN.String(): tailnetFQDN,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -192,7 +192,7 @@ func (esr *egressSvcsReconciler) maybeProvision(ctx context.Context, svc *corev1
|
|||||||
upToDate := svcConfigurationUpToDate(svc, l)
|
upToDate := svcConfigurationUpToDate(svc, l)
|
||||||
provisioned := true
|
provisioned := true
|
||||||
if !upToDate {
|
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
|
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 {
|
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)
|
cond := tsoperator.GetServiceCondition(svc, tsapi.EgressSvcConfigured)
|
||||||
if cond == nil {
|
if cond == nil {
|
||||||
return 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) {
|
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{
|
pg := &tsapi.ProxyGroup{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: proxyGroupName,
|
Name: proxyGroupName,
|
||||||
@ -563,7 +563,7 @@ func validateEgressService(svc *corev1.Service, pg *tsapi.ProxyGroup) []string {
|
|||||||
violations := validateService(svc)
|
violations := validateService(svc)
|
||||||
|
|
||||||
// We check that only one of these two is set in the earlier validateService function.
|
// 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))
|
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 {
|
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,
|
// Service must contain exactly one of tailscale.com/tailnet-ip,
|
||||||
// tailscale.com/tailnet-fqdn annotations.
|
// tailscale.com/tailnet-fqdn annotations.
|
||||||
func tailnetTargetFromSvc(svc *corev1.Service) egressservices.TailnetTarget {
|
func tailnetTargetFromSvc(svc *corev1.Service) egressservices.TailnetTarget {
|
||||||
if fqdn := svc.Annotations[AnnotationTailnetTargetFQDN]; fqdn != "" {
|
if fqdn := AnnotationTailnetTargetFQDN.GetValue(svc); fqdn != "" {
|
||||||
return egressservices.TailnetTarget{
|
return egressservices.TailnetTarget{
|
||||||
FQDN: fqdn,
|
FQDN: fqdn,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return egressservices.TailnetTarget{
|
return egressservices.TailnetTarget{
|
||||||
IP: svc.Annotations[AnnotationTailnetTargetIP],
|
IP: AnnotationTailnetTargetIP.GetValue(svc),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -642,8 +642,7 @@ func isEgressSvcForProxyGroup(obj client.Object) bool {
|
|||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
annots := s.ObjectMeta.Annotations
|
return AnnotationProxyGroup.GetValue(s) != "" && (AnnotationTailnetTargetFQDN.GetValue(s) != "" || AnnotationTailnetTargetIP.GetValue(s) != "")
|
||||||
return annots[AnnotationProxyGroup] != "" && (annots[AnnotationTailnetTargetFQDN] != "" || annots[AnnotationTailnetTargetIP] != "")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// egressSvcConfig returns a ConfigMap that contains egress services configuration for the provided ProxyGroup as well
|
// 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",
|
LabelParentType: "svc",
|
||||||
LabelParentName: svc.Name,
|
LabelParentName: svc.Name,
|
||||||
LabelParentNamespace: svc.Namespace,
|
LabelParentNamespace: svc.Namespace,
|
||||||
labelProxyGroup: svc.Annotations[AnnotationProxyGroup],
|
labelProxyGroup: AnnotationProxyGroup.GetValue(svc),
|
||||||
labelSvcType: typeEgress,
|
labelSvcType: typeEgress,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -743,12 +742,12 @@ func svcConfiguredReason(svc *corev1.Service, configured bool, l *zap.SugaredLog
|
|||||||
} else {
|
} else {
|
||||||
r = fmt.Sprintf("ConfigurationFailed:%s", r)
|
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)
|
tt := tailnetTargetFromSvc(svc)
|
||||||
s := cfg{
|
s := cfg{
|
||||||
Ports: svc.Spec.Ports,
|
Ports: svc.Spec.Ports,
|
||||||
TailnetTarget: tt,
|
TailnetTarget: tt,
|
||||||
ProxyGroup: svc.Annotations[AnnotationProxyGroup],
|
ProxyGroup: AnnotationProxyGroup.GetValue(svc),
|
||||||
}
|
}
|
||||||
r += fmt.Sprintf(":Config:%s", cfgHash(s, l))
|
r += fmt.Sprintf(":Config:%s", cfgHash(s, l))
|
||||||
return r
|
return r
|
||||||
|
@ -69,8 +69,8 @@ func TestTailscaleEgressServices(t *testing.T) {
|
|||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
UID: types.UID("1234-UID"),
|
UID: types.UID("1234-UID"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationTailnetTargetFQDN: tailnetTargetFQDN,
|
AnnotationTailnetTargetFQDN.String(): tailnetTargetFQDN,
|
||||||
AnnotationProxyGroup: "foo",
|
AnnotationProxyGroup.String(): "foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
|
@ -50,9 +50,6 @@ const (
|
|||||||
FinalizerNamePG = "tailscale.com/ingress-pg-finalizer"
|
FinalizerNamePG = "tailscale.com/ingress-pg-finalizer"
|
||||||
|
|
||||||
indexIngressProxyGroup = ".metadata.annotations.ingress-proxy-group"
|
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"
|
labelDomain = "tailscale.com/domain"
|
||||||
)
|
)
|
||||||
@ -147,7 +144,7 @@ func (r *HAIngressReconciler) maybeProvision(ctx context.Context, hostname strin
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
// Get and validate ProxyGroup readiness
|
// Get and validate ProxyGroup readiness
|
||||||
pgName := ing.Annotations[AnnotationProxyGroup]
|
pgName := ing.Annotations[AnnotationProxyGroup.String()]
|
||||||
if pgName == "" {
|
if pgName == "" {
|
||||||
logger.Infof("[unexpected] no ProxyGroup annotation, skipping VIPService provisioning")
|
logger.Infof("[unexpected] no ProxyGroup annotation, skipping VIPService provisioning")
|
||||||
return false, nil
|
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.
|
// 4. Ensure that the VIPService exists and is up to date.
|
||||||
tags := r.defaultTags
|
tags := r.defaultTags
|
||||||
if tstr, ok := ing.Annotations[AnnotationTags]; ok {
|
if tstr, ok := ing.Annotations[AnnotationTags.String()]; ok {
|
||||||
tags = strings.Split(tstr, ",")
|
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.
|
// 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)
|
cm, cfg, err := r.proxyGroupServeConfig(ctx, pg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("error getting ProxyGroup serve config: %w", err)
|
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 &&
|
isTSIngress := ing != nil &&
|
||||||
ing.Spec.IngressClassName != nil &&
|
ing.Spec.IngressClassName != nil &&
|
||||||
*ing.Spec.IngressClassName == tailscaleIngressClassName
|
*ing.Spec.IngressClassName == tailscaleIngressClassName
|
||||||
pgAnnot := ing.Annotations[AnnotationProxyGroup]
|
pgAnnot := ing.Annotations[AnnotationProxyGroup.String()]
|
||||||
return isTSIngress && pgAnnot != ""
|
return isTSIngress && pgAnnot != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -624,7 +621,7 @@ func (r *HAIngressReconciler) validateIngress(ctx context.Context, ing *networki
|
|||||||
var errs []error
|
var errs []error
|
||||||
|
|
||||||
// Validate tags if present
|
// Validate tags if present
|
||||||
if tstr, ok := ing.Annotations[AnnotationTags]; ok {
|
if tstr, ok := ing.Annotations[AnnotationTags.String()]; ok {
|
||||||
tags := strings.Split(tstr, ",")
|
tags := strings.Split(tstr, ",")
|
||||||
for _, tag := range tags {
|
for _, tag := range tags {
|
||||||
tag = strings.TrimSpace(tag)
|
tag = strings.TrimSpace(tag)
|
||||||
@ -714,7 +711,7 @@ func (r *HAIngressReconciler) cleanupVIPService(ctx context.Context, name tailcf
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("error marshalling updated VIPService owner reference: %w", err)
|
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)
|
return true, r.tsClient.CreateOrUpdateVIPService(ctx, svc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -723,7 +720,7 @@ func isHTTPEndpointEnabled(ing *networkingv1.Ingress) bool {
|
|||||||
if ing == nil {
|
if ing == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
return ing.Annotations[annotationHTTPEndpoint] == "enabled"
|
return AnnotationHTTPEndpoint.GetValue(ing) == "enabled"
|
||||||
}
|
}
|
||||||
|
|
||||||
// serviceAdvertisementMode describes the desired state of a VIPService.
|
// serviceAdvertisementMode describes the desired state of a VIPService.
|
||||||
@ -824,8 +821,6 @@ func (a *HAIngressReconciler) numberPodsAdvertising(ctx context.Context, pgName
|
|||||||
return count, nil
|
return count, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const ownerAnnotation = "tailscale.com/owner-references"
|
|
||||||
|
|
||||||
// ownerAnnotationValue is the content of the VIPService.Annotation[ownerAnnotation] field.
|
// ownerAnnotationValue is the content of the VIPService.Annotation[ownerAnnotation] field.
|
||||||
type ownerAnnotationValue struct {
|
type ownerAnnotationValue struct {
|
||||||
// OwnerRefs is a list of owner references that identify all operator
|
// 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 nil, fmt.Errorf("[unexpected] unable to marshal VIPService owner annotation contents: %w, please report this", err)
|
||||||
}
|
}
|
||||||
return map[string]string{
|
return map[string]string{
|
||||||
ownerAnnotation: string(json),
|
AnnotationOwnerReferences.String(): string(json),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
o, err := parseOwnerAnnotation(svc)
|
o, err := parseOwnerAnnotation(svc)
|
||||||
@ -879,18 +874,18 @@ func (r *HAIngressReconciler) ownerAnnotations(svc *tailscale.VIPService) (map[s
|
|||||||
for k, v := range svc.Annotations {
|
for k, v := range svc.Annotations {
|
||||||
newAnnots[k] = v
|
newAnnots[k] = v
|
||||||
}
|
}
|
||||||
newAnnots[ownerAnnotation] = string(json)
|
newAnnots[AnnotationOwnerReferences.String()] = string(json)
|
||||||
return newAnnots, nil
|
return newAnnots, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseOwnerAnnotation returns nil if no valid owner found.
|
// parseOwnerAnnotation returns nil if no valid owner found.
|
||||||
func parseOwnerAnnotation(vipSvc *tailscale.VIPService) (*ownerAnnotationValue, error) {
|
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
|
return nil, nil
|
||||||
}
|
}
|
||||||
o := &ownerAnnotationValue{}
|
o := &ownerAnnotationValue{}
|
||||||
if err := json.Unmarshal([]byte(vipSvc.Annotations[ownerAnnotation]), o); err != nil {
|
if err := json.Unmarshal([]byte(vipSvc.Annotations[AnnotationOwnerReferences.String()]), o); err != nil {
|
||||||
return nil, fmt.Errorf("error parsing VIPService %s annotation %q: %w", ownerAnnotation, vipSvc.Annotations[ownerAnnotation], err)
|
return nil, fmt.Errorf("error parsing VIPService %s annotation %q: %w", AnnotationOwnerReferences.String(), vipSvc.Annotations[AnnotationOwnerReferences.String()], err)
|
||||||
}
|
}
|
||||||
return o, nil
|
return o, nil
|
||||||
}
|
}
|
||||||
@ -898,9 +893,9 @@ func parseOwnerAnnotation(vipSvc *tailscale.VIPService) (*ownerAnnotationValue,
|
|||||||
func ownersAreSetAndEqual(a, b *tailscale.VIPService) bool {
|
func ownersAreSetAndEqual(a, b *tailscale.VIPService) bool {
|
||||||
return a != nil && b != nil &&
|
return a != nil && b != nil &&
|
||||||
a.Annotations != nil && b.Annotations != nil &&
|
a.Annotations != nil && b.Annotations != nil &&
|
||||||
a.Annotations[ownerAnnotation] != "" &&
|
a.Annotations[AnnotationOwnerReferences.String()] != "" &&
|
||||||
b.Annotations[ownerAnnotation] != "" &&
|
b.Annotations[AnnotationOwnerReferences.String()] != "" &&
|
||||||
strings.EqualFold(a.Annotations[ownerAnnotation], b.Annotations[ownerAnnotation])
|
strings.EqualFold(a.Annotations[AnnotationOwnerReferences.String()], b.Annotations[AnnotationOwnerReferences.String()])
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensureCertResources ensures that the TLS Secret for an HA Ingress and RBAC
|
// ensureCertResources ensures that the TLS Secret for an HA Ingress and RBAC
|
||||||
|
@ -277,7 +277,7 @@ func TestValidateIngress(t *testing.T) {
|
|||||||
Name: "test-ingress",
|
Name: "test-ingress",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationProxyGroup: "test-pg",
|
AnnotationProxyGroup.String(): "test-pg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: networkingv1.IngressSpec{
|
Spec: networkingv1.IngressSpec{
|
||||||
@ -338,7 +338,7 @@ func TestValidateIngress(t *testing.T) {
|
|||||||
Name: baseIngress.Name,
|
Name: baseIngress.Name,
|
||||||
Namespace: baseIngress.Namespace,
|
Namespace: baseIngress.Namespace,
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationTags: "tag:invalid!",
|
AnnotationTags.String(): "tag:invalid!",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -411,7 +411,7 @@ func TestValidateIngress(t *testing.T) {
|
|||||||
Name: "existing-ingress",
|
Name: "existing-ingress",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationProxyGroup: "test-pg",
|
AnnotationProxyGroup.String(): "test-pg",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: networkingv1.IngressSpec{
|
Spec: networkingv1.IngressSpec{
|
||||||
@ -759,7 +759,7 @@ func TestIngressPGReconciler_MultiCluster(t *testing.T) {
|
|||||||
existingVIPSvc := &tailscale.VIPService{
|
existingVIPSvc := &tailscale.VIPService{
|
||||||
Name: "svc:my-svc",
|
Name: "svc:my-svc",
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
ownerAnnotation: `{"ownerrefs":[{"operatorID":"operator-2"}]}`,
|
AnnotationOwnerReferences.String(): `{"ownerrefs":[{"operatorID":"operator-2"}]}`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
ft.vipServices = map[tailcfg.ServiceName]*tailscale.VIPService{
|
ft.vipServices = map[tailcfg.ServiceName]*tailscale.VIPService{
|
||||||
|
@ -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{
|
sc.AllowFunnel = map[ipn.HostPort]bool{
|
||||||
magic443: true,
|
magic443: true,
|
||||||
}
|
}
|
||||||
@ -204,7 +204,7 @@ func (a *IngressReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
|
|||||||
|
|
||||||
crl := childResourceLabels(ing.Name, ing.Namespace, "ingress")
|
crl := childResourceLabels(ing.Name, ing.Namespace, "ingress")
|
||||||
var tags []string
|
var tags []string
|
||||||
if tstr, ok := ing.Annotations[AnnotationTags]; ok {
|
if tstr, ok := ing.Annotations[AnnotationTags.String()]; ok {
|
||||||
tags = strings.Split(tstr, ",")
|
tags = strings.Split(tstr, ",")
|
||||||
}
|
}
|
||||||
hostname := hostnameForIngress(ing)
|
hostname := hostnameForIngress(ing)
|
||||||
@ -220,7 +220,7 @@ func (a *IngressReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
|
|||||||
proxyType: proxyTypeIngressResource,
|
proxyType: proxyTypeIngressResource,
|
||||||
}
|
}
|
||||||
|
|
||||||
if val := ing.GetAnnotations()[AnnotationExperimentalForwardClusterTrafficViaL7IngresProxy]; val == "true" {
|
if val := ing.GetAnnotations()[AnnotationExperimentalForwardClusterTrafficViaL7IngresProxy.String()]; val == "true" {
|
||||||
sts.ForwardClusterTrafficViaL7IngressProxy = true
|
sts.ForwardClusterTrafficViaL7IngressProxy = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +264,7 @@ func (a *IngressReconciler) shouldExpose(ing *networkingv1.Ingress) bool {
|
|||||||
return ing != nil &&
|
return ing != nil &&
|
||||||
ing.Spec.IngressClassName != nil &&
|
ing.Spec.IngressClassName != nil &&
|
||||||
*ing.Spec.IngressClassName == tailscaleIngressClassName &&
|
*ing.Spec.IngressClassName == tailscaleIngressClassName &&
|
||||||
ing.Annotations[AnnotationProxyGroup] == ""
|
ing.Annotations[AnnotationProxyGroup.String()] == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// validateIngressClass attempts to validate that 'tailscale' IngressClass
|
// validateIngressClass attempts to validate that 'tailscale' IngressClass
|
||||||
|
@ -94,7 +94,7 @@ func TestTailscaleIngress(t *testing.T) {
|
|||||||
// 3. Resources get created for Ingress that should allow forwarding
|
// 3. Resources get created for Ingress that should allow forwarding
|
||||||
// cluster traffic
|
// cluster traffic
|
||||||
mustUpdate(t, fc, "default", "test", func(ing *networkingv1.Ingress) {
|
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
|
opts.shouldEnableForwardingClusterTrafficViaIngress = true
|
||||||
expectReconciled(t, ingR, "default", "test")
|
expectReconciled(t, ingR, "default", "test")
|
||||||
@ -230,7 +230,8 @@ func TestTailscaleIngressWithProxyClass(t *testing.T) {
|
|||||||
Spec: tsapi.ProxyClassSpec{StatefulSet: &tsapi.StatefulSet{
|
Spec: tsapi.ProxyClassSpec{StatefulSet: &tsapi.StatefulSet{
|
||||||
Labels: tsapi.Labels{"foo": "bar"},
|
Labels: tsapi.Labels{"foo": "bar"},
|
||||||
Annotations: map[string]string{"bar.io/foo": "some-val"},
|
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().
|
fc := fake.NewClientBuilder().
|
||||||
WithScheme(tsapi.GlobalScheme).
|
WithScheme(tsapi.GlobalScheme).
|
||||||
@ -285,7 +286,7 @@ func TestTailscaleIngressWithProxyClass(t *testing.T) {
|
|||||||
// 2. Ingress is updated to specify a ProxyClass, ProxyClass is not yet
|
// 2. Ingress is updated to specify a ProxyClass, ProxyClass is not yet
|
||||||
// ready, so proxy resource configuration does not change.
|
// ready, so proxy resource configuration does not change.
|
||||||
mustUpdate(t, fc, "default", "test", func(ing *networkingv1.Ingress) {
|
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")
|
expectReconciled(t, ingR, "default", "test")
|
||||||
expectEqual(t, fc, expectedSTSUserspace(t, fc, opts), removeHashAnnotation, removeResourceReqs)
|
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
|
// Ingress gets reconciled and the custom ProxyClass configuration is
|
||||||
// removed from the proxy resources.
|
// removed from the proxy resources.
|
||||||
mustUpdate(t, fc, "default", "test", func(ing *networkingv1.Ingress) {
|
mustUpdate(t, fc, "default", "test", func(ing *networkingv1.Ingress) {
|
||||||
delete(ing.ObjectMeta.Labels, LabelProxyClass)
|
delete(ing.ObjectMeta.Labels, LabelAnnotationProxyClass)
|
||||||
})
|
})
|
||||||
expectReconciled(t, ingR, "default", "test")
|
expectReconciled(t, ingR, "default", "test")
|
||||||
opts.proxyClass = ""
|
opts.proxyClass = ""
|
||||||
@ -325,14 +326,15 @@ func TestTailscaleIngressWithServiceMonitor(t *testing.T) {
|
|||||||
Status: metav1.ConditionTrue,
|
Status: metav1.ConditionTrue,
|
||||||
Type: string(tsapi.ProxyClassReady),
|
Type: string(tsapi.ProxyClassReady),
|
||||||
ObservedGeneration: 1,
|
ObservedGeneration: 1,
|
||||||
}}},
|
}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
crd := &apiextensionsv1.CustomResourceDefinition{ObjectMeta: metav1.ObjectMeta{Name: serviceMonitorCRD}}
|
crd := &apiextensionsv1.CustomResourceDefinition{ObjectMeta: metav1.ObjectMeta{Name: serviceMonitorCRD}}
|
||||||
|
|
||||||
// Create fake client with ProxyClass, IngressClass, Ingress with metrics ProxyClass, and Service
|
// Create fake client with ProxyClass, IngressClass, Ingress with metrics ProxyClass, and Service
|
||||||
ing := ingress()
|
ing := ingress()
|
||||||
ing.Labels = map[string]string{
|
ing.Labels = map[string]string{
|
||||||
LabelProxyClass: "metrics",
|
LabelAnnotationProxyClass: "metrics",
|
||||||
}
|
}
|
||||||
fc := fake.NewClientBuilder().
|
fc := fake.NewClientBuilder().
|
||||||
WithScheme(tsapi.GlobalScheme).
|
WithScheme(tsapi.GlobalScheme).
|
||||||
@ -452,7 +454,7 @@ func TestIngressLetsEncryptStaging(t *testing.T) {
|
|||||||
ing := ingress()
|
ing := ingress()
|
||||||
if tt.proxyClassPerResource != "" {
|
if tt.proxyClassPerResource != "" {
|
||||||
ing.Labels = map[string]string{
|
ing.Labels = map[string]string{
|
||||||
LabelProxyClass: tt.proxyClassPerResource,
|
LabelAnnotationProxyClass: tt.proxyClassPerResource,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mustCreate(t, fc, ing)
|
mustCreate(t, fc, ing)
|
||||||
|
@ -753,7 +753,7 @@ func proxyClassHandlerForSvc(cl client.Client, logger *zap.SugaredLogger) handle
|
|||||||
return func(ctx context.Context, o client.Object) []reconcile.Request {
|
return func(ctx context.Context, o client.Object) []reconcile.Request {
|
||||||
svcList := new(corev1.ServiceList)
|
svcList := new(corev1.ServiceList)
|
||||||
labels := map[string]string{
|
labels := map[string]string{
|
||||||
LabelProxyClass: o.GetName(),
|
LabelAnnotationProxyClass: o.GetName(),
|
||||||
}
|
}
|
||||||
if err := cl.List(ctx, svcList, client.MatchingLabels(labels)); err != nil {
|
if err := cl.List(ctx, svcList, client.MatchingLabels(labels)); err != nil {
|
||||||
logger.Debugf("error listing Services for ProxyClass: %v", err)
|
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 {
|
return func(ctx context.Context, o client.Object) []reconcile.Request {
|
||||||
ingList := new(networkingv1.IngressList)
|
ingList := new(networkingv1.IngressList)
|
||||||
labels := map[string]string{
|
labels := map[string]string{
|
||||||
LabelProxyClass: o.GetName(),
|
LabelAnnotationProxyClass: o.GetName(),
|
||||||
}
|
}
|
||||||
if err := cl.List(ctx, ingList, client.MatchingLabels(labels)); err != nil {
|
if err := cl.List(ctx, ingList, client.MatchingLabels(labels)); err != nil {
|
||||||
logger.Debugf("error listing Ingresses for ProxyClass: %v", err)
|
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 {
|
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.
|
// Do not reconcile Services for ProxyGroup.
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -1275,7 +1275,7 @@ func indexEgressServices(o client.Object) []string {
|
|||||||
if !isEgressSvcForProxyGroup(o) {
|
if !isEgressSvcForProxyGroup(o) {
|
||||||
return nil
|
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
|
// 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) {
|
if !hasProxyGroupAnnotation(o) {
|
||||||
return nil
|
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
|
// 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 {
|
func hasProxyGroupAnnotation(obj client.Object) bool {
|
||||||
ing := obj.(*networkingv1.Ingress)
|
ing := obj.(*networkingv1.Ingress)
|
||||||
return ing.Annotations[AnnotationProxyGroup] != ""
|
return ing.Annotations[AnnotationProxyGroup.String()] != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func id(ctx context.Context, lc *local.Client) (string, error) {
|
func id(ctx context.Context, lc *local.Client) (string, error) {
|
||||||
|
@ -65,7 +65,7 @@ func TestLoadBalancerClass(t *testing.T) {
|
|||||||
// on it being set.
|
// on it being set.
|
||||||
UID: types.UID("1234-UID"),
|
UID: types.UID("1234-UID"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationTailnetTargetFQDN: "invalid.example.com",
|
AnnotationTailnetTargetFQDN.String(): "invalid.example.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
@ -88,7 +88,7 @@ func TestLoadBalancerClass(t *testing.T) {
|
|||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
UID: types.UID("1234-UID"),
|
UID: types.UID("1234-UID"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationTailnetTargetFQDN: "invalid.example.com",
|
AnnotationTailnetTargetFQDN.String(): "invalid.example.com",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
@ -242,7 +242,7 @@ func TestTailnetTargetFQDNAnnotation(t *testing.T) {
|
|||||||
// on it being set.
|
// on it being set.
|
||||||
UID: types.UID("1234-UID"),
|
UID: types.UID("1234-UID"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationTailnetTargetFQDN: tailnetTargetFQDN,
|
AnnotationTailnetTargetFQDN.String(): tailnetTargetFQDN,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
@ -276,7 +276,7 @@ func TestTailnetTargetFQDNAnnotation(t *testing.T) {
|
|||||||
Finalizers: []string{"tailscale.com/finalizer"},
|
Finalizers: []string{"tailscale.com/finalizer"},
|
||||||
UID: types.UID("1234-UID"),
|
UID: types.UID("1234-UID"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationTailnetTargetFQDN: tailnetTargetFQDN,
|
AnnotationTailnetTargetFQDN.String(): tailnetTargetFQDN,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
@ -298,7 +298,7 @@ func TestTailnetTargetFQDNAnnotation(t *testing.T) {
|
|||||||
tailnetTargetFQDN = "bar.baz.ts.net"
|
tailnetTargetFQDN = "bar.baz.ts.net"
|
||||||
mustUpdate(t, fc, "default", "test", func(s *corev1.Service) {
|
mustUpdate(t, fc, "default", "test", func(s *corev1.Service) {
|
||||||
s.ObjectMeta.Annotations = map[string]string{
|
s.ObjectMeta.Annotations = map[string]string{
|
||||||
AnnotationTailnetTargetFQDN: tailnetTargetFQDN,
|
AnnotationTailnetTargetFQDN.String(): tailnetTargetFQDN,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -354,7 +354,7 @@ func TestTailnetTargetIPAnnotation(t *testing.T) {
|
|||||||
// on it being set.
|
// on it being set.
|
||||||
UID: types.UID("1234-UID"),
|
UID: types.UID("1234-UID"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationTailnetTargetIP: tailnetTargetIP,
|
AnnotationTailnetTargetIP.String(): tailnetTargetIP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
@ -388,7 +388,7 @@ func TestTailnetTargetIPAnnotation(t *testing.T) {
|
|||||||
Finalizers: []string{"tailscale.com/finalizer"},
|
Finalizers: []string{"tailscale.com/finalizer"},
|
||||||
UID: types.UID("1234-UID"),
|
UID: types.UID("1234-UID"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationTailnetTargetIP: tailnetTargetIP,
|
AnnotationTailnetTargetIP.String(): tailnetTargetIP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
@ -410,7 +410,7 @@ func TestTailnetTargetIPAnnotation(t *testing.T) {
|
|||||||
tailnetTargetIP = "100.77.77.77"
|
tailnetTargetIP = "100.77.77.77"
|
||||||
mustUpdate(t, fc, "default", "test", func(s *corev1.Service) {
|
mustUpdate(t, fc, "default", "test", func(s *corev1.Service) {
|
||||||
s.ObjectMeta.Annotations = map[string]string{
|
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"),
|
UID: types.UID("1234-UID"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationTailnetTargetIP: tailnetTargetIP,
|
AnnotationTailnetTargetIP.String(): tailnetTargetIP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
@ -482,7 +482,7 @@ func TestTailnetTargetIPAnnotation_IPCouldNotBeParsed(t *testing.T) {
|
|||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
UID: types.UID("1234-UID"),
|
UID: types.UID("1234-UID"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationTailnetTargetIP: tailnetTargetIP,
|
AnnotationTailnetTargetIP.String(): tailnetTargetIP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
@ -533,7 +533,7 @@ func TestTailnetTargetIPAnnotation_InvalidIP(t *testing.T) {
|
|||||||
|
|
||||||
UID: types.UID("1234-UID"),
|
UID: types.UID("1234-UID"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationTailnetTargetIP: tailnetTargetIP,
|
AnnotationTailnetTargetIP.String(): tailnetTargetIP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
@ -553,7 +553,7 @@ func TestTailnetTargetIPAnnotation_InvalidIP(t *testing.T) {
|
|||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
UID: types.UID("1234-UID"),
|
UID: types.UID("1234-UID"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationTailnetTargetIP: tailnetTargetIP,
|
AnnotationTailnetTargetIP.String(): tailnetTargetIP,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
@ -1132,7 +1132,9 @@ func TestProxyClassForService(t *testing.T) {
|
|||||||
StatefulSet: &tsapi.StatefulSet{
|
StatefulSet: &tsapi.StatefulSet{
|
||||||
Labels: tsapi.Labels{"foo": "bar"},
|
Labels: tsapi.Labels{"foo": "bar"},
|
||||||
Annotations: map[string]string{"bar.io/foo": "some-val"},
|
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().
|
fc := fake.NewClientBuilder().
|
||||||
WithScheme(tsapi.GlobalScheme).
|
WithScheme(tsapi.GlobalScheme).
|
||||||
@ -1194,7 +1196,7 @@ func TestProxyClassForService(t *testing.T) {
|
|||||||
// pointing at the 'custom-metadata' ProxyClass. The ProxyClass is not
|
// pointing at the 'custom-metadata' ProxyClass. The ProxyClass is not
|
||||||
// yet ready, so no changes are actually applied to the proxy resources.
|
// yet ready, so no changes are actually applied to the proxy resources.
|
||||||
mustUpdate(t, fc, "default", "test", func(svc *corev1.Service) {
|
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")
|
expectReconciled(t, sr, "default", "test")
|
||||||
expectEqual(t, fc, expectedSTS(t, fc, opts), removeHashAnnotation, removeResourceReqs)
|
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
|
// configuration from the ProxyClass is removed from the cluster
|
||||||
// resources.
|
// resources.
|
||||||
mustUpdate(t, fc, "default", "test", func(svc *corev1.Service) {
|
mustUpdate(t, fc, "default", "test", func(svc *corev1.Service) {
|
||||||
delete(svc.Labels, LabelProxyClass)
|
delete(svc.Labels, LabelAnnotationProxyClass)
|
||||||
})
|
})
|
||||||
opts.proxyClass = ""
|
opts.proxyClass = ""
|
||||||
expectReconciled(t, sr, "default", "test")
|
expectReconciled(t, sr, "default", "test")
|
||||||
@ -1667,7 +1669,7 @@ func Test_externalNameService(t *testing.T) {
|
|||||||
// on it being set.
|
// on it being set.
|
||||||
UID: types.UID("1234-UID"),
|
UID: types.UID("1234-UID"),
|
||||||
Annotations: map[string]string{
|
Annotations: map[string]string{
|
||||||
AnnotationExpose: "true",
|
AnnotationExpose.String(): "true",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
@ -1711,14 +1713,15 @@ func Test_metricsResourceCreation(t *testing.T) {
|
|||||||
Status: metav1.ConditionTrue,
|
Status: metav1.ConditionTrue,
|
||||||
Type: string(tsapi.ProxyClassReady),
|
Type: string(tsapi.ProxyClassReady),
|
||||||
ObservedGeneration: 1,
|
ObservedGeneration: 1,
|
||||||
}}},
|
}},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
svc := &corev1.Service{
|
svc := &corev1.Service{
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
Name: "test",
|
Name: "test",
|
||||||
Namespace: "default",
|
Namespace: "default",
|
||||||
UID: types.UID("1234-UID"),
|
UID: types.UID("1234-UID"),
|
||||||
Labels: map[string]string{LabelProxyClass: "metrics"},
|
Labels: map[string]string{LabelAnnotationProxyClass: "metrics"},
|
||||||
},
|
},
|
||||||
Spec: corev1.ServiceSpec{
|
Spec: corev1.ServiceSpec{
|
||||||
ClusterIP: "10.20.30.40",
|
ClusterIP: "10.20.30.40",
|
||||||
|
@ -327,11 +327,11 @@ func (r *ProxyGroupReconciler) maybeProvision(ctx context.Context, pg *tsapi.Pro
|
|||||||
// TODO(irbekrm): remove this in 1.84.
|
// TODO(irbekrm): remove this in 1.84.
|
||||||
hash := cfgHash
|
hash := cfgHash
|
||||||
if capver >= 110 {
|
if capver >= 110 {
|
||||||
hash = s.Spec.Template.GetAnnotations()[podAnnotationLastSetConfigFileHash]
|
hash = PodAnnotationLastSetConfigFileHash.GetValue(s)
|
||||||
}
|
}
|
||||||
s.Spec = ss.Spec
|
s.Spec = ss.Spec
|
||||||
if hash != "" && pg.Spec.Type == tsapi.ProxyGroupTypeEgress {
|
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
|
s.ObjectMeta.Labels = ss.ObjectMeta.Labels
|
||||||
|
@ -617,7 +617,7 @@ func expectProxyGroupResources(t *testing.T, fc client.WithWatch, pg *tsapi.Prox
|
|||||||
}
|
}
|
||||||
statefulSet.Annotations = defaultProxyClassAnnotations
|
statefulSet.Annotations = defaultProxyClassAnnotations
|
||||||
if cfgHash != "" {
|
if cfgHash != "" {
|
||||||
mak.Set(&statefulSet.Spec.Template.Annotations, podAnnotationLastSetConfigFileHash, cfgHash)
|
mak.Set(&statefulSet.Spec.Template.Annotations, PodAnnotationLastSetConfigFileHash.String(), cfgHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
if shouldExist {
|
if shouldExist {
|
||||||
|
@ -161,7 +161,7 @@ func Test_applyProxyClassToStatefulSet(t *testing.T) {
|
|||||||
LabelParentName: "foo",
|
LabelParentName: "foo",
|
||||||
}
|
}
|
||||||
annots := map[string]string{
|
annots := map[string]string{
|
||||||
podAnnotationLastSetClusterIP: "1.2.3.4",
|
PodAnnotationLastSetClusterIP.String(): "1.2.3.4",
|
||||||
}
|
}
|
||||||
env := []corev1.EnvVar{{Name: "TS_HOSTNAME", Value: "nginx"}}
|
env := []corev1.EnvVar{{Name: "TS_HOSTNAME", Value: "nginx"}}
|
||||||
userspaceProxySS.Labels = labels
|
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",
|
name: "no custom annots specified and none present in current annots, return current annots",
|
||||||
current: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"},
|
current: map[string]string{PodAnnotationLastSetClusterIP.String(): "1.2.3.4"},
|
||||||
want: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"},
|
want: map[string]string{PodAnnotationLastSetClusterIP.String(): "1.2.3.4"},
|
||||||
managed: tailscaleManagedAnnotations,
|
managed: tailscaleManagedAnnotations,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "no custom annots specified, but some present in current annots, return tailscale managed annots only from the current annots",
|
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"},
|
current: map[string]string{"foo": "bar", "something.io/foo": "bar", PodAnnotationLastSetClusterIP.String(): "1.2.3.4"},
|
||||||
want: map[string]string{podAnnotationLastSetClusterIP: "1.2.3.4"},
|
want: map[string]string{PodAnnotationLastSetClusterIP.String(): "1.2.3.4"},
|
||||||
managed: tailscaleManagedAnnotations,
|
managed: tailscaleManagedAnnotations,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "custom annots specified, current annots only contain tailscale managed annots, return a union of both",
|
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"},
|
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,
|
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",
|
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"},
|
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,
|
managed: tailscaleManagedAnnotations,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -93,7 +93,7 @@ func childResourceLabels(name, ns, typ string) map[string]string {
|
|||||||
|
|
||||||
func (a *ServiceReconciler) isTailscaleService(svc *corev1.Service) bool {
|
func (a *ServiceReconciler) isTailscaleService(svc *corev1.Service) bool {
|
||||||
targetIP := tailnetTargetAnnotation(svc)
|
targetIP := tailnetTargetAnnotation(svc)
|
||||||
targetFQDN := svc.Annotations[AnnotationTailnetTargetFQDN]
|
targetFQDN := AnnotationTailnetTargetFQDN.GetValue(svc)
|
||||||
return a.shouldExpose(svc) || targetIP != "" || targetFQDN != ""
|
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)
|
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
|
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")
|
crl := childResourceLabels(svc.Name, svc.Namespace, "svc")
|
||||||
var tags []string
|
var tags []string
|
||||||
if tstr, ok := svc.Annotations[AnnotationTags]; ok {
|
if tstr := AnnotationTags.GetValue(svc); tstr != "" {
|
||||||
tags = strings.Split(tstr, ",")
|
tags = strings.Split(tstr, ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -287,8 +287,9 @@ func (a *ServiceReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
|
|||||||
sts.TailnetTargetIP = ip
|
sts.TailnetTargetIP = ip
|
||||||
a.managedEgressProxies.Add(svc.UID)
|
a.managedEgressProxies.Add(svc.UID)
|
||||||
gaugeEgressProxies.Set(int64(a.managedEgressProxies.Len()))
|
gaugeEgressProxies.Set(int64(a.managedEgressProxies.Len()))
|
||||||
} else if fqdn := svc.Annotations[AnnotationTailnetTargetFQDN]; fqdn != "" {
|
} else if fqdn := AnnotationTailnetTargetFQDN.GetValue(svc); fqdn != "" {
|
||||||
fqdn := svc.Annotations[AnnotationTailnetTargetFQDN]
|
// NOTE (TOM): Do we need this? fqdn should already be set...
|
||||||
|
fqdn := AnnotationTailnetTargetFQDN.GetValue(svc)
|
||||||
if !strings.HasSuffix(fqdn, ".") {
|
if !strings.HasSuffix(fqdn, ".") {
|
||||||
fqdn = fqdn + "."
|
fqdn = fqdn + "."
|
||||||
}
|
}
|
||||||
@ -367,15 +368,15 @@ func (a *ServiceReconciler) maybeProvision(ctx context.Context, logger *zap.Suga
|
|||||||
|
|
||||||
func validateService(svc *corev1.Service) []string {
|
func validateService(svc *corev1.Service) []string {
|
||||||
violations := make([]string, 0)
|
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))
|
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) {
|
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))
|
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)
|
ip, err := netip.ParseAddr(ipStr)
|
||||||
if err != nil {
|
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))
|
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)
|
svcName := nameForService(svc)
|
||||||
if err := dnsname.ValidLabel(svcName); err != nil {
|
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))
|
violations = append(violations, fmt.Sprintf("invalid Tailscale hostname specified %q: %s", svcName, err))
|
||||||
} else {
|
} else {
|
||||||
violations = append(violations, fmt.Sprintf("invalid Tailscale hostname %q, use %q annotation to override: %s", svcName, AnnotationHostname, err))
|
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
|
// hasExposeAnnotation reports whether Service has the tailscale.com/expose
|
||||||
// annotation set
|
// annotation set
|
||||||
func hasExposeAnnotation(svc *corev1.Service) bool {
|
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
|
// tailnetTargetAnnotation returns the value of tailscale.com/tailnet-ip
|
||||||
@ -431,19 +432,24 @@ func tailnetTargetAnnotation(svc *corev1.Service) string {
|
|||||||
if svc == nil {
|
if svc == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if ip := svc.Annotations[AnnotationTailnetTargetIP]; ip != "" {
|
if ip := AnnotationTailnetTargetIP.GetValue(svc); ip != "" {
|
||||||
return ip
|
return ip
|
||||||
}
|
}
|
||||||
return svc.Annotations[annotationTailnetTargetIPOld]
|
|
||||||
|
return AnnotationTailnetTargetIPOld.GetValue(svc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// proxyClassForObject returns the proxy class for the given object. If the
|
// 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
|
// object does not have a proxy class label, it returns the default proxy class
|
||||||
func proxyClassForObject(o client.Object, proxyDefaultClass string) string {
|
func proxyClassForObject(o client.Object, proxyDefaultClass string) string {
|
||||||
proxyClass, exists := o.GetLabels()[LabelProxyClass]
|
proxyClass, exists := o.GetLabels()[LabelAnnotationProxyClass]
|
||||||
if !exists {
|
if !exists {
|
||||||
proxyClass = proxyDefaultClass
|
proxyClass, exists = o.GetAnnotations()[LabelAnnotationProxyClass]
|
||||||
|
if !exists {
|
||||||
|
proxyClass = proxyDefaultClass
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return proxyClass
|
return proxyClass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,7 +826,7 @@ func (c *fakeTSClient) Deleted() []string {
|
|||||||
// that we don't have to change the annotation in each test case after any
|
// that we don't have to change the annotation in each test case after any
|
||||||
// change to the configfile contents).
|
// change to the configfile contents).
|
||||||
func removeHashAnnotation(sts *appsv1.StatefulSet) {
|
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 {
|
if len(sts.Spec.Template.Annotations) == 0 {
|
||||||
sts.Spec.Template.Annotations = nil
|
sts.Spec.Template.Annotations = nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user