Skip to content

Commit

Permalink
refactor: mirror-resources
Browse files Browse the repository at this point in the history
Signed-off-by: Philip Laine <[email protected]>
  • Loading branch information
phillebaba committed Sep 17, 2024
1 parent 3c8dcb8 commit a749e9b
Show file tree
Hide file tree
Showing 11 changed files with 740 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ zarf package mirror-resources [ PACKAGE_SOURCE ] [flags]
# Mirror resources to internal Zarf resources
$ zarf package mirror-resources <your-package.tar.zst> \
--registry-url 127.0.0.1:31999 \
--registry-url http://zarf-docker-registry.zarf.svc.cluster.local:5000 \
--registry-push-username zarf-push \
--registry-push-password <generated-registry-push-password> \
--git-url http://zarf-gitea-http.zarf.svc.cluster.local:3000 \
Expand Down
62 changes: 46 additions & 16 deletions src/cmd/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,27 @@ import (
"os"
"path/filepath"
"regexp"
"runtime"
"strings"

"github.com/AlecAivazis/survey/v2"
"github.com/defenseunicorns/pkg/helpers/v2"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"oras.land/oras-go/v2/registry"

"github.com/zarf-dev/zarf/src/cmd/common"
"github.com/zarf-dev/zarf/src/config"
"github.com/zarf-dev/zarf/src/config/lang"
"github.com/zarf-dev/zarf/src/internal/dns"
"github.com/zarf-dev/zarf/src/internal/packager2"
"github.com/zarf-dev/zarf/src/pkg/cluster"
"github.com/zarf-dev/zarf/src/pkg/lint"
"github.com/zarf-dev/zarf/src/pkg/message"
"github.com/zarf-dev/zarf/src/pkg/packager"
"github.com/zarf-dev/zarf/src/pkg/packager/filters"
"github.com/zarf-dev/zarf/src/pkg/packager/sources"
"github.com/zarf-dev/zarf/src/types"

"oras.land/oras-go/v2/registry"

"github.com/AlecAivazis/survey/v2"
"github.com/defenseunicorns/pkg/helpers/v2"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/zarf-dev/zarf/src/config"
"github.com/zarf-dev/zarf/src/pkg/cluster"
"github.com/zarf-dev/zarf/src/pkg/packager"
)

