diff --git a/api/v1/nodefeaturediscovery_types.go b/api/v1/nodefeaturediscovery_types.go index 8d675dd0..70716853 100644 --- a/api/v1/nodefeaturediscovery_types.go +++ b/api/v1/nodefeaturediscovery_types.go @@ -17,7 +17,6 @@ limitations under the License. package v1 import ( - conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -92,7 +91,7 @@ type ConfigMap struct { type NodeFeatureDiscoveryStatus struct { // Conditions represents the latest available observations of current state. // +optional - Conditions []conditionsv1.Condition `json:"conditions,omitempty"` + Conditions []metav1.Condition `json:"conditions,omitempty"` } // +kubebuilder:object:root=true diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index e40680f7..a579367f 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* @@ -21,7 +22,7 @@ limitations under the License. package v1 import ( - conditionsv1 "github.com/openshift/custom-resource-status/conditions/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -131,7 +132,7 @@ func (in *NodeFeatureDiscoveryStatus) DeepCopyInto(out *NodeFeatureDiscoveryStat *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]conditionsv1.Condition, len(*in)) + *out = make([]metav1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } diff --git a/controllers/nodefeaturediscovery_controller.go b/controllers/nodefeaturediscovery_controller.go index 33f9308f..d1917dd5 100644 --- a/controllers/nodefeaturediscovery_controller.go +++ b/controllers/nodefeaturediscovery_controller.go @@ -151,17 +151,115 @@ func (r *NodeFeatureDiscoveryReconciler) Reconcile(ctx context.Context, req ctrl klog.Info("Ready to apply components") nfd.init(r, instance) + result, err := applyComponents() + if err != nil { + return ctrl.Result{Requeue: true}, err + } + + // Check the status of the NFD Operator Worker ServiceAccount + if rstatus, err := r.getWorkerServiceAccountConditions(ctx); err != nil { + return r.updateDegradedCondition(instance, conditionFailedGettingNFDWorkerServiceAccount, err.Error()) + } else if rstatus.isDegraded { + return r.updateDegradedCondition(instance, conditionNFDWorkerServiceAccountDegraded, "nfd-worker service account has been degraded") + } + + // Check the status of the NFD Operator Master ServiceAccount + if rstatus, err := r.getMasterServiceAccountConditions(ctx); err != nil { + return r.updateDegradedCondition(instance, conditionFailedGettingNFDMasterServiceAccount, err.Error()) + } else if rstatus.isDegraded { + return r.updateDegradedCondition(instance, conditionNFDMasterServiceAccountDegraded, "nfd-master service account has been degraded") + } + + // Check the status of the NFD Operator role + if rstatus, err := r.getRoleConditions(ctx); err != nil { + return r.updateDegradedCondition(instance, conditionNFDRoleDegraded, err.Error()) + } else if rstatus.isDegraded { + return r.updateDegradedCondition(instance, conditionNFDRoleDegraded, "nfd-worker role has been degraded") + } + + // Check the status of the NFD Operator cluster role + if rstatus, err := r.getClusterRoleConditions(ctx); err != nil { + return r.updateDegradedCondition(instance, conditionNFDClusterRoleDegraded, err.Error()) + } else if rstatus.isDegraded { + return r.updateDegradedCondition(instance, conditionNFDClusterRoleDegraded, "nfd ClusterRole has been degraded") + } + + // Check the status of the NFD Operator cluster role binding + if rstatus, err := r.getClusterRoleBindingConditions(ctx); err != nil { + return r.updateDegradedCondition(instance, conditionFailedGettingNFDClusterRoleBinding, err.Error()) + } else if rstatus.isDegraded { + return r.updateDegradedCondition(instance, conditionNFDClusterRoleBindingDegraded, "nfd ClusterRoleBinding has been degraded") + } + + // Check the status of the NFD Operator role binding + if rstatus, err := r.getRoleBindingConditions(ctx); err != nil { + return r.updateDegradedCondition(instance, conditionFailedGettingNFDRoleBinding, err.Error()) + } else if rstatus.isDegraded { + return r.updateDegradedCondition(instance, conditionNFDRoleBindingDegraded, "nfd RoleBinding has been degraded") + } + + // Check the status of the NFD Operator Service + if rstatus, err := r.getServiceConditions(ctx); err != nil { + return r.updateDegradedCondition(instance, conditionFailedGettingNFDService, err.Error()) + } else if rstatus.isDegraded { + return r.updateDegradedCondition(instance, conditionNFDServiceDegraded, "nfd Service has been degraded") + } + + // Check the status of the NFD Operator worker ConfigMap + if rstatus, err := r.getWorkerConfigConditions(nfd); err != nil { + return r.updateDegradedCondition(instance, conditionFailedGettingNFDWorkerConfig, err.Error()) + } else if rstatus.isDegraded { + return r.updateDegradedCondition(instance, conditionNFDWorkerConfigDegraded, "nfd-worker ConfigMap has been degraded") + } + + // Check the status of the NFD Operator Worker DaemonSet + if rstatus, err := r.getWorkerDaemonSetConditions(ctx); err != nil { + return r.updateDegradedCondition(instance, conditionFailedGettingNFDWorkerDaemonSet, err.Error()) + } else if rstatus.isProgressing { + return r.updateProgressingCondition(instance, err.Error(), "nfd-worker Daemonset is progressing") + } else if rstatus.isDegraded { + return r.updateDegradedCondition(instance, err.Error(), "nfd-worker Daemonset has been degraded") + } + + // Check the status of the NFD Operator Master DaemonSet + if rstatus, err := r.getMasterDaemonSetConditions(ctx); err != nil { + return r.updateDegradedCondition(instance, conditionFailedGettingNFDMasterDaemonSet, err.Error()) + } else if rstatus.isProgressing { + return r.updateProgressingCondition(instance, err.Error(), "nfd-master Daemonset is progressing") + } else if rstatus.isDegraded { + return r.updateDegradedCondition(instance, err.Error(), "nfd-master Daemonset has been degraded") + } + + // Get available conditions + conditions := r.getAvailableConditions() + + // Update the status of the resource on the CRD + if err := r.updateStatus(instance, conditions); err != nil { + if result != nil { + return *result, err + } + return reconcile.Result{}, err + } + + if result != nil { + return *result, nil + } + + // All objects are healthy during reconcile loop + return ctrl.Result{}, nil +} + +func applyComponents() (*reconcile.Result, error) { // Run through all control functions, return an error on any NotReady resource. for { err := nfd.step() if err != nil { - return reconcile.Result{}, err + return &reconcile.Result{}, err } if nfd.last() { break } } - - return ctrl.Result{}, nil + return &ctrl.Result{}, nil } diff --git a/controllers/nodefeaturediscovery_resources.go b/controllers/nodefeaturediscovery_resources.go index e9b415c0..15062466 100644 --- a/controllers/nodefeaturediscovery_resources.go +++ b/controllers/nodefeaturediscovery_resources.go @@ -17,6 +17,7 @@ limitations under the License. package controllers import ( + "context" "io/ioutil" "os" "path/filepath" @@ -29,6 +30,7 @@ import ( "k8s.io/apimachinery/pkg/runtime/serializer/json" "k8s.io/klog/v2" "k8s.io/kubectl/pkg/scheme" + "sigs.k8s.io/controller-runtime/pkg/client" ) // assetsFromFile is the content of an asset file as raw data @@ -163,3 +165,52 @@ func panicIfError(err error) { panic(err) } } + +// getServiceAccount gets one of the NFD Operator's ServiceAccounts +func (r *NodeFeatureDiscoveryReconciler) getServiceAccount(ctx context.Context, namespace string, name string) (*corev1.ServiceAccount, error) { + sa := &corev1.ServiceAccount{} + err := r.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, sa) + return sa, err +} + +// getDaemonSet gets one of the NFD Operator's DaemonSets +func (r *NodeFeatureDiscoveryReconciler) getDaemonSet(ctx context.Context, namespace string, name string) (*appsv1.DaemonSet, error) { + ds := &appsv1.DaemonSet{} + err := r.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, ds) + return ds, err +} + +// getService gets one of the NFD Operator's Services +func (r *NodeFeatureDiscoveryReconciler) getService(ctx context.Context, namespace string, name string) (*corev1.Service, error) { + svc := &corev1.Service{} + err := r.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, svc) + return svc, err +} + +// getRole gets one of the NFD Operator's Roles +func (r *NodeFeatureDiscoveryReconciler) getRole(ctx context.Context, namespace string, name string) (*rbacv1.Role, error) { + role := &rbacv1.Role{} + err := r.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, role) + return role, err +} + +// getRoleBinding gets one of the NFD Operator's RoleBindings +func (r *NodeFeatureDiscoveryReconciler) getRoleBinding(ctx context.Context, namespace string, name string) (*rbacv1.RoleBinding, error) { + rb := &rbacv1.RoleBinding{} + err := r.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, rb) + return rb, err +} + +// getClusterRole gets one of the NFD Operator's ClusterRoles +func (r *NodeFeatureDiscoveryReconciler) getClusterRole(ctx context.Context, namespace string, name string) (*rbacv1.ClusterRole, error) { + cr := &rbacv1.ClusterRole{} + err := r.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, cr) + return cr, err +} + +// getClusterRoleBinding gets one of the NFD Operator's ClusterRoleBindings +func (r *NodeFeatureDiscoveryReconciler) getClusterRoleBinding(ctx context.Context, namespace string, name string) (*rbacv1.ClusterRoleBinding, error) { + crb := &rbacv1.ClusterRoleBinding{} + err := r.Get(ctx, client.ObjectKey{Namespace: namespace, Name: name}, crb) + return crb, err +} diff --git a/controllers/nodefeaturediscovery_status.go b/controllers/nodefeaturediscovery_status.go new file mode 100644 index 00000000..92562284 --- /dev/null +++ b/controllers/nodefeaturediscovery_status.go @@ -0,0 +1,515 @@ +/* +Copyright 2021 The Kubernetes 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 controllers + +import ( + "context" + "errors" + "time" + + meta "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + nfdv1 "github.com/kubernetes-sigs/node-feature-discovery-operator/api/v1" +) + +const ( + nfdNamespace = "node-feature-discovery-operator" + nfdWorkerApp string = "nfd-worker" + nfdMasterApp string = "nfd-master" +) + +const ( + // Resource is missing + conditionFailedGettingNFDWorkerConfig = "FailedGettingNFDWorkerConfig" + conditionFailedGettingNFDWorkerServiceAccount = "FailedGettingNFDWorkerServiceAccount" + conditionFailedGettingNFDMasterServiceAccount = "FailedGettingNFDMasterServiceAccount" + conditionFailedGettingNFDService = "FailedGettingNFDService" + conditionFailedGettingNFDWorkerDaemonSet = "FailedGettingNFDWorkerDaemonSet" + conditionFailedGettingNFDMasterDaemonSet = "FailedGettingNFDMasterDaemonSet" + conditionFailedGettingNFDRoleBinding = "FailedGettingNFDRoleBinding" + conditionFailedGettingNFDClusterRoleBinding = "FailedGettingNFDClusterRole" + + // Resource degraded + conditionNFDWorkerConfigDegraded = "NFDWorkerConfigResourceDegraded" + conditionNFDWorkerServiceAccountDegraded = "NFDWorkerServiceAccountDegraded" + conditionNFDMasterServiceAccountDegraded = "NFDMasterServiceAccountDegraded" + conditionNFDServiceDegraded = "NFDServiceDegraded" + conditionNFDWorkerDaemonSetDegraded = "NFDWorkerDaemonSetDegraded" + conditionNFDMasterDaemonSetDegraded = "NFDMasterDaemonSetDegraded" + conditionNFDRoleDegraded = "NFDRoleDegraded" + conditionNFDRoleBindingDegraded = "NFDRoleBindingDegraded" + conditionNFDClusterRoleDegraded = "NFDClusterRoleDegraded" + conditionNFDClusterRoleBindingDegraded = "NFDClusterRoleBindingDegraded" + + // Unknown errors. (Catch all) + errorNFDWorkerDaemonSetUnknown = "NFDWorkerDaemonSetCorrupted" + errorNFDMasterDaemonSetUnknown = "NFDMasterDaemonSetCorrupted" + + // More nodes are listed as "ready" than selected + errorTooManyNFDWorkerDaemonSetReadyNodes = "NFDWorkerDaemonSetHasMoreNodesThanScheduled" + errorTooManyNFDMasterDaemonSetReadyNodes = "NFDMasterDaemonSetHasMoreNodesThanScheduled" + + // DaemonSet warnings (for "Progressing" conditions) + warningNumberOfReadyNodesIsLessThanScheduled = "warningNumberOfReadyNodesIsLessThanScheduled" + warningNFDWorkerDaemonSetProgressing = "warningNFDWorkerDaemonSetProgressing" + warningNFDMasterDaemonSetProgressing = "warningNFDMasterDaemonSetProgressing" + + // ConditionAvailable indicates that the resources maintained by the operator, + // is functional and available in the cluster. + ConditionAvailable string = "Available" + + // ConditionProgressing indicates that the operator is actively making changes to the resources maintained by the + // operator + ConditionProgressing string = "Progressing" + + // ConditionDegraded indicates that the resources maintained by the operator are not functioning completely. + // An example of a degraded state would be if not all pods in a deployment were running. + // It may still be available, but it is degraded + ConditionDegraded string = "Degraded" + + // ConditionUpgradeable indicates whether the resources maintained by the operator are in a state that is safe to upgrade. + // When `False`, the resources maintained by the operator should not be upgraded and the + // message field should contain a human readable description of what the administrator should do to + // allow the operator to successfully update the resources maintained by the operator. + ConditionUpgradeable string = "Upgradeable" +) + +// updateStatus is used to update the status of a resource (e.g., degraded, +// available, etc.) +func (r *NodeFeatureDiscoveryReconciler) updateStatus(nfd *nfdv1.NodeFeatureDiscovery, condition []metav1.Condition) error { + // The actual 'nfd' object should *not* be modified when trying to + // check the object's status. This variable is a dummy variable used + // to set temporary conditions. + nfdCopy := nfd.DeepCopy() + + // If a set of conditions exists, then it should be added to the + // 'nfd' Copy. + if condition != nil { + nfdCopy.Status.Conditions = condition + } + + // Next step is to check if we need to update the status + modified := false + + // Because there are only four possible conditions (degraded, available, + // updatable, and progressing), it isn't necessary to check if old + // conditions should be removed. + for _, newCondition := range nfdCopy.Status.Conditions { + oldCondition := meta.FindStatusCondition(nfd.Status.Conditions, newCondition.Type) + if oldCondition == nil { + modified = true + break + } + // Ignore timestamps to avoid infinite reconcile loops + if oldCondition.Status != newCondition.Status || + oldCondition.Reason != newCondition.Reason || + oldCondition.Message != newCondition.Message { + modified = true + break + } + } + + // If nothing has been modified, then return nothing. Even if the list + // of 'conditions' is not empty, it should not be counted as an update + // if it was already counted as an update before. + if !modified { + return nil + } + return r.Status().Update(context.TODO(), nfdCopy) +} + +// updateDegradedCondition is used to mark a given resource as "degraded" so that +// the reconciler can take steps to rectify the situation. +func (r *NodeFeatureDiscoveryReconciler) updateDegradedCondition(nfd *nfdv1.NodeFeatureDiscovery, reason, message string) (ctrl.Result, error) { + degradedCondition := r.getDegradedConditions(reason, message) + if err := r.updateStatus(nfd, degradedCondition); err != nil { + return reconcile.Result{}, err + } + + return reconcile.Result{Requeue: true}, nil +} + +// updateProgressingCondition is used to mark a given resource as "progressing" so +// that the reconciler can take steps to rectify the situation. +func (r *NodeFeatureDiscoveryReconciler) updateProgressingCondition(nfd *nfdv1.NodeFeatureDiscovery, reason, message string) (ctrl.Result, error) { + progressingCondition := r.getProgressingConditions(reason, message) + if err := r.updateStatus(nfd, progressingCondition); err != nil { + return reconcile.Result{}, err + } + return reconcile.Result{Requeue: true}, nil +} + +// getAvailableConditions returns a list of Condition objects and marks +// every condition as FALSE except for ConditionAvailable so that the +// reconciler can determine that the resource is available. +func (r *NodeFeatureDiscoveryReconciler) getAvailableConditions() []metav1.Condition { + now := time.Now() + return []metav1.Condition{ + { + Type: ConditionAvailable, + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.Time{Time: now}, + }, + { + Type: ConditionUpgradeable, + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.Time{Time: now}, + }, + { + Type: ConditionProgressing, + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Time{Time: now}, + }, + { + Type: ConditionDegraded, + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Time{Time: now}, + }, + } +} + +// getDegradedConditions returns a list of conditions.Condition objects and marks +// every condition as FALSE except for conditions.ConditionDegraded so that the +// reconciler can determine that the resource is degraded. +func (r *NodeFeatureDiscoveryReconciler) getDegradedConditions(reason string, message string) []metav1.Condition { + now := time.Now() + return []metav1.Condition{ + { + Type: ConditionAvailable, + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Time{Time: now}, + }, + { + Type: ConditionUpgradeable, + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Time{Time: now}, + }, + { + Type: ConditionProgressing, + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Time{Time: now}, + }, + { + Type: ConditionDegraded, + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.Time{Time: now}, + Reason: reason, + Message: message, + }, + } +} + +// getProgressingConditions returns a list of Condition objects and marks +// every condition as FALSE except for ConditionProgressing so that the +// reconciler can determine that the resource is progressing. +func (r *NodeFeatureDiscoveryReconciler) getProgressingConditions(reason string, message string) []metav1.Condition { + now := time.Now() + return []metav1.Condition{ + { + Type: ConditionAvailable, + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Time{Time: now}, + }, + { + Type: ConditionUpgradeable, + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Time{Time: now}, + }, + { + Type: ConditionProgressing, + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.Time{Time: now}, + Reason: reason, + Message: message, + }, + { + Type: ConditionDegraded, + Status: metav1.ConditionFalse, + LastTransitionTime: metav1.Time{Time: now}, + }, + } +} + +// The status of the resource (available, upgradeable, progressing, or +// degraded). +type Status struct { + // Is the resource available, upgradable, etc.? + isAvailable bool + isUpgradeable bool + isProgressing bool + isDegraded bool +} + +// initializeDegradedStatus initializes the status struct to degraded +func initializeDegradedStatus() Status { + return Status{ + isAvailable: false, + isUpgradeable: false, + isProgressing: false, + isDegraded: true, + } +} + +// getWorkerDaemonSetConditions is a wrapper around "getDaemonSetConditions" for +// worker DaemonSets +func (r *NodeFeatureDiscoveryReconciler) getWorkerDaemonSetConditions(ctx context.Context) (Status, error) { + return r.getDaemonSetConditions(ctx, nfdWorkerApp) +} + +// getMasterDaemonSetConditions is a wrapper around "getDaemonSetConditions" for +// master DaemonSets +func (r *NodeFeatureDiscoveryReconciler) getMasterDaemonSetConditions(ctx context.Context) (Status, error) { + return r.getDaemonSetConditions(ctx, nfdMasterApp) +} + +// getDaemonSetConditions gets the current status of a DaemonSet. If an error +// occurs, this function returns the corresponding error message +func (r *NodeFeatureDiscoveryReconciler) getDaemonSetConditions(ctx context.Context, nfdAppName string) (Status, error) { + // Initialize the resource's status to 'Degraded' + status := initializeDegradedStatus() + + ds, err := r.getDaemonSet(ctx, nfdNamespace, nfdAppName) + if err != nil { + return status, err + } + + // Index the DaemonSet status. (Note: there is no "Conditions" array here.) + dsStatus := ds.Status + + // Index the relevant values from here + numberReady := dsStatus.NumberReady + currentNumberScheduled := dsStatus.CurrentNumberScheduled + numberDesired := dsStatus.DesiredNumberScheduled + numberUnavailable := dsStatus.NumberUnavailable + + // If the number desired is zero or the number of unavailable nodes is zero, + // then we have a problem because we should at least see 1 pod per node + if numberDesired == 0 { + if nfdAppName == nfdWorkerApp { + return status, errors.New(errorNFDWorkerDaemonSetUnknown) + } + return status, errors.New(errorNFDMasterDaemonSetUnknown) + } + if numberUnavailable > 0 { + status.isProgressing = true + status.isDegraded = false + if nfdAppName == nfdWorkerApp { + return status, errors.New(warningNFDWorkerDaemonSetProgressing) + } + return status, errors.New(warningNFDMasterDaemonSetProgressing) + } + + // If there are none scheduled, then we have a problem because we should + // at least see 1 pod per node, even after the scheduling happens. + if currentNumberScheduled == 0 { + if nfdAppName == nfdWorkerApp { + return status, errors.New(conditionNFDWorkerDaemonSetDegraded) + } + return status, errors.New(conditionNFDMasterDaemonSetDegraded) + } + + // Just check in case the number of "ready" nodes is greater than the + // number of scheduled ones (for whatever reason) + if numberReady > currentNumberScheduled { + status.isDegraded = false + if nfdAppName == nfdWorkerApp { + return status, errors.New(errorTooManyNFDWorkerDaemonSetReadyNodes) + } + return status, errors.New(errorTooManyNFDMasterDaemonSetReadyNodes) + } + + // If we have less than the number of scheduled pods, then the DaemonSet + // is in progress + if numberReady < currentNumberScheduled { + status.isProgressing = true + status.isDegraded = false + return status, errors.New(warningNumberOfReadyNodesIsLessThanScheduled) + } + + // If all nodes are ready, then update the status to be "isAvailable" + status.isAvailable = true + status.isDegraded = false + + return status, nil +} + +// getServiceConditions gets the current status of a Service. If an error +// occurs, this function returns the corresponding error message +func (r *NodeFeatureDiscoveryReconciler) getServiceConditions(ctx context.Context) (Status, error) { + // Initialize status to 'Degraded' + status := initializeDegradedStatus() + + // Get the existing Service from the reconciler + _, err := r.getService(ctx, nfdNamespace, nfdMasterApp) + + // If the Service could not be obtained, then it is degraded + if err != nil { + return status, errors.New(conditionNFDServiceDegraded) + } + + // If we could get the Service, then it is not empty and it exists + status.isAvailable = true + status.isDegraded = false + + return status, nil + +} + +// getWorkerConfigConditions gets the current status of a worker config. If an error +// occurs, this function returns the corresponding error message +func (r *NodeFeatureDiscoveryReconciler) getWorkerConfigConditions(n NFD) (Status, error) { + // Initialize status to 'Degraded' + status := initializeDegradedStatus() + + // Get the existing ConfigMap from the reconciler + wc := n.ins.Spec.WorkerConfig.ConfigData + + // If 'wc' is nil, then the resource hasn't been (re)created yet + if wc == "" { + return status, errors.New(conditionNFDWorkerConfigDegraded) + } + + // If we could get the WorkerConfig, then it is not empty and it exists + status.isDegraded = false + status.isAvailable = true + + return status, nil +} + +// getRoleConditions gets the current status of a Role. If an error occurs, this +// function returns the corresponding error message +func (r *NodeFeatureDiscoveryReconciler) getRoleConditions(ctx context.Context) (Status, error) { + // Initialize status to 'Degraded' + status := initializeDegradedStatus() + + // Get the existing Role from the reconciler + _, err := r.getRole(ctx, nfdNamespace, nfdWorkerApp) + + // If the error is not nil, then the Role hasn't been (re)created yet + if err != nil { + return status, errors.New(conditionNFDRoleDegraded) + } + + // Set the resource to available + status.isAvailable = true + status.isDegraded = false + + return status, nil +} + +// getRoleBindingConditions gets the current status of a RoleBinding. If an error +// occurs, this function returns the corresponding error message +func (r *NodeFeatureDiscoveryReconciler) getRoleBindingConditions(ctx context.Context) (Status, error) { + // Initialize status to 'Degraded' + status := initializeDegradedStatus() + + // Get the existing RoleBinding from the reconciler + _, err := r.getRoleBinding(ctx, nfdNamespace, nfdWorkerApp) + + // If the error is not nil, then the RoleBinding hasn't been (re)created yet + if err != nil { + return status, errors.New(conditionNFDRoleBindingDegraded) + } + + // Set the resource to available + status.isAvailable = true + status.isDegraded = false + + return status, nil +} + +// geClusterRoleConditions gets the current status of a ClusterRole. If an error +// occurs, this function returns the corresponding error message +func (r *NodeFeatureDiscoveryReconciler) getClusterRoleConditions(ctx context.Context) (Status, error) { + // Initialize status to 'Degraded' + status := initializeDegradedStatus() + + // Get the existing ClusterRole from the reconciler + _, err := r.getClusterRole(ctx, "", nfdMasterApp) + + // If 'clusterRole' is nil, then it hasn't been (re)created yet + if err != nil { + return status, errors.New(conditionNFDClusterRoleDegraded) + } + + // Set the resource to available + status.isAvailable = true + status.isDegraded = false + + return status, nil +} + +// getClusterRoleBindingConditions gets the current status of a ClusterRoleBinding. +// If an error occurs, this function returns the corresponding error message +func (r *NodeFeatureDiscoveryReconciler) getClusterRoleBindingConditions(ctx context.Context) (Status, error) { + // Initialize status to 'Degraded' + status := initializeDegradedStatus() + + // Get the existing ClusterRoleBinding from the reconciler + _, err := r.getClusterRoleBinding(ctx, "", nfdMasterApp) + + // If the error is not nil, then the ClusterRoleBinding hasn't been (re)created + // yet + if err != nil { + return status, errors.New(conditionNFDClusterRoleBindingDegraded) + } + + // Set the resource to available + status.isAvailable = true + status.isDegraded = false + + return status, nil +} + +// getWorkerServiceAccountConditions is a wrapper around "getServiceAccountConditions" for +// worker service account. +func (r *NodeFeatureDiscoveryReconciler) getWorkerServiceAccountConditions(ctx context.Context) (Status, error) { + return r.getServiceAccountConditions(ctx, nfdWorkerApp) +} + +// getMasterServiceAccountConditions is a wrapper around "getServiceAccountConditions" for +// master service account. +func (r *NodeFeatureDiscoveryReconciler) getMasterServiceAccountConditions(ctx context.Context) (Status, error) { + return r.getServiceAccountConditions(ctx, nfdMasterApp) +} + +// getServiceAccountConditions gets the current status of a ServiceAccount. If an error +// occurs, this function returns the corresponding error message +func (r *NodeFeatureDiscoveryReconciler) getServiceAccountConditions(ctx context.Context, nfdAppName string) (Status, error) { + // Initialize status to 'Degraded' + status := initializeDegradedStatus() + + // Get the service account from the reconciler + _, err := r.getServiceAccount(ctx, nfdNamespace, nfdAppName) + + // If the error is not nil, then the ServiceAccount hasn't been (re)created yet + if err != nil { + if nfdAppName == nfdWorkerApp { + return status, errors.New(conditionNFDWorkerServiceAccountDegraded) + } + return status, errors.New(conditionNFDMasterServiceAccountDegraded) + } + + // Set the resource to available + status.isAvailable = true + status.isDegraded = false + + return status, nil +} diff --git a/go.mod b/go.mod index c44ead76..ed0b9983 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,6 @@ go 1.16 require ( github.com/onsi/ginkgo v1.14.1 github.com/onsi/gomega v1.10.2 - github.com/openshift/custom-resource-status v0.0.0-20210221154447-420d9ecf2a00 k8s.io/api v0.20.4 k8s.io/apimachinery v0.20.4 k8s.io/client-go v0.20.4 diff --git a/go.sum b/go.sum index f115f808..5b49c3d0 100644 --- a/go.sum +++ b/go.sum @@ -106,7 +106,6 @@ github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfc github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -120,13 +119,11 @@ github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= -github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -200,7 +197,6 @@ github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+ github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= -github.com/gogo/protobuf v1.0.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls= @@ -217,7 +213,6 @@ github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfb github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -244,7 +239,6 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/gofuzz v0.0.0-20161122191042-44d81051d367/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -261,8 +255,6 @@ github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gnostic v0.0.0-20170426233943-68f4ded48ba9/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= -github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= @@ -305,7 +297,6 @@ github.com/imdario/mergo v0.3.10 h1:6q5mVkdH/vYmqngx7kZQTjJ5HRsx+ImorDIEQ+beJgc= github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10 h1:Kz6Cvnvv2wGdaG/V8yMvfkmNiXq9Ya2KUv4rouJJr68= @@ -358,7 +349,6 @@ github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/f github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -372,21 +362,17 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs= github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/openshift/custom-resource-status v0.0.0-20210221154447-420d9ecf2a00 h1:w/APGa+Tkf3TUaws5TiPa7ZCkXT0GHY6GK0f/7+MDPc= -github.com/openshift/custom-resource-status v0.0.0-20210221154447-420d9ecf2a00/go.mod h1:GDjWl0tX6FNIj82vIxeudWeSx2Ff6nDZ8uJn0ohUFvo= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= @@ -395,7 +381,6 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -422,7 +407,6 @@ github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4O github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= -github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= @@ -456,7 +440,6 @@ github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= -github.com/stretchr/testify v0.0.0-20151208002404-e3a8ff8ce365/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -513,9 +496,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190125153040-c74c464bbbf2/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190312203227-4b39c73a6495/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= @@ -546,7 +527,6 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -592,7 +572,6 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -632,7 +611,6 @@ golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -652,7 +630,6 @@ golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190125232054-d66bd3c5d5a6/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -699,9 +676,6 @@ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1N golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gomodules.xyz/jsonpatch/v2 v2.1.0 h1:Phva6wqu+xR//Njw6iorylFFgn/z547tw5Ne3HZPQ+k= gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= -gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0= -gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= -gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmKJ7gzohV1XkqsFehRA2FbsbkopSuQ= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -765,7 +739,6 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -794,13 +767,11 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.0.0-20190725062911-6607c48751ae/go.mod h1:1O0xzX/RAtnm7l+5VEUxZ1ysO2ghatfq/OZED4zM9kA= k8s.io/api v0.19.2/go.mod h1:IQpK0zFQ1xc5iNIQPqzgoOwuFugaYHK4iCknlAQP9nI= k8s.io/api v0.20.4 h1:xZjKidCirayzX6tHONRQyTNDVIR55TYVqgATqo6ZULY= k8s.io/api v0.20.4/go.mod h1:++lNL1AJMkDymriNniQsWRkMDzRaX2Y/POTUi8yvqYQ= k8s.io/apiextensions-apiserver v0.19.2 h1:oG84UwiDsVDu7dlsGQs5GySmQHCzMhknfhFExJMz9tA= k8s.io/apiextensions-apiserver v0.19.2/go.mod h1:EYNjpqIAvNZe+svXVx9j4uBaVhTB4C94HkY3w058qcg= -k8s.io/apimachinery v0.0.0-20190719140911-bfcf53abc9f8/go.mod h1:sBJWIJZfxLhp7mRsRyuAE/NfKTr3kXGR1iaqg8O0gJo= k8s.io/apimachinery v0.19.2/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA= k8s.io/apimachinery v0.20.4 h1:vhxQ0PPUUU2Ns1b9r4/UFp13UPs8cw2iOoTjnY9faa0= k8s.io/apimachinery v0.20.4/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= @@ -809,25 +780,19 @@ k8s.io/cli-runtime v0.20.4/go.mod h1:dz38e1CM4uuIhy8PMFUZv7qsvIdoE3ByZYlmbHNCkt4 k8s.io/client-go v0.19.2/go.mod h1:S5wPhCqyDNAlzM9CnEdgTGV4OqhsW3jGO1UM1epwfJA= k8s.io/client-go v0.20.4 h1:85crgh1IotNkLpKYKZHVNI1JT86nr/iDCvq2iWKsql4= k8s.io/client-go v0.20.4/go.mod h1:LiMv25ND1gLUdBeYxBIwKpkSC5IsozMMmOOeSJboP+k= -k8s.io/code-generator v0.0.0-20190717022600-77f3a1fe56bb/go.mod h1:cDx5jQmWH25Ff74daM7NVYty9JWw9dvIS9zT9eIubCY= k8s.io/code-generator v0.19.2/go.mod h1:moqLn7w0t9cMs4+5CQyxnfA/HV8MF6aAVENF+WZZhgk= k8s.io/code-generator v0.20.4/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg= k8s.io/component-base v0.19.2/go.mod h1:g5LrsiTiabMLZ40AR6Hl45f088DevyGY+cCE2agEIVo= k8s.io/component-base v0.20.4 h1:gdvPs4G11e99meQnW4zN+oYOjH8qkLz1sURrAzvKWqc= k8s.io/component-base v0.20.4/go.mod h1:t4p9EdiagbVCJKrQ1RsA5/V4rFQNDfRlevJajlGwgjI= k8s.io/component-helpers v0.20.4/go.mod h1:S7jGg8zQp3kwvSzfuGtNaQAMVmvzomXDioTm5vABn9g= -k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= -k8s.io/klog v0.3.1 h1:RVgyDHY/kFKtLqh67NvEWIgkMneNoIrdkN0CxDSQc68= -k8s.io/klog v0.3.1/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/kube-openapi v0.0.0-20190709113604-33be087ad058/go.mod h1:nfDlWeOsu3pUf4yWGL+ERqohP4YsZcBJXWMK+gkzOA4= k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= @@ -838,11 +803,6 @@ k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/ k8s.io/utils v0.0.0-20200912215256-4140de9c8800/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g7yaSHkYPkpgelw= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw= -modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk= -modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k= -modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs= -modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= @@ -850,8 +810,6 @@ sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.9/go.mod h1:dzAXnQb sigs.k8s.io/controller-runtime v0.7.0 h1:bU20IBBEPccWz5+zXpLnpVsgBYxqclaHu1pVDl/gEt8= sigs.k8s.io/controller-runtime v0.7.0/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU= sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU= -sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ= -sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI= sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=