Skip to content

Commit

Permalink
Merge branch 'main' into schristoff_injector
Browse files Browse the repository at this point in the history
  • Loading branch information
schristoff-du committed May 9, 2024
2 parents c8e9f8f + 898061d commit 2f8ecc4
Show file tree
Hide file tree
Showing 17 changed files with 232 additions and 98 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ delete-packages: ## Delete all Zarf package tarballs in the project recursively
# Note: the path to the main.go file is not used due to https://github.com/golang/go/issues/51831#issuecomment-1074188363
.PHONY: build
build: ## Build the Zarf CLI for the machines OS and architecture
go mod tidy
$(MAKE) $(BUILD_CLI_FOR_SYSTEM)

build-cli-linux-amd: ## Build the Zarf CLI for Linux on AMD64
Expand Down
47 changes: 47 additions & 0 deletions SUPPORT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Support Guidelines

We strive to create clear guidelines on communication to the Zarf team to provide a good community experience.

## Questions
For guidance on using Zarf, [the documentation](https://docs.zarf.dev/) should cover most use cases.
For all questions documentation may not cover, we suggest utilizing [Github Discussions](https://github.com/defenseunicorns/zarf/discussions).

## Standard Process
All code issues should be a [Github Issue](https://github.com/defenseunicorns/zarf/issues/new/choose) that follows the issue template.

Following the templates provides the Zarf community a foundation of understanding to be able to assist quickly.
After an issue is made, this issue can be brought into other chanels such as the [Kubernetes Slack #Zarf](https://zarf.dev/slack) channel or the [bi-weekly Zarf Community Meeting](https://docs.zarf.dev/contribute/contributor-guide/).

Github Issue
/ \
Zarf Slack Channel Zarf Community Call



## Sensitive Information Process
For issues from those who are unable to post on Github, you may send an email using the following issue template filled out to [zarf-dev-private@googlegroups.com](zarf-dev-private@googlegroups.com)

The response time to emails may be delayed as they are not able to receive community help, so we encourage participation into Github Issues as much as possible.

```
### Environment
Device and OS:
App version:
Kubernetes distro being used:
Other:
### Steps to reproduce
1.
### Expected result
### Actual Result
### Visual Proof (screenshots, videos, text, etc)
### Severity/Priority
### Additional Context
Add any other context or screenshots about the technical debt here.
```
1 change: 1 addition & 0 deletions site/src/content/docs/commands/zarf_package_inspect.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ zarf package inspect [ PACKAGE_SOURCE ] [flags]

```
-h, --help help for inspect
--list-images List images in the package (prints to stdout)
-s, --sbom View SBOM contents while inspecting the package
--sbom-out string Specify an output directory for the SBOMs from the inspected Zarf package
```
Expand Down
38 changes: 38 additions & 0 deletions site/src/content/docs/ref/deploy.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,41 @@ $ zarf connect [service name]
You can also specify a package locally, or via oci such as `zarf package deploy oci://defenseunicorns/dos-games:1.0.0-$(uname -m) --key=https://zarf.dev/cosign.pub`

:::

## Installing, Upgrading, and Rolling Back with Helm

Zarf deploys resources in Kubernetes using [Helm's Go SDK](https://helm.sh/docs/topics/advanced/#go-sdk), and converts manifests into Helm charts for installation.

If no existing Helm releases match a given chart in the cluster, Zarf executes a `helm install`.

Should matching releases exist, a `helm upgrade` is performed.

### Handling CustomResourceDefinitions (CRDs)

- CRDs are _included_ during `helm install` to support Kubernetes Operator deployments
- CRDs are _excluded_ during `helm upgrade` due to [Helm's lack of support for upgrading CRDs](https://helm.sh/docs/chart_best_practices/custom_resource_definitions/#some-caveats-and-explanations)

### Waiting for Resource Readiness

By default, Zarf waits for all resources to deploy successfully during install, upgrade, and rollback operations.

You can override this behavior during install and upgrade by setting the `noWait: true` key under the `charts` and `manifests` fields.

### Timeout Settings

The default timeout for Helm operations in Zarf is 15 minutes.

Use the `--timeout` flag with `zarf init` and `zarf package deploy` to modify the timeout duration.

### Retry Policy

Zarf retries install and upgrade operations up to three times by default if an error occurs.

Use the `--retries` flag with `zarf init` and `zarf package deploy` to change the number of retry attempts.

### Rollback Process

If attempts to upgrade a chart fail, Zarf tries to roll the chart back to its last successful release. During this rollback process:

- Any resources created during the failed upgrade attempt are deleted (`helm rollback --cleanup-on-fail`)
- Resource updates are forced through delete and recreate if needed (`helm rollback --force`)
1 change: 1 addition & 0 deletions src/cmd/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ func bindInspectFlags(_ *viper.Viper) {
inspectFlags := packageInspectCmd.Flags()
inspectFlags.BoolVarP(&pkgConfig.InspectOpts.ViewSBOM, "sbom", "s", false, lang.CmdPackageInspectFlagSbom)
inspectFlags.StringVar(&pkgConfig.InspectOpts.SBOMOutputDir, "sbom-out", "", lang.CmdPackageInspectFlagSbomOut)
inspectFlags.BoolVar(&pkgConfig.InspectOpts.ListImages, "list-images", false, lang.CmdPackageInspectFlagListImages)
}

func bindRemoveFlags(v *viper.Viper) {
Expand Down
7 changes: 4 additions & 3 deletions src/config/lang/english.go
Original file line number Diff line number Diff line change
Expand Up @@ -308,9 +308,10 @@ $ zarf package mirror-resources <your-package.tar.zst> \
CmdPackageMirrorFlagComponents = "Comma-separated list of components to mirror. This list will be respected regardless of a component's 'required' or 'default' status. Globbing component names with '*' and deselecting components with a leading '-' are also supported."
CmdPackageMirrorFlagNoChecksum = "Turns off the addition of a checksum to image tags (as would be used by the Zarf Agent) while mirroring images."

CmdPackageInspectFlagSbom = "View SBOM contents while inspecting the package"
CmdPackageInspectFlagSbomOut = "Specify an output directory for the SBOMs from the inspected Zarf package"
CmdPackageInspectErr = "Failed to inspect package: %s"
CmdPackageInspectFlagSbom = "View SBOM contents while inspecting the package"
CmdPackageInspectFlagSbomOut = "Specify an output directory for the SBOMs from the inspected Zarf package"
CmdPackageInspectFlagListImages = "List images in the package (prints to stdout)"
CmdPackageInspectErr = "Failed to inspect package: %s"

CmdPackageRemoveShort = "Removes a Zarf package that has been deployed already (runs offline)"
CmdPackageRemoveFlagConfirm = "REQUIRED. Confirm the removal action to prevent accidental deletions"
Expand Down
25 changes: 10 additions & 15 deletions src/internal/packager/helm/chart.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ func (h *Helm) InstallOrUpgradeChart() (types.ConnectStrings, string, error) {
}

if err != nil {
return fmt.Errorf("unable to complete the helm chart install/upgrade: %w", err)
return err
}

message.Debug(output.Info.Description)
Expand All @@ -92,7 +92,6 @@ func (h *Helm) InstallOrUpgradeChart() (types.ConnectStrings, string, error) {

err = helpers.Retry(tryHelm, h.retries, 5*time.Second, message.Warnf)
if err != nil {
// Try to rollback any deployed releases
releases, _ := histClient.Run(h.chart.ReleaseName)
previouslyDeployedVersion := 0

Expand All @@ -103,25 +102,21 @@ func (h *Helm) InstallOrUpgradeChart() (types.ConnectStrings, string, error) {
}
}

// On total failure try to rollback (if there was a previously deployed version) or uninstall.
if previouslyDeployedVersion > 0 {
spinner.Updatef("Performing chart rollback")

err = h.rollbackChart(h.chart.ReleaseName, previouslyDeployedVersion)
if err != nil {
return nil, "", fmt.Errorf("unable to upgrade chart after %d attempts and unable to rollback: %w", h.retries, err)
}
removeMsg := "if you need to remove the failed chart, use `zarf package remove`"

return nil, "", fmt.Errorf("unable to upgrade chart after %d attempts", h.retries)
// No prior releases means this was an initial install.
if previouslyDeployedVersion == 0 {
return nil, "", fmt.Errorf("unable to install chart after %d attempts: %s", h.retries, removeMsg)
}

spinner.Updatef("Performing chart uninstall")
_, err = h.uninstallChart(h.chart.ReleaseName)
// Attempt to rollback on a failed upgrade.
spinner.Updatef("Performing chart rollback")
err = h.rollbackChart(h.chart.ReleaseName, previouslyDeployedVersion)
if err != nil {
return nil, "", fmt.Errorf("unable to install chart after %d attempts and unable to uninstall: %w", h.retries, err)
return nil, "", fmt.Errorf("unable to upgrade chart after %d attempts and unable to rollback: %s", h.retries, removeMsg)
}

return nil, "", fmt.Errorf("unable to install chart after %d attempts", h.retries)
return nil, "", fmt.Errorf("unable to upgrade chart after %d attempts: %s", h.retries, removeMsg)
}

// return any collected connect strings for zarf connect.
Expand Down
48 changes: 0 additions & 48 deletions src/pkg/packager/creator/differential.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,13 @@
package creator

import (
"fmt"
"os"

"github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/internal/packager/git"
"github.com/defenseunicorns/zarf/src/pkg/layout"
"github.com/defenseunicorns/zarf/src/pkg/packager/sources"
"github.com/defenseunicorns/zarf/src/pkg/transform"
"github.com/defenseunicorns/zarf/src/pkg/utils"
"github.com/defenseunicorns/zarf/src/types"
"github.com/go-git/go-git/v5/plumbing"
)

// loadDifferentialData sets any images and repos from the existing reference package in the DifferentialData and returns it.
Expand Down Expand Up @@ -58,47 +54,3 @@ func loadDifferentialData(diffPkgPath string) (diffData *types.DifferentialData,
DifferentialPackageVersion: diffPkg.Metadata.Version,
}, nil
}

// removeCopiesFromComponents removes any images and repos already present in the reference package components.
func removeCopiesFromComponents(components []types.ZarfComponent, loadedDiffData *types.DifferentialData) (diffComponents []types.ZarfComponent, err error) {
for _, component := range components {
newImageList := []string{}
newRepoList := []string{}

for _, img := range component.Images {
imgRef, err := transform.ParseImageRef(img)
if err != nil {
return nil, fmt.Errorf("unable to parse image ref %s: %s", img, err.Error())
}

imgTag := imgRef.TagOrDigest
includeImage := imgTag == ":latest" || imgTag == ":stable" || imgTag == ":nightly"
if includeImage || !loadedDiffData.DifferentialImages[img] {
newImageList = append(newImageList, img)
}
}

for _, repoURL := range component.Repos {
_, refPlain, err := transform.GitURLSplitRef(repoURL)
if err != nil {
return nil, err
}

var ref plumbing.ReferenceName
if refPlain != "" {
ref = git.ParseRef(refPlain)
}

includeRepo := ref == "" || (!ref.IsTag() && !plumbing.IsHash(refPlain))
if includeRepo || !loadedDiffData.DifferentialRepos[repoURL] {
newRepoList = append(newRepoList, repoURL)
}
}

component.Images = newImageList
component.Repos = newRepoList
diffComponents = append(diffComponents, component)
}

return diffComponents, nil
}
4 changes: 3 additions & 1 deletion src/pkg/packager/creator/normal.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/defenseunicorns/zarf/src/pkg/layout"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/packager/actions"
"github.com/defenseunicorns/zarf/src/pkg/packager/filters"
"github.com/defenseunicorns/zarf/src/pkg/packager/sources"
"github.com/defenseunicorns/zarf/src/pkg/transform"
"github.com/defenseunicorns/zarf/src/pkg/utils"
Expand Down Expand Up @@ -110,7 +111,8 @@ func (pc *PackageCreator) LoadPackageDefinition(dst *layout.PackagePaths) (pkg t
return types.ZarfPackage{}, nil, errors.New(lang.PkgCreateErrDifferentialNoVersion)
}

pkg.Components, err = removeCopiesFromComponents(pkg.Components, diffData)
filter := filters.ByDifferentialData(diffData)
pkg.Components, err = filter.Apply(pkg)
if err != nil {
return types.ZarfPackage{}, nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion src/pkg/packager/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -340,7 +340,7 @@ func (p *Packager) deployComponent(component types.ZarfComponent, noImgChecksum

if hasCharts || hasManifests {
if charts, err = p.installChartAndManifests(componentPath, component); err != nil {
return charts, fmt.Errorf("unable to install helm chart(s): %w", err)
return charts, err
}
}

Expand Down
63 changes: 63 additions & 0 deletions src/pkg/packager/filters/diff.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

package filters

import (
"fmt"

"github.com/defenseunicorns/zarf/src/internal/packager/git"
"github.com/defenseunicorns/zarf/src/pkg/transform"
"github.com/defenseunicorns/zarf/src/types"
"github.com/go-git/go-git/v5/plumbing"
)

// ByDifferentialData filters any images and repos already present in the reference package components.
func ByDifferentialData(diffData *types.DifferentialData) ComponentFilterStrategy {
return &differentialDataFilter{
diffData: diffData,
}
}

type differentialDataFilter struct {
diffData *types.DifferentialData
}

func (f *differentialDataFilter) Apply(pkg types.ZarfPackage) ([]types.ZarfComponent, error) {
diffComponents := []types.ZarfComponent{}
for _, component := range pkg.Components {
filteredImages := []string{}
for _, img := range component.Images {
imgRef, err := transform.ParseImageRef(img)
if err != nil {
return nil, fmt.Errorf("unable to parse image ref %s: %w", img, err)
}
imgTag := imgRef.TagOrDigest
includeImage := imgTag == ":latest" || imgTag == ":stable" || imgTag == ":nightly"
if includeImage || !f.diffData.DifferentialImages[img] {
filteredImages = append(filteredImages, img)
}
}
component.Images = filteredImages

filteredRepos := []string{}
for _, repoURL := range component.Repos {
_, refPlain, err := transform.GitURLSplitRef(repoURL)
if err != nil {
return nil, err
}
var ref plumbing.ReferenceName
if refPlain != "" {
ref = git.ParseRef(refPlain)
}
includeRepo := ref == "" || (!ref.IsTag() && !plumbing.IsHash(refPlain))
if includeRepo || !f.diffData.DifferentialRepos[repoURL] {
filteredRepos = append(filteredRepos, repoURL)
}
}
component.Repos = filteredRepos

diffComponents = append(diffComponents, component)
}
return diffComponents, nil
}
Loading

0 comments on commit 2f8ecc4

Please sign in to comment.