diff --git a/src/cmd/destroy.go b/src/cmd/destroy.go index 1e3d1bb646..1b71740aa3 100644 --- a/src/cmd/destroy.go +++ b/src/cmd/destroy.go @@ -44,7 +44,7 @@ var destroyCmd = &cobra.Command{ // the scripts to remove k3s, we will still try to remove a locally installed k3s cluster state, err := c.LoadZarfState(ctx) if err != nil { - message.WarnErr(err, lang.ErrLoadState) + message.WarnErr(err, err.Error()) } // If Zarf deployed the cluster, burn it all down diff --git a/src/cmd/internal.go b/src/cmd/internal.go index 7ff0315356..907125688d 100644 --- a/src/cmd/internal.go +++ b/src/cmd/internal.go @@ -204,14 +204,12 @@ var createReadOnlyGiteaUser = &cobra.Command{ if err != nil { return err } - // Load the state so we can get the credentials for the admin git user state, err := c.LoadZarfState(cmd.Context()) if err != nil { - message.WarnErr(err, lang.ErrLoadState) + return err } - // Create the non-admin user if err = git.New(state.GitServer).CreateReadOnlyUser(cmd.Context()); err != nil { - message.WarnErr(err, lang.CmdInternalCreateReadOnlyGiteaUserErr) + return fmt.Errorf("unable to create a read only user in Gitea: %w", err) } return nil }, @@ -228,25 +226,22 @@ var createPackageRegistryToken = &cobra.Command{ if err != nil { return err } - ctx := cmd.Context() state, err := c.LoadZarfState(ctx) if err != nil { - message.WarnErr(err, lang.ErrLoadState) + return err } - - // If we are setup to use an internal artifact server, create the artifact registry token - if state.ArtifactServer.InternalServer { - token, err := git.New(state.GitServer).CreatePackageRegistryToken(ctx) - if err != nil { - message.WarnErr(err, lang.CmdInternalArtifactRegistryGiteaTokenErr) - } - - state.ArtifactServer.PushToken = token.Sha1 - - if err := c.SaveZarfState(ctx, state); err != nil { - return err - } + if !state.ArtifactServer.InternalServer { + return nil + } + token, err := git.New(state.GitServer).CreatePackageRegistryToken(ctx) + if err != nil { + return fmt.Errorf("unable to create an artifact registry token for Gitea: %w", err) + } + state.ArtifactServer.PushToken = token.Sha1 + err = c.SaveZarfState(ctx, state) + if err != nil { + return err } return nil }, diff --git a/src/cmd/tools/crane.go b/src/cmd/tools/crane.go index 4df8daebb3..dd76955339 100644 --- a/src/cmd/tools/crane.go +++ b/src/cmd/tools/crane.go @@ -176,7 +176,7 @@ func zarfCraneInternalWrapper(commandToWrap func(*[]crane.Option) *cobra.Command zarfState, err := c.LoadZarfState(ctx) if err != nil { - message.Warnf(lang.CmdToolsCraneConnectedButBadStateErr, err.Error()) + message.Warnf("could not get Zarf state from Kubernetes cluster, continuing without state information %s", err.Error()) return originalListFn(cmd, args) } diff --git a/src/config/lang/english.go b/src/config/lang/english.go index 780a50a3bc..5cb2db2d61 100644 --- a/src/config/lang/english.go +++ b/src/config/lang/english.go @@ -17,14 +17,12 @@ import ( // Debug messages will not be a part of the language strings since they are not intended to be user facing // Include sprintf formatting directives in the string if needed. const ( - ErrLoadState = "Failed to load the Zarf State from the cluster." ErrUnmarshal = "failed to unmarshal file: %w" ErrWritingFile = "failed to write file %s: %s" ErrDownloading = "failed to download %s: %s" ErrCreatingDir = "failed to create directory %s: %s" ErrRemoveFile = "failed to remove file %s: %s" ErrUnarchive = "failed to unarchive %s: %s" - ErrConfirmCancel = "confirm selection canceled: %s" ErrFileExtract = "failed to extract filename %s from archive %s: %s" ErrFileNameExtract = "failed to extract filename from URL %s: %s" ErrUnableToGenerateRandomSecret = "unable to generate a random secret" @@ -199,7 +197,6 @@ $ zarf init --artifact-push-password={PASSWORD} --artifact-push-username={USERNA CmdInternalArtifactRegistryGiteaTokenShort = "Creates an artifact registry token for Gitea" CmdInternalArtifactRegistryGiteaTokenLong = "Creates an artifact registry token in Gitea using the Gitea API. " + "This is called internally by the supported Gitea package component." - CmdInternalArtifactRegistryGiteaTokenErr = "Unable to create an artifact registry token for the Gitea service." CmdInternalUpdateGiteaPVCShort = "Updates an existing Gitea persistent volume claim" CmdInternalUpdateGiteaPVCLong = "Updates an existing Gitea persistent volume claim by assessing if claim is a custom user provided claim or default." + @@ -489,8 +486,6 @@ zarf tools yq e '.a.b = "cool"' -i file.yaml CmdToolsClearCacheSuccess = "Successfully cleared the cache from %s" CmdToolsClearCacheFlagCachePath = "Specify the location of the Zarf artifact cache (images and git repositories)" - CmdToolsCraneConnectedButBadStateErr = "Detected a K8s cluster but was unable to get Zarf state - continuing without state information: %s" - CmdToolsDownloadInitShort = "Downloads the init package for the current Zarf version into the specified directory" CmdToolsDownloadInitFlagOutputDirectory = "Specify a directory to place the init package in." @@ -608,7 +603,6 @@ const ( AgentErrBadRequest = "could not read request body: %s" AgentErrBindHandler = "Unable to bind the webhook handler" AgentErrCouldNotDeserializeReq = "could not deserialize request: %s" - AgentErrGetState = "failed to load zarf state: %w" AgentErrParsePod = "failed to parse pod: %w" AgentErrHostnameMatch = "failed to complete hostname matching: %w" AgentErrInvalidMethod = "invalid method only POST requests are allowed" diff --git a/src/internal/agent/hooks/argocd-application.go b/src/internal/agent/hooks/argocd-application.go index f9d3238aee..b234f29e84 100644 --- a/src/internal/agent/hooks/argocd-application.go +++ b/src/internal/agent/hooks/argocd-application.go @@ -62,7 +62,7 @@ func NewApplicationMutationHook(ctx context.Context, cluster *cluster.Cluster) o func mutateApplication(ctx context.Context, r *v1.AdmissionRequest, cluster *cluster.Cluster) (result *operations.Result, err error) { state, err := cluster.LoadZarfState(ctx) if err != nil { - return nil, fmt.Errorf(lang.AgentErrGetState, err) + return nil, err } message.Debugf("Using the url of (%s) to mutate the ArgoCD Application", state.GitServer.Address) diff --git a/src/internal/agent/hooks/argocd-repository.go b/src/internal/agent/hooks/argocd-repository.go index 2311b50511..1875772d05 100644 --- a/src/internal/agent/hooks/argocd-repository.go +++ b/src/internal/agent/hooks/argocd-repository.go @@ -54,7 +54,7 @@ func mutateRepositorySecret(ctx context.Context, r *v1.AdmissionRequest, cluster state, err := cluster.LoadZarfState(ctx) if err != nil { - return nil, fmt.Errorf(lang.AgentErrGetState, err) + return nil, err } message.Infof("Using the url of (%s) to mutate the ArgoCD Repository Secret", state.GitServer.Address) diff --git a/src/internal/agent/hooks/flux-gitrepo.go b/src/internal/agent/hooks/flux-gitrepo.go index 38a5aedadb..2fda2969bb 100644 --- a/src/internal/agent/hooks/flux-gitrepo.go +++ b/src/internal/agent/hooks/flux-gitrepo.go @@ -48,7 +48,7 @@ func mutateGitRepo(ctx context.Context, r *v1.AdmissionRequest, cluster *cluster state, err := cluster.LoadZarfState(ctx) if err != nil { - return nil, fmt.Errorf(lang.AgentErrGetState, err) + return nil, err } message.Debugf("Using the url of (%s) to mutate the flux repository", state.GitServer.Address) diff --git a/src/internal/agent/hooks/flux-helmrepo.go b/src/internal/agent/hooks/flux-helmrepo.go index c053bb669b..64ad78e40a 100644 --- a/src/internal/agent/hooks/flux-helmrepo.go +++ b/src/internal/agent/hooks/flux-helmrepo.go @@ -56,7 +56,7 @@ func mutateHelmRepo(ctx context.Context, r *v1.AdmissionRequest, cluster *cluste zarfState, err := cluster.LoadZarfState(ctx) if err != nil { - return nil, fmt.Errorf(lang.AgentErrGetState, err) + return nil, err } // Get the registry service info if this is a NodePort service to use the internal kube-dns diff --git a/src/internal/agent/hooks/flux-ocirepo.go b/src/internal/agent/hooks/flux-ocirepo.go index 021a0a619d..e00362c906 100644 --- a/src/internal/agent/hooks/flux-ocirepo.go +++ b/src/internal/agent/hooks/flux-ocirepo.go @@ -59,7 +59,7 @@ func mutateOCIRepo(ctx context.Context, r *v1.AdmissionRequest, cluster *cluster zarfState, err := cluster.LoadZarfState(ctx) if err != nil { - return nil, fmt.Errorf(lang.AgentErrGetState, err) + return nil, err } // Get the registry service info if this is a NodePort service to use the internal kube-dns diff --git a/src/internal/agent/hooks/pods.go b/src/internal/agent/hooks/pods.go index 7d7a6a8023..86fae81e0f 100644 --- a/src/internal/agent/hooks/pods.go +++ b/src/internal/agent/hooks/pods.go @@ -61,7 +61,7 @@ func mutatePod(ctx context.Context, r *v1.AdmissionRequest, cluster *cluster.Clu state, err := cluster.LoadZarfState(ctx) if err != nil { - return nil, fmt.Errorf(lang.AgentErrGetState, err) + return nil, err } registryURL := state.RegistryInfo.Address diff --git a/src/pkg/cluster/state.go b/src/pkg/cluster/state.go index bdc14e5989..82ee49424b 100644 --- a/src/pkg/cluster/state.go +++ b/src/pkg/cluster/state.go @@ -7,11 +7,11 @@ package cluster import ( "context" "encoding/json" + "errors" "fmt" "slices" "time" - "github.com/fatih/color" corev1 "k8s.io/api/core/v1" kerrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -210,13 +210,14 @@ func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitO // LoadZarfState returns the current zarf/zarf-state secret data or an empty ZarfState. func (c *Cluster) LoadZarfState(ctx context.Context) (state *types.ZarfState, err error) { + stateErr := errors.New("failed to load the Zarf State from the cluster, has Zarf been initiated?") secret, err := c.Clientset.CoreV1().Secrets(ZarfNamespaceName).Get(ctx, ZarfStateSecretName, metav1.GetOptions{}) if err != nil { - return nil, fmt.Errorf("%w. %s", err, message.ColorWrap("Did you remember to zarf init?", color.Bold)) + return nil, fmt.Errorf("%w: %w", stateErr, err) } err = json.Unmarshal(secret.Data[ZarfStateDataKey], &state) if err != nil { - return nil, err + return nil, fmt.Errorf("%w: %w", stateErr, err) } c.debugPrintZarfState(state) return state, nil diff --git a/src/pkg/packager/deploy.go b/src/pkg/packager/deploy.go index 735a0b69db..c4e9e33904 100644 --- a/src/pkg/packager/deploy.go +++ b/src/pkg/packager/deploy.go @@ -25,7 +25,6 @@ import ( "github.com/defenseunicorns/pkg/helpers/v2" "github.com/zarf-dev/zarf/src/config" - "github.com/zarf-dev/zarf/src/config/lang" "github.com/zarf-dev/zarf/src/internal/packager/git" "github.com/zarf-dev/zarf/src/internal/packager/helm" "github.com/zarf-dev/zarf/src/internal/packager/images" @@ -128,7 +127,10 @@ func (p *Packager) Deploy(ctx context.Context) error { // Notify all the things about the successful deployment message.Successf("Zarf deployment complete") - p.printTablesForDeployment(ctx, deployedComponents) + err = p.printTablesForDeployment(ctx, deployedComponents) + if err != nil { + return err + } return nil } @@ -453,10 +455,15 @@ func (p *Packager) setupState(ctx context.Context) (err error) { defer spinner.Stop() state, err := p.cluster.LoadZarfState(ctx) - // Return on error if we are not in YOLO mode + // We ignore the error if in YOLO mode because Zarf should not be initiated. if err != nil && !p.cfg.Pkg.Metadata.YOLO { - return fmt.Errorf("%s %w", lang.ErrLoadState, err) - } else if state == nil && p.cfg.Pkg.Metadata.YOLO { + return err + } + // Only ignore state load error in yolo mode when secret could not be found. + if err != nil && !kerrors.IsNotFound(err) && p.cfg.Pkg.Metadata.YOLO { + return err + } + if state == nil && p.cfg.Pkg.Metadata.YOLO { state = &types.ZarfState{} // YOLO mode, so minimal state needed state.Distro = "YOLO" @@ -714,21 +721,26 @@ func (p *Packager) installChartAndManifests(ctx context.Context, componentPaths return installedCharts, nil } -func (p *Packager) printTablesForDeployment(ctx context.Context, componentsToDeploy []types.DeployedComponent) { +func (p *Packager) printTablesForDeployment(ctx context.Context, componentsToDeploy []types.DeployedComponent) error { // If not init config, print the application connection table if !p.cfg.Pkg.IsInitConfig() { message.PrintConnectStringTable(p.connectStrings) - } else { - if p.cluster != nil { - // Grab a fresh copy of the state (if we are able) to print the most up-to-date version of the creds - freshState, err := p.cluster.LoadZarfState(ctx) - if err != nil { - freshState = p.state - } - // otherwise, print the init config connection and passwords - message.PrintCredentialTable(freshState, componentsToDeploy) - } + return nil + } + // Don't print if cluster is not configured + if p.cluster == nil { + return nil + } + // Grab a fresh copy of the state to print the most up-to-date version of the creds + latestState, err := p.cluster.LoadZarfState(ctx) + if err != nil { + return err } + if latestState == nil { + latestState = p.state + } + message.PrintCredentialTable(latestState, componentsToDeploy) + return nil } // ServiceInfoFromServiceURL takes a serviceURL and parses it to find the service info for connecting to the cluster. The string is expected to follow the following format: