From 6ca786cfc309341c3759cca761205ccee46d3037 Mon Sep 17 00:00:00 2001 From: Tim Ebert Date: Fri, 3 Nov 2023 14:23:09 +0100 Subject: [PATCH] Add `ClusterRing` API types and CRD --- Makefile | 2 +- config/crds/kustomization.yaml | 5 + .../sharding.timebertt.dev_clusterrings.yaml | 118 +++++++++++++ config/default/kustomization.yaml | 1 + pkg/apis/sharding/v1alpha1/register.go | 20 +++ .../sharding/v1alpha1/types_clusterring.go | 95 +++++++++++ .../v1alpha1/zz_generated.deepcopy.go | 157 ++++++++++++++++++ 7 files changed, 397 insertions(+), 1 deletion(-) create mode 100644 config/crds/kustomization.yaml create mode 100644 config/crds/sharding.timebertt.dev_clusterrings.yaml create mode 100644 pkg/apis/sharding/v1alpha1/types_clusterring.go create mode 100644 pkg/apis/sharding/v1alpha1/zz_generated.deepcopy.go diff --git a/Makefile b/Makefile index 8bb01275..19adbc16 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,7 @@ modules: ## Runs go mod to ensure modules are up to date. .PHONY: generate generate: $(CONTROLLER_GEN) modules ## Run all code generators - $(CONTROLLER_GEN) rbac:roleName=sharder paths="./pkg/..." output:rbac:artifacts:config=config/rbac + $(CONTROLLER_GEN) rbac:roleName=sharder crd paths="./pkg/..." output:rbac:artifacts:config=config/rbac output:crd:artifacts:config=config/crds $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./pkg/..." hack/update-codegen.sh diff --git a/config/crds/kustomization.yaml b/config/crds/kustomization.yaml new file mode 100644 index 00000000..7bfc3002 --- /dev/null +++ b/config/crds/kustomization.yaml @@ -0,0 +1,5 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization + +resources: +- sharding.timebertt.dev_clusterrings.yaml diff --git a/config/crds/sharding.timebertt.dev_clusterrings.yaml b/config/crds/sharding.timebertt.dev_clusterrings.yaml new file mode 100644 index 00000000..2a8e0b01 --- /dev/null +++ b/config/crds/sharding.timebertt.dev_clusterrings.yaml @@ -0,0 +1,118 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: clusterrings.sharding.timebertt.dev +spec: + group: sharding.timebertt.dev + names: + kind: ClusterRing + listKind: ClusterRingList + plural: clusterrings + singular: clusterring + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .status.availableShards + name: Available + type: string + - jsonPath: .status.shards + name: Shards + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: 'ClusterRing declares a virtual ring of sharded controller instances. + TODO(timebertt): implement validation for ClusterRings.' + 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: + description: Spec contains the specification of the desired behavior of + the ClusterRing. + properties: + kinds: + description: Kinds specifies the list of object kinds that are distributed + across shards in this ClusterRing. + items: + description: ClusterRingKind specifies an object kind that is distributed + across shards in the ClusterRing. This kind is the controller's + main kind, i.e., the kind of which it updates the object status. + properties: + apiGroup: + description: APIGroup is the API group of the object. Specify + "" for the core API group. + type: string + controlledKinds: + description: ControlledKinds are additional object kinds that + are distributed across shards in the ClusterRing. These kinds + are controlled by the controller's main kind, i.e., they have + an owner reference with controller=true back to the object + kind of this ClusterRingKind. Typically, the controller also + watches objects of this kind and enqueues the owning object + (of the main kind) whenever the status of a controlled object + changes. + items: + description: ObjectKind specifies an object kind that is distributed + across shards in the ClusterRing. + properties: + apiGroup: + description: APIGroup is the API group of the object. + Specify "" for the core API group. + type: string + kind: + description: Kind is the kind of the object. + type: string + required: + - kind + type: object + type: array + kind: + description: Kind is the kind of the object. + type: string + required: + - kind + type: object + type: array + type: object + status: + description: Status contains the most recently observed status of the + ClusterRing. + properties: + availableShards: + description: AvailableShards is the total number of available shards + of this ring. + format: int32 + type: integer + observedGeneration: + description: The generation observed by the ClusterRing controller. + format: int64 + type: integer + shards: + description: Shards is the total number of shards of this ring. + format: int32 + type: integer + required: + - availableShards + - shards + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml index 61d822f4..cc20e540 100644 --- a/config/default/kustomization.yaml +++ b/config/default/kustomization.yaml @@ -19,6 +19,7 @@ resources: - deployment.yaml - service.yaml - ../rbac +- ../crds configMapGenerator: - name: sharder-config diff --git a/pkg/apis/sharding/v1alpha1/register.go b/pkg/apis/sharding/v1alpha1/register.go index 13fdfbc9..c9465e8c 100644 --- a/pkg/apis/sharding/v1alpha1/register.go +++ b/pkg/apis/sharding/v1alpha1/register.go @@ -20,6 +20,8 @@ limitations under the License. package v1alpha1 import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" ) @@ -28,3 +30,21 @@ const GroupName = "sharding.timebertt.dev" // SchemeGroupVersion is group version used to register these objects var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +var ( + // SchemeBuilder is a new Scheme Builder which registers our API. + SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes) + // AddToScheme is a reference to the Scheme Builder's AddToScheme function. + AddToScheme = SchemeBuilder.AddToScheme +) + +// Adds the list of known types to the given scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &ClusterRing{}, + &ClusterRingList{}, + ) + + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/pkg/apis/sharding/v1alpha1/types_clusterring.go b/pkg/apis/sharding/v1alpha1/types_clusterring.go new file mode 100644 index 00000000..3219c50b --- /dev/null +++ b/pkg/apis/sharding/v1alpha1/types_clusterring.go @@ -0,0 +1,95 @@ +/* +Copyright 2023 Tim Ebert. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +//+kubebuilder:object:root=true +//+kubebuilder:resource:scope=Cluster +//+kubebuilder:subresource:status +//+kubebuilder:printcolumn:name="Available",type=string,JSONPath=`.status.availableShards` +//+kubebuilder:printcolumn:name="Shards",type=string,JSONPath=`.status.shards` +//+kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" + +// ClusterRing declares a virtual ring of sharded controller instances. +// TODO(timebertt): implement validation for ClusterRings. +type ClusterRing struct { + metav1.TypeMeta `json:",inline"` + // Standard object's metadata. + // +optional + metav1.ObjectMeta `json:"metadata,omitempty"` + // Spec contains the specification of the desired behavior of the ClusterRing. + // +optional + Spec ClusterRingSpec `json:"spec,omitempty"` + // Status contains the most recently observed status of the ClusterRing. + // +optional + Status ClusterRingStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// ClusterRingList contains a list of ClusterRings. +type ClusterRingList struct { + metav1.TypeMeta `json:",inline"` + // Standard list metadata. + // +optional + metav1.ListMeta `json:"metadata,omitempty"` + // Items is the list of ClusterRings. + Items []ClusterRing `json:"items"` +} + +// ClusterRingSpec defines the desired state of a ClusterRing. +type ClusterRingSpec struct { + // Kinds specifies the list of object kinds that are distributed across shards in this ClusterRing. + // +optional + Kinds []ClusterRingKind `json:"kinds,omitempty"` +} + +// ClusterRingKind specifies an object kind that is distributed across shards in the ClusterRing. +// This kind is the controller's main kind, i.e., the kind of which it updates the object status. +type ClusterRingKind struct { + ObjectKind `json:",inline"` + + // ControlledKinds are additional object kinds that are distributed across shards in the ClusterRing. + // These kinds are controlled by the controller's main kind, i.e., they have an owner reference with controller=true + // back to the object kind of this ClusterRingKind. Typically, the controller also watches objects of this kind and + // enqueues the owning object (of the main kind) whenever the status of a controlled object changes. + // +optional + ControlledKinds []ObjectKind `json:"controlledKinds,omitempty"` +} + +// ObjectKind specifies an object kind that is distributed across shards in the ClusterRing. +type ObjectKind struct { + // APIGroup is the API group of the object. Specify "" for the core API group. + // +optional + APIGroup string `json:"apiGroup,omitempty"` + // Kind is the kind of the object. + Kind string `json:"kind"` +} + +// ClusterRingStatus defines the observed state of a ClusterRing. +type ClusterRingStatus struct { + // The generation observed by the ClusterRing controller. + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + // Shards is the total number of shards of this ring. + Shards int32 `json:"shards"` + // AvailableShards is the total number of available shards of this ring. + AvailableShards int32 `json:"availableShards"` +} diff --git a/pkg/apis/sharding/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/sharding/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000..6692d00c --- /dev/null +++ b/pkg/apis/sharding/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,157 @@ +//go:build !ignore_autogenerated + +/* +Copyright 2023 Tim Ebert. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterRing) DeepCopyInto(out *ClusterRing) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + out.Status = in.Status +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterRing. +func (in *ClusterRing) DeepCopy() *ClusterRing { + if in == nil { + return nil + } + out := new(ClusterRing) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterRing) 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 *ClusterRingKind) DeepCopyInto(out *ClusterRingKind) { + *out = *in + out.ObjectKind = in.ObjectKind + if in.ControlledKinds != nil { + in, out := &in.ControlledKinds, &out.ControlledKinds + *out = make([]ObjectKind, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterRingKind. +func (in *ClusterRingKind) DeepCopy() *ClusterRingKind { + if in == nil { + return nil + } + out := new(ClusterRingKind) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterRingList) DeepCopyInto(out *ClusterRingList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ClusterRing, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterRingList. +func (in *ClusterRingList) DeepCopy() *ClusterRingList { + if in == nil { + return nil + } + out := new(ClusterRingList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ClusterRingList) 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 *ClusterRingSpec) DeepCopyInto(out *ClusterRingSpec) { + *out = *in + if in.Kinds != nil { + in, out := &in.Kinds, &out.Kinds + *out = make([]ClusterRingKind, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterRingSpec. +func (in *ClusterRingSpec) DeepCopy() *ClusterRingSpec { + if in == nil { + return nil + } + out := new(ClusterRingSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ClusterRingStatus) DeepCopyInto(out *ClusterRingStatus) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterRingStatus. +func (in *ClusterRingStatus) DeepCopy() *ClusterRingStatus { + if in == nil { + return nil + } + out := new(ClusterRingStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ObjectKind) DeepCopyInto(out *ObjectKind) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ObjectKind. +func (in *ObjectKind) DeepCopy() *ObjectKind { + if in == nil { + return nil + } + out := new(ObjectKind) + in.DeepCopyInto(out) + return out +}