diff --git a/cmd/argocd-util/main.go b/cmd/argocd-util/main.go index c226c4a96a..fdafa0906b 100644 --- a/cmd/argocd-util/main.go +++ b/cmd/argocd-util/main.go @@ -366,7 +366,8 @@ func NewSettingsCommand() *cobra.Command { errors.CheckError(err) settingsMgr := settings.NewSettingsManager(kubeclientset, namespace) - _ = settings.UpdateSettings(superuserPassword, settingsMgr, updateSignature, updateSuperuser, namespace) + _, err = settings.UpdateSettings(superuserPassword, settingsMgr, updateSignature, updateSuperuser, namespace) + errors.CheckError(err) }, } command.Flags().BoolVar(&updateSuperuser, "update-superuser", false, "force updating the superuser password") diff --git a/cmd/argocd/commands/account.go b/cmd/argocd/commands/account.go index b816c407c6..ca5067a6ef 100644 --- a/cmd/argocd/commands/account.go +++ b/cmd/argocd/commands/account.go @@ -50,7 +50,9 @@ func NewAccountUpdatePasswordCommand(clientOpts *argocdclient.ClientOptions) *co fmt.Print("\n") } if newPassword == "" { - newPassword = settings.ReadAndConfirmPassword() + var err error + newPassword, err = settings.ReadAndConfirmPassword() + errors.CheckError(err) } updatePasswordRequest := account.UpdatePasswordRequest{ diff --git a/server/server.go b/server/server.go index f65aedfce6..9539a7d4ce 100644 --- a/server/server.go +++ b/server/server.go @@ -144,7 +144,15 @@ func initializeSettings(settingsMgr *settings_util.SettingsManager, opts ArgoCDS defaultPassword, err := os.Hostname() errors.CheckError(err) - cdSettings := settings_util.UpdateSettings(defaultPassword, settingsMgr, false, false, opts.Namespace) + cdSettings, err := settings_util.UpdateSettings(defaultPassword, settingsMgr, false, false, opts.Namespace) + if err != nil { + // assume settings are initialized by another instance of api server + if apierrors.IsConflict(err) { + return settingsMgr.GetSettings() + } else { + log.Fatal(err) + } + } return cdSettings, nil } diff --git a/util/settings/settings.go b/util/settings/settings.go index b0089aa57b..38b728f2c8 100644 --- a/util/settings/settings.go +++ b/util/settings/settings.go @@ -23,7 +23,6 @@ import ( "k8s.io/client-go/tools/cache" "github.com/argoproj/argo-cd/common" - "github.com/argoproj/argo-cd/errors" "github.com/argoproj/argo-cd/util" "github.com/argoproj/argo-cd/util/password" tlsutil "github.com/argoproj/argo-cd/util/tls" @@ -87,6 +86,14 @@ type SettingsManager struct { mutex *sync.Mutex } +type incompleteSettingsError struct { + message string +} + +func (e *incompleteSettingsError) Error() string { + return e.message +} + // GetSettings retrieves settings from the ArgoCD configmap and secret. func (mgr *SettingsManager) GetSettings() (*ArgoCDSettings, error) { var settings ArgoCDSettings @@ -111,11 +118,11 @@ func updateSettingsFromConfigMap(settings *ArgoCDSettings, argoCDCM *apiv1.Confi settings.URL = argoCDCM.Data[settingURLKey] } -// UpdateSettingsFromSecret transfers settings from a Kubernetes secret into an ArgoCDSettings struct. +// updateSettingsFromSecret transfers settings from a Kubernetes secret into an ArgoCDSettings struct. func updateSettingsFromSecret(settings *ArgoCDSettings, argoCDSecret *apiv1.Secret) error { adminPasswordHash, ok := argoCDSecret.Data[settingAdminPasswordHashKey] if !ok { - return fmt.Errorf("admin user not found") + return &incompleteSettingsError{message: "admin-password is missing"} } settings.AdminPasswordHash = string(adminPasswordHash) settings.AdminPasswordMtime = time.Now().UTC() @@ -127,7 +134,7 @@ func updateSettingsFromSecret(settings *ArgoCDSettings, argoCDSecret *apiv1.Secr secretKey, ok := argoCDSecret.Data[settingServerSignatureKey] if !ok { - return fmt.Errorf("server secret key not found") + return &incompleteSettingsError{message: "server-signature-key is missing"} } settings.ServerSignature = secretKey if githubWebhookSecret := argoCDSecret.Data[settingsWebhookGitHubSecretKey]; len(githubWebhookSecret) > 0 { @@ -145,7 +152,7 @@ func updateSettingsFromSecret(settings *ArgoCDSettings, argoCDSecret *apiv1.Secr if certOk && keyOk { cert, err := tls.X509KeyPair(serverCert, serverKey) if err != nil { - return fmt.Errorf("invalid x509 key pair %s/%s in secret: %s", settingServerCertificate, settingServerPrivateKey, err) + return &incompleteSettingsError{message: fmt.Sprintf("invalid x509 key pair %s/%s in secret: %s", settingServerCertificate, settingServerPrivateKey, err)} } settings.Certificate = &cert } @@ -400,31 +407,38 @@ func (mgr *SettingsManager) notifySubscribers() { } } -func ReadAndConfirmPassword() string { +func ReadAndConfirmPassword() (string, error) { for { fmt.Print("*** Enter new password: ") password, err := terminal.ReadPassword(syscall.Stdin) - errors.CheckError(err) + if err != nil { + return "", err + } fmt.Print("\n") fmt.Print("*** Confirm new password: ") confirmPassword, err := terminal.ReadPassword(syscall.Stdin) - errors.CheckError(err) + if err != nil { + return "", err + } fmt.Print("\n") if string(password) == string(confirmPassword) { - return string(password) + return string(password), nil } log.Error("Passwords do not match") } } +func isIncompleteSettingsError(err error) bool { + _, ok := err.(*incompleteSettingsError) + return ok +} + // UpdateSettings is used to update the admin password, signature, certificate etc -func UpdateSettings(defaultPassword string, settingsMgr *SettingsManager, updateSignature bool, updateSuperuser bool, Namespace string) *ArgoCDSettings { +func UpdateSettings(defaultPassword string, settingsMgr *SettingsManager, updateSignature bool, updateSuperuser bool, Namespace string) (*ArgoCDSettings, error) { cdSettings, err := settingsMgr.GetSettings() - if err != nil { - if apierr.IsNotFound(err) { - log.Fatal(err) - } + if err != nil && !apierr.IsNotFound(err) && !isIncompleteSettingsError(err) { + return nil, err } if cdSettings == nil { cdSettings = &ArgoCDSettings{} @@ -432,16 +446,23 @@ func UpdateSettings(defaultPassword string, settingsMgr *SettingsManager, update if cdSettings.ServerSignature == nil || updateSignature { // set JWT signature signature, err := util.MakeSignature(32) - errors.CheckError(err) + if err != nil { + return nil, err + } cdSettings.ServerSignature = signature } if cdSettings.AdminPasswordHash == "" || updateSuperuser { passwordRaw := defaultPassword if passwordRaw == "" { - passwordRaw = ReadAndConfirmPassword() + passwordRaw, err = ReadAndConfirmPassword() + if err != nil { + return nil, err + } } hashedPassword, err := password.HashPassword(passwordRaw) - errors.CheckError(err) + if err != nil { + return nil, err + } cdSettings.AdminPasswordHash = hashedPassword cdSettings.AdminPasswordMtime = time.Now().UTC() } @@ -461,11 +482,11 @@ func UpdateSettings(defaultPassword string, settingsMgr *SettingsManager, update IsCA: true, } cert, err := tlsutil.GenerateX509KeyPair(certOpts) - errors.CheckError(err) + if err != nil { + return nil, err + } cdSettings.Certificate = cert } - err = settingsMgr.SaveSettings(cdSettings) - errors.CheckError(err) - return cdSettings + return cdSettings, settingsMgr.SaveSettings(cdSettings) }