diff --git a/PROJECT b/PROJECT index f0a3d11074..305246e8a9 100644 --- a/PROJECT +++ b/PROJECT @@ -1,11 +1,77 @@ domain: nmstate.io -layout: go.kubebuilder.io/v2 +layout: +- go.kubebuilder.io/v3 projectName: kubernetes-nmstate repo: github.com/nmstate/kubernetes-nmstate resources: -- group: nmstate.io +- api: + crdVersion: v1 + controller: true + domain: nmstate.io + group: nmstate.io kind: NMState + path: github.com/nmstate/kubernetes-nmstate/api/v1 + version: v1 +- api: + crdVersion: v1 + controller: true + domain: nmstate.io + group: nmstate.io + kind: NodeNetworkConfigurationPolicy + path: github.com/nmstate/kubernetes-nmstate/api/v1 + version: v1 +- api: + crdVersion: v1 + controller: true + domain: nmstate.io + group: nmstate.io + kind: NMState + path: github.com/nmstate/kubernetes-nmstate/api/v1beta1 + version: v1beta1 +- api: + crdVersion: v1 + controller: true + domain: nmstate.io + group: nmstate.io + kind: NodeNetworkConfigurationEnactment + path: github.com/nmstate/kubernetes-nmstate/api/v1beta1 + version: v1beta1 +- api: + crdVersion: v1 + controller: true + domain: nmstate.io + group: nmstate.io + kind: NodeNetworkConfigurationPolicy + path: github.com/nmstate/kubernetes-nmstate/api/v1beta1 + version: v1beta1 +- api: + crdVersion: v1 + domain: nmstate.io + group: nmstate.io + kind: NodeNetworkState + path: github.com/nmstate/kubernetes-nmstate/api/v1beta1 version: v1beta1 -version: 3-alpha -plugins: - go.sdk.operatorframework.io/v2-alpha: {} +- api: + crdVersion: v1 + controller: true + domain: nmstate.io + group: nmstate.io + kind: NodeNetworkConfigurationEnactment + path: github.com/nmstate/kubernetes-nmstate/api/v1alpha1 + version: v1alpha1 +- api: + crdVersion: v1 + controller: true + domain: nmstate.io + group: nmstate.io + kind: NodeNetworkConfigurationPolicy + path: github.com/nmstate/kubernetes-nmstate/api/v1alpha1 + version: v1alpha1 +- api: + crdVersion: v1 + domain: nmstate.io + group: nmstate.io + kind: NodeNetworkState + path: github.com/nmstate/kubernetes-nmstate/api/v1alpha1 + version: v1alpha1 +version: "3" diff --git a/README.md b/README.md index db9dfac05d..e1f624eb12 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ configuration on cluster nodes and to report back their current state. Both the configuration and reporting is controlled via Kubernetes objects. ```yaml -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: br1-eth0 diff --git a/api/v1/groupversion_info.go b/api/v1/groupversion_info.go new file mode 100644 index 0000000000..48ebb74c30 --- /dev/null +++ b/api/v1/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright The Kubernetes NMState Authors. + +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 v1 contains API Schema definitions for the nmstate.io v1 API group +//+kubebuilder:object:generate=true +//+groupName=nmstate.io +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "nmstate.io", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/v1/nmstate_types.go b/api/v1/nmstate_types.go new file mode 100644 index 0000000000..2487d76d28 --- /dev/null +++ b/api/v1/nmstate_types.go @@ -0,0 +1,78 @@ +/* +Copyright The Kubernetes NMState Authors. + +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 v1 + +import ( + "github.com/nmstate/kubernetes-nmstate/api/shared" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// NMStateSpec defines the desired state of NMState +type NMStateSpec struct { + // NodeSelector is an optional selector that will be added to handler DaemonSet manifest + // for both workers and control-plane (https://github.com/nmstate/kubernetes-nmstate/blob/main/deploy/handler/operator.yaml). + // If NodeSelector is specified, the handler will run only on nodes that have each of the indicated key-value pairs + // as labels applied to the node. + // +optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + // Tolerations is an optional list of tolerations to be added to handler DaemonSet manifest + // If Tolerations is specified, the handler daemonset will be also scheduled on nodes with corresponding taints + // +optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + // InfraNodeSelector is an optional selector that will be added to webhook & certmanager Deployment manifests + // If InfraNodeSelector is specified, the webhook and certmanager will run only on nodes that have each of the indicated + // key-value pairs as labels applied to the node. + // +optional + InfraNodeSelector map[string]string `json:"infraNodeSelector,omitempty"` + // InfraTolerations is an optional list of tolerations to be added to webhook & certmanager Deployment manifests + // If InfraTolerations is specified, the handler daemonset will be able to be scheduled on nodes with corresponding taints + // +optional + InfraTolerations []corev1.Toleration `json:"infraTolerations,omitempty"` +} + +// NMStateStatus defines the observed state of NMState +type NMStateStatus struct { + Conditions shared.ConditionList `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:resource:path=nmstates,scope=Cluster +// +kubebuilder:storageversion +// +kubebuilder:subresource=status + +// NMState is the Schema for the nmstates API +type NMState struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + Spec NMStateSpec `json:"spec,omitempty"` + Status NMStateStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// NMStateList contains a list of NMState +type NMStateList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []NMState `json:"items"` +} + +func init() { + SchemeBuilder.Register(&NMState{}, &NMStateList{}) +} diff --git a/api/v1/nodenetworkconfigurationpolicy_types.go b/api/v1/nodenetworkconfigurationpolicy_types.go new file mode 100644 index 0000000000..42e962c357 --- /dev/null +++ b/api/v1/nodenetworkconfigurationpolicy_types.go @@ -0,0 +1,54 @@ +/* +Copyright The Kubernetes NMState Authors. + +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 v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/nmstate/kubernetes-nmstate/api/shared" +) + +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// +kubebuilder:object:root=true + +// NodeNetworkConfigurationPolicyList contains a list of NodeNetworkConfigurationPolicy +type NodeNetworkConfigurationPolicyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []NodeNetworkConfigurationPolicy `json:"items"` +} + +// +genclient +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:path=nodenetworkconfigurationpolicies,shortName=nncp,scope=Cluster +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.status==\"True\")].type",description="Status" +// +kubebuilder:storageversion + +// NodeNetworkConfigurationPolicy is the Schema for the nodenetworkconfigurationpolicies API +type NodeNetworkConfigurationPolicy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec shared.NodeNetworkConfigurationPolicySpec `json:"spec,omitempty"` + Status shared.NodeNetworkConfigurationPolicyStatus `json:"status,omitempty"` +} + +func init() { + SchemeBuilder.Register(&NodeNetworkConfigurationPolicy{}, &NodeNetworkConfigurationPolicyList{}) +} diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..7f4952bca8 --- /dev/null +++ b/api/v1/zz_generated.deepcopy.go @@ -0,0 +1,210 @@ +// +build !ignore_autogenerated + +/* +Copyright The Kubernetes NMState Authors. + +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 v1 + +import ( + "github.com/nmstate/kubernetes-nmstate/api/shared" + corev1 "k8s.io/api/core/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NMState) DeepCopyInto(out *NMState) { + *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 NMState. +func (in *NMState) DeepCopy() *NMState { + if in == nil { + return nil + } + out := new(NMState) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NMState) 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 *NMStateList) DeepCopyInto(out *NMStateList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NMState, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NMStateList. +func (in *NMStateList) DeepCopy() *NMStateList { + if in == nil { + return nil + } + out := new(NMStateList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NMStateList) 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 *NMStateSpec) DeepCopyInto(out *NMStateSpec) { + *out = *in + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.InfraNodeSelector != nil { + in, out := &in.InfraNodeSelector, &out.InfraNodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.InfraTolerations != nil { + in, out := &in.InfraTolerations, &out.InfraTolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NMStateSpec. +func (in *NMStateSpec) DeepCopy() *NMStateSpec { + if in == nil { + return nil + } + out := new(NMStateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NMStateStatus) DeepCopyInto(out *NMStateStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make(shared.ConditionList, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NMStateStatus. +func (in *NMStateStatus) DeepCopy() *NMStateStatus { + if in == nil { + return nil + } + out := new(NMStateStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeNetworkConfigurationPolicy) DeepCopyInto(out *NodeNetworkConfigurationPolicy) { + *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 NodeNetworkConfigurationPolicy. +func (in *NodeNetworkConfigurationPolicy) DeepCopy() *NodeNetworkConfigurationPolicy { + if in == nil { + return nil + } + out := new(NodeNetworkConfigurationPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeNetworkConfigurationPolicy) 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 *NodeNetworkConfigurationPolicyList) DeepCopyInto(out *NodeNetworkConfigurationPolicyList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NodeNetworkConfigurationPolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeNetworkConfigurationPolicyList. +func (in *NodeNetworkConfigurationPolicyList) DeepCopy() *NodeNetworkConfigurationPolicyList { + if in == nil { + return nil + } + out := new(NodeNetworkConfigurationPolicyList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeNetworkConfigurationPolicyList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} diff --git a/api/v1alpha1/nodenetworkconfigurationenactment_types.go b/api/v1alpha1/nodenetworkconfigurationenactment_types.go index 5470b6e7d2..36c73086ea 100644 --- a/api/v1alpha1/nodenetworkconfigurationenactment_types.go +++ b/api/v1alpha1/nodenetworkconfigurationenactment_types.go @@ -22,6 +22,7 @@ type NodeNetworkConfigurationEnactmentList struct { // +kubebuilder:subresource:status // +kubebuilder:resource:path=nodenetworkconfigurationenactments,shortName=nnce,scope=Cluster // +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.status==\"True\")].type",description="Status" +// +kubebuilder:deprecatedversion // NodeNetworkConfigurationEnactment is the Schema for the nodenetworkconfigurationenactments API type NodeNetworkConfigurationEnactment struct { diff --git a/api/v1alpha1/nodenetworkconfigurationpolicy_types.go b/api/v1alpha1/nodenetworkconfigurationpolicy_types.go index 375e9020d7..497620ddbd 100644 --- a/api/v1alpha1/nodenetworkconfigurationpolicy_types.go +++ b/api/v1alpha1/nodenetworkconfigurationpolicy_types.go @@ -22,6 +22,7 @@ type NodeNetworkConfigurationPolicyList struct { // +kubebuilder:subresource:status // +kubebuilder:resource:path=nodenetworkconfigurationpolicies,shortName=nncp,scope=Cluster // +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.status==\"True\")].type",description="Status" +// +kubebuilder:deprecatedversion // NodeNetworkConfigurationPolicy is the Schema for the nodenetworkconfigurationpolicies API type NodeNetworkConfigurationPolicy struct { diff --git a/api/v1alpha1/nodenetworkstate_types.go b/api/v1alpha1/nodenetworkstate_types.go index 8b0d11a20a..38ca28a32d 100644 --- a/api/v1alpha1/nodenetworkstate_types.go +++ b/api/v1alpha1/nodenetworkstate_types.go @@ -9,6 +9,7 @@ import ( // +kubebuilder:object:root=true // +kubebuilder:subresource:status // +kubebuilder:resource:path=nodenetworkstates,shortName=nns,scope=Cluster +// +kubebuilder:deprecatedversion // NodeNetworkState is the Schema for the nodenetworkstates API type NodeNetworkState struct { diff --git a/api/v1beta1/nmstate_types.go b/api/v1beta1/nmstate_types.go index 5c930ee47b..3e4ddba3ee 100644 --- a/api/v1beta1/nmstate_types.go +++ b/api/v1beta1/nmstate_types.go @@ -52,8 +52,8 @@ type NMStateStatus struct { // +kubebuilder:object:root=true // +kubebuilder:resource:path=nmstates,scope=Cluster -// +kubebuilder:storageversion // +kubebuilder:subresource=status +// +kubebuilder:deprecatedversion // NMState is the Schema for the nmstates API type NMState struct { diff --git a/api/v1beta1/nodenetworkconfigurationenactment_types.go b/api/v1beta1/nodenetworkconfigurationenactment_types.go index 8e5df8a370..27e69dacec 100644 --- a/api/v1beta1/nodenetworkconfigurationenactment_types.go +++ b/api/v1beta1/nodenetworkconfigurationenactment_types.go @@ -5,6 +5,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/nmstate/kubernetes-nmstate/api/shared" + nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" "github.com/nmstate/kubernetes-nmstate/pkg/names" ) @@ -33,7 +34,7 @@ type NodeNetworkConfigurationEnactment struct { Status shared.NodeNetworkConfigurationEnactmentStatus `json:"status,omitempty"` } -func NewEnactment(node *corev1.Node, policy NodeNetworkConfigurationPolicy) NodeNetworkConfigurationEnactment { +func NewEnactment(node *corev1.Node, policy nmstatev1.NodeNetworkConfigurationPolicy) NodeNetworkConfigurationEnactment { enactment := NodeNetworkConfigurationEnactment{ ObjectMeta: metav1.ObjectMeta{ Name: shared.EnactmentKey(node.Name, policy.Name).Name, diff --git a/api/v1beta1/nodenetworkconfigurationenactment_types_test.go b/api/v1beta1/nodenetworkconfigurationenactment_types_test.go index fbf3c605d2..a6af350292 100644 --- a/api/v1beta1/nodenetworkconfigurationenactment_types_test.go +++ b/api/v1beta1/nodenetworkconfigurationenactment_types_test.go @@ -8,13 +8,14 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/nmstate/kubernetes-nmstate/api/shared" + nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" ) var _ = Describe("NodeNetworkEnactment", func() { var ( - nncp = NodeNetworkConfigurationPolicy{ + nncp = nmstatev1.NodeNetworkConfigurationPolicy{ TypeMeta: metav1.TypeMeta{ - APIVersion: "nmstate.io/v1beta1", + APIVersion: "nmstate.io/v1", Kind: "NodeNetworkConfigurationPolicy", }, ObjectMeta: metav1.ObjectMeta{ diff --git a/api/v1beta1/nodenetworkconfigurationpolicy_types.go b/api/v1beta1/nodenetworkconfigurationpolicy_types.go index a4f543b315..2dbc0bbf5c 100644 --- a/api/v1beta1/nodenetworkconfigurationpolicy_types.go +++ b/api/v1beta1/nodenetworkconfigurationpolicy_types.go @@ -22,7 +22,7 @@ type NodeNetworkConfigurationPolicyList struct { // +kubebuilder:subresource:status // +kubebuilder:resource:path=nodenetworkconfigurationpolicies,shortName=nncp,scope=Cluster // +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.status==\"True\")].type",description="Status" -// +kubebuilder:storageversion +// +kubebuilder:deprecatedversion // NodeNetworkConfigurationPolicy is the Schema for the nodenetworkconfigurationpolicies API type NodeNetworkConfigurationPolicy struct { diff --git a/bundle/manifests/kubernetes-nmstate-operator.clusterserviceversion.yaml b/bundle/manifests/kubernetes-nmstate-operator.clusterserviceversion.yaml index b9ecc079e7..07e3b7fc07 100644 --- a/bundle/manifests/kubernetes-nmstate-operator.clusterserviceversion.yaml +++ b/bundle/manifests/kubernetes-nmstate-operator.clusterserviceversion.yaml @@ -4,7 +4,7 @@ metadata: annotations: alm-examples: |- [{ - "apiVersion": "nmstate.io/v1beta1", + "apiVersion": "nmstate.io/v1", "kind": "NMState", "metadata": { "name": "nmstate" @@ -33,7 +33,7 @@ spec: owned: - kind: NMState name: nmstates.nmstate.io - version: v1beta1 + version: v1 description: Represents an NMState deployment. displayName: NMState description: A Kubernetes Operator to install Kubernetes NMState diff --git a/bundle/manifests/nmstate.io_nmstates.yaml b/bundle/manifests/nmstate.io_nmstates.yaml index 6801200a2e..5dae12fdde 100644 --- a/bundle/manifests/nmstate.io_nmstates.yaml +++ b/bundle/manifests/nmstate.io_nmstates.yaml @@ -14,7 +14,7 @@ spec: singular: nmstate scope: Cluster versions: - - name: v1beta1 + - name: v1 schema: openAPIV3Schema: description: NMState is the Schema for the nmstates API diff --git a/cluster/clean.sh b/cluster/clean.sh index 6a136fad2b..960b1d5179 100755 --- a/cluster/clean.sh +++ b/cluster/clean.sh @@ -28,7 +28,7 @@ function clean() { # Delete the CR only if the CRD is installed otherwise it will fail if $kubectl get crds nmstates.nmstate.io; then - $kubectl delete --ignore-not-found -f deploy/crds/nmstate.io_v1beta1_nmstate_cr.yaml + $kubectl delete --ignore-not-found -f deploy/crds/nmstate.io_v1_nmstate_cr.yaml fi $kubectl delete --ignore-not-found -f $MANIFESTS_DIR/operator.yaml $kubectl delete --ignore-not-found -f deploy/crds/nmstate.io_nodenetworkconfigurationenactments.yaml diff --git a/cluster/sync.sh b/cluster/sync.sh index 90c065fc44..83000b27aa 100755 --- a/cluster/sync.sh +++ b/cluster/sync.sh @@ -7,7 +7,7 @@ source ./cluster/sync-operator.sh kubectl=./cluster/kubectl.sh -nmstate_cr_manifest=deploy/crds/nmstate.io_v1beta1_nmstate_cr.yaml +nmstate_cr_manifest=deploy/crds/nmstate.io_v1_nmstate_cr.yaml function deploy_handler() { $kubectl apply -f $nmstate_cr_manifest diff --git a/controllers/nmstate_controller.go b/controllers/nmstate_controller.go index 8e6894d35e..be3301aa41 100644 --- a/controllers/nmstate_controller.go +++ b/controllers/nmstate_controller.go @@ -39,7 +39,7 @@ import ( "github.com/openshift/cluster-network-operator/pkg/apply" "github.com/openshift/cluster-network-operator/pkg/render" - nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1" + nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" "github.com/nmstate/kubernetes-nmstate/pkg/names" nmstaterenderer "github.com/nmstate/kubernetes-nmstate/pkg/render" ) @@ -66,12 +66,12 @@ func (r *NMStateReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct _ = r.Log.WithValues("nmstate", req.NamespacedName) // Fetch the NMState instance - instanceList := &nmstatev1beta1.NMStateList{} + instanceList := &nmstatev1.NMStateList{} err := r.Client.List(context.TODO(), instanceList, &client.ListOptions{}) if err != nil { return ctrl.Result{}, errors.Wrap(err, "failed listing all NMState instances") } - instance := &nmstatev1beta1.NMState{} + instance := &nmstatev1.NMState{} err = r.Client.Get(context.TODO(), req.NamespacedName, instance) if err != nil { if apierrors.IsNotFound(err) { @@ -131,23 +131,23 @@ func (r *NMStateReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ct func (r *NMStateReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). - For(&nmstatev1beta1.NMState{}). + For(&nmstatev1.NMState{}). Complete(r) } -func (r *NMStateReconciler) applyCRDs(instance *nmstatev1beta1.NMState) error { +func (r *NMStateReconciler) applyCRDs(instance *nmstatev1.NMState) error { data := render.MakeRenderData() return r.renderAndApply(instance, data, "crds", false) } -func (r *NMStateReconciler) applyNamespace(instance *nmstatev1beta1.NMState) error { +func (r *NMStateReconciler) applyNamespace(instance *nmstatev1.NMState) error { data := render.MakeRenderData() data.Data["HandlerNamespace"] = os.Getenv("HANDLER_NAMESPACE") data.Data["HandlerPrefix"] = os.Getenv("HANDLER_PREFIX") return r.renderAndApply(instance, data, "namespace", false) } -func (r *NMStateReconciler) applyRBAC(instance *nmstatev1beta1.NMState) error { +func (r *NMStateReconciler) applyRBAC(instance *nmstatev1.NMState) error { data := render.MakeRenderData() data.Data["HandlerNamespace"] = os.Getenv("HANDLER_NAMESPACE") data.Data["HandlerImage"] = os.Getenv("RELATED_IMAGE_HANDLER_IMAGE") @@ -156,7 +156,7 @@ func (r *NMStateReconciler) applyRBAC(instance *nmstatev1beta1.NMState) error { return r.renderAndApply(instance, data, "rbac", true) } -func (r *NMStateReconciler) applyHandler(instance *nmstatev1beta1.NMState) error { +func (r *NMStateReconciler) applyHandler(instance *nmstatev1.NMState) error { data := render.MakeRenderData() // Register ToYaml template method data.Funcs["toYaml"] = nmstaterenderer.ToYaml @@ -224,7 +224,7 @@ func (r *NMStateReconciler) applyHandler(instance *nmstatev1beta1.NMState) error return r.renderAndApply(instance, data, "handler", true) } -func (r *NMStateReconciler) renderAndApply(instance *nmstatev1beta1.NMState, data render.RenderData, sourceDirectory string, setControllerReference bool) error { +func (r *NMStateReconciler) renderAndApply(instance *nmstatev1.NMState, data render.RenderData, sourceDirectory string, setControllerReference bool) error { var err error objs := []*uns.Unstructured{} diff --git a/controllers/nmstate_controller_test.go b/controllers/nmstate_controller_test.go index 8ecaf7d2f2..674a4898ab 100644 --- a/controllers/nmstate_controller_test.go +++ b/controllers/nmstate_controller_test.go @@ -23,7 +23,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1" + nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" "github.com/nmstate/kubernetes-nmstate/pkg/names" ) @@ -48,7 +48,7 @@ var _ = Describe("NMState controller reconcile", func() { Operator: "Exists", }, } - nmstate = nmstatev1beta1.NMState{ + nmstate = nmstatev1.NMState{ ObjectMeta: metav1.ObjectMeta{ Name: existingNMStateName, UID: "12345", @@ -68,9 +68,9 @@ var _ = Describe("NMState controller reconcile", func() { Expect(err).ToNot(HaveOccurred()) s := scheme.Scheme - s.AddKnownTypes(nmstatev1beta1.GroupVersion, - &nmstatev1beta1.NMState{}, - &nmstatev1beta1.NMStateList{}, + s.AddKnownTypes(nmstatev1.GroupVersion, + &nmstatev1.NMState{}, + &nmstatev1.NMStateList{}, ) objs := []runtime.Object{&nmstate} // Create a fake client to mock API calls. @@ -104,7 +104,7 @@ var _ = Describe("NMState controller reconcile", func() { It("and should delete the second one", func() { _, err := reconciler.Reconcile(context.Background(), request) Expect(err).ToNot(HaveOccurred()) - nmstateList := &nmstatev1beta1.NMStateList{} + nmstateList := &nmstatev1.NMStateList{} err = cl.List(context.TODO(), nmstateList, &client.ListOptions{}) Expect(err).ToNot(HaveOccurred()) Expect(len(nmstateList.Items)).To(Equal(1)) @@ -147,8 +147,8 @@ var _ = Describe("NMState controller reconcile", func() { ) BeforeEach(func() { s := scheme.Scheme - s.AddKnownTypes(nmstatev1beta1.GroupVersion, - &nmstatev1beta1.NMState{}, + s.AddKnownTypes(nmstatev1.GroupVersion, + &nmstatev1.NMState{}, ) // set NodeSelector field in operator Spec nmstate.Spec.NodeSelector = handlerNodeSelector @@ -186,8 +186,8 @@ var _ = Describe("NMState controller reconcile", func() { ) BeforeEach(func() { s := scheme.Scheme - s.AddKnownTypes(nmstatev1beta1.GroupVersion, - &nmstatev1beta1.NMState{}, + s.AddKnownTypes(nmstatev1.GroupVersion, + &nmstatev1.NMState{}, ) // set Tolerations field in operator Spec nmstate.Spec.Tolerations = handlerTolerations @@ -221,8 +221,8 @@ var _ = Describe("NMState controller reconcile", func() { ) BeforeEach(func() { s := scheme.Scheme - s.AddKnownTypes(nmstatev1beta1.GroupVersion, - &nmstatev1beta1.NMState{}, + s.AddKnownTypes(nmstatev1.GroupVersion, + &nmstatev1.NMState{}, ) // set InfraNodeSelector field in operator Spec nmstate.Spec.InfraNodeSelector = infraNodeSelector @@ -269,8 +269,8 @@ var _ = Describe("NMState controller reconcile", func() { ) BeforeEach(func() { s := scheme.Scheme - s.AddKnownTypes(nmstatev1beta1.GroupVersion, - &nmstatev1beta1.NMState{}, + s.AddKnownTypes(nmstatev1.GroupVersion, + &nmstatev1.NMState{}, ) // set Tolerations field in operator Spec nmstate.Spec.InfraTolerations = infraTolerations @@ -311,8 +311,8 @@ var _ = Describe("NMState controller reconcile", func() { ) BeforeEach(func() { s := scheme.Scheme - s.AddKnownTypes(nmstatev1beta1.GroupVersion, - &nmstatev1beta1.NMState{}, + s.AddKnownTypes(nmstatev1.GroupVersion, + &nmstatev1.NMState{}, ) objs := []runtime.Object{&nmstate} // Create a fake client to mock API calls. @@ -340,8 +340,8 @@ var _ = Describe("NMState controller reconcile", func() { }) BeforeEach(func() { s := scheme.Scheme - s.AddKnownTypes(nmstatev1beta1.GroupVersion, - &nmstatev1beta1.NMState{}, + s.AddKnownTypes(nmstatev1.GroupVersion, + &nmstatev1.NMState{}, ) objs := []runtime.Object{&nmstate} // Create a fake client to mock API calls. diff --git a/controllers/nodenetworkconfigurationenactment_controller.go b/controllers/nodenetworkconfigurationenactment_controller.go index ad9cbbda87..bcbfac99d7 100644 --- a/controllers/nodenetworkconfigurationenactment_controller.go +++ b/controllers/nodenetworkconfigurationenactment_controller.go @@ -32,6 +32,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "github.com/nmstate/kubernetes-nmstate/api/shared" + nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1" "github.com/nmstate/kubernetes-nmstate/pkg/enactment" ) @@ -67,7 +68,7 @@ func (r *NodeNetworkConfigurationEnactmentReconciler) Reconcile(ctx context.Cont } policyName := enactmentInstance.Labels[shared.EnactmentPolicyLabel] - policyInstance := &nmstatev1beta1.NodeNetworkConfigurationPolicy{} + policyInstance := &nmstatev1.NodeNetworkConfigurationPolicy{} err = r.Client.Get(context.TODO(), types.NamespacedName{Name: policyName}, policyInstance) if err != nil { if apierrors.IsNotFound(err) { diff --git a/controllers/nodenetworkconfigurationenactment_controller_test.go b/controllers/nodenetworkconfigurationenactment_controller_test.go index 82543953c8..1bb7a36dbe 100644 --- a/controllers/nodenetworkconfigurationenactment_controller_test.go +++ b/controllers/nodenetworkconfigurationenactment_controller_test.go @@ -17,6 +17,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" "github.com/nmstate/kubernetes-nmstate/api/shared" + nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1" nmstateenactment "github.com/nmstate/kubernetes-nmstate/pkg/enactment" ) @@ -25,9 +26,9 @@ var _ = Describe("Node Network Configuration Enactment controller reconcile", fu var ( cl client.Client reconciler NodeNetworkConfigurationEnactmentReconciler - policy = nmstatev1beta1.NodeNetworkConfigurationPolicy{ + policy = nmstatev1.NodeNetworkConfigurationPolicy{ TypeMeta: metav1.TypeMeta{ - APIVersion: "nmstate.io/v1beta1", + APIVersion: "nmstate.io/v1", Kind: "NodeNetworkConfigurationPolicy", }, ObjectMeta: metav1.ObjectMeta{ @@ -50,7 +51,9 @@ var _ = Describe("Node Network Configuration Enactment controller reconcile", fu s := scheme.Scheme s.AddKnownTypes(nmstatev1beta1.GroupVersion, &nmstatev1beta1.NodeNetworkConfigurationEnactment{}, - &nmstatev1beta1.NodeNetworkConfigurationPolicy{}, + ) + s.AddKnownTypes(nmstatev1.GroupVersion, + &nmstatev1.NodeNetworkConfigurationPolicy{}, ) objs := []runtime.Object{&policy, &enactment} diff --git a/controllers/nodenetworkconfigurationpolicy_controller.go b/controllers/nodenetworkconfigurationpolicy_controller.go index aca969c588..a745d42562 100644 --- a/controllers/nodenetworkconfigurationpolicy_controller.go +++ b/controllers/nodenetworkconfigurationpolicy_controller.go @@ -45,6 +45,7 @@ import ( "k8s.io/apimachinery/pkg/util/wait" nmstateapi "github.com/nmstate/kubernetes-nmstate/api/shared" + nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1" "github.com/nmstate/kubernetes-nmstate/pkg/enactment" "github.com/nmstate/kubernetes-nmstate/pkg/enactmentstatus" @@ -122,7 +123,7 @@ func (r *NodeNetworkConfigurationPolicyReconciler) Reconcile(ctx context.Context log := r.Log.WithValues("nodenetworkconfigurationpolicy", request.NamespacedName) // Fetch the NodeNetworkConfigurationPolicy instance - instance := &nmstatev1beta1.NodeNetworkConfigurationPolicy{} + instance := &nmstatev1.NodeNetworkConfigurationPolicy{} err := r.Client.Get(context.TODO(), request.NamespacedName, instance) if err != nil { if apierrors.IsNotFound(err) { @@ -216,7 +217,7 @@ func (r *NodeNetworkConfigurationPolicyReconciler) SetupWithManager(mgr ctrl.Man func(client.Object) []reconcile.Request { log := r.Log.WithName("allPolicies") allPoliciesAsRequest := []reconcile.Request{} - policyList := nmstatev1beta1.NodeNetworkConfigurationPolicyList{} + policyList := nmstatev1.NodeNetworkConfigurationPolicyList{} err := r.Client.List(context.TODO(), &policyList) if err != nil { log.Error(err, "failed listing all NodeNetworkConfigurationPolicies to re-reconcile them after node created or updated") @@ -233,7 +234,7 @@ func (r *NodeNetworkConfigurationPolicyReconciler) SetupWithManager(mgr ctrl.Man // Reconcile NNCP if they are created or updated err := ctrl.NewControllerManagedBy(mgr). - For(&nmstatev1beta1.NodeNetworkConfigurationPolicy{}). + For(&nmstatev1.NodeNetworkConfigurationPolicy{}). WithEventFilter(onCreateOrUpdateWithDifferentGenerationOrDelete). Complete(r) if err != nil { @@ -252,7 +253,7 @@ func (r *NodeNetworkConfigurationPolicyReconciler) SetupWithManager(mgr ctrl.Man return nil } -func (r *NodeNetworkConfigurationPolicyReconciler) initializeEnactment(policy nmstatev1beta1.NodeNetworkConfigurationPolicy) (*nmstateapi.ConditionList, error) { +func (r *NodeNetworkConfigurationPolicyReconciler) initializeEnactment(policy nmstatev1.NodeNetworkConfigurationPolicy) (*nmstateapi.ConditionList, error) { desiredStateWithDefaults, err := nmstate.ApplyDefaultVlanFiltering(policy.Spec.DesiredState) if err != nil { return nil, errors.Wrap(err, "error applying defaults to policy desiredState") @@ -294,7 +295,7 @@ func (r *NodeNetworkConfigurationPolicyReconciler) initializeEnactment(policy nm }) } -func (r *NodeNetworkConfigurationPolicyReconciler) enactmentForPolicy(policy *nmstatev1beta1.NodeNetworkConfigurationPolicy) (*nmstatev1beta1.NodeNetworkConfigurationEnactment, error) { +func (r *NodeNetworkConfigurationPolicyReconciler) enactmentForPolicy(policy *nmstatev1.NodeNetworkConfigurationPolicy) (*nmstatev1beta1.NodeNetworkConfigurationEnactment, error) { enactmentKey := nmstateapi.EnactmentKey(nodeName, policy.Name) instance := &nmstatev1beta1.NodeNetworkConfigurationEnactment{} err := r.APIClient.Get(context.TODO(), enactmentKey, instance) @@ -336,13 +337,13 @@ func (r *NodeNetworkConfigurationPolicyReconciler) deleteEnactmentForPolicy(poli return nil } -func (r *NodeNetworkConfigurationPolicyReconciler) shouldIncrementUnavailableNodeCount(policy *nmstatev1beta1.NodeNetworkConfigurationPolicy, conditions *nmstateapi.ConditionList) bool { +func (r *NodeNetworkConfigurationPolicyReconciler) shouldIncrementUnavailableNodeCount(policy *nmstatev1.NodeNetworkConfigurationPolicy, conditions *nmstateapi.ConditionList) bool { return !enactmentstatus.IsProgressing(conditions) && (policy.Status.LastUnavailableNodeCountUpdate == nil || time.Now().Sub(policy.Status.LastUnavailableNodeCountUpdate.Time) < (nmstate.DesiredStateConfigurationTimeout+probe.ProbesTotalTimeout)) } -func (r *NodeNetworkConfigurationPolicyReconciler) incrementUnavailableNodeCount(policy *nmstatev1beta1.NodeNetworkConfigurationPolicy) error { +func (r *NodeNetworkConfigurationPolicyReconciler) incrementUnavailableNodeCount(policy *nmstatev1.NodeNetworkConfigurationPolicy) error { policyKey := types.NamespacedName{Name: policy.GetName(), Namespace: policy.GetNamespace()} err := r.Client.Get(context.TODO(), policyKey, policy) if err != nil { @@ -364,7 +365,7 @@ func (r *NodeNetworkConfigurationPolicyReconciler) incrementUnavailableNodeCount return nil } -func (r *NodeNetworkConfigurationPolicyReconciler) decrementUnavailableNodeCount(policy *nmstatev1beta1.NodeNetworkConfigurationPolicy) { +func (r *NodeNetworkConfigurationPolicyReconciler) decrementUnavailableNodeCount(policy *nmstatev1.NodeNetworkConfigurationPolicy) { policyKey := types.NamespacedName{Name: policy.GetName(), Namespace: policy.GetNamespace()} err := tryDecrementingUnavailableNodeCount(r.Client, r.Client, policyKey) if err != nil { @@ -377,7 +378,7 @@ func (r *NodeNetworkConfigurationPolicyReconciler) decrementUnavailableNodeCount } func tryDecrementingUnavailableNodeCount(statusWriterClient client.StatusClient, readerClient client.Reader, policyKey types.NamespacedName) error { - instance := &nmstatev1beta1.NodeNetworkConfigurationPolicy{} + instance := &nmstatev1.NodeNetworkConfigurationPolicy{} err := retry.RetryOnConflict(retry.DefaultRetry, func() error { err := readerClient.Get(context.TODO(), policyKey, instance) if err != nil { @@ -418,7 +419,7 @@ func desiredState(object runtime.Object) (nmstateapi.State, error) { switch v := object.(type) { default: return nmstateapi.State{}, fmt.Errorf("unexpected type %T", v) - case *nmstatev1beta1.NodeNetworkConfigurationPolicy: + case *nmstatev1.NodeNetworkConfigurationPolicy: state = v.Spec.DesiredState } return state, nil diff --git a/controllers/nodenetworkconfigurationpolicy_controller_test.go b/controllers/nodenetworkconfigurationpolicy_controller_test.go index 518343a1ab..cb7e9478c5 100644 --- a/controllers/nodenetworkconfigurationpolicy_controller_test.go +++ b/controllers/nodenetworkconfigurationpolicy_controller_test.go @@ -15,6 +15,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/event" "github.com/nmstate/kubernetes-nmstate/api/shared" + nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1" "github.com/nmstate/kubernetes-nmstate/pkg/enactmentstatus/conditions" ) @@ -27,12 +28,12 @@ var _ = Describe("NodeNetworkConfigurationPolicy controller predicates", func() } DescribeTable("testing predicates", func(c predicateCase) { - oldNNCP := nmstatev1beta1.NodeNetworkConfigurationPolicy{ + oldNNCP := nmstatev1.NodeNetworkConfigurationPolicy{ ObjectMeta: metav1.ObjectMeta{ Generation: c.GenerationOld, }, } - newNNCP := nmstatev1beta1.NodeNetworkConfigurationPolicy{ + newNNCP := nmstatev1.NodeNetworkConfigurationPolicy{ ObjectMeta: metav1.ObjectMeta{ Generation: c.GenerationNew, }, @@ -80,17 +81,19 @@ var _ = Describe("NodeNetworkConfigurationPolicy controller predicates", func() reconciler := NodeNetworkConfigurationPolicyReconciler{} s := scheme.Scheme s.AddKnownTypes(nmstatev1beta1.GroupVersion, - &nmstatev1beta1.NodeNetworkConfigurationPolicy{}, &nmstatev1beta1.NodeNetworkConfigurationEnactment{}, &nmstatev1beta1.NodeNetworkConfigurationEnactmentList{}, ) + s.AddKnownTypes(nmstatev1.GroupVersion, + &nmstatev1.NodeNetworkConfigurationPolicy{}, + ) node := corev1.Node{ ObjectMeta: metav1.ObjectMeta{ Name: nodeName, }, } - nncp := nmstatev1beta1.NodeNetworkConfigurationPolicy{ + nncp := nmstatev1.NodeNetworkConfigurationPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "test", }, @@ -127,7 +130,7 @@ var _ = Describe("NodeNetworkConfigurationPolicy controller predicates", func() Expect(err).To(BeNil()) Expect(res).To(Equal(c.expectedReconcileResult)) - obtainedNNCP := nmstatev1beta1.NodeNetworkConfigurationPolicy{} + obtainedNNCP := nmstatev1.NodeNetworkConfigurationPolicy{} cl.Get(context.TODO(), types.NamespacedName{Name: nncp.Name}, &obtainedNNCP) Expect(obtainedNNCP.Status.UnavailableNodeCount).To(Equal(c.expectedUnavailableNodeCount)) if c.shouldUpdateUnavailableNodeCount { diff --git a/deploy/crds/nmstate.io_nmstates.yaml b/deploy/crds/nmstate.io_nmstates.yaml index 59e75e7ca9..a82518eaae 100644 --- a/deploy/crds/nmstate.io_nmstates.yaml +++ b/deploy/crds/nmstate.io_nmstates.yaml @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.5.0 + controller-gen.kubebuilder.io/version: v0.6.0 creationTimestamp: null name: nmstates.nmstate.io spec: @@ -16,7 +16,7 @@ spec: singular: nmstate scope: Cluster versions: - - name: v1beta1 + - name: v1 schema: openAPIV3Schema: description: NMState is the Schema for the nmstates API @@ -173,6 +173,164 @@ spec: type: object served: true storage: true + - deprecated: true + name: v1beta1 + schema: + openAPIV3Schema: + description: NMState is the Schema for the nmstates API + 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: NMStateSpec defines the desired state of NMState + properties: + infraNodeSelector: + additionalProperties: + type: string + description: InfraNodeSelector is an optional selector that will be + added to webhook & certmanager Deployment manifests If InfraNodeSelector + is specified, the webhook and certmanager will run only on nodes + that have each of the indicated key-value pairs as labels applied + to the node. + type: object + infraTolerations: + description: InfraTolerations is an optional list of tolerations to + be added to webhook & certmanager Deployment manifests If InfraTolerations + is specified, the handler daemonset will be able to be scheduled + on nodes with corresponding taints + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + nodeSelector: + additionalProperties: + type: string + description: NodeSelector is an optional selector that will be added + to handler DaemonSet manifest for both workers and control-plane + (https://github.com/nmstate/kubernetes-nmstate/blob/main/deploy/handler/operator.yaml). + If NodeSelector is specified, the handler will run only on nodes + that have each of the indicated key-value pairs as labels applied + to the node. + type: object + tolerations: + description: Tolerations is an optional list of tolerations to be + added to handler DaemonSet manifest If Tolerations is specified, + the handler daemonset will be also scheduled on nodes with corresponding + taints + items: + description: The pod this Toleration is attached to tolerates any + taint that matches the triple using the matching + operator . + properties: + effect: + description: Effect indicates the taint effect to match. Empty + means match all taint effects. When specified, allowed values + are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: Key is the taint key that the toleration applies + to. Empty means match all taint keys. If the key is empty, + operator must be Exists; this combination means to match all + values and all keys. + type: string + operator: + description: Operator represents a key's relationship to the + value. Valid operators are Exists and Equal. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod + can tolerate all taints of a particular category. + type: string + tolerationSeconds: + description: TolerationSeconds represents the period of time + the toleration (which must be of effect NoExecute, otherwise + this field is ignored) tolerates the taint. By default, it + is not set, which means tolerate the taint forever (do not + evict). Zero and negative values will be treated as 0 (evict + immediately) by the system. + format: int64 + type: integer + value: + description: Value is the taint value the toleration matches + to. If the operator is Exists, the value should be empty, + otherwise just a regular string. + type: string + type: object + type: array + type: object + status: + description: NMStateStatus defines the observed state of NMState + properties: + conditions: + items: + properties: + lastHearbeatTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + messageEncoded: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: false status: acceptedNames: kind: "" diff --git a/deploy/crds/nmstate.io_nodenetworkconfigurationenactments.yaml b/deploy/crds/nmstate.io_nodenetworkconfigurationenactments.yaml index 6b905b8368..57db920d26 100644 --- a/deploy/crds/nmstate.io_nodenetworkconfigurationenactments.yaml +++ b/deploy/crds/nmstate.io_nodenetworkconfigurationenactments.yaml @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.5.0 + controller-gen.kubebuilder.io/version: v0.6.0 creationTimestamp: null name: nodenetworkconfigurationenactments.nmstate.io spec: @@ -23,6 +23,7 @@ spec: jsonPath: .status.conditions[?(@.status=="True")].type name: Status type: string + deprecated: true name: v1alpha1 schema: openAPIV3Schema: diff --git a/deploy/crds/nmstate.io_nodenetworkconfigurationpolicies.yaml b/deploy/crds/nmstate.io_nodenetworkconfigurationpolicies.yaml index 4a1fda57c4..ebdc63fcd9 100644 --- a/deploy/crds/nmstate.io_nodenetworkconfigurationpolicies.yaml +++ b/deploy/crds/nmstate.io_nodenetworkconfigurationpolicies.yaml @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.5.0 + controller-gen.kubebuilder.io/version: v0.6.0 creationTimestamp: null name: nodenetworkconfigurationpolicies.nmstate.io spec: @@ -23,6 +23,96 @@ spec: jsonPath: .status.conditions[?(@.status=="True")].type name: Status type: string + name: v1 + schema: + openAPIV3Schema: + description: NodeNetworkConfigurationPolicy is the Schema for the nodenetworkconfigurationpolicies + API + 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: NodeNetworkConfigurationPolicySpec defines the desired state + of NodeNetworkConfigurationPolicy + properties: + desiredState: + description: The desired configuration of the policy + type: object + x-kubernetes-preserve-unknown-fields: true + maxUnavailable: + anyOf: + - type: integer + - type: string + description: MaxUnavailable specifies percentage or number of machines + that can be updating at a time. Default is "50%". + x-kubernetes-int-or-string: true + nodeSelector: + additionalProperties: + type: string + description: 'NodeSelector is a selector which must be true for the + policy to be applied to the node. Selector which must match a node''s + labels for the policy to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/' + type: object + type: object + status: + description: NodeNetworkConfigurationPolicyStatus defines the observed + state of NodeNetworkConfigurationPolicy + properties: + conditions: + items: + properties: + lastHearbeatTime: + format: date-time + type: string + lastTransitionTime: + format: date-time + type: string + message: + type: string + messageEncoded: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - status + - type + type: object + type: array + lastUnavailableNodeCountUpdate: + description: LastUnavailableNodeCountUpdate is time of the last UnavailableNodeCount + update + format: date-time + type: string + unavailableNodeCount: + description: UnavailableNodeCount represents the total number of potentially + unavailable nodes that are processing a NodeNetworkConfigurationPolicy + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} + - additionalPrinterColumns: + - description: Status + jsonPath: .status.conditions[?(@.status=="True")].type + name: Status + type: string + deprecated: true name: v1alpha1 schema: openAPIV3Schema: @@ -112,6 +202,7 @@ spec: jsonPath: .status.conditions[?(@.status=="True")].type name: Status type: string + deprecated: true name: v1beta1 schema: openAPIV3Schema: @@ -193,7 +284,7 @@ spec: type: object type: object served: true - storage: true + storage: false subresources: status: {} status: diff --git a/deploy/crds/nmstate.io_nodenetworkstates.yaml b/deploy/crds/nmstate.io_nodenetworkstates.yaml index 806ca1bebd..b2175f1746 100644 --- a/deploy/crds/nmstate.io_nodenetworkstates.yaml +++ b/deploy/crds/nmstate.io_nodenetworkstates.yaml @@ -4,7 +4,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.5.0 + controller-gen.kubebuilder.io/version: v0.6.0 creationTimestamp: null name: nodenetworkstates.nmstate.io spec: @@ -18,7 +18,8 @@ spec: singular: nodenetworkstate scope: Cluster versions: - - name: v1alpha1 + - deprecated: true + name: v1alpha1 schema: openAPIV3Schema: description: NodeNetworkState is the Schema for the nodenetworkstates API diff --git a/deploy/crds/nmstate.io_v1beta1_nmstate_cr.yaml b/deploy/crds/nmstate.io_v1_nmstate_cr.yaml similarity index 56% rename from deploy/crds/nmstate.io_v1beta1_nmstate_cr.yaml rename to deploy/crds/nmstate.io_v1_nmstate_cr.yaml index 49e371725b..cbba0c6c1b 100644 --- a/deploy/crds/nmstate.io_v1beta1_nmstate_cr.yaml +++ b/deploy/crds/nmstate.io_v1_nmstate_cr.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NMState metadata: name: nmstate diff --git a/deploy/crds/nmstate.io_v1beta1_nodenetworkconfigurationpolicy_cr.yaml b/deploy/crds/nmstate.io_v1_nodenetworkconfigurationpolicy_cr.yaml similarity index 93% rename from deploy/crds/nmstate.io_v1beta1_nodenetworkconfigurationpolicy_cr.yaml rename to deploy/crds/nmstate.io_v1_nodenetworkconfigurationpolicy_cr.yaml index fd4166d898..eed213ce15 100644 --- a/deploy/crds/nmstate.io_v1beta1_nodenetworkconfigurationpolicy_cr.yaml +++ b/deploy/crds/nmstate.io_v1_nodenetworkconfigurationpolicy_cr.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: example-nodenetworkconfigurationpolicy diff --git a/deploy/crds/nmstate.io_v1beta1_nodenetworkconfigurationenactment_cr.yaml b/deploy/crds/nmstate.io_v1beta1_nodenetworkconfigurationenactment_cr.yaml index 9981cef0c7..86f30e99c2 100644 --- a/deploy/crds/nmstate.io_v1beta1_nodenetworkconfigurationenactment_cr.yaml +++ b/deploy/crds/nmstate.io_v1beta1_nodenetworkconfigurationenactment_cr.yaml @@ -5,7 +5,7 @@ metadata: generation: 1 name: node01.test-policy ownerReferences: - - apiVersion: nmstate.io/v1beta1 + - apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy name: test-policy uid: d7e35a96-6094-4b2e-a899-9ee6a5eef157 diff --git a/deploy/handler/operator.yaml b/deploy/handler/operator.yaml index 677cfc80cf..2ed31de1ba 100644 --- a/deploy/handler/operator.yaml +++ b/deploy/handler/operator.yaml @@ -318,7 +318,7 @@ webhooks: rules: - operations: ["CREATE", "UPDATE"] apiGroups: ["*"] - apiVersions: ["v1alpha1","v1beta1"] + apiVersions: ["v1alpha1","v1beta1","v1"] resources: ["nodenetworkconfigurationpolicies"] - name: nodenetworkconfigurationpolicies-status-mutate.nmstate.io admissionReviewVersions: ["v1", "v1beta1"] @@ -331,7 +331,7 @@ webhooks: rules: - operations: ["CREATE", "UPDATE"] apiGroups: ["*"] - apiVersions: ["v1alpha1","v1beta1"] + apiVersions: ["v1alpha1","v1beta1","v1"] resources: ["nodenetworkconfigurationpolicies/status"] - name: nodenetworkconfigurationpolicies-timestamp-mutate.nmstate.io admissionReviewVersions: ["v1", "v1beta1"] @@ -344,7 +344,7 @@ webhooks: rules: - operations: ["CREATE", "UPDATE"] apiGroups: ["*"] - apiVersions: ["v1alpha1","v1beta1"] + apiVersions: ["v1alpha1","v1beta1","v1"] resources: ["nodenetworkconfigurationpolicies", "nodenetworkconfigurationpolicies/status"] - name: nodenetworkconfigurationpolicies-update-validate.nmstate.io admissionReviewVersions: ["v1", "v1beta1"] @@ -357,7 +357,7 @@ webhooks: rules: - operations: ["UPDATE"] apiGroups: ["*"] - apiVersions: ["v1alpha1","v1beta1"] + apiVersions: ["v1alpha1","v1beta1","v1"] resources: ["nodenetworkconfigurationpolicies"] - name: nodenetworkconfigurationpolicies-create-validate.nmstate.io admissionReviewVersions: [ "v1", "v1beta1" ] @@ -370,7 +370,7 @@ webhooks: rules: - operations: ["CREATE"] apiGroups: ["*"] - apiVersions: ["v1alpha1","v1beta1"] + apiVersions: ["v1alpha1","v1beta1","v1"] resources: ["nodenetworkconfigurationpolicies"] --- apiVersion: policy/v1 diff --git a/docs/examples/bond-vlan.yaml b/docs/examples/bond-vlan.yaml index a4eeec7017..f50a657b56 100644 --- a/docs/examples/bond-vlan.yaml +++ b/docs/examples/bond-vlan.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: bond-vlan diff --git a/docs/examples/bond.yaml b/docs/examples/bond.yaml index b0dcee2504..aa722854a7 100644 --- a/docs/examples/bond.yaml +++ b/docs/examples/bond.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: bond diff --git a/docs/examples/detach-bridge-port-and-restore-eth.yaml b/docs/examples/detach-bridge-port-and-restore-eth.yaml index 6b259035a0..5d4077a2cf 100644 --- a/docs/examples/detach-bridge-port-and-restore-eth.yaml +++ b/docs/examples/detach-bridge-port-and-restore-eth.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: detach-bridge-port-and-restore-eth diff --git a/docs/examples/dhcp.yaml b/docs/examples/dhcp.yaml index 6c85419368..136379955b 100644 --- a/docs/examples/dhcp.yaml +++ b/docs/examples/dhcp.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: dhcp diff --git a/docs/examples/dns.yaml b/docs/examples/dns.yaml index 3259f8d07e..82fd91ede2 100644 --- a/docs/examples/dns.yaml +++ b/docs/examples/dns.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: dns diff --git a/docs/examples/ethernet.yaml b/docs/examples/ethernet.yaml index b096e5d8be..251595ffdc 100644 --- a/docs/examples/ethernet.yaml +++ b/docs/examples/ethernet.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: ethernet diff --git a/docs/examples/linux-bridge-vlan.yaml b/docs/examples/linux-bridge-vlan.yaml index d4426b1193..6c9d12fe3d 100644 --- a/docs/examples/linux-bridge-vlan.yaml +++ b/docs/examples/linux-bridge-vlan.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: linux-bridge-vlan diff --git a/docs/examples/linux-bridge.yaml b/docs/examples/linux-bridge.yaml index 925abc3719..9b145635d6 100644 --- a/docs/examples/linux-bridge.yaml +++ b/docs/examples/linux-bridge.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: linux-bridge diff --git a/docs/examples/ovs-bridge-iface.yaml b/docs/examples/ovs-bridge-iface.yaml index 12a43cefc6..a95988da61 100644 --- a/docs/examples/ovs-bridge-iface.yaml +++ b/docs/examples/ovs-bridge-iface.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: ovs-bridge-iface diff --git a/docs/examples/ovs-bridge.yaml b/docs/examples/ovs-bridge.yaml index 636edffe94..587190f7d3 100644 --- a/docs/examples/ovs-bridge.yaml +++ b/docs/examples/ovs-bridge.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: ovs-bridge diff --git a/docs/examples/route.yaml b/docs/examples/route.yaml index a7fb53f728..6078b3d831 100644 --- a/docs/examples/route.yaml +++ b/docs/examples/route.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: route diff --git a/docs/examples/static-ip.yaml b/docs/examples/static-ip.yaml index 0f4a5a5aff..e7077fdb39 100644 --- a/docs/examples/static-ip.yaml +++ b/docs/examples/static-ip.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: static-ip diff --git a/docs/examples/vlan.yaml b/docs/examples/vlan.yaml index eb43480d61..cffa1cdb48 100644 --- a/docs/examples/vlan.yaml +++ b/docs/examples/vlan.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: vlan diff --git a/docs/examples/worker-selector.yaml b/docs/examples/worker-selector.yaml index aa1b374db9..1758e15f61 100644 --- a/docs/examples/worker-selector.yaml +++ b/docs/examples/worker-selector.yaml @@ -1,4 +1,4 @@ -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: worker-selector diff --git a/docs/index.md b/docs/index.md index 20bb3628c0..6733271fbb 100644 --- a/docs/index.md +++ b/docs/index.md @@ -12,7 +12,7 @@ configuration on cluster nodes and to report back their current state. Both the configuration and reporting is controlled via Kubernetes objects. ```yaml -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: br1-eth0 diff --git a/docs/user-guide/bond0-eth1-eth2_absent.yaml b/docs/user-guide/bond0-eth1-eth2_absent.yaml index 23ae0f2285..e8e7055dc0 100644 --- a/docs/user-guide/bond0-eth1-eth2_absent.yaml +++ b/docs/user-guide/bond0-eth1-eth2_absent.yaml @@ -1,5 +1,5 @@ # When updating this file, don't forget to update the tutorial. -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: bond0-eth1-eth2 diff --git a/docs/user-guide/bond0-eth1-eth2_up.yaml b/docs/user-guide/bond0-eth1-eth2_up.yaml index f8afc073e8..2f683a88a3 100644 --- a/docs/user-guide/bond0-eth1-eth2_up.yaml +++ b/docs/user-guide/bond0-eth1-eth2_up.yaml @@ -1,5 +1,5 @@ # When updating this file, don't forget to update the tutorial. -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: bond0-eth1-eth2 diff --git a/docs/user-guide/eth1-eth2_up.yaml b/docs/user-guide/eth1-eth2_up.yaml index 655ebf0d4c..3937b5c3c7 100644 --- a/docs/user-guide/eth1-eth2_up.yaml +++ b/docs/user-guide/eth1-eth2_up.yaml @@ -1,5 +1,5 @@ # When updating this file, don't forget to update the tutorial. -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: eth1 @@ -13,7 +13,7 @@ spec: dhcp: true enabled: true --- -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: eth2 diff --git a/docs/user-guide/eth666_up.yaml b/docs/user-guide/eth666_up.yaml index 655c0a3fdb..8c81c07632 100644 --- a/docs/user-guide/eth666_up.yaml +++ b/docs/user-guide/eth666_up.yaml @@ -1,5 +1,5 @@ # When updating this file, don't forget to update the tutorial. -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: eth666 diff --git a/docs/user-guide/linux-bridge_maxunavailable.yaml b/docs/user-guide/linux-bridge_maxunavailable.yaml index ecee6cefdd..de684dc682 100644 --- a/docs/user-guide/linux-bridge_maxunavailable.yaml +++ b/docs/user-guide/linux-bridge_maxunavailable.yaml @@ -1,5 +1,5 @@ # When updating this file, don't forget to update the tutorial. -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: linux-bridge-maxunavailable diff --git a/docs/user-guide/vlan100_node01_up.yaml b/docs/user-guide/vlan100_node01_up.yaml index 2935b2ad34..fe39217926 100644 --- a/docs/user-guide/vlan100_node01_up.yaml +++ b/docs/user-guide/vlan100_node01_up.yaml @@ -1,5 +1,5 @@ # When updating this file, don't forget to update the tutorial. -apiVersion: nmstate.io/v1beta1 +apiVersion: nmstate.io/v1 kind: NodeNetworkConfigurationPolicy metadata: name: vlan100 diff --git a/go.mod b/go.mod index e92bd51891..049e030813 100644 --- a/go.mod +++ b/go.mod @@ -31,7 +31,7 @@ require ( k8s.io/release v0.9.0 kubevirt.io/qe-tools v0.1.7 sigs.k8s.io/controller-runtime v0.9.0 - sigs.k8s.io/controller-tools v0.5.0 + sigs.k8s.io/controller-tools v0.6.0 sigs.k8s.io/yaml v1.2.0 ) diff --git a/go.sum b/go.sum index 70acd4f9cf..daf618f213 100644 --- a/go.sum +++ b/go.sum @@ -368,6 +368,8 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.10.0 h1:s36xzo75JdqLaaWoiEHk767eHiwo0598uUxyfiPkDsg= github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= +github.com/fatih/color v1.12.0 h1:mRhaKNwANqRgUBGKmnI5ZxEk7QXmjQeCcuYFMX2bfcc= +github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= github.com/fatih/structtag v1.1.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= @@ -622,6 +624,8 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-containerregistry v0.5.1 h1:/+mFTs4AlwsJ/mJe8NDtKb7BxLtbZFpcn8vDsneEkwQ= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= @@ -2199,6 +2203,8 @@ sigs.k8s.io/controller-tools v0.2.8/go.mod h1:9VKHPszmf2DHz/QmHkcfZoewO6BL7pPs9u sigs.k8s.io/controller-tools v0.4.1/go.mod h1:G9rHdZMVlBDocIxGkK3jHLWqcTMNvveypYJwrvYKjWU= sigs.k8s.io/controller-tools v0.5.0 h1:3u2RCwOlp0cjCALAigpOcbAf50pE+kHSdueUosrC/AE= sigs.k8s.io/controller-tools v0.5.0/go.mod h1:JTsstrMpxs+9BUj6eGuAaEb6SDSPTeVtUyp0jmnAM/I= +sigs.k8s.io/controller-tools v0.6.0 h1:o2Fm1K7CmIp8OVaBtXsWB/ssBAzyoKZPPAGR3VuxaKs= +sigs.k8s.io/controller-tools v0.6.0/go.mod h1:baRMVPrctU77F+rfAuH2uPqW93k6yQnZA2dhUOr7ihc= sigs.k8s.io/k8s-container-image-promoter v1.337.0/go.mod h1:wdNhLd/SlIs+rgTw8D6RaaUWSdTnM0OEhGfXU3kI50o= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= sigs.k8s.io/kustomize/api v0.8.8/go.mod h1:He1zoK0nk43Pc6NlV085xDXDXTNprtcyKZVm3swsdNY= diff --git a/hack/release-notes.tmpl b/hack/release-notes.tmpl index 418acea76a..b528daf320 100644 --- a/hack/release-notes.tmpl +++ b/hack/release-notes.tmpl @@ -32,7 +32,7 @@ kubernetes-nmstate handler: ```yaml cat < 0 { diff --git a/pkg/webhook/nodenetworkconfigurationpolicy/validation_test.go b/pkg/webhook/nodenetworkconfigurationpolicy/validation_test.go index 1c5aaa1768..f6d486be40 100644 --- a/pkg/webhook/nodenetworkconfigurationpolicy/validation_test.go +++ b/pkg/webhook/nodenetworkconfigurationpolicy/validation_test.go @@ -8,14 +8,14 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" shared "github.com/nmstate/kubernetes-nmstate/api/shared" - nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1" + nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" "github.com/nmstate/kubernetes-nmstate/pkg/policyconditions" ) -func p(nodeSelector map[string]string, conditionsSetter func(*shared.ConditionList, string), message string) nmstatev1beta1.NodeNetworkConfigurationPolicy { +func p(nodeSelector map[string]string, conditionsSetter func(*shared.ConditionList, string), message string) nmstatev1.NodeNetworkConfigurationPolicy { conditions := shared.ConditionList{} conditionsSetter(&conditions, message) - return nmstatev1beta1.NodeNetworkConfigurationPolicy{ + return nmstatev1.NodeNetworkConfigurationPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "testPolicy", }, @@ -30,7 +30,7 @@ func p(nodeSelector map[string]string, conditionsSetter func(*shared.ConditionLi var _ = Describe("NNCP Conditions Validation Admission Webhook", func() { var allNodes = map[string]string{} - var testPolicy = nmstatev1beta1.NodeNetworkConfigurationPolicy{ + var testPolicy = nmstatev1.NodeNetworkConfigurationPolicy{ ObjectMeta: metav1.ObjectMeta{ Name: "testPolicy", }, @@ -38,9 +38,9 @@ var _ = Describe("NNCP Conditions Validation Admission Webhook", func() { Status: shared.NodeNetworkConfigurationPolicyStatus{}, } type ValidationWebhookCase struct { - policy nmstatev1beta1.NodeNetworkConfigurationPolicy - currentPolicy nmstatev1beta1.NodeNetworkConfigurationPolicy - validationFn func(policy nmstatev1beta1.NodeNetworkConfigurationPolicy, current nmstatev1beta1.NodeNetworkConfigurationPolicy) []metav1.StatusCause + policy nmstatev1.NodeNetworkConfigurationPolicy + currentPolicy nmstatev1.NodeNetworkConfigurationPolicy + validationFn func(policy nmstatev1.NodeNetworkConfigurationPolicy, current nmstatev1.NodeNetworkConfigurationPolicy) []metav1.StatusCause validationResult []metav1.StatusCause } DescribeTable("the NNCP conditions", func(v ValidationWebhookCase) { @@ -108,7 +108,7 @@ var _ = Describe("NNCP Conditions Validation Admission Webhook", func() { validationResult: []metav1.StatusCause{}, }), Entry("policy has name with length beyond the limit", ValidationWebhookCase{ - policy: nmstatev1beta1.NodeNetworkConfigurationPolicy{ObjectMeta: metav1.ObjectMeta{Name: "this-is-longer-than-sixty-three-characters-hostname-bar-bar-bar.foo.com"}}, + policy: nmstatev1.NodeNetworkConfigurationPolicy{ObjectMeta: metav1.ObjectMeta{Name: "this-is-longer-than-sixty-three-characters-hostname-bar-bar-bar.foo.com"}}, validationFn: validatePolicyName, validationResult: []metav1.StatusCause{{ Type: metav1.CauseTypeFieldValueInvalid, @@ -117,7 +117,7 @@ var _ = Describe("NNCP Conditions Validation Admission Webhook", func() { }}, }), Entry("policy has name with invalid format", ValidationWebhookCase{ - policy: nmstatev1beta1.NodeNetworkConfigurationPolicy{ObjectMeta: metav1.ObjectMeta{Name: "foo+bar"}}, + policy: nmstatev1.NodeNetworkConfigurationPolicy{ObjectMeta: metav1.ObjectMeta{Name: "foo+bar"}}, validationFn: validatePolicyName, validationResult: []metav1.StatusCause{{ Type: metav1.CauseTypeFieldValueInvalid, diff --git a/test/e2e/handler/upgrade_test.go b/test/e2e/handler/upgrade_test.go index b54d058aa9..a4d0a54a9e 100644 --- a/test/e2e/handler/upgrade_test.go +++ b/test/e2e/handler/upgrade_test.go @@ -11,6 +11,7 @@ import ( nmstate "github.com/nmstate/kubernetes-nmstate/api/shared" nmstatev1alpha1 "github.com/nmstate/kubernetes-nmstate/api/v1alpha1" + nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1" testenv "github.com/nmstate/kubernetes-nmstate/test/env" ) @@ -35,9 +36,32 @@ var _ = Describe("NodeNetworkConfigurationPolicy upgrade", func() { updateDesiredStateAndWait(linuxBrAbsent(bridge1)) resetDesiredStateForNodes() }) - It("should be stored as v1beta1 and end with available state", func() { + It("should be stored as v1 and end with available state", func() { waitForAvailableTestPolicy() }) }) + Context("when v1beta1 is populated", func() { + BeforeEach(func() { + maxUnavailableIntOrString := intstr.FromString(maxUnavailable) + policy := nmstatev1beta1.NodeNetworkConfigurationPolicy{ + ObjectMeta: metav1.ObjectMeta{ + Name: TestPolicy, + }, + Spec: nmstate.NodeNetworkConfigurationPolicySpec{ + DesiredState: linuxBrUp(bridge1), + NodeSelector: map[string]string{"node-role.kubernetes.io/worker": ""}, + MaxUnavailable: &maxUnavailableIntOrString, + }, + } + Expect(testenv.Client.Create(context.TODO(), &policy)).To(Succeed(), "should success creating a v1beta1 nncp") + }) + AfterEach(func() { + updateDesiredStateAndWait(linuxBrAbsent(bridge1)) + resetDesiredStateForNodes() + }) + It("should be stored as v1 and end with available state", func() { + waitForAvailableTestPolicy() + }) + }) }) diff --git a/test/e2e/handler/utils.go b/test/e2e/handler/utils.go index 8e8f745519..975b016068 100644 --- a/test/e2e/handler/utils.go +++ b/test/e2e/handler/utils.go @@ -21,6 +21,7 @@ import ( dynclient "sigs.k8s.io/controller-runtime/pkg/client" nmstate "github.com/nmstate/kubernetes-nmstate/api/shared" + nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1" nmstatenode "github.com/nmstate/kubernetes-nmstate/pkg/node" "github.com/nmstate/kubernetes-nmstate/test/cmd" @@ -68,7 +69,7 @@ func interfaceByName(interfaces []interface{}, searchedName string) map[string]i } func setDesiredStateWithPolicyAndNodeSelector(name string, desiredState nmstate.State, nodeSelector map[string]string) error { - policy := nmstatev1beta1.NodeNetworkConfigurationPolicy{} + policy := nmstatev1.NodeNetworkConfigurationPolicy{} policy.Name = name key := types.NamespacedName{Name: name} err := testenv.Client.Get(context.TODO(), key, &policy) @@ -144,9 +145,9 @@ func nodeNetworkState(key types.NamespacedName) nmstatev1beta1.NodeNetworkState return state } -func nodeNetworkConfigurationPolicy(policyName string) nmstatev1beta1.NodeNetworkConfigurationPolicy { +func nodeNetworkConfigurationPolicy(policyName string) nmstatev1.NodeNetworkConfigurationPolicy { key := types.NamespacedName{Name: policyName} - policy := nmstatev1beta1.NodeNetworkConfigurationPolicy{} + policy := nmstatev1.NodeNetworkConfigurationPolicy{} EventuallyWithOffset(1, func() error { return testenv.Client.Get(context.TODO(), key, &policy) }, ReadTimeout, ReadInterval).ShouldNot(HaveOccurred()) @@ -166,7 +167,7 @@ func deleteNodeNeworkStates() { func deletePolicy(name string) { Byf("Deleting policy %s", name) - policy := &nmstatev1beta1.NodeNetworkConfigurationPolicy{} + policy := &nmstatev1.NodeNetworkConfigurationPolicy{} policy.Name = name err := testenv.Client.Delete(context.TODO(), policy) if apierrors.IsNotFound(err) { @@ -176,7 +177,7 @@ func deletePolicy(name string) { // Wait for policy to be removed EventuallyWithOffset(1, func() bool { - err := testenv.Client.Get(context.TODO(), types.NamespacedName{Name: name}, &nmstatev1beta1.NodeNetworkConfigurationPolicy{}) + err := testenv.Client.Get(context.TODO(), types.NamespacedName{Name: name}, &nmstatev1.NodeNetworkConfigurationPolicy{}) return apierrors.IsNotFound(err) }, 60*time.Second, 1*time.Second).Should(BeTrue(), fmt.Sprintf("Policy %s not deleted", name)) diff --git a/test/e2e/handler/webhook_test.go b/test/e2e/handler/webhook_test.go index de41514f17..bdce8517bc 100644 --- a/test/e2e/handler/webhook_test.go +++ b/test/e2e/handler/webhook_test.go @@ -9,7 +9,7 @@ import ( "k8s.io/client-go/util/retry" - nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1" + nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" nncpwebhook "github.com/nmstate/kubernetes-nmstate/pkg/webhook/nodenetworkconfigurationpolicy" testenv "github.com/nmstate/kubernetes-nmstate/test/env" ) @@ -35,7 +35,7 @@ var _ = Describe("Mutating Admission Webhook", func() { }) Context("and we updated it", func() { var ( - oldPolicy nmstatev1beta1.NodeNetworkConfigurationPolicy + oldPolicy nmstatev1.NodeNetworkConfigurationPolicy ) BeforeEach(func() { oldPolicy = nodeNetworkConfigurationPolicy(TestPolicy) @@ -80,7 +80,7 @@ var _ = Describe("Validation Admission Webhook", func() { Context("When a policy with too long name is created", func() { const tooLongName = "this-is-longer-than-sixty-three-characters-hostnames-bar-bar.com" It("Should deny creating policy with name longer than 63 characters", func() { - policy := nmstatev1beta1.NodeNetworkConfigurationPolicy{} + policy := nmstatev1.NodeNetworkConfigurationPolicy{} policy.Name = tooLongName err := testenv.Client.Create(context.TODO(), &policy) Expect(err).To(MatchError("admission webhook \"nodenetworkconfigurationpolicies-create-validate.nmstate.io\" denied the request: failed to admit NodeNetworkConfigurationPolicy this-is-longer-than-sixty-three-characters-hostnames-bar-bar.com: message: invalid policy name: \"this-is-longer-than-sixty-three-characters-hostnames-bar-bar.com\": must be no more than 63 characters. ")) diff --git a/test/e2e/operator/main_test.go b/test/e2e/operator/main_test.go index 3c779eb608..8712ef7ecf 100644 --- a/test/e2e/operator/main_test.go +++ b/test/e2e/operator/main_test.go @@ -23,7 +23,7 @@ import ( logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" - nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1" + nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" "github.com/nmstate/kubernetes-nmstate/test/e2e/daemonset" "github.com/nmstate/kubernetes-nmstate/test/e2e/deployment" testenv "github.com/nmstate/kubernetes-nmstate/test/env" @@ -32,7 +32,7 @@ import ( type operatorTestData struct { ns string - nmstate nmstatev1beta1.NMState + nmstate nmstatev1.NMState webhookKey, handlerKey, certManagerKey types.NamespacedName handlerLabels map[string]string } @@ -40,7 +40,7 @@ type operatorTestData struct { func newOperatorTestData(ns string) operatorTestData { return operatorTestData{ ns: ns, - nmstate: nmstatev1beta1.NMState{ + nmstate: nmstatev1.NMState{ ObjectMeta: metav1.ObjectMeta{ Name: "nmstate", Namespace: ns, @@ -99,13 +99,13 @@ var _ = AfterSuite(func() { uninstallNMStateAndWaitForDeletion(defaultOperator) }) -func installNMState(nmstate nmstatev1beta1.NMState) { +func installNMState(nmstate nmstatev1.NMState) { By(fmt.Sprintf("Creating NMState CR '%s'", nmstate.Name)) err := testenv.Client.Create(context.TODO(), &nmstate) ExpectWithOffset(1, err).ToNot(HaveOccurred(), "NMState CR created without error") } -func uninstallNMState(nmstate nmstatev1beta1.NMState) { +func uninstallNMState(nmstate nmstatev1.NMState) { By(fmt.Sprintf("Deleting NMState CR '%s'", nmstate.Name)) err := testenv.Client.Delete(context.TODO(), &nmstate, &client.DeleteOptions{}) Expect(err).To(SatisfyAny(Succeed(), WithTransform(apierrors.IsNotFound, BeTrue())), "NMState CR successfully removed") diff --git a/test/env/env.go b/test/env/env.go index 4c211e3df7..a72a6f1160 100644 --- a/test/env/env.go +++ b/test/env/env.go @@ -9,6 +9,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/envtest" + nmstatev1 "github.com/nmstate/kubernetes-nmstate/api/v1" nmstatev1alpha1 "github.com/nmstate/kubernetes-nmstate/api/v1alpha1" nmstatev1beta1 "github.com/nmstate/kubernetes-nmstate/api/v1beta1" "github.com/nmstate/kubernetes-nmstate/test/environment" @@ -37,6 +38,8 @@ func Start() { ExpectWithOffset(1, err).ToNot(HaveOccurred()) ExpectWithOffset(1, cfg).ToNot(BeNil()) + err = nmstatev1.AddToScheme(scheme.Scheme) + ExpectWithOffset(1, err).NotTo(HaveOccurred()) err = nmstatev1beta1.AddToScheme(scheme.Scheme) ExpectWithOffset(1, err).NotTo(HaveOccurred()) err = nmstatev1alpha1.AddToScheme(scheme.Scheme) diff --git a/vendor/github.com/fatih/color/README.md b/vendor/github.com/fatih/color/README.md index d62e4024aa..5c751f2158 100644 --- a/vendor/github.com/fatih/color/README.md +++ b/vendor/github.com/fatih/color/README.md @@ -127,14 +127,16 @@ fmt.Println("All text will now be bold magenta.") There might be a case where you want to explicitly disable/enable color output. the `go-isatty` package will automatically disable color output for non-tty output streams -(for example if the output were piped directly to `less`) +(for example if the output were piped directly to `less`). -`Color` has support to disable/enable colors both globally and for single color -definitions. For example suppose you have a CLI app and a `--no-color` bool flag. You -can easily disable the color output with: +The `color` package also disables color output if the [`NO_COLOR`](https://no-color.org) environment +variable is set (regardless of its value). -```go +`Color` has support to disable/enable colors programatically both globally and +for single color definitions. For example suppose you have a CLI app and a +`--no-color` bool flag. You can easily disable the color output with: +```go var flagNoColor = flag.Bool("no-color", false, "Disable color output") if *flagNoColor { @@ -156,6 +158,10 @@ c.EnableColor() c.Println("This prints again cyan...") ``` +## GitHub Actions + +To output color in GitHub Actions (or other CI systems that support ANSI colors), make sure to set `color.NoColor = false` so that it bypasses the check for non-tty output streams. + ## Todo * Save/Return previous values @@ -170,4 +176,3 @@ c.Println("This prints again cyan...") ## License The MIT License (MIT) - see [`LICENSE.md`](https://github.com/fatih/color/blob/master/LICENSE.md) for more details - diff --git a/vendor/github.com/fatih/color/color.go b/vendor/github.com/fatih/color/color.go index 91c8e9f062..98a60f3c88 100644 --- a/vendor/github.com/fatih/color/color.go +++ b/vendor/github.com/fatih/color/color.go @@ -15,9 +15,11 @@ import ( var ( // NoColor defines if the output is colorized or not. It's dynamically set to // false or true based on the stdout's file descriptor referring to a terminal - // or not. This is a global option and affects all colors. For more control - // over each color block use the methods DisableColor() individually. - NoColor = os.Getenv("TERM") == "dumb" || + // or not. It's also set to true if the NO_COLOR environment variable is + // set (regardless of its value). This is a global option and affects all + // colors. For more control over each color block use the methods + // DisableColor() individually. + NoColor = noColorExists() || os.Getenv("TERM") == "dumb" || (!isatty.IsTerminal(os.Stdout.Fd()) && !isatty.IsCygwinTerminal(os.Stdout.Fd())) // Output defines the standard output of the print functions. By default @@ -33,6 +35,12 @@ var ( colorsCacheMu sync.Mutex // protects colorsCache ) +// noColorExists returns true if the environment variable NO_COLOR exists. +func noColorExists() bool { + _, exists := os.LookupEnv("NO_COLOR") + return exists +} + // Color defines a custom color object which is defined by SGR parameters. type Color struct { params []Attribute @@ -108,7 +116,14 @@ const ( // New returns a newly created color object. func New(value ...Attribute) *Color { - c := &Color{params: make([]Attribute, 0)} + c := &Color{ + params: make([]Attribute, 0), + } + + if noColorExists() { + c.noColor = boolPtr(true) + } + c.Add(value...) return c } @@ -387,7 +402,7 @@ func (c *Color) EnableColor() { } func (c *Color) isNoColorSet() bool { - // check first if we have user setted action + // check first if we have user set action if c.noColor != nil { return *c.noColor } diff --git a/vendor/github.com/fatih/color/doc.go b/vendor/github.com/fatih/color/doc.go index cf1e96500f..04541de786 100644 --- a/vendor/github.com/fatih/color/doc.go +++ b/vendor/github.com/fatih/color/doc.go @@ -118,6 +118,8 @@ the color output with: color.NoColor = true // disables colorized output } +You can also disable the color by setting the NO_COLOR environment variable to any value. + It also has support for single color definitions (local). You can disable/enable color output on the fly: diff --git a/vendor/github.com/google/go-cmp/cmp/path.go b/vendor/github.com/google/go-cmp/cmp/path.go index 3d45c1a47f..f01eff318c 100644 --- a/vendor/github.com/google/go-cmp/cmp/path.go +++ b/vendor/github.com/google/go-cmp/cmp/path.go @@ -315,7 +315,7 @@ func (tf Transform) Option() Option { return tf.trans } // pops the address from the stack. Thus, when traversing into a pointer from // reflect.Ptr, reflect.Slice element, or reflect.Map, we can detect cycles // by checking whether the pointer has already been visited. The cycle detection -// uses a seperate stack for the x and y values. +// uses a separate stack for the x and y values. // // If a cycle is detected we need to determine whether the two pointers // should be considered equal. The definition of equality chosen by Equal diff --git a/vendor/github.com/google/go-cmp/cmp/report_slices.go b/vendor/github.com/google/go-cmp/cmp/report_slices.go index 168f92f3c1..2ad3bc85ba 100644 --- a/vendor/github.com/google/go-cmp/cmp/report_slices.go +++ b/vendor/github.com/google/go-cmp/cmp/report_slices.go @@ -7,6 +7,7 @@ package cmp import ( "bytes" "fmt" + "math" "reflect" "strconv" "strings" @@ -96,15 +97,16 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { } // Auto-detect the type of the data. - var isLinedText, isText, isBinary bool var sx, sy string + var ssx, ssy []string + var isString, isMostlyText, isPureLinedText, isBinary bool switch { case t.Kind() == reflect.String: sx, sy = vx.String(), vy.String() - isText = true // Initial estimate, verify later + isString = true case t.Kind() == reflect.Slice && t.Elem() == reflect.TypeOf(byte(0)): sx, sy = string(vx.Bytes()), string(vy.Bytes()) - isBinary = true // Initial estimate, verify later + isString = true case t.Kind() == reflect.Array: // Arrays need to be addressable for slice operations to work. vx2, vy2 := reflect.New(t).Elem(), reflect.New(t).Elem() @@ -112,13 +114,12 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { vy2.Set(vy) vx, vy = vx2, vy2 } - if isText || isBinary { - var numLines, lastLineIdx, maxLineLen int - isBinary = !utf8.ValidString(sx) || !utf8.ValidString(sy) + if isString { + var numTotalRunes, numValidRunes, numLines, lastLineIdx, maxLineLen int for i, r := range sx + sy { - if !(unicode.IsPrint(r) || unicode.IsSpace(r)) || r == utf8.RuneError { - isBinary = true - break + numTotalRunes++ + if (unicode.IsPrint(r) || unicode.IsSpace(r)) && r != utf8.RuneError { + numValidRunes++ } if r == '\n' { if maxLineLen < i-lastLineIdx { @@ -128,8 +129,26 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { numLines++ } } - isText = !isBinary - isLinedText = isText && numLines >= 4 && maxLineLen <= 1024 + isPureText := numValidRunes == numTotalRunes + isMostlyText = float64(numValidRunes) > math.Floor(0.90*float64(numTotalRunes)) + isPureLinedText = isPureText && numLines >= 4 && maxLineLen <= 1024 + isBinary = !isMostlyText + + // Avoid diffing by lines if it produces a significantly more complex + // edit script than diffing by bytes. + if isPureLinedText { + ssx = strings.Split(sx, "\n") + ssy = strings.Split(sy, "\n") + esLines := diff.Difference(len(ssx), len(ssy), func(ix, iy int) diff.Result { + return diff.BoolResult(ssx[ix] == ssy[iy]) + }) + esBytes := diff.Difference(len(sx), len(sy), func(ix, iy int) diff.Result { + return diff.BoolResult(sx[ix] == sy[iy]) + }) + efficiencyLines := float64(esLines.Dist()) / float64(len(esLines)) + efficiencyBytes := float64(esBytes.Dist()) / float64(len(esBytes)) + isPureLinedText = efficiencyLines < 4*efficiencyBytes + } } // Format the string into printable records. @@ -138,9 +157,7 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { switch { // If the text appears to be multi-lined text, // then perform differencing across individual lines. - case isLinedText: - ssx := strings.Split(sx, "\n") - ssy := strings.Split(sy, "\n") + case isPureLinedText: list = opts.formatDiffSlice( reflect.ValueOf(ssx), reflect.ValueOf(ssy), 1, "line", func(v reflect.Value, d diffMode) textRecord { @@ -229,7 +246,7 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { // If the text appears to be single-lined text, // then perform differencing in approximately fixed-sized chunks. // The output is printed as quoted strings. - case isText: + case isMostlyText: list = opts.formatDiffSlice( reflect.ValueOf(sx), reflect.ValueOf(sy), 64, "byte", func(v reflect.Value, d diffMode) textRecord { @@ -237,7 +254,6 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { return textRecord{Diff: d, Value: textLine(s)} }, ) - delim = "" // If the text appears to be binary data, // then perform differencing in approximately fixed-sized chunks. @@ -299,7 +315,7 @@ func (opts formatOptions) FormatDiffSlice(v *valueNode) textNode { // Wrap the output with appropriate type information. var out textNode = &textWrap{Prefix: "{", Value: list, Suffix: "}"} - if !isText { + if !isMostlyText { // The "{...}" byte-sequence literal is not valid Go syntax for strings. // Emit the type for extra clarity (e.g. "string{...}"). if t.Kind() == reflect.String { @@ -338,8 +354,11 @@ func (opts formatOptions) formatDiffSlice( vx, vy reflect.Value, chunkSize int, name string, makeRec func(reflect.Value, diffMode) textRecord, ) (list textList) { - es := diff.Difference(vx.Len(), vy.Len(), func(ix int, iy int) diff.Result { - return diff.BoolResult(vx.Index(ix).Interface() == vy.Index(iy).Interface()) + eq := func(ix, iy int) bool { + return vx.Index(ix).Interface() == vy.Index(iy).Interface() + } + es := diff.Difference(vx.Len(), vy.Len(), func(ix, iy int) diff.Result { + return diff.BoolResult(eq(ix, iy)) }) appendChunks := func(v reflect.Value, d diffMode) int { @@ -364,6 +383,7 @@ func (opts formatOptions) formatDiffSlice( groups := coalesceAdjacentEdits(name, es) groups = coalesceInterveningIdentical(groups, chunkSize/4) + groups = cleanupSurroundingIdentical(groups, eq) maxGroup := diffStats{Name: name} for i, ds := range groups { if maxLen >= 0 && numDiffs >= maxLen { @@ -416,25 +436,36 @@ func (opts formatOptions) formatDiffSlice( // coalesceAdjacentEdits coalesces the list of edits into groups of adjacent // equal or unequal counts. +// +// Example: +// +// Input: "..XXY...Y" +// Output: [ +// {NumIdentical: 2}, +// {NumRemoved: 2, NumInserted 1}, +// {NumIdentical: 3}, +// {NumInserted: 1}, +// ] +// func coalesceAdjacentEdits(name string, es diff.EditScript) (groups []diffStats) { - var prevCase int // Arbitrary index into which case last occurred - lastStats := func(i int) *diffStats { - if prevCase != i { + var prevMode byte + lastStats := func(mode byte) *diffStats { + if prevMode != mode { groups = append(groups, diffStats{Name: name}) - prevCase = i + prevMode = mode } return &groups[len(groups)-1] } for _, e := range es { switch e { case diff.Identity: - lastStats(1).NumIdentical++ + lastStats('=').NumIdentical++ case diff.UniqueX: - lastStats(2).NumRemoved++ + lastStats('!').NumRemoved++ case diff.UniqueY: - lastStats(2).NumInserted++ + lastStats('!').NumInserted++ case diff.Modified: - lastStats(2).NumModified++ + lastStats('!').NumModified++ } } return groups @@ -444,6 +475,35 @@ func coalesceAdjacentEdits(name string, es diff.EditScript) (groups []diffStats) // equal groups into adjacent unequal groups that currently result in a // dual inserted/removed printout. This acts as a high-pass filter to smooth // out high-frequency changes within the windowSize. +// +// Example: +// +// WindowSize: 16, +// Input: [ +// {NumIdentical: 61}, // group 0 +// {NumRemoved: 3, NumInserted: 1}, // group 1 +// {NumIdentical: 6}, // ├── coalesce +// {NumInserted: 2}, // ├── coalesce +// {NumIdentical: 1}, // ├── coalesce +// {NumRemoved: 9}, // └── coalesce +// {NumIdentical: 64}, // group 2 +// {NumRemoved: 3, NumInserted: 1}, // group 3 +// {NumIdentical: 6}, // ├── coalesce +// {NumInserted: 2}, // ├── coalesce +// {NumIdentical: 1}, // ├── coalesce +// {NumRemoved: 7}, // ├── coalesce +// {NumIdentical: 1}, // ├── coalesce +// {NumRemoved: 2}, // └── coalesce +// {NumIdentical: 63}, // group 4 +// ] +// Output: [ +// {NumIdentical: 61}, +// {NumIdentical: 7, NumRemoved: 12, NumInserted: 3}, +// {NumIdentical: 64}, +// {NumIdentical: 8, NumRemoved: 12, NumInserted: 3}, +// {NumIdentical: 63}, +// ] +// func coalesceInterveningIdentical(groups []diffStats, windowSize int) []diffStats { groups, groupsOrig := groups[:0], groups for i, ds := range groupsOrig { @@ -463,3 +523,91 @@ func coalesceInterveningIdentical(groups []diffStats, windowSize int) []diffStat } return groups } + +// cleanupSurroundingIdentical scans through all unequal groups, and +// moves any leading sequence of equal elements to the preceding equal group and +// moves and trailing sequence of equal elements to the succeeding equal group. +// +// This is necessary since coalesceInterveningIdentical may coalesce edit groups +// together such that leading/trailing spans of equal elements becomes possible. +// Note that this can occur even with an optimal diffing algorithm. +// +// Example: +// +// Input: [ +// {NumIdentical: 61}, +// {NumIdentical: 1 , NumRemoved: 11, NumInserted: 2}, // assume 3 leading identical elements +// {NumIdentical: 67}, +// {NumIdentical: 7, NumRemoved: 12, NumInserted: 3}, // assume 10 trailing identical elements +// {NumIdentical: 54}, +// ] +// Output: [ +// {NumIdentical: 64}, // incremented by 3 +// {NumRemoved: 9}, +// {NumIdentical: 67}, +// {NumRemoved: 9}, +// {NumIdentical: 64}, // incremented by 10 +// ] +// +func cleanupSurroundingIdentical(groups []diffStats, eq func(i, j int) bool) []diffStats { + var ix, iy int // indexes into sequence x and y + for i, ds := range groups { + // Handle equal group. + if ds.NumDiff() == 0 { + ix += ds.NumIdentical + iy += ds.NumIdentical + continue + } + + // Handle unequal group. + nx := ds.NumIdentical + ds.NumRemoved + ds.NumModified + ny := ds.NumIdentical + ds.NumInserted + ds.NumModified + var numLeadingIdentical, numTrailingIdentical int + for i := 0; i < nx && i < ny && eq(ix+i, iy+i); i++ { + numLeadingIdentical++ + } + for i := 0; i < nx && i < ny && eq(ix+nx-1-i, iy+ny-1-i); i++ { + numTrailingIdentical++ + } + if numIdentical := numLeadingIdentical + numTrailingIdentical; numIdentical > 0 { + if numLeadingIdentical > 0 { + // Remove leading identical span from this group and + // insert it into the preceding group. + if i-1 >= 0 { + groups[i-1].NumIdentical += numLeadingIdentical + } else { + // No preceding group exists, so prepend a new group, + // but do so after we finish iterating over all groups. + defer func() { + groups = append([]diffStats{{Name: groups[0].Name, NumIdentical: numLeadingIdentical}}, groups...) + }() + } + // Increment indexes since the preceding group would have handled this. + ix += numLeadingIdentical + iy += numLeadingIdentical + } + if numTrailingIdentical > 0 { + // Remove trailing identical span from this group and + // insert it into the succeeding group. + if i+1 < len(groups) { + groups[i+1].NumIdentical += numTrailingIdentical + } else { + // No succeeding group exists, so append a new group, + // but do so after we finish iterating over all groups. + defer func() { + groups = append(groups, diffStats{Name: groups[len(groups)-1].Name, NumIdentical: numTrailingIdentical}) + }() + } + // Do not increment indexes since the succeeding group will handle this. + } + + // Update this group since some identical elements were removed. + nx -= numIdentical + ny -= numIdentical + groups[i] = diffStats{Name: ds.Name, NumRemoved: nx, NumInserted: ny} + } + ix += nx + iy += ny + } + return groups +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 77fe465aca..f632e162b4 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -190,7 +190,7 @@ github.com/emirpasic/gods/utils # github.com/evanphx/json-patch v4.11.0+incompatible ## explicit github.com/evanphx/json-patch -# github.com/fatih/color v1.10.0 +# github.com/fatih/color v1.12.0 github.com/fatih/color # github.com/fsnotify/fsnotify v1.4.9 github.com/fsnotify/fsnotify @@ -304,7 +304,7 @@ github.com/golang/protobuf/ptypes/timestamp github.com/gomarkdown/markdown/ast github.com/gomarkdown/markdown/html github.com/gomarkdown/markdown/parser -# github.com/google/go-cmp v0.5.5 +# github.com/google/go-cmp v0.5.6 github.com/google/go-cmp/cmp github.com/google/go-cmp/cmp/internal/diff github.com/google/go-cmp/cmp/internal/flags @@ -1233,7 +1233,7 @@ sigs.k8s.io/controller-runtime/pkg/webhook sigs.k8s.io/controller-runtime/pkg/webhook/admission sigs.k8s.io/controller-runtime/pkg/webhook/conversion sigs.k8s.io/controller-runtime/pkg/webhook/internal/metrics -# sigs.k8s.io/controller-tools v0.5.0 +# sigs.k8s.io/controller-tools v0.6.0 ## explicit sigs.k8s.io/controller-tools/cmd/controller-gen sigs.k8s.io/controller-tools/pkg/crd diff --git a/vendor/sigs.k8s.io/controller-tools/pkg/crd/gen.go b/vendor/sigs.k8s.io/controller-tools/pkg/crd/gen.go index 5253977b99..dd154c549f 100644 --- a/vendor/sigs.k8s.io/controller-tools/pkg/crd/gen.go +++ b/vendor/sigs.k8s.io/controller-tools/pkg/crd/gen.go @@ -84,6 +84,9 @@ type Generator struct { // You'll need to use "v1" to get support for features like defaulting, // along with an API server that supports it (Kubernetes 1.16+). CRDVersions []string `marker:"crdVersions,optional"` + + // GenerateEmbeddedObjectMeta specifies if any embedded ObjectMeta in the CRD should be generated + GenerateEmbeddedObjectMeta *bool `marker:",optional"` } func (Generator) CheckFilter() loader.NodeFilter { @@ -98,6 +101,8 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error { Checker: ctx.Checker, // Perform defaulting here to avoid ambiguity later AllowDangerousTypes: g.AllowDangerousTypes != nil && *g.AllowDangerousTypes == true, + // Indicates the parser on whether to register the ObjectMeta type or not + GenerateEmbeddedObjectMeta: g.GenerateEmbeddedObjectMeta != nil && *g.GenerateEmbeddedObjectMeta == true, } AddKnownTypes(parser) @@ -129,6 +134,9 @@ func (g Generator) Generate(ctx *genall.GenerationContext) error { crdRaw := parser.CustomResourceDefinitions[groupKind] addAttribution(&crdRaw) + // Prevent the top level metadata for the CRD to be generate regardless of the intention in the arguments + FixTopLevelMetadata(crdRaw) + versionedCRDs := make([]interface{}, len(crdVersions)) for i, ver := range crdVersions { conv, err := AsVersion(crdRaw, schema.GroupVersion{Group: apiext.SchemeGroupVersion.Group, Version: ver}) @@ -269,6 +277,18 @@ func removeDefaultsFromSchemaProps(v *apiextlegacy.JSONSchemaProps) { } } +// FixTopLevelMetadata resets the schema for the top-level metadata field which is needed for CRD validation +func FixTopLevelMetadata(crd apiext.CustomResourceDefinition) { + for _, v := range crd.Spec.Versions { + if v.Schema != nil && v.Schema.OpenAPIV3Schema != nil && v.Schema.OpenAPIV3Schema.Properties != nil { + schemaProperties := v.Schema.OpenAPIV3Schema.Properties + if _, ok := schemaProperties["metadata"]; ok { + schemaProperties["metadata"] = apiext.JSONSchemaProps{Type: "object"} + } + } + } +} + // toTrivialVersions strips out all schemata except for the storage schema, // and moves that up into the root object. This makes the CRD compatible // with pre 1.13 clusters. diff --git a/vendor/sigs.k8s.io/controller-tools/pkg/crd/known_types.go b/vendor/sigs.k8s.io/controller-tools/pkg/crd/known_types.go index e247dcf4fa..7e862cfb17 100644 --- a/vendor/sigs.k8s.io/controller-tools/pkg/crd/known_types.go +++ b/vendor/sigs.k8s.io/controller-tools/pkg/crd/known_types.go @@ -34,8 +34,6 @@ var KnownPackages = map[string]PackageOverride{ }, "k8s.io/apimachinery/pkg/apis/meta/v1": func(p *Parser, pkg *loader.Package) { - // ObjectMeta is managed by the Kubernetes API server, so no need to - // generate validation for it. p.Schemata[TypeIdent{Name: "ObjectMeta", Package: pkg}] = apiext.JSONSchemaProps{ Type: "object", } @@ -113,6 +111,53 @@ var KnownPackages = map[string]PackageOverride{ }, } +// ObjectMetaPackages overrides the ObjectMeta in all types +var ObjectMetaPackages = map[string]PackageOverride{ + "k8s.io/apimachinery/pkg/apis/meta/v1": func(p *Parser, pkg *loader.Package) { + // execute the KnowPackages for `k8s.io/apimachinery/pkg/apis/meta/v1` if any + if f, ok := KnownPackages["k8s.io/apimachinery/pkg/apis/meta/v1"]; ok { + f(p, pkg) + } + // This is an allow-listed set of properties of ObjectMeta, other runtime properties are not part of this list + // See more discussion: https://github.com/kubernetes-sigs/controller-tools/pull/395#issuecomment-691919433 + p.Schemata[TypeIdent{Name: "ObjectMeta", Package: pkg}] = apiext.JSONSchemaProps{ + Type: "object", + Properties: map[string]apiext.JSONSchemaProps{ + "name": { + Type: "string", + }, + "namespace": { + Type: "string", + }, + "annotations": { + Type: "object", + AdditionalProperties: &apiext.JSONSchemaPropsOrBool{ + Schema: &apiext.JSONSchemaProps{ + Type: "string", + }, + }, + }, + "labels": { + Type: "object", + AdditionalProperties: &apiext.JSONSchemaPropsOrBool{ + Schema: &apiext.JSONSchemaProps{ + Type: "string", + }, + }, + }, + "finalizers": { + Type: "array", + Items: &apiext.JSONSchemaPropsOrArray{ + Schema: &apiext.JSONSchemaProps{ + Type: "string", + }, + }, + }, + }, + } + }, +} + func boolPtr(b bool) *bool { return &b } @@ -125,4 +170,10 @@ func AddKnownTypes(parser *Parser) { for pkgName, override := range KnownPackages { parser.PackageOverrides[pkgName] = override } + // if we want to generate the embedded ObjectMeta in the CRD we need to add the ObjectMetaPackages + if parser.GenerateEmbeddedObjectMeta { + for pkgName, override := range ObjectMetaPackages { + parser.PackageOverrides[pkgName] = override + } + } } diff --git a/vendor/sigs.k8s.io/controller-tools/pkg/crd/markers/crd.go b/vendor/sigs.k8s.io/controller-tools/pkg/crd/markers/crd.go index 9f1d19ac95..5e99256c12 100644 --- a/vendor/sigs.k8s.io/controller-tools/pkg/crd/markers/crd.go +++ b/vendor/sigs.k8s.io/controller-tools/pkg/crd/markers/crd.go @@ -48,6 +48,9 @@ var CRDMarkers = []*definitionWithHelp{ must(markers.MakeDefinition("kubebuilder:unservedversion", markers.DescribesType, UnservedVersion{})). WithHelp(UnservedVersion{}.Help()), + + must(markers.MakeDefinition("kubebuilder:deprecatedversion", markers.DescribesType, DeprecatedVersion{})). + WithHelp(DeprecatedVersion{}.Help()), } // TODO: categories and singular used to be annotations types @@ -316,3 +319,29 @@ func (s UnservedVersion) ApplyToCRD(crd *apiext.CustomResourceDefinitionSpec, ve } // NB(directxman12): singular was historically distinct, so we keep it here for backwards compat + +// +controllertools:marker:generateHelp:category=CRD + +// DeprecatedVersion marks this version as deprecated. +type DeprecatedVersion struct { + // Warning message to be shown on the deprecated version + Warning *string `marker:",optional"` +} + +func (s DeprecatedVersion) ApplyToCRD(crd *apiext.CustomResourceDefinitionSpec, version string) error { + if version == "" { + // single-version, do nothing + return nil + } + // multi-version + for i := range crd.Versions { + ver := &crd.Versions[i] + if ver.Name != version { + continue + } + ver.Deprecated = true + ver.DeprecationWarning = s.Warning + break + } + return nil +} diff --git a/vendor/sigs.k8s.io/controller-tools/pkg/crd/markers/zz_generated.markerhelp.go b/vendor/sigs.k8s.io/controller-tools/pkg/crd/markers/zz_generated.markerhelp.go index 7c6aca4e1c..e6875bb5f5 100644 --- a/vendor/sigs.k8s.io/controller-tools/pkg/crd/markers/zz_generated.markerhelp.go +++ b/vendor/sigs.k8s.io/controller-tools/pkg/crd/markers/zz_generated.markerhelp.go @@ -32,7 +32,7 @@ func (Default) Help() *markers.DefinitionHelp { Details: "A default value will be accepted as any value valid for the field. Formatting for common types include: boolean: `true`, string: `Cluster`, numerical: `1.24`, array: `{1,2}`, object: `{policy: \"delete\"}`). Defaults should be defined in pruned form, and only best-effort validation will be performed. Full validation of a default requires submission of the containing CRD to an apiserver.", }, FieldHelp: map[string]markers.DetailedHelp{ - "Value": markers.DetailedHelp{ + "Value": { Summary: "", Details: "", }, @@ -40,6 +40,22 @@ func (Default) Help() *markers.DefinitionHelp { } } +func (DeprecatedVersion) Help() *markers.DefinitionHelp { + return &markers.DefinitionHelp{ + Category: "CRD", + DetailedHelp: markers.DetailedHelp{ + Summary: "marks this version as deprecated.", + Details: "", + }, + FieldHelp: map[string]markers.DetailedHelp{ + "Warning": markers.DetailedHelp{ + Summary: "message to be shown on the deprecated version", + Details: "", + }, + }, + } +} + func (Enum) Help() *markers.DefinitionHelp { return &markers.DefinitionHelp{ Category: "CRD validation", @@ -246,27 +262,27 @@ func (PrintColumn) Help() *markers.DefinitionHelp { Details: "", }, FieldHelp: map[string]markers.DetailedHelp{ - "Name": markers.DetailedHelp{ + "Name": { Summary: "specifies the name of the column.", Details: "", }, - "Type": markers.DetailedHelp{ + "Type": { Summary: "indicates the type of the column. ", Details: "It may be any OpenAPI data type listed at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types.", }, - "JSONPath": markers.DetailedHelp{ + "JSONPath": { Summary: "specifies the jsonpath expression used to extract the value of the column.", Details: "", }, - "Description": markers.DetailedHelp{ + "Description": { Summary: "specifies the help/description for this column.", Details: "", }, - "Format": markers.DetailedHelp{ + "Format": { Summary: "specifies the format of the column. ", Details: "It may be any OpenAPI data format corresponding to the type, listed at https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types.", }, - "Priority": markers.DetailedHelp{ + "Priority": { Summary: "indicates how important it is that this column be displayed. ", Details: "Lower priority (*higher* numbered) columns will be hidden if the terminal width is too small.", }, @@ -282,23 +298,23 @@ func (Resource) Help() *markers.DefinitionHelp { Details: "", }, FieldHelp: map[string]markers.DetailedHelp{ - "Path": markers.DetailedHelp{ + "Path": { Summary: "specifies the plural \"resource\" for this CRD. ", Details: "It generally corresponds to a plural, lower-cased version of the Kind. See https://book.kubebuilder.io/cronjob-tutorial/gvks.html.", }, - "ShortName": markers.DetailedHelp{ + "ShortName": { Summary: "specifies aliases for this CRD. ", Details: "Short names are often used when people have work with your resource over and over again. For instance, \"rs\" for \"replicaset\" or \"crd\" for customresourcedefinition.", }, - "Categories": markers.DetailedHelp{ + "Categories": { Summary: "specifies which group aliases this resource is part of. ", Details: "Group aliases are used to work with groups of resources at once. The most common one is \"all\" which covers about a third of the base resources in Kubernetes, and is generally used for \"user-facing\" resources.", }, - "Singular": markers.DetailedHelp{ + "Singular": { Summary: "overrides the singular form of your resource. ", Details: "The singular form is otherwise defaulted off the plural (path).", }, - "Scope": markers.DetailedHelp{ + "Scope": { Summary: "overrides the scope of the CRD (Cluster vs Namespaced). ", Details: "Scope defaults to \"Namespaced\". Cluster-scoped (\"Cluster\") resources don't exist in namespaces.", }, @@ -358,15 +374,15 @@ func (SubresourceScale) Help() *markers.DefinitionHelp { Details: "", }, FieldHelp: map[string]markers.DetailedHelp{ - "SpecPath": markers.DetailedHelp{ + "SpecPath": { Summary: "specifies the jsonpath to the replicas field for the scale's spec.", Details: "", }, - "StatusPath": markers.DetailedHelp{ + "StatusPath": { Summary: "specifies the jsonpath to the replicas field for the scale's status.", Details: "", }, - "SelectorPath": markers.DetailedHelp{ + "SelectorPath": { Summary: "specifies the jsonpath to the pod label selector field for the scale's status. ", Details: "The selector field must be the *string* form (serialized form) of a selector. Setting a pod label selector is necessary for your type to work with the HorizontalPodAutoscaler.", }, diff --git a/vendor/sigs.k8s.io/controller-tools/pkg/crd/parser.go b/vendor/sigs.k8s.io/controller-tools/pkg/crd/parser.go index 60bea3295f..164e4756d3 100644 --- a/vendor/sigs.k8s.io/controller-tools/pkg/crd/parser.go +++ b/vendor/sigs.k8s.io/controller-tools/pkg/crd/parser.go @@ -86,6 +86,9 @@ type Parser struct { // because the implementation is too difficult/clunky to promote them to category 3. // TODO: Should we have a more formal mechanism for putting "type patterns" in each of the above categories? AllowDangerousTypes bool + + // GenerateEmbeddedObjectMeta specifies if any embedded ObjectMeta should be generated + GenerateEmbeddedObjectMeta bool } func (p *Parser) init() { diff --git a/vendor/sigs.k8s.io/controller-tools/pkg/crd/zz_generated.markerhelp.go b/vendor/sigs.k8s.io/controller-tools/pkg/crd/zz_generated.markerhelp.go index 5c0a45dd90..4b008f5949 100644 --- a/vendor/sigs.k8s.io/controller-tools/pkg/crd/zz_generated.markerhelp.go +++ b/vendor/sigs.k8s.io/controller-tools/pkg/crd/zz_generated.markerhelp.go @@ -32,26 +32,30 @@ func (Generator) Help() *markers.DefinitionHelp { Details: "", }, FieldHelp: map[string]markers.DetailedHelp{ - "TrivialVersions": markers.DetailedHelp{ + "TrivialVersions": { Summary: "indicates that we should produce a single-version CRD. ", Details: "Single \"trivial-version\" CRDs are compatible with older (pre 1.13) Kubernetes API servers. The storage version's schema will be used as the CRD's schema. \n Only works with the v1beta1 CRD version.", }, - "PreserveUnknownFields": markers.DetailedHelp{ + "PreserveUnknownFields": { Summary: "indicates whether or not we should turn off pruning. ", Details: "Left unspecified, it'll default to true when only a v1beta1 CRD is generated (to preserve compatibility with older versions of this tool), or false otherwise. \n It's required to be false for v1 CRDs.", }, - "AllowDangerousTypes": markers.DetailedHelp{ + "AllowDangerousTypes": { Summary: "allows types which are usually omitted from CRD generation because they are not recommended. ", Details: "Currently the following additional types are allowed when this is true: float32 float64 \n Left unspecified, the default is false", }, - "MaxDescLen": markers.DetailedHelp{ + "MaxDescLen": { Summary: "specifies the maximum description length for fields in CRD's OpenAPI schema. ", Details: "0 indicates drop the description for all fields completely. n indicates limit the description to at most n characters and truncate the description to closest sentence boundary if it exceeds n characters.", }, - "CRDVersions": markers.DetailedHelp{ + "CRDVersions": { Summary: "specifies the target API versions of the CRD type itself to generate. Defaults to v1. ", Details: "The first version listed will be assumed to be the \"default\" version and will not get a version suffix in the output filename. \n You'll need to use \"v1\" to get support for features like defaulting, along with an API server that supports it (Kubernetes 1.16+).", }, + "GenerateEmbeddedObjectMeta": { + Summary: "specifies if any embedded ObjectMeta in the CRD should be generated", + Details: "", + }, }, } } diff --git a/vendor/sigs.k8s.io/controller-tools/pkg/deepcopy/zz_generated.markerhelp.go b/vendor/sigs.k8s.io/controller-tools/pkg/deepcopy/zz_generated.markerhelp.go index a04355836f..6e001c6e25 100644 --- a/vendor/sigs.k8s.io/controller-tools/pkg/deepcopy/zz_generated.markerhelp.go +++ b/vendor/sigs.k8s.io/controller-tools/pkg/deepcopy/zz_generated.markerhelp.go @@ -32,11 +32,11 @@ func (Generator) Help() *markers.DefinitionHelp { Details: "", }, FieldHelp: map[string]markers.DetailedHelp{ - "HeaderFile": markers.DetailedHelp{ + "HeaderFile": { Summary: "specifies the header text (e.g. license) to prepend to generated files.", Details: "", }, - "Year": markers.DetailedHelp{ + "Year": { Summary: "specifies the year to substitute for \" YEAR\" in the header file.", Details: "", }, diff --git a/vendor/sigs.k8s.io/controller-tools/pkg/genall/zz_generated.markerhelp.go b/vendor/sigs.k8s.io/controller-tools/pkg/genall/zz_generated.markerhelp.go index 824d3af3f8..1319397e63 100644 --- a/vendor/sigs.k8s.io/controller-tools/pkg/genall/zz_generated.markerhelp.go +++ b/vendor/sigs.k8s.io/controller-tools/pkg/genall/zz_generated.markerhelp.go @@ -43,11 +43,11 @@ func (OutputArtifacts) Help() *markers.DefinitionHelp { Details: "Non-package associated artifacts are output to the Config directory, while package-associated ones are output to their package's source files' directory, unless an alternate path is specified in Code.", }, FieldHelp: map[string]markers.DetailedHelp{ - "Config": markers.DetailedHelp{ + "Config": { Summary: "points to the directory to which to write configuration.", Details: "", }, - "Code": markers.DetailedHelp{ + "Code": { Summary: "overrides the directory in which to write new code (defaults to where the existing code lives).", Details: "", }, diff --git a/vendor/sigs.k8s.io/controller-tools/pkg/rbac/zz_generated.markerhelp.go b/vendor/sigs.k8s.io/controller-tools/pkg/rbac/zz_generated.markerhelp.go index 707fc042e6..29deffea30 100644 --- a/vendor/sigs.k8s.io/controller-tools/pkg/rbac/zz_generated.markerhelp.go +++ b/vendor/sigs.k8s.io/controller-tools/pkg/rbac/zz_generated.markerhelp.go @@ -32,7 +32,7 @@ func (Generator) Help() *markers.DefinitionHelp { Details: "", }, FieldHelp: map[string]markers.DetailedHelp{ - "RoleName": markers.DetailedHelp{ + "RoleName": { Summary: "sets the name of the generated ClusterRole.", Details: "", }, @@ -48,27 +48,27 @@ func (Rule) Help() *markers.DefinitionHelp { Details: "", }, FieldHelp: map[string]markers.DetailedHelp{ - "Groups": markers.DetailedHelp{ + "Groups": { Summary: "specifies the API groups that this rule encompasses.", Details: "", }, - "Resources": markers.DetailedHelp{ + "Resources": { Summary: "specifies the API resources that this rule encompasses.", Details: "", }, - "ResourceNames": markers.DetailedHelp{ + "ResourceNames": { Summary: "specifies the names of the API resources that this rule encompasses. ", Details: "Create requests cannot be restricted by resourcename, as the object's name is not known at authorization time.", }, - "Verbs": markers.DetailedHelp{ + "Verbs": { Summary: "specifies the (lowercase) kubernetes API verbs that this rule encompasses.", Details: "", }, - "URLs": markers.DetailedHelp{ + "URLs": { Summary: "URL specifies the non-resource URLs that this rule encompasses.", Details: "", }, - "Namespace": markers.DetailedHelp{ + "Namespace": { Summary: "specifies the scope of the Rule. If not set, the Rule belongs to the generated ClusterRole. If set, the Rule belongs to a Role, whose namespace is specified by this field.", Details: "", }, diff --git a/vendor/sigs.k8s.io/controller-tools/pkg/schemapatcher/gen.go b/vendor/sigs.k8s.io/controller-tools/pkg/schemapatcher/gen.go index 6e71cbcfa1..f9b197a595 100644 --- a/vendor/sigs.k8s.io/controller-tools/pkg/schemapatcher/gen.go +++ b/vendor/sigs.k8s.io/controller-tools/pkg/schemapatcher/gen.go @@ -84,6 +84,9 @@ type Generator struct { // n indicates limit the description to at most n characters and truncate the description to // closest sentence boundary if it exceeds n characters. MaxDescLen *int `marker:",optional"` + + // GenerateEmbeddedObjectMeta specifies if any embedded ObjectMeta in the CRD should be generated + GenerateEmbeddedObjectMeta *bool `marker:",optional"` } var _ genall.Generator = &Generator{} @@ -100,6 +103,8 @@ func (g Generator) Generate(ctx *genall.GenerationContext) (result error) { parser := &crdgen.Parser{ Collector: ctx.Collector, Checker: ctx.Checker, + // Indicates the parser on whether to register the ObjectMeta type or not + GenerateEmbeddedObjectMeta: g.GenerateEmbeddedObjectMeta != nil && *g.GenerateEmbeddedObjectMeta == true, } crdgen.AddKnownTypes(parser) @@ -142,6 +147,12 @@ func (g Generator) Generate(ctx *genall.GenerationContext) (result error) { fullSchema = *fullSchema.DeepCopy() crdgen.TruncateDescription(&fullSchema, *g.MaxDescLen) } + + // Fix top level ObjectMeta regardless of the settings. + if _, ok := fullSchema.Properties["metadata"]; ok { + fullSchema.Properties["metadata"] = apiext.JSONSchemaProps{Type: "object"} + } + existingSet.NewSchemata[gv.Version] = fullSchema } } @@ -434,7 +445,7 @@ func crdsFromDirectory(ctx *genall.GenerationContext, dir string) (map[schema.Gr groupKind := schema.GroupKind{Group: actualCRD.Spec.Group, Kind: actualCRD.Spec.Names.Kind} var versions map[string]struct{} if len(actualCRD.Spec.Versions) == 0 { - versions = map[string]struct{}{actualCRD.Spec.Version: struct{}{}} + versions = map[string]struct{}{actualCRD.Spec.Version: {}} } else { versions = make(map[string]struct{}, len(actualCRD.Spec.Versions)) for _, ver := range actualCRD.Spec.Versions { diff --git a/vendor/sigs.k8s.io/controller-tools/pkg/schemapatcher/zz_generated.markerhelp.go b/vendor/sigs.k8s.io/controller-tools/pkg/schemapatcher/zz_generated.markerhelp.go index 230cb9c066..36cc0cba8c 100644 --- a/vendor/sigs.k8s.io/controller-tools/pkg/schemapatcher/zz_generated.markerhelp.go +++ b/vendor/sigs.k8s.io/controller-tools/pkg/schemapatcher/zz_generated.markerhelp.go @@ -32,11 +32,11 @@ func (Generator) Help() *markers.DefinitionHelp { Details: "For legacy (v1beta1) single-version CRDs, it will simply replace the global schema. \n For legacy (v1beta1) multi-version CRDs, and any v1 CRDs, it will replace schemata of existing versions and *clear the schema* from any versions not specified in the Go code. It will *not* add new versions, or remove old ones. \n For legacy multi-version CRDs with identical schemata, it will take care of lifting the per-version schema up to the global schema. \n It will generate output for each \"CRD Version\" (API version of the CRD type itself) , e.g. apiextensions/v1beta1 and apiextensions/v1) available.", }, FieldHelp: map[string]markers.DetailedHelp{ - "ManifestsPath": markers.DetailedHelp{ + "ManifestsPath": { Summary: "contains the CustomResourceDefinition YAML files.", Details: "", }, - "MaxDescLen": markers.DetailedHelp{ + "MaxDescLen": { Summary: "specifies the maximum description length for fields in CRD's OpenAPI schema. ", Details: "0 indicates drop the description for all fields completely. n indicates limit the description to at most n characters and truncate the description to closest sentence boundary if it exceeds n characters.", }, diff --git a/vendor/sigs.k8s.io/controller-tools/pkg/webhook/zz_generated.markerhelp.go b/vendor/sigs.k8s.io/controller-tools/pkg/webhook/zz_generated.markerhelp.go index 84e86cdbbb..15e9158cef 100644 --- a/vendor/sigs.k8s.io/controller-tools/pkg/webhook/zz_generated.markerhelp.go +++ b/vendor/sigs.k8s.io/controller-tools/pkg/webhook/zz_generated.markerhelp.go @@ -32,51 +32,51 @@ func (Config) Help() *markers.DefinitionHelp { Details: "It specifies only the details that are intrinsic to the application serving it (e.g. the resources it can handle, or the path it serves on).", }, FieldHelp: map[string]markers.DetailedHelp{ - "Mutating": markers.DetailedHelp{ + "Mutating": { Summary: "marks this as a mutating webhook (it's validating only if false) ", Details: "Mutating webhooks are allowed to change the object in their response, and are called *before* all validating webhooks. Mutating webhooks may choose to reject an object, similarly to a validating webhook.", }, - "FailurePolicy": markers.DetailedHelp{ + "FailurePolicy": { Summary: "specifies what should happen if the API server cannot reach the webhook. ", Details: "It may be either \"ignore\" (to skip the webhook and continue on) or \"fail\" (to reject the object in question).", }, - "MatchPolicy": markers.DetailedHelp{ + "MatchPolicy": { Summary: "defines how the \"rules\" list is used to match incoming requests. Allowed values are \"Exact\" (match only if it exactly matches the specified rule) or \"Equivalent\" (match a request if it modifies a resource listed in rules, even via another API group or version).", Details: "", }, - "SideEffects": markers.DetailedHelp{ + "SideEffects": { Summary: "specify whether calling the webhook will have side effects. This has an impact on dry runs and `kubectl diff`: if the sideEffect is \"Unknown\" (the default) or \"Some\", then the API server will not call the webhook on a dry-run request and fails instead. If the value is \"None\", then the webhook has no side effects and the API server will call it on dry-run. If the value is \"NoneOnDryRun\", then the webhook is responsible for inspecting the \"dryRun\" property of the AdmissionReview sent in the request, and avoiding side effects if that value is \"true.\"", Details: "", }, - "Groups": markers.DetailedHelp{ + "Groups": { Summary: "specifies the API groups that this webhook receives requests for.", Details: "", }, - "Resources": markers.DetailedHelp{ + "Resources": { Summary: "specifies the API resources that this webhook receives requests for.", Details: "", }, - "Verbs": markers.DetailedHelp{ + "Verbs": { Summary: "specifies the Kubernetes API verbs that this webhook receives requests for. ", Details: "Only modification-like verbs may be specified. May be \"create\", \"update\", \"delete\", \"connect\", or \"*\" (for all).", }, - "Versions": markers.DetailedHelp{ + "Versions": { Summary: "specifies the API versions that this webhook receives requests for.", Details: "", }, - "Name": markers.DetailedHelp{ + "Name": { Summary: "indicates the name of this webhook configuration. Should be a domain with at least three segments separated by dots", Details: "", }, - "Path": markers.DetailedHelp{ + "Path": { Summary: "specifies that path that the API server should connect to this webhook on. Must be prefixed with a '/validate-' or '/mutate-' depending on the type, and followed by $GROUP-$VERSION-$KIND where all values are lower-cased and the periods in the group are substituted for hyphens. For example, a validating webhook path for type batch.tutorial.kubebuilder.io/v1,Kind=CronJob would be /validate-batch-tutorial-kubebuilder-io-v1-cronjob", Details: "", }, - "WebhookVersions": markers.DetailedHelp{ + "WebhookVersions": { Summary: "specifies the target API versions of the {Mutating,Validating}WebhookConfiguration objects itself to generate. Defaults to v1.", Details: "", }, - "AdmissionReviewVersions": markers.DetailedHelp{ + "AdmissionReviewVersions": { Summary: "is an ordered list of preferred `AdmissionReview` versions the Webhook expects. For generating v1 {Mutating,Validating}WebhookConfiguration, this is mandatory. For generating v1beta1 {Mutating,Validating}WebhookConfiguration, this is optional, and default to v1beta1.", Details: "", },