Skip to content

Commit 619b012

Browse files
tomhjpirbekrm
authored andcommitted
cmd/k8s-operator,k8s-operator,go.{mod,sum}: publish proxy status condition for annotated services (tailscale#12463)
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 tailscale#12216 Co-authored-by: Irbe Krumina <[email protected]> Signed-off-by: Tom Proctor <[email protected]>
1 parent 75beae4 commit 619b012

24 files changed

+4176
-1043
lines changed

cmd/k8s-operator/connector.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,8 @@ import (
3333

3434
const (
3535
reasonConnectorCreationFailed = "ConnectorCreationFailed"
36-
37-
reasonConnectorCreated = "ConnectorCreated"
38-
reasonConnectorCleanupFailed = "ConnectorCleanupFailed"
39-
reasonConnectorCleanupInProgress = "ConnectorCleanupInProgress"
40-
reasonConnectorInvalid = "ConnectorInvalid"
36+
reasonConnectorCreated = "ConnectorCreated"
37+
reasonConnectorInvalid = "ConnectorInvalid"
4138

4239
messageConnectorCreationFailed = "Failed creating Connector: %v"
4340
messageConnectorInvalid = "Connector is invalid: %v"
@@ -108,7 +105,7 @@ func (a *ConnectorReconciler) Reconcile(ctx context.Context, req reconcile.Reque
108105
}
109106

110107
oldCnStatus := cn.Status.DeepCopy()
111-
setStatus := func(cn *tsapi.Connector, _ tsapi.ConnectorConditionType, status metav1.ConditionStatus, reason, message string) (reconcile.Result, error) {
108+
setStatus := func(cn *tsapi.Connector, _ tsapi.ConditionType, status metav1.ConditionStatus, reason, message string) (reconcile.Result, error) {
112109
tsoperator.SetConnectorCondition(cn, tsapi.ConnectorReady, status, reason, message, cn.Generation, a.clock, logger)
113110
if !apiequality.Semantic.DeepEqual(oldCnStatus, cn.Status) {
114111
// An error encountered here should get returned by the Reconcile function.

cmd/k8s-operator/connector_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -272,9 +272,9 @@ func TestConnectorWithProxyClass(t *testing.T) {
272272
// its resources.
273273
mustUpdateStatus(t, fc, "", "custom-metadata", func(pc *tsapi.ProxyClass) {
274274
pc.Status = tsapi.ProxyClassStatus{
275-
Conditions: []tsapi.ConnectorCondition{{
275+
Conditions: []metav1.Condition{{
276276
Status: metav1.ConditionTrue,
277-
Type: tsapi.ProxyClassready,
277+
Type: string(tsapi.ProxyClassready),
278278
ObservedGeneration: pc.Generation,
279279
}}}
280280
})

cmd/k8s-operator/deploy/crds/tailscale.com_connectors.yaml

Lines changed: 107 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ apiVersion: apiextensions.k8s.io/v1
22
kind: CustomResourceDefinition
33
metadata:
44
annotations:
5-
controller-gen.kubebuilder.io/version: v0.13.0
5+
controller-gen.kubebuilder.io/version: v0.15.1-0.20240618033008-7824932b0cab
66
name: connectors.tailscale.com
77
spec:
88
group: tailscale.com
@@ -31,48 +31,95 @@ spec:
3131
name: v1alpha1
3232
schema:
3333
openAPIV3Schema:
34-
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'
34+
description: |-
35+
Connector defines a Tailscale node that will be deployed in the cluster. The
36+
node can be configured to act as a Tailscale subnet router and/or a Tailscale
37+
exit node.
38+
Connector is a cluster-scoped resource.
39+
More info:
40+
https://tailscale.com/kb/1236/kubernetes-operator#deploying-exit-nodes-and-subnet-routers-on-kubernetes-using-connector-custom-resource
3541
type: object
3642
required:
3743
- spec
3844
properties:
3945
apiVersion:
40-
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'
46+
description: |-
47+
APIVersion defines the versioned schema of this representation of an object.
48+
Servers should convert recognized schemas to the latest internal value, and
49+
may reject unrecognized values.
50+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
4151
type: string
4252
kind:
43-
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'
53+
description: |-
54+
Kind is a string value representing the REST resource this object represents.
55+
Servers may infer this from the endpoint the client submits requests to.
56+
Cannot be updated.
57+
In CamelCase.
58+
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
4459
type: string
4560
metadata:
4661
type: object
4762
spec:
48-
description: 'ConnectorSpec describes the desired Tailscale component. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status'
63+
description: |-
64+
ConnectorSpec describes the desired Tailscale component.
65+
More info:
66+
https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
4967
type: object
5068
properties:
5169
exitNode:
52-
description: ExitNode defines whether the Connector node should act as a Tailscale exit node. Defaults to false. https://tailscale.com/kb/1103/exit-nodes
70+
description: |-
71+
ExitNode defines whether the Connector node should act as a
72+
Tailscale exit node. Defaults to false.
73+
https://tailscale.com/kb/1103/exit-nodes
5374
type: boolean
5475
hostname:
55-
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.
76+
description: |-
77+
Hostname is the tailnet hostname that should be assigned to the
78+
Connector node. If unset, hostname defaults to <connector
79+
name>-connector. Hostname can contain lower case letters, numbers and
80+
dashes, it must not start or end with a dash and must be between 2
81+
and 63 characters long.
5682
type: string
5783
pattern: ^[a-z0-9][a-z0-9-]{0,61}[a-z0-9]$
5884
proxyClass:
59-
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.
85+
description: |-
86+
ProxyClass is the name of the ProxyClass custom resource that
87+
contains configuration options that should be applied to the
88+
resources created for this Connector. If unset, the operator will
89+
create resources with the default configuration.
6090
type: string
6191
subnetRouter:
62-
description: SubnetRouter defines subnet routes that the Connector node should expose to tailnet. If unset, none are exposed. https://tailscale.com/kb/1019/subnets/
92+
description: |-
93+
SubnetRouter defines subnet routes that the Connector node should
94+
expose to tailnet. If unset, none are exposed.
95+
https://tailscale.com/kb/1019/subnets/
6396
type: object
6497
required:
6598
- advertiseRoutes
6699
properties:
67100
advertiseRoutes:
68-
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/
101+
description: |-
102+
AdvertiseRoutes refer to CIDRs that the subnet router should make
103+
available. Route values must be strings that represent a valid IPv4
104+
or IPv6 CIDR range. Values can be Tailscale 4via6 subnet routes.
105+
https://tailscale.com/kb/1201/4via6-subnets/
69106
type: array
70107
minItems: 1
71108
items:
72109
type: string
73110
format: cidr
74111
tags:
75-
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-]*$.
112+
description: |-
113+
Tags that the Tailscale node will be tagged with.
114+
Defaults to [tag:k8s].
115+
To autoapprove the subnet routes or exit node defined by a Connector,
116+
you can configure Tailscale ACLs to give these tags the necessary
117+
permissions.
118+
See https://tailscale.com/kb/1018/acls/#auto-approvers-for-routes-and-exit-nodes.
119+
If you specify custom tags here, you must also make the operator an owner of these tags.
120+
See https://tailscale.com/kb/1236/kubernetes-operator/#setting-up-the-kubernetes-operator.
121+
Tags cannot be changed once a Connector node has been created.
122+
Tag values must be in form ^tag:[a-zA-Z][a-zA-Z0-9-]*$.
76123
type: array
77124
items:
78125
type: string
@@ -81,53 +128,90 @@ spec:
81128
- rule: has(self.subnetRouter) || self.exitNode == true
82129
message: A Connector needs to be either an exit node or a subnet router, or both.
83130
status:
84-
description: ConnectorStatus describes the status of the Connector. This is set and managed by the Tailscale operator.
131+
description: |-
132+
ConnectorStatus describes the status of the Connector. This is set
133+
and managed by the Tailscale operator.
85134
type: object
86135
properties:
87136
conditions:
88-
description: List of status conditions to indicate the status of the Connector. Known condition types are `ConnectorReady`.
137+
description: |-
138+
List of status conditions to indicate the status of the Connector.
139+
Known condition types are `ConnectorReady`.
89140
type: array
90141
items:
91-
description: ConnectorCondition contains condition information for a Connector.
142+
description: Condition contains details for one aspect of the current state of this API Resource.
92143
type: object
93144
required:
145+
- lastTransitionTime
146+
- message
147+
- reason
94148
- status
95149
- type
96150
properties:
97151
lastTransitionTime:
98-
description: LastTransitionTime is the timestamp corresponding to the last status change of this condition.
152+
description: |-
153+
lastTransitionTime is the last time the condition transitioned from one status to another.
154+
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
99155
type: string
100156
format: date-time
101157
message:
102-
description: Message is a human readable description of the details of the last transition, complementing reason.
158+
description: |-
159+
message is a human readable message indicating details about the transition.
160+
This may be an empty string.
103161
type: string
162+
maxLength: 32768
104163
observedGeneration:
105-
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.
164+
description: |-
165+
observedGeneration represents the .metadata.generation that the condition was set based upon.
166+
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
167+
with respect to the current state of the instance.
106168
type: integer
107169
format: int64
170+
minimum: 0
108171
reason:
109-
description: Reason is a brief machine readable explanation for the condition's last transition.
172+
description: |-
173+
reason contains a programmatic identifier indicating the reason for the condition's last transition.
174+
Producers of specific condition types may define expected values and meanings for this field,
175+
and whether the values are considered a guaranteed API.
176+
The value should be a CamelCase string.
177+
This field may not be empty.
110178
type: string
179+
maxLength: 1024
180+
minLength: 1
181+
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
111182
status:
112-
description: Status of the condition, one of ('True', 'False', 'Unknown').
183+
description: status of the condition, one of True, False, Unknown.
113184
type: string
185+
enum:
186+
- "True"
187+
- "False"
188+
- Unknown
114189
type:
115-
description: Type of the condition, known values are (`SubnetRouterReady`).
190+
description: type of condition in CamelCase or in foo.example.com/CamelCase.
116191
type: string
192+
maxLength: 316
193+
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
117194
x-kubernetes-list-map-keys:
118195
- type
119196
x-kubernetes-list-type: map
120197
hostname:
121-
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.
198+
description: |-
199+
Hostname is the fully qualified domain name of the Connector node.
200+
If MagicDNS is enabled in your tailnet, it is the MagicDNS name of the
201+
node.
122202
type: string
123203
isExitNode:
124204
description: IsExitNode is set to true if the Connector acts as an exit node.
125205
type: boolean
126206
subnetRoutes:
127-
description: SubnetRoutes are the routes currently exposed to tailnet via this Connector instance.
207+
description: |-
208+
SubnetRoutes are the routes currently exposed to tailnet via this
209+
Connector instance.
128210
type: string
129211
tailnetIPs:
130-
description: TailnetIPs is the set of tailnet IP addresses (both IPv4 and IPv6) assigned to the Connector node.
212+
description: |-
213+
TailnetIPs is the set of tailnet IP addresses (both IPv4 and IPv6)
214+
assigned to the Connector node.
131215
type: array
132216
items:
133217
type: string

0 commit comments

Comments
 (0)