diff --git a/internal/k8shandler/serviceaccount.go b/internal/k8shandler/serviceaccount.go index a8c682c19c..17382e4a28 100644 --- a/internal/k8shandler/serviceaccount.go +++ b/internal/k8shandler/serviceaccount.go @@ -8,64 +8,9 @@ import ( "github.com/openshift/cluster-logging-operator/internal/runtime" "github.com/openshift/cluster-logging-operator/internal/utils" "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/types" - "k8s.io/client-go/util/retry" - - core "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -//CreateOrUpdateServiceAccount creates or updates a ServiceAccount for logging with the given name -func (clusterRequest *ClusterLoggingRequest) CreateOrUpdateServiceAccount(name string, annotations *map[string]string) error { - - serviceAccount := runtime.NewServiceAccount(clusterRequest.Cluster.Namespace, name) - if annotations != nil { - if serviceAccount.GetObjectMeta().GetAnnotations() == nil { - serviceAccount.GetObjectMeta().SetAnnotations(make(map[string]string)) - } - for key, value := range *annotations { - serviceAccount.GetObjectMeta().GetAnnotations()[key] = value - } - } - - utils.AddOwnerRefToObject(serviceAccount, utils.AsOwner(clusterRequest.Cluster)) - - if err := clusterRequest.Create(serviceAccount); err != nil { - if !errors.IsAlreadyExists(err) { - return fmt.Errorf("Failure creating %v serviceaccount: %v", serviceAccount.Name, err) - } - - current := &core.ServiceAccount{} - retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { - if err = clusterRequest.Get(serviceAccount.Name, current); err != nil { - if errors.IsNotFound(err) { - // the object doesn't exist -- it was likely culled - // recreate it on the next time through if necessary - return nil - } - return fmt.Errorf("Failed to get %v serviceaccount: %v", serviceAccount.Name, err) - } - if annotations != nil && serviceAccount.GetObjectMeta().GetAnnotations() != nil { - if current.GetObjectMeta().GetAnnotations() == nil { - current.GetObjectMeta().SetAnnotations(make(map[string]string)) - } - for key, value := range serviceAccount.GetObjectMeta().GetAnnotations() { - current.GetObjectMeta().GetAnnotations()[key] = value - } - } - if err = clusterRequest.Update(current); err != nil { - return err - } - return nil - }) - if retryErr != nil { - return retryErr - } - } - return nil - -} - //RemoveServiceAccount of given name and namespace func (clusterRequest *ClusterLoggingRequest) RemoveServiceAccount(serviceAccountName string) error { @@ -83,14 +28,3 @@ func (clusterRequest *ClusterLoggingRequest) RemoveServiceAccount(serviceAccount return nil } - -func NewLogCollectorServiceAccountRef(uid types.UID) metav1.OwnerReference { - return metav1.OwnerReference{ - APIVersion: "v1", // apiversion for serviceaccounts/finalizers in cluster-logging..clusterserviceversion.yaml - Kind: "ServiceAccount", - Name: constants.CollectorServiceAccountName, - UID: uid, - BlockOwnerDeletion: utils.GetBool(true), - Controller: utils.GetBool(true), - } -} diff --git a/internal/reconcile/service_account.go b/internal/reconcile/service_account.go new file mode 100644 index 0000000000..c3add1f10b --- /dev/null +++ b/internal/reconcile/service_account.go @@ -0,0 +1,76 @@ +package reconcile + +import ( + "context" + "fmt" + log "github.com/ViaQ/logerr/v2/log/static" + "github.com/openshift/cluster-logging-operator/internal/constants" + v1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/retry" + "reflect" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func ServiceAccount(er record.EventRecorder, k8Client client.Client, desired *v1.ServiceAccount) error { + reason := constants.EventReasonGetObject + updateReason := "" + retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error { + current := &v1.ServiceAccount{} + key := client.ObjectKeyFromObject(desired) + if err := k8Client.Get(context.TODO(), key, current); err != nil { + if errors.IsNotFound(err) { + reason = constants.EventReasonCreateObject + return k8Client.Create(context.TODO(), desired) + } + return fmt.Errorf("failed to get %v DaemonSet: %w", key, err) + } + same := false + + if same, updateReason = areSame(current, desired); same { + log.V(3).Info("ServiceAccount are the same skipping update") + return nil + } + reason = constants.EventReasonUpdateObject + current.Secrets = desired.Secrets + current.ImagePullSecrets = desired.ImagePullSecrets + current.AutomountServiceAccountToken = desired.AutomountServiceAccountToken + return k8Client.Update(context.TODO(), current) + }) + + eventType := v1.EventTypeNormal + msg := fmt.Sprintf("%s DaemonSet %s/%s", reason, desired.Namespace, desired.Name) + if updateReason != "" { + msg = fmt.Sprintf("%s because of change in %s.", msg, updateReason) + } + if retryErr != nil { + eventType = v1.EventTypeWarning + msg = fmt.Sprintf("Unable to %s: %v", msg, retryErr) + } + er.Event(desired, eventType, reason, msg) + return retryErr +} + +func areSame(current *v1.ServiceAccount, desired *v1.ServiceAccount) (bool, string) { + if current.AutomountServiceAccountToken != desired.AutomountServiceAccountToken { + return false, "automountServiceAccountToken" + } + if len(current.Secrets) != len(desired.Secrets) { + return false, "len of secrets are not equal" + } + for i, secret := range current.Secrets { + if reflect.DeepEqual(secret, desired.Secrets[0]) { + return false, fmt.Sprintf("secret[%d]", i) + } + } + if len(current.ImagePullSecrets) != len(desired.ImagePullSecrets) { + return false, "len of imagePullSecrets are not equal" + } + for i, secret := range current.ImagePullSecrets { + if reflect.DeepEqual(secret, desired.ImagePullSecrets[0]) { + return false, fmt.Sprintf("imagePullSecrets[%d]", i) + } + } + return true, "" +}