Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: recording deployed component status in package deploy #3556

Merged
merged 9 commits into from
Mar 10, 2025
13 changes: 11 additions & 2 deletions src/pkg/packager/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ func (p *Packager) deployComponents(ctx context.Context) ([]types.DeployedCompon

// Process all the components we are deploying
for _, component := range p.cfg.Pkg.Components {
packageGeneration := 1
// Connect to cluster if a component requires it.
if component.RequiresCluster() {
timeout := cluster.DefaultTimeout
Expand All @@ -162,10 +163,16 @@ func (p *Packager) deployComponents(ctx context.Context) ([]types.DeployedCompon
if err := p.connectToCluster(connectCtx); err != nil {
return nil, fmt.Errorf("unable to connect to the Kubernetes cluster: %w", err)
}
// If this package has been deployed before, increment the package generation within the secret
if existingDeployedPackage, _ := p.cluster.GetDeployedPackage(ctx, p.cfg.Pkg.Metadata.Name); existingDeployedPackage != nil {
packageGeneration = existingDeployedPackage.Generation + 1
}
}

deployedComponent := types.DeployedComponent{
Name: component.Name,
Name: component.Name,
Status: types.ComponentStatusDeploying,
ObservedGeneration: packageGeneration,
}

// Ensure we don't overwrite any installedCharts data when updating the package secret
Expand All @@ -182,6 +189,7 @@ func (p *Packager) deployComponents(ctx context.Context) ([]types.DeployedCompon
idx := len(deployedComponents) - 1

// Deploy the component
p.cluster.RecordPackageDeployment(ctx, p.cfg.Pkg, deployedComponents)
var charts []types.InstalledChart
var deployErr error
if p.cfg.Pkg.IsInitConfig() {
Expand All @@ -201,7 +209,7 @@ func (p *Packager) deployComponents(ctx context.Context) ([]types.DeployedCompon

if deployErr != nil {
onFailure()

deployedComponents[idx].Status = types.ComponentStatusFailed
if p.isConnectedToCluster() {
if _, err := p.cluster.RecordPackageDeployment(ctx, p.cfg.Pkg, deployedComponents); err != nil {
message.Debugf("Unable to record package deployment for component %q: this will affect features like `zarf package remove`: %s", component.Name, err.Error())
Expand All @@ -213,6 +221,7 @@ func (p *Packager) deployComponents(ctx context.Context) ([]types.DeployedCompon

// Update the package secret to indicate that we successfully deployed this component
deployedComponents[idx].InstalledCharts = charts
deployedComponents[idx].Status = types.ComponentStatusSucceeded
if p.isConnectedToCluster() {
if _, err := p.cluster.RecordPackageDeployment(ctx, p.cfg.Pkg, deployedComponents); err != nil {
message.Debugf("Unable to record package deployment for component %q: this will affect features like `zarf package remove`: %s", component.Name, err.Error())
Expand Down
74 changes: 74 additions & 0 deletions src/test/e2e/37_component_status_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

// Package test provides e2e tests for Zarf.
package test

import (
"encoding/base64"
"encoding/json"
"fmt"
"path/filepath"
"sync"
"testing"
"time"

"github.com/stretchr/testify/require"
"github.com/zarf-dev/zarf/src/types"
)

func TestComponentStatus(t *testing.T) {
t.Log("E2E: Component Status")
tmpDir := t.TempDir()
_, _, err := e2e.Zarf(t, "package", "create", "src/test/packages/37-component-status", "-o", tmpDir, "--confirm")
require.NoError(t, err)
packageName := fmt.Sprintf("zarf-package-component-status-%s.tar.zst", e2e.Arch)
path := filepath.Join(tmpDir, packageName)
// Stop channel getting the zarf state
stop := make(chan bool)
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
deployingSeen := false
for {
select {
case <-stop:
return
default:
deployedPackage := types.DeployedPackage{}
stdOut, _, err := e2e.Kubectl(t, "get", "secret", "zarf-package-component-status", "-n", "zarf", "-o", "jsonpath={.data.data}")
if err != nil {
// Wait for the secret to be created and try again
time.Sleep(2 * time.Second)
continue
}
decoded, err := base64.StdEncoding.DecodeString(stdOut)
require.NoError(t, err)
err = json.Unmarshal(decoded, &deployedPackage)
require.Len(t, deployedPackage.DeployedComponents, 1)
status := deployedPackage.DeployedComponents[0].Status
// We expect to see deploying first and then succeeded
if !deployingSeen {
require.Equal(t, types.ComponentStatusDeploying, status)
deployingSeen = true
} else {
if status != types.ComponentStatusDeploying {
require.Equal(t, types.ComponentStatusSucceeded, status)
break
}
}
require.NoError(t, err)
time.Sleep(2 * time.Second)
}
}
}()
_, _, err = e2e.Zarf(t, "package", "deploy", path, "--confirm")
require.NoError(t, err)
defer func() {
_, _, err = e2e.Zarf(t, "package", "remove", "component-status", "--confirm")
require.NoError(t, err)
}()
close(stop)
wg.Wait()
}
6 changes: 3 additions & 3 deletions src/test/packages/22-git-data/zarf.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ components:
onDeploy:
before:
# Check to verify the package secret has been saved for the already deployed component
- cmd: test $(./zarf tools kubectl get secret -n zarf zarf-package-git-data-test -o jsonpath='{.data.*}' | base64 --decode | jq -r .deployedComponents | jq '. | length') -eq 1
- cmd: test $(./zarf tools kubectl get secret -n zarf zarf-package-git-data-test -o jsonpath='{.data.*}' | base64 --decode | jq -r .deployedComponents | jq '. | length') -eq 2
description: Check that the package secret has been updated with the deployed component
maxRetries: 3

Expand All @@ -41,7 +41,7 @@ components:
onDeploy:
before:
# Check to verify the package secret has been saved for the already deployed component
- cmd: test $(./zarf tools kubectl get secret -n zarf zarf-package-git-data-test -o jsonpath='{.data.*}' | base64 --decode | jq -r .deployedComponents | jq '. | length') -eq 2
- cmd: test $(./zarf tools kubectl get secret -n zarf zarf-package-git-data-test -o jsonpath='{.data.*}' | base64 --decode | jq -r .deployedComponents | jq '. | length') -eq 3
description: Check that the package secret has been updated with the deployed component
maxRetries: 3

Expand All @@ -56,7 +56,7 @@ components:
onDeploy:
before:
# Check to verify the package secret has been saved for the already deployed component
- cmd: test $(./zarf tools kubectl get secret -n zarf zarf-package-git-data-test -o jsonpath='{.data.*}' | base64 --decode | jq -r .deployedComponents | jq '. | length') -eq 3
- cmd: test $(./zarf tools kubectl get secret -n zarf zarf-package-git-data-test -o jsonpath='{.data.*}' | base64 --decode | jq -r .deployedComponents | jq '. | length') -eq 4
description: Check that the package secret has been updated with the deployed component
maxRetries: 3
onSuccess:
Expand Down
13 changes: 13 additions & 0 deletions src/test/packages/37-component-status/component-status.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: component-status
spec:
# Extra security to ensure the pod isn't ready before the health checks run
initContainers:
- name: init-wait
image: ghcr.io/stefanprodan/podinfo:6.4.0
command: ["sh", "-c", "sleep 10"]
containers:
- name: component-status
image: ghcr.io/stefanprodan/podinfo:6.4.0
15 changes: 15 additions & 0 deletions src/test/packages/37-component-status/zarf.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
kind: ZarfPackageConfig
metadata:
name: component-status
description: Test the status of components

components:
- name: component-status
required: true
manifests:
- name: first-component
namespace: first-component
files:
- component-status.yaml
images:
- ghcr.io/stefanprodan/podinfo:6.4.0
7 changes: 5 additions & 2 deletions src/types/k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ type DeployedPackage struct {
Name string `json:"name"`
Data v1alpha1.ZarfPackage `json:"data"`
CLIVersion string `json:"cliVersion"`
Generation int `json:"generation"`
DeployedComponents []DeployedComponent `json:"deployedComponents"`
ConnectStrings ConnectStrings `json:"connectStrings,omitempty"`
}
Expand All @@ -89,8 +90,10 @@ type ConnectStrings map[string]ConnectString

// DeployedComponent contains information about a Zarf Package Component that has been deployed to a cluster.
type DeployedComponent struct {
Name string `json:"name"`
InstalledCharts []InstalledChart `json:"installedCharts"`
Name string `json:"name"`
InstalledCharts []InstalledChart `json:"installedCharts"`
Status ComponentStatus `json:"status"`
ObservedGeneration int `json:"observedGeneration"`
}

// InstalledChart contains information about a Helm Chart that has been deployed to a cluster.
Expand Down
Loading