Skip to content

Commit

Permalink
fix(bundles): --helm-compatible-chart and --rename-chart options for …
Browse files Browse the repository at this point in the history
…'bundle copy' and 'bundle publish'

Signed-off-by: Timofey Kirillov <timofey.kirillov@flant.com>
  • Loading branch information
distorhead committed Jan 31, 2023
1 parent f4f7d77 commit 3333d03
Show file tree
Hide file tree
Showing 10 changed files with 246 additions and 19 deletions.
9 changes: 9 additions & 0 deletions cmd/werf/bundle/copy/copy.go
Expand Up @@ -67,6 +67,9 @@ func NewCmd(ctx context.Context) *cobra.Command {
common.SetupLogProjectDir(&commonCmdData, cmd)
common.SetupPlatform(&commonCmdData, cmd)

commonCmdData.SetupHelmCompatibleChart(cmd, true)
commonCmdData.SetupRenameChart(cmd)

cmd.Flags().StringVarP(&cmdData.Repo, "repo", "", os.Getenv("WERF_REPO"), "Deprecated param, use --from=ADDR instead. Source address of bundle which should be copied.")
cmd.Flags().StringVarP(&cmdData.Tag, "tag", "", os.Getenv("WERF_TAG"), "Deprecated param, use --from=REPO:TAG instead. Provide from tag version of the bundle to copy ($WERF_TAG or latest by default).")
cmd.Flags().StringVarP(&cmdData.ToTag, "to-tag", "", os.Getenv("WERF_TO_TAG"), "Deprecated param, use --to=REPO:TAG instead. Provide to tag version of the bundle to copy ($WERF_TO_TAG or same as --tag by default).")
Expand Down Expand Up @@ -147,6 +150,10 @@ func runCopy(ctx context.Context) error {
}
}

if *commonCmdData.HelmCompatibleChart && *commonCmdData.RenameChart != "" {
return fmt.Errorf("incompatible options specified, could not use --helm-compatible-chart and --rename-chart=%q at the same time", *commonCmdData.RenameChart)
}

return logboek.Context(ctx).LogProcess("Copy bundle").DoError(func() error {
logboek.Context(ctx).LogFDetails("From: %s\n", fromAddr.String())
logboek.Context(ctx).LogFDetails("To: %s\n", toAddr.String())
Expand All @@ -155,6 +162,8 @@ func runCopy(ctx context.Context) error {
BundlesRegistryClient: bundlesRegistryClient,
FromRegistryClient: fromRegistry,
ToRegistryClient: toRegistry,
HelmCompatibleChart: *commonCmdData.HelmCompatibleChart,
RenameChart: *commonCmdData.RenameChart,
})
})
}
8 changes: 7 additions & 1 deletion cmd/werf/bundle/publish/publish.go
Expand Up @@ -134,6 +134,9 @@ func NewCmd(ctx context.Context) *cobra.Command {
common.SetupSkipBuild(&commonCmdData, cmd)
common.SetupPlatform(&commonCmdData, cmd)

commonCmdData.SetupHelmCompatibleChart(cmd, false)
commonCmdData.SetupRenameChart(cmd)

defaultTag := os.Getenv("WERF_TAG")
if defaultTag == "" {
defaultTag = "latest"
Expand Down Expand Up @@ -406,5 +409,8 @@ func runPublish(ctx context.Context, imagesToProcess build.ImagesToProcess) erro
bundleRepo = stagesStorage.Address()
}

return bundles.Publish(ctx, bundle, fmt.Sprintf("%s:%s", bundleRepo, cmdData.Tag), bundlesRegistryClient)
return bundles.Publish(ctx, bundle, fmt.Sprintf("%s:%s", bundleRepo, cmdData.Tag), bundlesRegistryClient, bundles.PublishOptions{
HelmCompatibleChart: *commonCmdData.HelmCompatibleChart,
RenameChart: *commonCmdData.RenameChart,
})
}
23 changes: 23 additions & 0 deletions cmd/werf/common/cmd_data.go
@@ -1,6 +1,9 @@
package common

