Skip to content

Commit

Permalink
Fix checks and rehookup breaking changes warning
Browse files Browse the repository at this point in the history
  • Loading branch information
Racer159 committed Oct 25, 2023
1 parent 4d5f1d3 commit 852b482
Show file tree
Hide file tree
Showing 10 changed files with 90 additions and 83 deletions.
2 changes: 1 addition & 1 deletion src/config/lang/english.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ const (
CmdPackageDeployFlagSget = "[Deprecated] Path to public sget key file for remote packages signed via cosign. This flag will be removed in v1.0.0 please use the --key flag instead."
CmdPackageDeployFlagSkipWebhooks = "[alpha] Skip waiting for external webhooks to execute as each package component is deployed"
CmdPackageDeployValidateArchitectureErr = "this package architecture is %s, but the target cluster has the %s architecture. These architectures must be the same"
CmdPackageDeployValidateLastNonBreakingVersionWarn = "the version of this Zarf binary '%s' is less than the LastNonBreakingVersion of '%s'. You may need to upgrade your Zarf version to at least '%s' to deploy this package"
CmdPackageDeployValidateLastNonBreakingVersionWarn = "The version of this Zarf binary '%s' is less than the LastNonBreakingVersion of '%s'. You may need to upgrade your Zarf version to at least '%s' to deploy this package"
CmdPackageDeployInvalidCLIVersionWarn = "CLIVersion is set to '%s' which can cause issues with package creation and deployment. To avoid such issues, please set the value to the valid semantic version for this version of Zarf."
CmdPackageDeployErr = "Failed to deploy package: %s"

Expand Down
6 changes: 6 additions & 0 deletions src/internal/cluster/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,11 @@ func NewCluster() (*Cluster, error) {
return nil, err
}

// Dogsled the version output. We just want to ensure no errors were returned to validate cluster connection.
_, err = c.GetServerVersion()
if err != nil {
return nil, err
}

return c, nil
}
2 changes: 1 addition & 1 deletion src/internal/cluster/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (c *Cluster) InitZarfState(initOptions types.ZarfInitOptions) error {
err error
)

spinner := message.NewProgressSpinner("Gathering cluster information")
spinner := message.NewProgressSpinner("Gathering cluster state information")
defer spinner.Stop()

spinner.Updatef("Getting cluster architecture")
Expand Down
57 changes: 57 additions & 0 deletions src/pkg/packager/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ package packager

