Skip to content

Commit

Permalink
refactor: move package state to local variable
Browse files Browse the repository at this point in the history
Signed-off-by: Philip Laine <[email protected]>
  • Loading branch information
phillebaba committed Aug 5, 2024
1 parent 594a283 commit 52bd248
Show file tree
Hide file tree
Showing 10 changed files with 185 additions and 248 deletions.
2 changes: 1 addition & 1 deletion src/internal/packager/helm/zarf.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func (h *Helm) UpdateZarfAgentValues(ctx context.Context) error {
Value: agentImage.Tag,
},
})
applicationTemplates, err := template.GetZarfTemplates("zarf-agent", h.state)
applicationTemplates, err := template.GetZarfTemplates("zarf-agent", h.state.RegistryInfo, h.state.GitServer, h.state.AgentTLS, h.state.StorageClass)
if err != nil {
return fmt.Errorf("error setting up the templates: %w", err)
}
Expand Down
88 changes: 41 additions & 47 deletions src/internal/packager/template/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,62 +40,56 @@ func GetZarfVariableConfig() *variables.VariableConfig {
}

// GetZarfTemplates returns the template keys and values to be used for templating.
func GetZarfTemplates(componentName string, state *types.ZarfState) (templateMap map[string]*variables.TextTemplate, err error) {
func GetZarfTemplates(componentName string, regInfo types.RegistryInfo, gitInfo types.GitServerInfo, agentTLS types.GeneratedPKI, storageClass string) (templateMap map[string]*variables.TextTemplate, err error) {
templateMap = make(map[string]*variables.TextTemplate)

if state != nil {
regInfo := state.RegistryInfo
gitInfo := state.GitServer
builtinMap := map[string]string{
"STORAGE_CLASS": storageClass,

builtinMap := map[string]string{
"STORAGE_CLASS": state.StorageClass,
// Registry info
"REGISTRY": regInfo.Address,
"NODEPORT": fmt.Sprintf("%d", regInfo.NodePort),
"REGISTRY_AUTH_PUSH": regInfo.PushPassword,
"REGISTRY_AUTH_PULL": regInfo.PullPassword,

// Registry info
"REGISTRY": regInfo.Address,
"NODEPORT": fmt.Sprintf("%d", regInfo.NodePort),
"REGISTRY_AUTH_PUSH": regInfo.PushPassword,
"REGISTRY_AUTH_PULL": regInfo.PullPassword,
// Git server info
"GIT_PUSH": gitInfo.PushUsername,
"GIT_AUTH_PUSH": gitInfo.PushPassword,
"GIT_PULL": gitInfo.PullUsername,
"GIT_AUTH_PULL": gitInfo.PullPassword,
}

builtinMap[depMarker] = config.GetDataInjectionMarker()

// Don't template component-specific variables for every component
switch componentName {
case "zarf-agent":
builtinMap["AGENT_CRT"] = base64.StdEncoding.EncodeToString(agentTLS.Cert)
builtinMap["AGENT_KEY"] = base64.StdEncoding.EncodeToString(agentTLS.Key)
builtinMap["AGENT_CA"] = base64.StdEncoding.EncodeToString(agentTLS.CA)

// Git server info
"GIT_PUSH": gitInfo.PushUsername,
"GIT_AUTH_PUSH": gitInfo.PushPassword,
"GIT_PULL": gitInfo.PullUsername,
"GIT_AUTH_PULL": gitInfo.PullPassword,
case "zarf-seed-registry", "zarf-registry":
builtinMap["SEED_REGISTRY"] = fmt.Sprintf("%s:%s", helpers.IPV4Localhost, config.ZarfSeedPort)
htpasswd, err := generateHtpasswd(&regInfo)
if err != nil {
return templateMap, err
}
builtinMap["HTPASSWD"] = htpasswd
builtinMap["REGISTRY_SECRET"] = regInfo.Secret
}

builtinMap[depMarker] = config.GetDataInjectionMarker()

// Don't template component-specific variables for every component
switch componentName {
case "zarf-agent":
agentTLS := state.AgentTLS
builtinMap["AGENT_CRT"] = base64.StdEncoding.EncodeToString(agentTLS.Cert)
builtinMap["AGENT_KEY"] = base64.StdEncoding.EncodeToString(agentTLS.Key)
builtinMap["AGENT_CA"] = base64.StdEncoding.EncodeToString(agentTLS.CA)

case "zarf-seed-registry", "zarf-registry":
builtinMap["SEED_REGISTRY"] = fmt.Sprintf("%s:%s", helpers.IPV4Localhost, config.ZarfSeedPort)
htpasswd, err := generateHtpasswd(&regInfo)
if err != nil {
return templateMap, err
}
builtinMap["HTPASSWD"] = htpasswd
builtinMap["REGISTRY_SECRET"] = regInfo.Secret
// Iterate over any custom variables and add them to the mappings for templating
for key, value := range builtinMap {
// Builtin keys are always uppercase in the format ###ZARF_KEY###
templateMap[strings.ToUpper(fmt.Sprintf("###ZARF_%s###", key))] = &variables.TextTemplate{
Value: value,
}

// Iterate over any custom variables and add them to the mappings for templating
for key, value := range builtinMap {
// Builtin keys are always uppercase in the format ###ZARF_KEY###
templateMap[strings.ToUpper(fmt.Sprintf("###ZARF_%s###", key))] = &variables.TextTemplate{
Value: value,
}

if key == "REGISTRY_SECRET" || key == "HTPASSWD" ||
key == "AGENT_CA" || key == "AGENT_KEY" || key == "AGENT_CRT" || key == "GIT_AUTH_PULL" ||
key == "GIT_AUTH_PUSH" || key == "REGISTRY_AUTH_PULL" || key == "REGISTRY_AUTH_PUSH" {
// Sanitize any builtin templates that are sensitive
templateMap[strings.ToUpper(fmt.Sprintf("###ZARF_%s###", key))].Sensitive = true
}
if key == "REGISTRY_SECRET" || key == "HTPASSWD" ||
key == "AGENT_CA" || key == "AGENT_KEY" || key == "AGENT_CRT" || key == "GIT_AUTH_PULL" ||
key == "GIT_AUTH_PUSH" || key == "REGISTRY_AUTH_PULL" || key == "REGISTRY_AUTH_PUSH" {
// Sanitize any builtin templates that are sensitive
templateMap[strings.ToUpper(fmt.Sprintf("###ZARF_%s###", key))].Sensitive = true
}
}

Expand Down
54 changes: 54 additions & 0 deletions src/pkg/cluster/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package cluster

import (
"context"
"fmt"
"time"

corev1 "k8s.io/api/core/v1"
Expand All @@ -15,6 +16,59 @@ import (
"github.com/zarf-dev/zarf/src/pkg/message"
)

func (c *Cluster) CreateZarfNamespace(ctx context.Context) error {
// Try to create the zarf namespace.
zarfNamespace := NewZarfManagedNamespace(ZarfNamespaceName)
err := func() error {
_, err := c.Clientset.CoreV1().Namespaces().Create(ctx, zarfNamespace, metav1.CreateOptions{})
if err != nil && !kerrors.IsAlreadyExists(err) {
return fmt.Errorf("unable to create the Zarf namespace: %w", err)
}
if err == nil {
return nil
}
_, err = c.Clientset.CoreV1().Namespaces().Update(ctx, zarfNamespace, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("unable to update the Zarf namespace: %w", err)
}
return nil
}()
if err != nil {
return err
}

// Wait up to 2 minutes for the default service account to be created.
// Some clusters seem to take a while to create this, see https://github.com/kubernetes/kubernetes/issues/66689.
// The default SA is required for pods to start properly.
saCtx, cancel := context.WithTimeout(ctx, 2*time.Minute)
defer cancel()
err = func(ctx context.Context, ns, name string) error {
timer := time.NewTimer(0)
defer timer.Stop()
for {
select {
case <-ctx.Done():
return fmt.Errorf("failed to get service account %s/%s: %w", ns, name, ctx.Err())
case <-timer.C:
_, err := c.Clientset.CoreV1().ServiceAccounts(ns).Get(ctx, name, metav1.GetOptions{})
if err != nil && !kerrors.IsNotFound(err) {
return err
}
if kerrors.IsNotFound(err) {
message.Debug("Service account %s/%s not found, retrying...", ns, name)
timer.Reset(1 * time.Second)
continue
}
return nil
}
}
}(saCtx, ZarfNamespaceName, "default")
if err != nil {
return fmt.Errorf("unable get default Zarf service account: %w", err)
}
return nil
}

// DeleteZarfNamespace deletes the Zarf namespace from the connected cluster.
func (c *Cluster) DeleteZarfNamespace(ctx context.Context) error {
spinner := message.NewProgressSpinner("Deleting the zarf namespace from this cluster")
Expand Down
76 changes: 12 additions & 64 deletions src/pkg/cluster/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"errors"
"fmt"
"slices"
"time"

corev1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
Expand All @@ -34,7 +33,7 @@ const (
)

// InitZarfState initializes the Zarf state with the given temporary directory and init configs.
func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitOptions) error {
func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitOptions) (*types.ZarfState, error) {
spinner := message.NewProgressSpinner("Gathering cluster state information")
defer spinner.Stop()

Expand All @@ -43,7 +42,7 @@ func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitO
spinner.Updatef("Checking cluster for existing Zarf deployment")
state, err := c.LoadZarfState(ctx)
if err != nil && !kerrors.IsNotFound(err) {
return fmt.Errorf("failed to check for existing state: %w", err)
return nil, fmt.Errorf("failed to check for existing state: %w", err)
}

// If state is nil, this is a new cluster.
Expand All @@ -59,14 +58,14 @@ func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitO
// Otherwise, trying to detect the K8s distro type.
nodeList, err := c.Clientset.CoreV1().Nodes().List(ctx, metav1.ListOptions{})
if err != nil {
return err
return nil, err
}
if len(nodeList.Items) == 0 {
return fmt.Errorf("cannot init Zarf state in empty cluster")
return nil, fmt.Errorf("cannot init Zarf state in empty cluster")
}
namespaceList, err := c.Clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
return err
return nil, err
}
state.Distro = detectDistro(nodeList.Items[0], namespaceList.Items)
}
Expand All @@ -78,13 +77,13 @@ func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitO
// Setup zarf agent PKI
agentTLS, err := pki.GeneratePKI(config.ZarfAgentHost)
if err != nil {
return err
return nil, err
}
state.AgentTLS = agentTLS

namespaceList, err := c.Clientset.CoreV1().Namespaces().List(ctx, metav1.ListOptions{})
if err != nil {
return fmt.Errorf("unable to get the Kubernetes namespaces: %w", err)
return nil, fmt.Errorf("unable to get the Kubernetes namespaces: %w", err)
}
// Mark existing namespaces as ignored for the zarf agent to prevent mutating resources we don't own.
for _, namespace := range namespaceList.Items {
Expand All @@ -98,69 +97,18 @@ func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitO
namespaceCopy := namespace
_, err := c.Clientset.CoreV1().Namespaces().Update(ctx, &namespaceCopy, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("unable to mark the namespace %s as ignored by Zarf Agent: %w", namespace.Name, err)
}
}

// Try to create the zarf namespace.
spinner.Updatef("Creating the Zarf namespace")
zarfNamespace := NewZarfManagedNamespace(ZarfNamespaceName)
err = func() error {
_, err := c.Clientset.CoreV1().Namespaces().Create(ctx, zarfNamespace, metav1.CreateOptions{})
if err != nil && !kerrors.IsAlreadyExists(err) {
return fmt.Errorf("unable to create the Zarf namespace: %w", err)
}
if err == nil {
return nil
}
_, err = c.Clientset.CoreV1().Namespaces().Update(ctx, zarfNamespace, metav1.UpdateOptions{})
if err != nil {
return fmt.Errorf("unable to update the Zarf namespace: %w", err)
}
return nil
}()
if err != nil {
return err
}

// Wait up to 2 minutes for the default service account to be created.
// Some clusters seem to take a while to create this, see https://github.com/kubernetes/kubernetes/issues/66689.
// The default SA is required for pods to start properly.
saCtx, cancel := context.WithTimeout(ctx, 2*time.Minute)
defer cancel()
err = func(ctx context.Context, ns, name string) error {
timer := time.NewTimer(0)
defer timer.Stop()
for {
select {
case <-ctx.Done():
return fmt.Errorf("failed to get service account %s/%s: %w", ns, name, ctx.Err())
case <-timer.C:
_, err := c.Clientset.CoreV1().ServiceAccounts(ns).Get(ctx, name, metav1.GetOptions{})
if err != nil && !kerrors.IsNotFound(err) {
return err
}
if kerrors.IsNotFound(err) {
message.Debug("Service account %s/%s not found, retrying...", ns, name)
timer.Reset(1 * time.Second)
continue
}
return nil
}
return nil, fmt.Errorf("unable to mark the namespace %s as ignored by Zarf Agent: %w", namespace.Name, err)
}
}(saCtx, ZarfNamespaceName, "default")
if err != nil {
return fmt.Errorf("unable get default Zarf service account: %w", err)
}

err = initOptions.GitServer.FillInEmptyValues()
if err != nil {
return err
return nil, err
}
state.GitServer = initOptions.GitServer
err = initOptions.RegistryInfo.FillInEmptyValues()
if err != nil {
return err
return nil, err
}
state.RegistryInfo = initOptions.RegistryInfo
initOptions.ArtifactServer.FillInEmptyValues()
Expand Down Expand Up @@ -199,10 +147,10 @@ func (c *Cluster) InitZarfState(ctx context.Context, initOptions types.ZarfInitO

// Save the state back to K8s
if err := c.SaveZarfState(ctx, state); err != nil {
return fmt.Errorf("unable to save the Zarf state: %w", err)
return nil, fmt.Errorf("unable to save the Zarf state: %w", err)
}

return nil
return state, nil
}

// LoadZarfState returns the current zarf/zarf-state secret data or an empty ZarfState.
Expand Down
2 changes: 1 addition & 1 deletion src/pkg/cluster/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ func TestInitZarfState(t *testing.T) {
}
}()

err := c.InitZarfState(ctx, tt.initOpts)
_, err := c.InitZarfState(ctx, tt.initOpts)
if tt.expectedErr != "" {
require.EqualError(t, err, tt.expectedErr)
return
Expand Down
1 change: 0 additions & 1 deletion src/pkg/packager/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import (
type Packager struct {
cfg *types.PackagerConfig
variableConfig *variables.VariableConfig
state *types.ZarfState
cluster *cluster.Cluster
layout *layout.PackagePaths
hpaModified bool
Expand Down
Loading

0 comments on commit 52bd248

Please sign in to comment.