Skip to content

Commit

Permalink
refactor: load state to return error if loading fails (zarf-dev#2763)
Browse files Browse the repository at this point in the history
Signed-off-by: Philip Laine <philip.laine@gmail.com>
Signed-off-by: Tim Seagren <timseagren@defenseunicorns.com>
  • Loading branch information
phillebaba authored and chaospuppy committed Aug 5, 2024
1 parent de6c092 commit 9a25d40
Show file tree
Hide file tree
Showing 12 changed files with 51 additions and 52 deletions.
2 changes: 1 addition & 1 deletion src/cmd/destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 14 additions & 19 deletions src/cmd/internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
},
Expand All @@ -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
},
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/tools/crane.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

Expand Down
6 changes: 0 additions & 6 deletions src/config/lang/english.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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." +
Expand Down Expand Up @@ -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."

Expand Down Expand Up @@ -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"
Expand Down
2 changes: 1 addition & 1 deletion src/internal/agent/hooks/argocd-application.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/internal/agent/hooks/argocd-repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/internal/agent/hooks/flux-gitrepo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion src/internal/agent/hooks/flux-helmrepo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/internal/agent/hooks/flux-ocirepo.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/internal/agent/hooks/pods.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 4 additions & 3 deletions src/pkg/cluster/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down
41 changes: 25 additions & 16 deletions src/pkg/packager/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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"
Expand Down Expand Up @@ -714,21 +721,23 @@ 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
}
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:
Expand Down

0 comments on commit 9a25d40

Please sign in to comment.