import (
"encoding/json"
"errors"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"time"

"github.com/Masterminds/semver/v3"
"github.com/defenseunicorns/zarf/src/config/lang"
Expand All @@ -25,6 +27,7 @@ import (
"github.com/defenseunicorns/zarf/src/pkg/layout"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/oci"
"github.com/defenseunicorns/zarf/src/pkg/packager/deprecated"
"github.com/defenseunicorns/zarf/src/pkg/packager/sources"
"github.com/defenseunicorns/zarf/src/pkg/utils"
)
Expand Down Expand Up @@ -201,6 +204,60 @@ func (p *Packager) ClearTempPaths() {
_ = os.RemoveAll(layout.SBOMDir)
}

// connectToCluster attempts to connect to a cluster if a connection is not already established
func (p *Packager) connectToCluster(timeout time.Duration) (err error) {
if p.isConnectedToCluster() {
return nil
}

p.cluster, err = cluster.NewClusterWithWait(timeout)
if err != nil {
return err
}

return p.attemptClusterChecks()
}

// isConnectedToCluster returns whether the current packager instance is connected to a cluster
func (p *Packager) isConnectedToCluster() bool {
return p.cluster != nil
}

// attemptClusterChecks attempts to connect to the cluster and check for useful metadata and config mismatches.
// NOTE: attemptClusterChecks should only return an error if there is a problem significant enough to halt a deployment, otherwise it should return nil and print a warning message.
func (p *Packager) attemptClusterChecks() (err error) {

spinner := message.NewProgressSpinner("Gathering additional cluster information (if available)")
defer spinner.Stop()

// Check if the package has already been deployed and get its generation
if existingDeployedPackage, _ := p.cluster.GetDeployedPackage(p.cfg.Pkg.Metadata.Name); existingDeployedPackage != nil {
// If this package has been deployed before, increment the package generation within the secret
p.generation = existingDeployedPackage.Generation + 1
}

// Check the clusters architecture matches the package spec
if err := p.validatePackageArchitecture(); err != nil {
if errors.Is(err, lang.ErrUnableToCheckArch) {
message.Warnf("Unable to validate package architecture: %s", err.Error())
} else {
return err
}
}

// Check for any breaking changes between the initialized Zarf version and this CLI
if existingInitPackage, _ := p.cluster.GetDeployedPackage("init"); existingInitPackage != nil {
// Use the build version instead of the metadata since this will support older Zarf versions
deprecated.PrintBreakingChanges(existingInitPackage.Data.Build.Version)
} else {
message.Warnf("Unable to retrieve the initialized Zarf version. There is potential for breaking changes.")
}

spinner.Success()

return nil
}

// validatePackageArchitecture validates that the package architecture matches the target cluster architecture.
func (p *Packager) validatePackageArchitecture() error {
// Ignore this check if the architecture is explicitly "multi" or we don't have a cluster connection
Expand Down
13 changes: 2 additions & 11 deletions src/pkg/packager/components.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,11 @@ func (p *Packager) getValidComponents() []types.ZarfComponent {
key = component.Name
} else {
// Otherwise, add the component name to the choice group list for later validation
choiceComponents = p.appendIfNotExists(choiceComponents, component.Name)
choiceComponents = helpers.AppendIfNotExists(choiceComponents, component.Name)
}

// Preserve component order
orderedKeys = p.appendIfNotExists(orderedKeys, key)
orderedKeys = helpers.AppendIfNotExists(orderedKeys, key)

// Append the component to the list of components in the group
componentGroups[key] = append(componentGroups[key], component)
Expand Down Expand Up @@ -208,15 +208,6 @@ func (p *Packager) confirmChoiceGroup(componentGroup []types.ZarfComponent) type
return componentGroup[chosen]
}

func (p *Packager) appendIfNotExists(slice []string, item string) []string {
for _, s := range slice {
if s == item {
return slice
}
}
return append(slice, item)
}

func (p *Packager) requiresCluster(component types.ZarfComponent) bool {
hasImages := len(component.Images) > 0
hasCharts := len(component.Charts) > 0
Expand Down
65 changes: 3 additions & 62 deletions src/pkg/packager/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package packager

import (
"errors"
"fmt"
"os"
"path/filepath"
Expand All @@ -15,7 +14,6 @@ import (
"time"

"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/config/lang"
"github.com/defenseunicorns/zarf/src/internal/cluster"
"github.com/defenseunicorns/zarf/src/internal/packager/git"
"github.com/defenseunicorns/zarf/src/internal/packager/helm"
Expand All @@ -37,6 +35,7 @@ func (p *Packager) Deploy() (err error) {
if err = p.source.LoadPackage(p.layout, true); err != nil {
return fmt.Errorf("unable to load the package: %w", err)
}

if err = p.readZarfYAML(p.layout.ZarfYAML); err != nil {
return err
}
Expand Down Expand Up @@ -87,64 +86,6 @@ func (p *Packager) Deploy() (err error) {
return nil
}

// attemptClusterChecks attempts to connect to the cluster and check for useful metadata and config mismatches.
// NOTE: attemptClusterChecks should only return an error if there is a problem significant enough to halt a deployment, otherwise it should return nil and print a warning message.
func (p *Packager) attemptClusterChecks() (err error) {
if !p.isConnectedToCluster() {
return nil
}
// Check if the package has already been deployed and get its generation
if existingDeployedPackage, _ := p.cluster.GetDeployedPackage(p.cfg.Pkg.Metadata.Name); existingDeployedPackage != nil {
// If this package has been deployed before, increment the package generation within the secret
p.generation = existingDeployedPackage.Generation + 1
}

// Check the clusters architecture vs the package spec
if err := p.validatePackageArchitecture(); err != nil {
if errors.Is(err, lang.ErrUnableToCheckArch) {
message.Warnf("Unable to validate package architecture: %s", err.Error())
} else {
return err
}
}

return nil
}

func (p *Packager) isConnectedToCluster() bool {
return p.cluster != nil
}

func (p *Packager) connectToCluster() (err error) {
if p.isConnectedToCluster() {
// TODO: what is the best way to handle this?
old := p.cluster.RestConfig.String()

// If we are already connected to the cluster, check if the server name has changed
cluster, err := cluster.NewCluster()
if err != nil {
return fmt.Errorf("unable to connect to the Kubernetes cluster: %w", err)
}

if old != cluster.RestConfig.String() {
message.Warnf("The Kubernetes cluster has changed from %q to %q", old, cluster.RestConfig.ServerName)

p.cluster = cluster

return p.attemptClusterChecks()
}

return nil
}

p.cluster, err = cluster.NewClusterWithWait(cluster.DefaultTimeout)
if err != nil {
return fmt.Errorf("unable to connect to the Kubernetes cluster: %w", err)
}

return p.attemptClusterChecks()
}

// deployComponents loops through a list of ZarfComponents and deploys them.
func (p *Packager) deployComponents() (deployedComponents []types.DeployedComponent, err error) {
componentsToDeploy := p.getValidComponents()
Expand Down Expand Up @@ -243,7 +184,7 @@ func (p *Packager) deployInitComponent(component types.ZarfComponent) (charts []

// Always init the state before the first component that requires the cluster (on most deployments, the zarf-seed-registry)
if p.requiresCluster(component) && p.cfg.State == nil {
if err := p.connectToCluster(); err != nil {
if err := p.connectToCluster(5 * time.Minute); err != nil {
return charts, fmt.Errorf("unable to connect to the Kubernetes cluster: %w", err)
}

Expand Down Expand Up @@ -312,7 +253,7 @@ func (p *Packager) deployComponent(component types.ZarfComponent, noImgChecksum

if !p.valueTemplate.Ready() && p.requiresCluster(component) {
// Make sure we have access to the cluster
if err := p.connectToCluster(); err != nil {
if err := p.connectToCluster(cluster.DefaultTimeout); err != nil {
return charts, fmt.Errorf("unable to connect to the Kubernetes cluster: %w", err)
}

Expand Down
2 changes: 2 additions & 0 deletions src/pkg/packager/deprecated/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,5 +119,7 @@ func PrintBreakingChanges(deployedZarfVersion string) {
pterm.Printfln("\n - %s", pterm.Bold.Sprint("Mitigation:"))
pterm.Printfln(" %s", strings.ReplaceAll(mitigationText, "\n", "\n "))
}

message.HorizontalRule()
}
}
8 changes: 3 additions & 5 deletions src/pkg/packager/remove.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,9 @@ func (p *Packager) Remove() (err error) {
deployedPackage := &types.DeployedPackage{}

if requiresCluster {
if !p.isConnectedToCluster() {
p.cluster, err = cluster.NewClusterWithWait(cluster.DefaultTimeout)
if err != nil {
return err
}
err = p.connectToCluster(cluster.DefaultTimeout)
if err != nil {
return err
}
deployedPackage, err = p.cluster.GetDeployedPackage(packageName)
if err != nil {
Expand Down
9 changes: 6 additions & 3 deletions src/pkg/packager/sources/tarball.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,17 @@ type TarballSource struct {
func (s *TarballSource) LoadPackage(dst *layout.PackagePaths, unarchiveAll bool) (err error) {
var pkg types.ZarfPackage

message.Debugf("Loading package from %q", s.PackageSource)
spinner := message.NewProgressSpinner("Loading package from %q", s.PackageSource)
defer spinner.Stop()

pathsExtracted := []string{}

if s.Shasum != "" {
if err := utils.SHAsMatch(s.PackageSource, s.Shasum); err != nil {
return err
}
}

pathsExtracted := []string{}

// Walk the package so that was can dynamically load a .tar or a .tar.zst without caring about filenames.
err = archiver.Walk(s.PackageSource, func(f archiver.File) error {
if f.IsDir() {
Expand Down Expand Up @@ -122,6 +123,8 @@ func (s *TarballSource) LoadPackage(dst *layout.PackagePaths, unarchiveAll bool)
}
}

spinner.Success()

return nil
}

Expand Down
9 changes: 9 additions & 0 deletions src/pkg/utils/helpers/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,3 +193,12 @@ func StringToSlice(s string) []string {

return []string{}
}

func AppendIfNotExists(slice []string, item string) []string {

Check warning on line 197 in src/pkg/utils/helpers/misc.go

View workflow job for this annotation

GitHub Actions / validate

exported function AppendIfNotExists should have comment or be unexported
for _, s := range slice {
if s == item {
return slice
}
}
return append(slice, item)
}

0 comments on commit 852b482

Please sign in to comment.