var packageCmd = &cobra.Command{
Expand Down Expand Up @@ -128,18 +129,47 @@ var packageMirrorCmd = &cobra.Command{
}
},
RunE: func(cmd *cobra.Command, args []string) error {
packageSource, err := choosePackage(args)
var c *cluster.Cluster
if dns.IsServiceURL(pkgConfig.InitOpts.RegistryInfo.Address) || dns.IsServiceURL(pkgConfig.InitOpts.GitServer.Address) {
var err error
c, err = cluster.NewCluster()
if err != nil {
return err
}
}
src, err := choosePackage(args)
if err != nil {
return err
}
pkgConfig.PkgOpts.PackageSource = packageSource
pkgClient, err := packager.New(&pkgConfig)
filter := filters.Combine(
filters.ByLocalOS(runtime.GOOS),
filters.BySelectState(pkgConfig.PkgOpts.OptionalComponents),
)

loadOpt := packager2.LoadOptions{
Source: src,
Shasum: pkgConfig.PkgOpts.Shasum,
PublicKeyPath: pkgConfig.PkgOpts.PublicKeyPath,
SkipSignatureValidation: pkgConfig.PkgOpts.SkipSignatureValidation,
Filter: filter,
}
pkgPaths, err := packager2.LoadPackage(cmd.Context(), loadOpt)
if err != nil {
return err
}
defer pkgClient.ClearTempPaths()
if err := pkgClient.Mirror(cmd.Context()); err != nil {
return fmt.Errorf("failed to mirror package: %w", err)
defer os.RemoveAll(pkgPaths.Base)
mirrorOpt := packager2.MirrorOptions{
Cluster: c,
PackagePaths: *pkgPaths,
Filter: filter,
RegistryInfo: pkgConfig.InitOpts.RegistryInfo,
GitInfo: pkgConfig.InitOpts.GitServer,
NoImageChecksum: pkgConfig.MirrorOpts.NoImgChecksum,
Retries: pkgConfig.PkgOpts.Retries,
}
err = packager2.Mirror(cmd.Context(), mirrorOpt)
if err != nil {
return err
}
return nil
},
Expand Down
2 changes: 1 addition & 1 deletion src/config/lang/english.go
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ $ zarf init --artifact-push-password={PASSWORD} --artifact-push-username={USERNA
CmdPackageMirrorExample = `
# Mirror resources to internal Zarf resources
$ zarf package mirror-resources <your-package.tar.zst> \
--registry-url 127.0.0.1:31999 \
--registry-url http://zarf-docker-registry.zarf.svc.cluster.local:5000 \
--registry-push-username zarf-push \
--registry-push-password <generated-registry-push-password> \
--git-url http://zarf-gitea-http.zarf.svc.cluster.local:3000 \
Expand Down
45 changes: 45 additions & 0 deletions src/internal/dns/dns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

// Package dns contains DNS related functionality.
package dns

import (
"errors"
"fmt"
"net/url"
"regexp"
"strconv"
)

var (
// localClusterServiceRegex is used to match the local cluster service format:
localClusterServiceRegex = regexp.MustCompile(`^(?P<name>[^\.]+)\.(?P<namespace>[^\.]+)\.svc\.cluster\.local$`)
)

// IsServiceURL returns true if the give url complies with the service url format.
func IsServiceURL(serviceURL string) bool {
_, _, _, err := ParseServiceURL(serviceURL)
return err == nil
}

// ParseServiceURL takes a serviceURL and parses it to find the service info for connecting to the cluster. The string is expected to follow the following format:
// Example serviceURL: http://{SERVICE_NAME}.{NAMESPACE}.svc.cluster.local:{PORT}.
func ParseServiceURL(serviceURL string) (string, string, int, error) {
parsedURL, err := url.Parse(serviceURL)
if err != nil {
return "", "", 0, err
}
if parsedURL.Port() == "" {
return "", "", 0, errors.New("service url does not have a port")
}
remotePort, err := strconv.Atoi(parsedURL.Port())
if err != nil {
return "", "", 0, err
}
matches := localClusterServiceRegex.FindStringSubmatch(parsedURL.Hostname())
if len(matches) != 3 {
return "", "", 0, fmt.Errorf("invalid service url %s", serviceURL)
}
return matches[2], matches[1], remotePort, nil
}
84 changes: 84 additions & 0 deletions src/internal/dns/dns_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors

package dns

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestIsServiceURL(t *testing.T) {
t.Parallel()

tests := []struct {
name string
serviceURL string
expected bool
}{
{
name: "is service url",
serviceURL: "http://registry.zarf.svc.cluster.local:1",
expected: true,
},
{
name: "is not service url",
serviceURL: "https://zarf.dev",
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

result := IsServiceURL(tt.serviceURL)
require.Equal(t, tt.expected, result)
})
}
}

func TestParseServiceURL(t *testing.T) {
t.Parallel()

tests := []struct {
name string
serviceURL string
expectedErr string
expectedNamespace string
expectedName string
expectedPort int
}{
{
name: "correct service url",
serviceURL: "http://foo.bar.svc.cluster.local:5000",
expectedNamespace: "bar",
expectedName: "foo",
expectedPort: 5000,
},
{
name: "invalid service url without port",
serviceURL: "http://google.com",
expectedErr: "service url does not have a port",
},
{
name: "invalid service url with port",
serviceURL: "http://google.com:3000",
expectedErr: "invalid service url http://google.com:3000",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()

namespace, name, port, err := ParseServiceURL(tt.serviceURL)
if tt.expectedErr != "" {
require.EqualError(t, err, tt.expectedErr)
return
}
require.Equal(t, tt.expectedNamespace, namespace)
require.Equal(t, tt.expectedName, name)
require.Equal(t, tt.expectedPort, port)
})
}
}
Loading

0 comments on commit a749e9b

Please sign in to comment.