controllers/user/chain/create_user.go (103 lines of code) (raw):

package chain import ( "context" "fmt" "strings" "github.com/datadrivers/go-nexus-client/nexus3/schema/security" "golang.org/x/exp/slices" corev1 "k8s.io/api/core/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" nexusApi "github.com/epam/edp-nexus-operator/api/v1alpha1" "github.com/epam/edp-nexus-operator/pkg/client/nexus" ) // CreateUser is a handler for creating user. type CreateUser struct { nexusUserApiClient nexus.User client client.Client } // NewCreateUser creates an instance of CreateUser handler. func NewCreateUser(nexusUserApiClient nexus.User, k8sClient client.Client) *CreateUser { return &CreateUser{nexusUserApiClient: nexusUserApiClient, client: k8sClient} } // ServeRequest implements the logic of creating user. func (c *CreateUser) ServeRequest(ctx context.Context, user *nexusApi.NexusUser) error { log := ctrl.LoggerFrom(ctx).WithValues("id", user.Spec.ID) log.Info("Start creating user") nexusUser, err := c.nexusUserApiClient.Get(user.Spec.ID) if err != nil { return fmt.Errorf("failed to get user: %w", err) } if nexusUser == nil { log.Info("User doesn't exist, creating new one") var pass string if pass, err = c.getSecretFromRef(ctx, user.Spec.Secret, user.Namespace); err != nil { return fmt.Errorf("failed to get password from secret: %w", err) } if err = c.nexusUserApiClient.Create(specToUser(&user.Spec, pass)); err != nil { return fmt.Errorf("failed to create user: %w", err) } log.Info("User has been created") return nil } if userChanged(&user.Spec, nexusUser) { log.Info("Updating user") updateUserFields(&user.Spec, nexusUser) if err = c.nexusUserApiClient.Update(user.Spec.ID, *nexusUser); err != nil { return fmt.Errorf("failed to update user: %w", err) } log.Info("User has been updated") return nil } log.Info("User unchanged, skip updating") return nil } func userChanged(spec *nexusApi.NexusUserSpec, nexusUser *security.User) bool { if spec.FirstName != nexusUser.FirstName || spec.LastName != nexusUser.LastName || spec.Email != nexusUser.EmailAddress || spec.Status != nexusUser.Status || !slices.Equal(spec.Roles, nexusUser.Roles) { return true } return false } func updateUserFields(spec *nexusApi.NexusUserSpec, user *security.User) { user.FirstName = spec.FirstName user.LastName = spec.LastName user.EmailAddress = spec.Email user.Status = spec.Status user.Roles = slices.Clone(spec.Roles) } func specToUser(spec *nexusApi.NexusUserSpec, password string) security.User { return security.User{ UserID: spec.ID, FirstName: spec.FirstName, LastName: spec.LastName, EmailAddress: spec.Email, Status: spec.Status, Roles: slices.Clone(spec.Roles), Password: password, } } func (c *CreateUser) getSecretFromRef(ctx context.Context, refVal, secretNamespace string) (string, error) { if !hasSecretRef(refVal) { return "", fmt.Errorf("invalid config secret reference %s is not in format '$secretName:secretKey'", refVal) } ref := strings.Split(refVal[1:], ":") if len(ref) != 2 { return "", fmt.Errorf("invalid config secret reference %s is not in format '$secretName:secretKey'", refVal) } secret := &corev1.Secret{} if err := c.client.Get(ctx, client.ObjectKey{ Namespace: secretNamespace, Name: ref[0], }, secret); err != nil { return "", fmt.Errorf("failed to get secret %s: %w", ref[0], err) } secretVal, ok := secret.Data[ref[1]] if !ok { return "", fmt.Errorf("secret %s does not contain key %s", ref[0], ref[1]) } return string(secretVal), nil } func hasSecretRef(val string) bool { return strings.HasPrefix(val, "$") }