import (
"fmt"
"os"

"github.com/spf13/cobra"

"github.com/werf/werf/pkg/util"
Expand Down Expand Up @@ -41,6 +44,8 @@ type CmdData struct {
IgnoreSecretKey *bool
DisableDefaultValues *bool
DisableDefaultSecretValues *bool
HelmCompatibleChart *bool
RenameChart *string

WithoutImages *bool
Repo *RepoData
Expand Down Expand Up @@ -123,3 +128,21 @@ func (cmdData *CmdData) SetupSkipDependenciesRepoRefresh(cmd *cobra.Command) {
cmdData.SkipDependenciesRepoRefresh = new(bool)
cmd.Flags().BoolVarP(cmdData.SkipDependenciesRepoRefresh, "skip-dependencies-repo-refresh", "L", util.GetBoolEnvironmentDefaultFalse("WERF_SKIP_DEPENDENCIES_REPO_REFRESH"), `Do not refresh helm chart repositories locally cached index`)
}

func (cmdData *CmdData) SetupHelmCompatibleChart(cmd *cobra.Command, defaultEnabled bool) {
cmdData.HelmCompatibleChart = new(bool)

var defaultVal bool
if defaultEnabled {
defaultVal = util.GetBoolEnvironmentDefaultTrue("WERF_HELM_COMPATIBLE_CHART")
} else {
defaultVal = util.GetBoolEnvironmentDefaultFalse("WERF_HELM_COMPATIBLE_CHART")
}

cmd.Flags().BoolVarP(cmdData.HelmCompatibleChart, "helm-compatible-chart", "C", defaultVal, fmt.Sprintf(`Set chart name in the Chart.yaml of the published chart to the last path component of container registry repo (for REGISTRY/PATH/TO/REPO address chart name will be REPO, more info https://helm.sh/docs/topics/registries/#oci-feature-deprecation-and-behavior-changes-with-v370). In helm compatibility mode chart is fully conforming with the helm OCI registry requirements. Default %v or $WERF_HELM_COMPATIBLE_CHART.`, defaultEnabled))
}

func (cmdData *CmdData) SetupRenameChart(cmd *cobra.Command) {
cmdData.RenameChart = new(string)
cmd.Flags().StringVarP(cmdData.RenameChart, "rename-chart", "", os.Getenv("WERF_RENAME_CHART"), `Force setting of chart name in the Chart.yaml of the published chart to the specified value (can be set by the $WERF_RENAME_CHART, no rename by default, could not be used together with the '--helm-compatible-chart' option).`)
}
11 changes: 8 additions & 3 deletions pkg/deploy/bundles/bundle_accessor.go
Expand Up @@ -9,13 +9,18 @@ import (
"github.com/werf/werf/pkg/docker_registry"
)

type copyToOptions struct {
HelmCompatibleChart bool
RenameChart string
}

type BundleAccessor interface {
ReadChart(ctx context.Context) (*chart.Chart, error)
WriteChart(ctx context.Context, ch *chart.Chart) error

CopyTo(ctx context.Context, to BundleAccessor) error
CopyFromArchive(ctx context.Context, fromArchive *BundleArchive) error
CopyFromRemote(ctx context.Context, fromRemote *RemoteBundle) error
CopyTo(ctx context.Context, to BundleAccessor, opts copyToOptions) error
CopyFromArchive(ctx context.Context, fromArchive *BundleArchive, opts copyToOptions) error
CopyFromRemote(ctx context.Context, fromRemote *RemoteBundle, opts copyToOptions) error
}

type BundleAccessorOptions struct {
Expand Down
8 changes: 4 additions & 4 deletions pkg/deploy/bundles/bundle_archive.go
Expand Up @@ -56,11 +56,11 @@ func (bundle *BundleArchive) WriteChart(ctx context.Context, ch *chart.Chart) er
return nil
}

func (bundle *BundleArchive) CopyTo(ctx context.Context, to BundleAccessor) error {
return to.CopyFromArchive(ctx, bundle)
func (bundle *BundleArchive) CopyTo(ctx context.Context, to BundleAccessor, opts copyToOptions) error {
return to.CopyFromArchive(ctx, bundle, opts)
}

func (bundle *BundleArchive) CopyFromArchive(ctx context.Context, fromArchive *BundleArchive) error {
func (bundle *BundleArchive) CopyFromArchive(ctx context.Context, fromArchive *BundleArchive, opts copyToOptions) error {
ch, err := fromArchive.ReadChart(ctx)
if err != nil {
return fmt.Errorf("unable to read chart from the bundle archive %q: %w", fromArchive.Reader.String(), err)
Expand Down Expand Up @@ -122,7 +122,7 @@ func (bundle *BundleArchive) CopyFromArchive(ctx context.Context, fromArchive *B
return nil
}

func (bundle *BundleArchive) CopyFromRemote(ctx context.Context, fromRemote *RemoteBundle) error {
func (bundle *BundleArchive) CopyFromRemote(ctx context.Context, fromRemote *RemoteBundle, opts copyToOptions) error {
ch, err := fromRemote.ReadChart(ctx)
if err != nil {
return fmt.Errorf("unable to read chart from remote bundle: %w", err)
Expand Down
4 changes: 3 additions & 1 deletion pkg/deploy/bundles/copy.go
Expand Up @@ -9,6 +9,8 @@ import (
type CopyOptions struct {
BundlesRegistryClient BundlesRegistryClient
FromRegistryClient, ToRegistryClient docker_registry.Interface
HelmCompatibleChart bool
RenameChart string
}

func Copy(ctx context.Context, fromAddr, toAddr *Addr, opts CopyOptions) error {
Expand All @@ -21,5 +23,5 @@ func Copy(ctx context.Context, fromAddr, toAddr *Addr, opts CopyOptions) error {
RegistryClient: opts.ToRegistryClient,
})

return fromBundle.CopyTo(ctx, toBundle)
return fromBundle.CopyTo(ctx, toBundle, copyToOptions{HelmCompatibleChart: opts.HelmCompatibleChart, RenameChart: opts.RenameChart})
}
156 changes: 152 additions & 4 deletions pkg/deploy/bundles/copy_test.go
Expand Up @@ -68,7 +68,7 @@ werf:
from := NewBundleArchive(fromArchiveReaderStub, fromArchiveWriterStub)
to := NewBundleArchive(toArchiveReaderStub, toArchiveWriterStub)

Expect(from.CopyTo(ctx, to)).To(Succeed())
Expect(from.CopyTo(ctx, to, copyToOptions{})).To(Succeed())
Expect(toArchiveWriterStub.StubChart.Metadata).To(Equal(fromArchiveReaderStub.StubChart.Metadata))
Expect(toArchiveWriterStub.StubChart.Values).To(Equal(fromArchiveReaderStub.StubChart.Values))

Expand Down Expand Up @@ -129,7 +129,7 @@ werf:
registryClient := NewDockerRegistryStub()
to := NewRemoteBundle(addr.RegistryAddress, bundlesRegistryClient, registryClient)

Expect(from.CopyTo(ctx, to)).To(Succeed())
Expect(from.CopyTo(ctx, to, copyToOptions{HelmCompatibleChart: true})).To(Succeed())

remoteChart := bundlesRegistryClient.StubCharts[addr.RegistryAddress.FullName()]
Expect(remoteChart).NotTo(BeNil())
Expand All @@ -152,6 +152,154 @@ werf:
}
})

It("should copy archive to remote (without chart rename)", func() {
ctx := context.Background()

ch := &chart.Chart{
Metadata: &chart.Metadata{
APIVersion: "v2",
Name: "test-bundle",
Version: "0.1.0",
Type: "application",
},
Values: map[string]interface{}{
"werf": map[string]interface{}{
"image": map[string]interface{}{
"image-1": "REPO:tag-1",
"image-2": "REPO:tag-2",
"image-3": "REPO:tag-3",
},
"repo": "REPO",
},
},
Raw: []*chart.File{
{
Name: "values.yaml",
Data: []byte(`
werf:
image:
image-1: REPO:tag-1
image-2: REPO:tag-2
image-3: REPO:tag-3
repo: REPO
`),
},
},
}

images := map[string][]byte{
"tag-1": []byte(`image-1-bytes`),
"tag-2": []byte(`image-2-bytes`),
"tag-3": []byte(`image-3-bytes`),
}

fromArchiveReaderStub := NewBundleArchiveStubReader(ch, images)
fromArchiveWriterStub := NewBundleArchiveStubWriter()
from := NewBundleArchive(fromArchiveReaderStub, fromArchiveWriterStub)

addr, err := ParseAddr("registry.example.com/group/testproject:1.2.3")
Expect(err).NotTo(HaveOccurred())
bundlesRegistryClient := NewBundlesRegistryClientStub()
registryClient := NewDockerRegistryStub()
to := NewRemoteBundle(addr.RegistryAddress, bundlesRegistryClient, registryClient)

Expect(from.CopyTo(ctx, to, copyToOptions{})).To(Succeed())

remoteChart := bundlesRegistryClient.StubCharts[addr.RegistryAddress.FullName()]
Expect(remoteChart).NotTo(BeNil())

VerifyChart(ctx, remoteChart, VerifyChartOptions{
ExpectedName: "test-bundle",
ExpectedVersion: "1.2.3",
ExpectedRepo: "registry.example.com/group/testproject",
ExpectedImages: map[string]string{
"image-1": "registry.example.com/group/testproject:tag-1",
"image-2": "registry.example.com/group/testproject:tag-2",
"image-3": "registry.example.com/group/testproject:tag-3",
},
})

{
Expect(registryClient.ImagesByReference["registry.example.com/group/testproject:tag-1"]).To(Equal([]byte(`image-1-bytes`)))
Expect(registryClient.ImagesByReference["registry.example.com/group/testproject:tag-2"]).To(Equal([]byte(`image-2-bytes`)))
Expect(registryClient.ImagesByReference["registry.example.com/group/testproject:tag-3"]).To(Equal([]byte(`image-3-bytes`)))
}
})

It("should copy archive to remote (without chart rename)", func() {
ctx := context.Background()

ch := &chart.Chart{
Metadata: &chart.Metadata{
APIVersion: "v2",
Name: "test-bundle",
Version: "0.1.0",
Type: "application",
},
Values: map[string]interface{}{
"werf": map[string]interface{}{
"image": map[string]interface{}{
"image-1": "REPO:tag-1",
"image-2": "REPO:tag-2",
"image-3": "REPO:tag-3",
},
"repo": "REPO",
},
},
Raw: []*chart.File{
{
Name: "values.yaml",
Data: []byte(`
werf:
image:
image-1: REPO:tag-1
image-2: REPO:tag-2
image-3: REPO:tag-3
repo: REPO
`),
},
},
}

images := map[string][]byte{
"tag-1": []byte(`image-1-bytes`),
"tag-2": []byte(`image-2-bytes`),
"tag-3": []byte(`image-3-bytes`),
}

fromArchiveReaderStub := NewBundleArchiveStubReader(ch, images)
fromArchiveWriterStub := NewBundleArchiveStubWriter()
from := NewBundleArchive(fromArchiveReaderStub, fromArchiveWriterStub)

addr, err := ParseAddr("registry.example.com/group/testproject:1.2.3")
Expect(err).NotTo(HaveOccurred())
bundlesRegistryClient := NewBundlesRegistryClientStub()
registryClient := NewDockerRegistryStub()
to := NewRemoteBundle(addr.RegistryAddress, bundlesRegistryClient, registryClient)

Expect(from.CopyTo(ctx, to, copyToOptions{RenameChart: "new-chart-name"})).To(Succeed())

remoteChart := bundlesRegistryClient.StubCharts[addr.RegistryAddress.FullName()]
Expect(remoteChart).NotTo(BeNil())

VerifyChart(ctx, remoteChart, VerifyChartOptions{
ExpectedName: "new-chart-name",
ExpectedVersion: "1.2.3",
ExpectedRepo: "registry.example.com/group/testproject",
ExpectedImages: map[string]string{
"image-1": "registry.example.com/group/testproject:tag-1",
"image-2": "registry.example.com/group/testproject:tag-2",
"image-3": "registry.example.com/group/testproject:tag-3",
},
})

{
Expect(registryClient.ImagesByReference["registry.example.com/group/testproject:tag-1"]).To(Equal([]byte(`image-1-bytes`)))
Expect(registryClient.ImagesByReference["registry.example.com/group/testproject:tag-2"]).To(Equal([]byte(`image-2-bytes`)))
Expect(registryClient.ImagesByReference["registry.example.com/group/testproject:tag-3"]).To(Equal([]byte(`image-3-bytes`)))
}
})

It("should copy remote to archive", func() {
ctx := context.Background()

Expand Down Expand Up @@ -202,7 +350,7 @@ werf:
toArchiveWriterStub := NewBundleArchiveStubWriter()
to := NewBundleArchive(toArchiveReaderStub, toArchiveWriterStub)

Expect(from.CopyTo(ctx, to)).To(Succeed())
Expect(from.CopyTo(ctx, to, copyToOptions{})).To(Succeed())

newCh := toArchiveWriterStub.StubChart
Expect(newCh).NotTo(BeNil())
Expand Down Expand Up @@ -277,7 +425,7 @@ werf:
Expect(err).NotTo(HaveOccurred())
to := NewRemoteBundle(toAddr.RegistryAddress, bundlesRegistryClient, registryClient)

Expect(from.CopyTo(ctx, to)).To(Succeed())
Expect(from.CopyTo(ctx, to, copyToOptions{})).To(Succeed())

newCh := bundlesRegistryClient.StubCharts[toAddr.RegistryAddress.FullName()]
Expect(newCh).NotTo(BeNil())
Expand Down
11 changes: 10 additions & 1 deletion pkg/deploy/bundles/publish.go
Expand Up @@ -12,7 +12,12 @@ import (
"github.com/werf/werf/pkg/deploy/helm/chart_extender"
)

func Publish(ctx context.Context, bundle *chart_extender.Bundle, bundleRef string, bundlesRegistryClient *registry.Client) error {
type PublishOptions struct {
HelmCompatibleChart bool
RenameChart string
}

func Publish(ctx context.Context, bundle *chart_extender.Bundle, bundleRef string, bundlesRegistryClient *registry.Client, opts PublishOptions) error {
r, err := registry.ParseReference(bundleRef)
if err != nil {
return fmt.Errorf("error parsing bundle ref %q: %w", bundleRef, err)
Expand All @@ -31,6 +36,10 @@ func Publish(ctx context.Context, bundle *chart_extender.Bundle, bundleRef strin
return fmt.Errorf("error loading chart %q: %w", path, err)
}

if nameOverwrite := GetChartNameOverwrite(r.Repo, opts.RenameChart, opts.HelmCompatibleChart); nameOverwrite != nil {
ch.Metadata.Name = *nameOverwrite
}

if err := bundlesRegistryClient.SaveChart(ch, r); err != nil {
return fmt.Errorf("unable to save bundle to the local chart helm cache: %w", err)
}
Expand Down

0 comments on commit 3333d03

Please sign in to comment.