Adds a new TailscaleProxyReady condition type for use in corev1.Service
conditions.
Also switch our CRDs to use metav1.Condition instead of
ConnectorCondition. The Go structs are seralized identically, but it
updates some descriptions and validation rules. Update k8s
controller-tools and controller-runtime deps to fix the documentation
generation for metav1.Condition so that it excludes comments and
TODOs.
Stop expecting the fake client to populate TypeMeta in tests. See
kubernetes-sigs/controller-runtime#2633 for details of the change.
Finally, make some minor improvements to validation for service hostnames.
Fixes#12216
Co-authored-by: Irbe Krumina <irbe@tailscale.com>
Signed-off-by: Tom Proctor <tomhjp@users.noreply.github.com>
description: 'Connector defines a Tailscale node that will be deployed in the cluster. The node can be configured to act as a Tailscale subnet router and/or a Tailscale exit node. Connector is a cluster-scoped resource. More info:https://tailscale.com/kb/1236/kubernetes-operator#deploying-exit-nodes-and-subnet-routers-on-kubernetes-using-connector-custom-resource'
description:|-
Connector defines a Tailscale node that will be deployed in the cluster. The
node can be configured to act as a Tailscale subnet router and/or a Tailscale
description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description:|-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type:string
kind:
description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description:|-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type:string
metadata:
type:object
spec:
description: 'ConnectorSpec describes the desired Tailscale component. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status'
description:|-
ConnectorSpec describes the desired Tailscale component.
description:ExitNode defines whether the Connector node should act as a Tailscale exit node. Defaults to false. https://tailscale.com/kb/1103/exit-nodes
description:|-
ExitNode defines whether the Connector node should act as a
Tailscale exit node. Defaults to false.
https://tailscale.com/kb/1103/exit-nodes
type:boolean
hostname:
description:Hostname is the tailnet hostname that should be assigned to the Connector node. If unset, hostname defaults to <connector name>-connector. Hostname can contain lower case letters, numbers and dashes, it must not start or end with a dash and must be between 2 and 63 characters long.
description:|-
Hostname is the tailnet hostname that should be assigned to the
Connector node. If unset, hostname defaults to <connector
name>-connector. Hostname can contain lower case letters, numbers and
dashes, it must not start or end with a dash and must be between 2
and 63 characters long.
type:string
pattern:^[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$
proxyClass:
description:ProxyClass is the name of the ProxyClass custom resource that contains configuration options that should be applied to the resources created for this Connector. If unset, the operator will create resources with the default configuration.
description:|-
ProxyClass is the name of the ProxyClass custom resource that
contains configuration options that should be applied to the
resources created for this Connector. If unset, the operator will
create resources with the default configuration.
type:string
subnetRouter:
description:SubnetRouter defines subnet routes that the Connector node should expose to tailnet. If unset, none are exposed. https://tailscale.com/kb/1019/subnets/
description:|-
SubnetRouter defines subnet routes that the Connector node should
expose to tailnet. If unset, none are exposed.
https://tailscale.com/kb/1019/subnets/
type:object
required:
- advertiseRoutes
properties:
advertiseRoutes:
description:AdvertiseRoutes refer to CIDRs that the subnet router should make available. Route values must be strings that represent a valid IPv4 or IPv6 CIDR range. Values can be Tailscale 4via6 subnet routes. https://tailscale.com/kb/1201/4via6-subnets/
description:|-
AdvertiseRoutes refer to CIDRs that the subnet router should make
available. Route values must be strings that represent a valid IPv4
or IPv6 CIDR range. Values can be Tailscale 4via6 subnet routes.
https://tailscale.com/kb/1201/4via6-subnets/
type:array
minItems:1
items:
type:string
format:cidr
tags:
description:Tags that the Tailscale node will be tagged with. Defaults to [tag:k8s]. To autoapprove the subnet routes or exit node defined by a Connector, you can configure Tailscale ACLs to give these tags the necessary permissions. See https://tailscale.com/kb/1018/acls/#auto-approvers-for-routes-and-exit-nodes. If you specify custom tags here, you must also make the operator an owner of these tags. See https://tailscale.com/kb/1236/kubernetes-operator/#setting-up-the-kubernetes-operator. Tags cannot be changed once a Connector node has been created. Tag values must be in form ^tag:[a-zA-Z][a-zA-Z0-9-]*$.
description:|-
Tags that the Tailscale node will be tagged with.
Defaults to [tag:k8s].
To autoapprove the subnet routes or exit node defined by a Connector,
you can configure Tailscale ACLs to give these tags the necessary
permissions.
See https://tailscale.com/kb/1018/acls/#auto-approvers-for-routes-and-exit-nodes.
If you specify custom tags here, you must also make the operator an owner of these tags.
See https://tailscale.com/kb/1236/kubernetes-operator/#setting-up-the-kubernetes-operator.
Tags cannot be changed once a Connector node has been created.
Tag values must be in form ^tag:[a-zA-Z][a-zA-Z0-9-]*$.
message:A Connector needs to be either an exit node or a subnet router, or both.
status:
description:ConnectorStatus describes the status of the Connector. This is set and managed by the Tailscale operator.
description:|-
ConnectorStatus describes the status of the Connector. This is set
and managed by the Tailscale operator.
type:object
properties:
conditions:
description:List of status conditions to indicate the status of the Connector. Known condition types are `ConnectorReady`.
description:|-
List of status conditions to indicate the status of the Connector.
Known condition types are `ConnectorReady`.
type:array
items:
description:ConnectorCondition contains condition information for a Connector.
description:Condition contains details for one aspect of the current state of this API Resource.
type:object
required:
- lastTransitionTime
- message
- reason
- status
- type
properties:
lastTransitionTime:
description:LastTransitionTime is the timestamp corresponding to the last status change of this condition.
description:|-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
type:string
format:date-time
message:
description:Message is a human readable description of the details of the last transition, complementing reason.
description:|-
message is a human readable message indicating details about the transition.
This may be an empty string.
type:string
maxLength:32768
observedGeneration:
description:If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Connector.
description:|-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
type:integer
format:int64
minimum:0
reason:
description:Reason is a brief machine readable explanation for the condition's last transition.
description:|-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
type:string
maxLength:1024
minLength:1
pattern:^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
status:
description:Status of the condition, one of ('True', 'False', 'Unknown').
description:status of the condition, one of True, False, Unknown.
type:string
enum:
- "True"
- "False"
- Unknown
type:
description:Type of the condition, known values are (`SubnetRouterReady`).
description:type of condition in CamelCase or in foo.example.com/CamelCase.
description:Hostname is the fully qualified domain name of the Connector node. If MagicDNS is enabled in your tailnet, it is the MagicDNS name of the node.
description:|-
Hostname is the fully qualified domain name of the Connector node.
If MagicDNS is enabled in your tailnet, it is the MagicDNS name of the
node.
type:string
isExitNode:
description:IsExitNode is set to true if the Connector acts as an exit node.
type:boolean
subnetRoutes:
description:SubnetRoutes are the routes currently exposed to tailnet via this Connector instance.
description:|-
SubnetRoutes are the routes currently exposed to tailnet via this
Connector instance.
type:string
tailnetIPs:
description:TailnetIPs is the set of tailnet IP addresses (both IPv4 and IPv6) assigned to the Connector node.
description:|-
TailnetIPs is the set of tailnet IP addresses (both IPv4 and IPv6)
description: 'DNSConfig can be deployed to cluster to make a subset of Tailscale MagicDNS names resolvable by cluster workloads. Use this if: A) you need to refer to tailnet services, exposed to cluster via Tailscale Kubernetes operator egress proxies by the MagicDNS names of those tailnet services (usually because the services run over HTTPS) B) you have exposed a cluster workload to the tailnet using Tailscale Ingress and you also want to refer to the workload from within the cluster over the Ingress''s MagicDNS name (usually because you have some callback component that needs to use the same URL as that used by a non-cluster client on tailnet). When a DNSConfig is applied to a cluster, Tailscale Kubernetes operator will deploy a nameserver for ts.net DNS names and automatically populate it with records for any Tailscale egress or Ingress proxies deployed to that cluster. Currently you must manually update your cluster DNS configuration to add the IP address of the deployed nameserver as a ts.net stub nameserver. Instructions for how to do it: https://kubernetes.io/docs/tasks/administer-cluster/dns-custom-nameservers/#configuration-of-stub-domain-and-upstream-nameserver-using-coredns (for CoreDNS), https://cloud.google.com/kubernetes-engine/docs/how-to/kube-dns (for kube-dns). Tailscale Kubernetes operator will write the address of a Service fronting the nameserver to dsnconfig.status.nameserver.ip. DNSConfig is a singleton - you must not create more than one. NB: if you want cluster workloads to be able to refer to Tailscale Ingress using its MagicDNS name, you must also annotate the Ingress resource with tailscale.com/experimental-forward-cluster-traffic-via-ingress annotation to ensure that the proxy created for the Ingress listens on its Pod IP address. NB:Clusters where Pods get assigned IPv6 addresses only are currently not supported.'
description:|-
DNSConfig can be deployed to cluster to make a subset of Tailscale MagicDNS
names resolvable by cluster workloads. Use this if:A) you need to refer to
tailnet services, exposed to cluster via Tailscale Kubernetes operator egress
proxies by the MagicDNS names of those tailnet services (usually because the
services run over HTTPS)
B) you have exposed a cluster workload to the tailnet using Tailscale Ingress
and you also want to refer to the workload from within the cluster over the
Ingress's MagicDNS name (usually because you have some callback component
that needs to use the same URL as that used by a non-cluster client on
tailnet).
When a DNSConfig is applied to a cluster, Tailscale Kubernetes operator will
deploy a nameserver for ts.net DNS names and automatically populate it with records
for any Tailscale egress or Ingress proxies deployed to that cluster.
Currently you must manually update your cluster DNS configuration to add the
IP address of the deployed nameserver as a ts.net stub nameserver.
Tailscale Kubernetes operator will write the address of a Service fronting
the nameserver to dsnconfig.status.nameserver.ip.
DNSConfig is a singleton - you must not create more than one.
NB:if you want cluster workloads to be able to refer to Tailscale Ingress
using its MagicDNS name, you must also annotate the Ingress resource with
tailscale.com/experimental-forward-cluster-traffic-via-ingress annotation to
ensure that the proxy created for the Ingress listens on its Pod IP address.
NB:Clusters where Pods get assigned IPv6 addresses only are currently not supported.
type:object
required:
- spec
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
description:|-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type:string
kind:
description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
description:|-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type:string
metadata:
type:object
spec:
description: 'Spec describes the desired DNS configuration. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status'
description:Configuration for a nameserver that can resolve ts.net DNS names associated with in-cluster proxies for Tailscale egress Services and Tailscale Ingresses. The operator will always deploy this nameserver when a DNSConfig is applied.
description:|-
Configuration for a nameserver that can resolve ts.net DNS names
associated with in-cluster proxies for Tailscale egress Services and
Tailscale Ingresses. The operator will always deploy this nameserver
when a DNSConfig is applied.
type:object
properties:
image:
@ -57,38 +99,66 @@ spec:
description:Tag defaults to operator's own tag.
type:string
status:
description:Status describes the status of the DNSConfig. This is set and managed by the Tailscale operator.
description:|-
Status describes the status of the DNSConfig. This is set
and managed by the Tailscale operator.
type:object
properties:
conditions:
type:array
items:
description:ConnectorCondition contains condition information for a Connector.
description:Condition contains details for one aspect of the current state of this API Resource.
type:object
required:
- lastTransitionTime
- message
- reason
- status
- type
properties:
lastTransitionTime:
description:LastTransitionTime is the timestamp corresponding to the last status change of this condition.
description:|-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
type:string
format:date-time
message:
description:Message is a human readable description of the details of the last transition, complementing reason.
description:|-
message is a human readable message indicating details about the transition.
This may be an empty string.
type:string
maxLength:32768
observedGeneration:
description:If set, this represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.condition[x].observedGeneration is 9, the condition is out of date with respect to the current state of the Connector.
description:|-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
type:integer
format:int64
minimum:0
reason:
description:Reason is a brief machine readable explanation for the condition's last transition.
description:|-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
type:string
maxLength:1024
minLength:1
pattern:^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
status:
description:Status of the condition, one of ('True', 'False', 'Unknown').
description:status of the condition, one of True, False, Unknown.
type:string
enum:
- "True"
- "False"
- Unknown
type:
description:Type of the condition, known values are (`SubnetRouterReady`).
description:type of condition in CamelCase or in foo.example.com/CamelCase.
description:IP is the ClusterIP of the Service fronting the deployed ts.net nameserver. Currently you must manually update your cluster DNS config to add this address as a stub nameserver for ts.net for cluster workloads to be able to resolve MagicDNS names associated with egress or Ingress proxies. The IP address will change if you delete and recreate the DNSConfig.
description:|-
IP is the ClusterIP of the Service fronting the deployed ts.net nameserver.
Currently you must manually update your cluster DNS config to add
this address as a stub nameserver for ts.net for cluster workloads to be
able to resolve MagicDNS names associated with egress or Ingress
proxies.
The IP address will change if you delete and recreate the DNSConfig.
Message:`unable to provision proxy resources: invalid Service: invalid value of annotation tailscale.com/tailnet-fqdn: "invalid.example.com" does not appear to be a valid MagicDNS name`,
}},
},
}
expectEqual(t,fc,want,nil)
// Delete the misconfiguration so the proxy starts getting created on the