From f82dfcc1066b3a350049a9f473625b34193cc7dc Mon Sep 17 00:00:00 2001 From: Irbe Krumina Date: Sun, 10 Mar 2024 22:44:48 +0000 Subject: [PATCH] cmd/k8s-operator/deploy/crds,k8s-operator: add DNSConfig CustomResource Definition DNSConfig CRD can be used to configure the operator to deploy kube nameserver (./cmd/k8s-nameserver) to cluster. Signed-off-by: Irbe Krumina --- .../deploy/crds/tailscale.com_dnsconfigs.yaml | 96 +++++++ k8s-operator/api.md | 270 ++++++++++++++++++ k8s-operator/apis/v1alpha1/register.go | 2 +- .../apis/v1alpha1/types_tsdnsconfig.go | 71 +++++ .../apis/v1alpha1/zz_generated.deepcopy.go | 156 ++++++++++ 5 files changed, 594 insertions(+), 1 deletion(-) create mode 100644 cmd/k8s-operator/deploy/crds/tailscale.com_dnsconfigs.yaml create mode 100644 k8s-operator/apis/v1alpha1/types_tsdnsconfig.go diff --git a/cmd/k8s-operator/deploy/crds/tailscale.com_dnsconfigs.yaml b/cmd/k8s-operator/deploy/crds/tailscale.com_dnsconfigs.yaml new file mode 100644 index 000000000..ba4a66c98 --- /dev/null +++ b/cmd/k8s-operator/deploy/crds/tailscale.com_dnsconfigs.yaml @@ -0,0 +1,96 @@ +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: dnsconfigs.tailscale.com +spec: + group: tailscale.com + names: + kind: DNSConfig + listKind: DNSConfigList + plural: dnsconfigs + shortNames: + - dc + singular: dnsconfig + scope: Cluster + versions: + - additionalPrinterColumns: + - description: Service IP address of the nameserver + jsonPath: .status.nameserverStatus.ip + name: NameserverIP + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + 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' + 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' + type: string + metadata: + type: object + spec: + type: object + required: + - nameserver + properties: + nameserver: + type: object + properties: + image: + type: object + properties: + repo: + type: string + tag: + type: string + status: + type: object + properties: + conditions: + type: array + items: + description: ConnectorCondition contains condition information for a Connector. + type: object + required: + - status + - type + properties: + lastTransitionTime: + description: LastTransitionTime is the timestamp corresponding to the last status change of this condition. + type: string + format: date-time + message: + description: Message is a human readable description of the details of the last transition, complementing reason. + type: string + 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. + type: integer + format: int64 + reason: + description: Reason is a brief machine readable explanation for the condition's last transition. + type: string + status: + description: Status of the condition, one of ('True', 'False', 'Unknown'). + type: string + type: + description: Type of the condition, known values are (`SubnetRouterReady`). + type: string + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + nameserverStatus: + type: object + properties: + ip: + type: string + served: true + storage: true + subresources: + status: {} diff --git a/k8s-operator/api.md b/k8s-operator/api.md index 6b254351e..1e7c9879b 100644 --- a/k8s-operator/api.md +++ b/k8s-operator/api.md @@ -10,6 +10,8 @@ Resource Types: - [Connector](#connector) +- [DNSConfig](#dnsconfig) + - [ProxyClass](#proxyclass) @@ -259,6 +261,274 @@ ConnectorCondition contains condition information for a Connector. +## DNSConfig +[↩ Parent](#tailscalecomv1alpha1 ) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
apiVersionstringtailscale.com/v1alpha1true
kindstringDNSConfigtrue
metadataobjectRefer to the Kubernetes API documentation for the fields of the `metadata` field.true
specobject +
+
true
statusobject +
+
false
+ + +### DNSConfig.spec +[↩ Parent](#dnsconfig) + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
nameserverobject +
+
true
+ + +### DNSConfig.spec.nameserver +[↩ Parent](#dnsconfigspec) + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
imageobject +
+
false
+ + +### DNSConfig.spec.nameserver.image +[↩ Parent](#dnsconfigspecnameserver) + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
repostring +
+
false
tagstring +
+
false
+ + +### DNSConfig.status +[↩ Parent](#dnsconfig) + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
conditions[]object +
+
false
nameserverStatusobject +
+
false
+ + +### DNSConfig.status.conditions[index] +[↩ Parent](#dnsconfigstatus) + + + +ConnectorCondition contains condition information for a Connector. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
statusstring + Status of the condition, one of ('True', 'False', 'Unknown').
+
true
typestring + Type of the condition, known values are (`SubnetRouterReady`).
+
true
lastTransitionTimestring + LastTransitionTime is the timestamp corresponding to the last status change of this condition.
+
+ Format: date-time
+
false
messagestring + Message is a human readable description of the details of the last transition, complementing reason.
+
false
observedGenerationinteger + 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.
+
+ Format: int64
+
false
reasonstring + Reason is a brief machine readable explanation for the condition's last transition.
+
false
+ + +### DNSConfig.status.nameserverStatus +[↩ Parent](#dnsconfigstatus) + + + + + + + + + + + + + + + + + + + + +
NameTypeDescriptionRequired
ipstring +
+
false
+ ## ProxyClass [↩ Parent](#tailscalecomv1alpha1 ) diff --git a/k8s-operator/apis/v1alpha1/register.go b/k8s-operator/apis/v1alpha1/register.go index 4e6bfda64..8c888ff05 100644 --- a/k8s-operator/apis/v1alpha1/register.go +++ b/k8s-operator/apis/v1alpha1/register.go @@ -49,7 +49,7 @@ func init() { // Adds the list of known types to api.Scheme. func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(SchemeGroupVersion, &Connector{}, &ConnectorList{}, &ProxyClass{}, &ProxyClassList{}) + scheme.AddKnownTypes(SchemeGroupVersion, &Connector{}, &ConnectorList{}, &ProxyClass{}, &ProxyClassList{}, &DNSConfig{}, &DNSConfigList{}) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/k8s-operator/apis/v1alpha1/types_tsdnsconfig.go b/k8s-operator/apis/v1alpha1/types_tsdnsconfig.go new file mode 100644 index 000000000..7104d3c13 --- /dev/null +++ b/k8s-operator/apis/v1alpha1/types_tsdnsconfig.go @@ -0,0 +1,71 @@ +// Copyright (c) Tailscale Inc & AUTHORS +// SPDX-License-Identifier: BSD-3-Clause + +//go:build !plan9 + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// Code comments on these types should be treated as user facing documentation- +// they will appear on the DNSConfig CRD i.e if someone runs kubectl explain dnsconfig. + +var DNSConfigKind = "DNSConfig" + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:scope=Cluster,shortName=dc +// +kubebuilder:printcolumn:name="NameserverIP",type="string",JSONPath=`.status.nameserverStatus.ip`,description="Service IP address of the nameserver" + +type DNSConfig struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec DNSConfigSpec `json:"spec"` + + // +optional + Status DNSConfigStatus `json:"status"` +} + +// +kubebuilder:object:root=true + +type DNSConfigList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + + Items []DNSConfig `json:"items"` +} + +type DNSConfigSpec struct { + Nameserver *Nameserver `json:"nameserver"` +} + +type Nameserver struct { + // +optional + Image *Image `json:"image,omitempty"` +} + +type Image struct { + // +optional + Repo string `json:"repo,omitempty"` + // +optional + Tag string `json:"tag,omitempty"` +} + +type DNSConfigStatus struct { + // +listType=map + // +listMapKey=type + // +optional + Conditions []ConnectorCondition `json:"conditions"` + // +optional + NameserverStatus *NameserverStatus `json:"nameserverStatus"` +} + +type NameserverStatus struct { + // +optional + IP string `json:"ip"` +} + +const NameserverReady ConnectorConditionType = `NameserverReady` diff --git a/k8s-operator/apis/v1alpha1/zz_generated.deepcopy.go b/k8s-operator/apis/v1alpha1/zz_generated.deepcopy.go index 4893f52e0..419a763fd 100644 --- a/k8s-operator/apis/v1alpha1/zz_generated.deepcopy.go +++ b/k8s-operator/apis/v1alpha1/zz_generated.deepcopy.go @@ -163,6 +163,112 @@ func (in *Container) DeepCopy() *Container { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DNSConfig) DeepCopyInto(out *DNSConfig) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSConfig. +func (in *DNSConfig) DeepCopy() *DNSConfig { + if in == nil { + return nil + } + out := new(DNSConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DNSConfig) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DNSConfigList) DeepCopyInto(out *DNSConfigList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]DNSConfig, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSConfigList. +func (in *DNSConfigList) DeepCopy() *DNSConfigList { + if in == nil { + return nil + } + out := new(DNSConfigList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DNSConfigList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DNSConfigSpec) DeepCopyInto(out *DNSConfigSpec) { + *out = *in + if in.Nameserver != nil { + in, out := &in.Nameserver, &out.Nameserver + *out = new(Nameserver) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSConfigSpec. +func (in *DNSConfigSpec) DeepCopy() *DNSConfigSpec { + if in == nil { + return nil + } + out := new(DNSConfigSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DNSConfigStatus) DeepCopyInto(out *DNSConfigStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]ConnectorCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.NameserverStatus != nil { + in, out := &in.NameserverStatus, &out.NameserverStatus + *out = new(NameserverStatus) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DNSConfigStatus. +func (in *DNSConfigStatus) DeepCopy() *DNSConfigStatus { + if in == nil { + return nil + } + out := new(DNSConfigStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Env) DeepCopyInto(out *Env) { *out = *in @@ -178,6 +284,21 @@ func (in *Env) DeepCopy() *Env { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Image) DeepCopyInto(out *Image) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Image. +func (in *Image) DeepCopy() *Image { + if in == nil { + return nil + } + out := new(Image) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Metrics) DeepCopyInto(out *Metrics) { *out = *in @@ -193,6 +314,41 @@ func (in *Metrics) DeepCopy() *Metrics { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Nameserver) DeepCopyInto(out *Nameserver) { + *out = *in + if in.Image != nil { + in, out := &in.Image, &out.Image + *out = new(Image) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Nameserver. +func (in *Nameserver) DeepCopy() *Nameserver { + if in == nil { + return nil + } + out := new(Nameserver) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NameserverStatus) DeepCopyInto(out *NameserverStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NameserverStatus. +func (in *NameserverStatus) DeepCopy() *NameserverStatus { + if in == nil { + return nil + } + out := new(NameserverStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Pod) DeepCopyInto(out *Pod) { *out = *in