Skip to content

Commit

Permalink
feat: handle external registry with zarf init opts (#842)
Browse files Browse the repository at this point in the history
  • Loading branch information
UncleGedd authored Jul 24, 2024
1 parent 7e774a0 commit dff77e3
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 18 deletions.
10 changes: 10 additions & 0 deletions docs/quickstart-and-usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,16 @@ In a bundle, variables can come from 6 sources. Those sources and their preceden

That is to say, variables set using the `--set` flag take precedence over all other variable sources.

### Configuring Zarf Init Packages
Zarf init packages that are typically deployed using `zarf init` have a few special flags that are attached to that command. These options can be configured like any other variable: specified in a `uds-config.yaml`, as an environment variable prefixed with `UDS_` or via the `--set` flag.
```yaml
# uds-config.yaml
variables:
zarf-init:
INIT_REGISTRY_URL: "https://my-registry.io"
INIT_REGISTRY_PUSH_USERNAME: "registry-user"
```

## Duplicate Packages And Naming

It is possible to deploy multiple instances of the same Zarf package in a bundle. For example, the following `uds-bundle.yaml` deploys 3 instances of the [helm-overrides](https://github.com/defenseunicorns/uds-cli/blob/main/src/test/packages/helm/zarf.yaml) Zarf packages:
Expand Down
31 changes: 18 additions & 13 deletions src/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"time"

"github.com/defenseunicorns/uds-cli/src/types"
zarfTypes "github.com/defenseunicorns/zarf/src/types"
)

const (
Expand Down Expand Up @@ -54,6 +53,24 @@ const (

// CachedLogs is a file containing cached logs
CachedLogs = "recent-logs"

// Special Zarf init configs, can potentially refactor after https://github.com/zarf-dev/zarf/issues/1725
RegistryURL = "INIT_REGISTRY_URL"
RegistryPushUsername = "INIT_REGISTRY_PUSH_USERNAME" // #nosec G101
RegistryPushPassword = "INIT_REGISTRY_PUSH_PASSWORD" // #nosec G101
RegistryPullUsername = "INIT_REGISTRY_PULL_USERNAME" // #nosec G101
RegistryPullPassword = "INIT_REGISTRY_PULL_PASSWORD" // #nosec G101
RegistrySecretName = "INIT_REGISTRY_SECRET"
RegistryNodeport = "INIT_REGISTRY_NODEPORT"
GitURL = "INIT_GIT_URL"
GitPushUsername = "INIT_GIT_PUSH_USERNAME" // #nosec G101
GitPushPassword = "INIT_GIT_PUSH_PASSWORD" // #nosec G101
GitPullUsername = "INIT_GIT_PULL_USERNAME" // #nosec G101
GitPullPassword = "INIT_GIT_PULL_PASSWORD" // #nosec G101
ArtifactURL = "INIT_ARTIFACT_URL"
ArtifactPushUsername = "INIT_ARTIFACT_PUSH_USERNAME"
ArtifactPushToken = "INIT_ARTIFACT_PUSH_TOKEN"
StorageClass = "INIT_STORAGE_CLASS"
)

var (
Expand Down Expand Up @@ -101,15 +118,3 @@ var (
// BundleAlwaysPull is a list of paths that will always be pulled from the remote repository.
BundleAlwaysPull = []string{BundleYAML, BundleYAMLSignature}
)

// DefaultZarfInitOptions set these in the case of deploying a Zarf init pkg
// typically these are set as part of Zarf's Viper config, which we don't use in UDS
// could technically remove, but it doesn't hurt anything for now
var DefaultZarfInitOptions = zarfTypes.ZarfInitOptions{
GitServer: zarfTypes.GitServerInfo{
PushUsername: zarfTypes.ZarfGitPushUser,
},
RegistryInfo: zarfTypes.RegistryInfo{
PushUsername: zarfTypes.ZarfRegistryPushUser,
},
}
85 changes: 80 additions & 5 deletions src/pkg/bundle/deploy.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"fmt"
"os"
"path/filepath"
"strconv"
"strings"

"github.com/AlecAivazis/survey/v2"
Expand All @@ -19,6 +20,7 @@ import (
"github.com/defenseunicorns/uds-cli/src/types/chartvariable"
"github.com/defenseunicorns/uds-cli/src/types/valuesources"
zarfConfig "github.com/defenseunicorns/zarf/src/config"
"github.com/defenseunicorns/zarf/src/pkg/layout"
"github.com/defenseunicorns/zarf/src/pkg/message"
"github.com/defenseunicorns/zarf/src/pkg/packager"
"github.com/defenseunicorns/zarf/src/pkg/utils"
Expand Down Expand Up @@ -120,24 +122,33 @@ func deployPackages(packagesToDeploy []types.Package, b *Bundle) error {
Timeout: config.HelmTimeout,
}

// Automatically confirm the package deployment
zarfConfig.CommonOptions.Confirm = true

source, err := sources.New(*b.cfg, pkg, opts, sha, nsOverrides)
if err != nil {
return err
}

pkgCfg := zarfTypes.PackagerConfig{
PkgOpts: opts,
InitOpts: config.DefaultZarfInitOptions,
DeployOpts: zarfDeployOpts,
}

// Automatically confirm the package deployment
zarfConfig.CommonOptions.Confirm = true

source, err := sources.New(*b.cfg, pkg, opts, sha, nsOverrides)
// handle zarf init configs that aren't Zarf variables
zarfPkg, _, err := source.LoadPackageMetadata(context.TODO(), layout.New(pkgTmp), false, false)
if err != nil {
return err
}

zarfInitOpts := handleZarfInitOpts(pkgVars, zarfPkg.Kind)
pkgCfg.InitOpts = zarfInitOpts

pkgClient, err := packager.New(&pkgCfg, packager.WithSource(source), packager.WithTemp(opts.PackageSource))
if err != nil {
return err
}

if err = pkgClient.Deploy(context.TODO()); err != nil {
return err
}
Expand All @@ -158,6 +169,70 @@ func deployPackages(packagesToDeploy []types.Package, b *Bundle) error {
return nil
}

// handleZarfInitOpts sets the ZarfInitOptions for a package if using custom Zarf init options
func handleZarfInitOpts(pkgVars zarfVarData, zarfPkgKind zarfTypes.ZarfPackageKind) zarfTypes.ZarfInitOptions {
if zarfPkgKind != zarfTypes.ZarfInitConfig {
return zarfTypes.ZarfInitOptions{}
}

// default zarf init opts
zarfInitOpts := zarfTypes.ZarfInitOptions{
GitServer: zarfTypes.GitServerInfo{
PushUsername: zarfTypes.ZarfGitPushUser,
},
RegistryInfo: zarfTypes.RegistryInfo{
PushUsername: zarfTypes.ZarfRegistryPushUser,
},
}
// populate zarf init opts from pkgVars
for k, v := range pkgVars {
switch k {
// registry info
case config.RegistryURL:
zarfInitOpts.RegistryInfo.Address = v
case config.RegistryPushUsername:
zarfInitOpts.RegistryInfo.PushUsername = v
case config.RegistryPushPassword:
zarfInitOpts.RegistryInfo.PushPassword = v
case config.RegistryPullUsername:
zarfInitOpts.RegistryInfo.PullUsername = v
case config.RegistryPullPassword:
zarfInitOpts.RegistryInfo.PullPassword = v
case config.RegistrySecretName:
zarfInitOpts.RegistryInfo.Secret = v
case config.RegistryNodeport:
np, err := strconv.Atoi(v)
if err != nil {
message.Warnf("failed to parse nodeport %s: %v", v, err)
return zarfTypes.ZarfInitOptions{}
}
zarfInitOpts.RegistryInfo.NodePort = np
// git server info
case config.GitURL:
zarfInitOpts.GitServer.Address = v
case config.GitPushUsername:
zarfInitOpts.GitServer.PushUsername = v
case config.GitPushPassword:
zarfInitOpts.GitServer.PushPassword = v
case config.GitPullUsername:
zarfInitOpts.GitServer.PullUsername = v
case config.GitPullPassword:
zarfInitOpts.GitServer.PullPassword = v
// artifact server info
case config.ArtifactURL:
zarfInitOpts.ArtifactServer.Address = v
case config.ArtifactPushUsername:
zarfInitOpts.ArtifactServer.PushUsername = v
case config.ArtifactPushToken:
zarfInitOpts.ArtifactServer.PushToken = v
// storage class
case config.StorageClass:
zarfInitOpts.StorageClass = v
}
}
return zarfInitOpts
}

// PreDeployValidation validates the bundle before deployment
func (b *Bundle) PreDeployValidation() (string, string, string, error) {
// Check that provided oci source path is valid, and update it if it's missing the full path
Expand Down
63 changes: 63 additions & 0 deletions src/pkg/bundle/deploy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/defenseunicorns/uds-cli/src/types"
"github.com/defenseunicorns/uds-cli/src/types/chartvariable"
"github.com/defenseunicorns/uds-cli/src/types/valuesources"
zarfTypes "github.com/defenseunicorns/zarf/src/types"
"github.com/stretchr/testify/require"
"helm.sh/helm/v3/pkg/cli/values"
)
Expand Down Expand Up @@ -574,3 +575,65 @@ func TestFilterOverrides(t *testing.T) {
actual := map[string]overrideData{"ZARFVAR": {"val", valuesources.Env}}
require.Equal(t, actual, filtered)
}

func Test_handleZarfInitOpts(t *testing.T) {
tests := []struct {
name string
pkgVars zarfVarData
zarfPkg zarfTypes.ZarfPackageKind
expected zarfTypes.ZarfInitOptions
}{
{
name: "init configs",
pkgVars: zarfVarData{
"INIT_REGISTRY_URL": "fake.io",
"INIT_REGISTRY_PUSH_USERNAME": "push-user",
"INIT_REGISTRY_PUSH_PASSWORD": "push-secret!",
"INIT_REGISTRY_PULL_USERNAME": "pull-user",
"INIT_REGISTRY_PULL_PASSWORD": "pull-secret!",
"INIT_REGISTRY_SECRET": "registry-secret",
"INIT_REGISTRY_NODEPORT": "1234",
"INIT_GIT_URL": "fake.git",
"INIT_GIT_PUSH_USERNAME": "push-user",
"INIT_GIT_PUSH_PASSWORD": "push-secret!",
"INIT_GIT_PULL_USERNAME": "pull-user",
"INIT_GIT_PULL_PASSWORD": "pull-secret!",
"INIT_ARTIFACT_URL": "fake.artifact",
"INIT_ARTIFACT_PUSH_USERNAME": "push-user",
"INIT_ARTIFACT_PUSH_TOKEN": "push-token!",
"INIT_STORAGE_CLASS": "ebs",
},
zarfPkg: zarfTypes.ZarfInitConfig,
expected: zarfTypes.ZarfInitOptions{
RegistryInfo: zarfTypes.RegistryInfo{
Address: "fake.io",
PushUsername: "push-user",
PushPassword: "push-secret!",
PullUsername: "pull-user",
PullPassword: "pull-secret!",
Secret: "registry-secret",
NodePort: 1234,
},
GitServer: zarfTypes.GitServerInfo{
Address: "fake.git",
PushUsername: "push-user",
PushPassword: "push-secret!",
PullUsername: "pull-user",
PullPassword: "pull-secret!",
},
ArtifactServer: zarfTypes.ArtifactServerInfo{
Address: "fake.artifact",
PushUsername: "push-user",
PushToken: "push-token!",
},
StorageClass: "ebs",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
actual := handleZarfInitOpts(tt.pkgVars, tt.zarfPkg)
require.Equal(t, tt.expected, actual)
})
}
}

0 comments on commit dff77e3

Please sign in to comment.