From 9f72b3e8b5cfee837b909362e1e49fed536948ad Mon Sep 17 00:00:00 2001 From: Martin Perez Date: Sat, 23 Sep 2023 07:30:57 +0200 Subject: [PATCH] Refactoring and lint fixing --- {chartutils/carvel => carvel}/carvel.go | 90 +++++++++++-------------- cmd/dt/carvelize.go | 22 +++--- cmd/dt/carvelize_test.go | 6 +- cmd/dt/root.go | 2 +- cmd/dt/wrap.go | 1 + cmd/dt/wrap_test.go | 5 +- relocator/chart.go | 22 +++--- 7 files changed, 67 insertions(+), 81 deletions(-) rename {chartutils/carvel => carvel}/carvel.go (66%) diff --git a/chartutils/carvel/carvel.go b/carvel/carvel.go similarity index 66% rename from chartutils/carvel/carvel.go rename to carvel/carvel.go index b3918a0..59a33fa 100644 --- a/chartutils/carvel/carvel.go +++ b/carvel/carvel.go @@ -1,10 +1,9 @@ -// Package chartutils implements helper functions to manipulate helm Charts -package chartutils +// Package carvel implements experimental Carvel support +package carvel import ( "fmt" "io" - "os" "strings" "github.com/vmware-labs/distribution-tooling-for-helm/chartutils" @@ -14,6 +13,14 @@ import ( "gopkg.in/yaml.v3" ) +// CarvelBundleFilePath represents the usual bundle file for Carvel packaging +const CarvelBundleFilePath = ".imgpkg/bundle.yml" + +// CarvelImagesFilePath represents the usual images file for Carvel packaging +const CarvelImagesFilePath = ".imgpkg/images.yml" + +const carvelID = "kbld.carvel.dev/id" + // Somehow there is no data structure for a bundle in Carvel. Copying some basics from the describe command. // Author information from a Bundle @@ -55,38 +62,8 @@ func (il *Metadata) ToYAML(w io.Writer) error { return enc.Encode(il) } -// CarvelBundleFromYAMLFile Deserializes a string into a Metadata struct -func CarvelBundleFromYAMLFile(file string) (*Metadata, error) { - fh, err := os.Open(file) - if err != nil { - return nil, fmt.Errorf("failed to open Images.lock file: %v", err) - } - defer fh.Close() - return CarvelBundleFromYAML(fh) -} - -// CarvelBundleFromYAML reads a Carvel metadata bundled from the YAML read from r -func CarvelBundleFromYAML(r io.Reader) (*Metadata, error) { - metadata := &Metadata{ - Version: BundleVersion{ - APIVersion: BundleAPIVersion, - Kind: BundleKind, - }, - Metadata: map[string]string{}, - Authors: []Author{}, - Websites: []Website{}, - } - dec := yaml.NewDecoder(r) - if err := dec.Decode(metadata); err != nil { - return nil, fmt.Errorf("failed to load Carvel bundle: %v", err) - } - - return metadata, nil -} - // NewCarvelBundle returns a new carvel bundle Metadata instance func NewCarvelBundle() *Metadata { - return &Metadata{ Version: BundleVersion{ APIVersion: BundleAPIVersion, @@ -98,9 +75,8 @@ func NewCarvelBundle() *Metadata { } } -// PrepareBundleMetadata builds and sets a new Carvel bundle struct -func PrepareBundleMetadata(chartPath string, lock *imagelock.ImagesLock) (*Metadata, error) { - +// CreateBundleMetadata builds and sets a new Carvel bundle struct +func CreateBundleMetadata(chartPath string, lock *imagelock.ImagesLock, cfg *chartutils.Configuration) (*Metadata, error) { bundleMetadata := NewCarvelBundle() chart, err := chartutils.LoadChart(chartPath) @@ -112,9 +88,7 @@ func PrepareBundleMetadata(chartPath string, lock *imagelock.ImagesLock) (*Metad author := Author{ Name: maintainer.Name, } - if maintainer.Email != "" { - author.Email = maintainer.Email - } + author.Email = maintainer.Email bundleMetadata.Authors = append(bundleMetadata.Authors, author) } for _, source := range chart.Metadata.Sources { @@ -126,16 +100,19 @@ func PrepareBundleMetadata(chartPath string, lock *imagelock.ImagesLock) (*Metad bundleMetadata.Metadata["name"] = lock.Chart.Name for key, value := range chart.Metadata.Annotations { - if key != "images" { + annotationsKey := cfg.AnnotationsKey + if annotationsKey == "" { + annotationsKey = imagelock.DefaultAnnotationsKey + } + if key != annotationsKey { bundleMetadata.Metadata[key] = value } } return bundleMetadata, nil } -// PrepareImagesLock builds and set a new Carvel images lock struct -func PrepareImagesLock(lock *imagelock.ImagesLock) (lockconfig.ImagesLock, error) { - +// CreateImagesLock builds and set a new Carvel images lock struct +func CreateImagesLock(lock *imagelock.ImagesLock) (lockconfig.ImagesLock, error) { imagesLock := lockconfig.ImagesLock{ LockVersion: lockconfig.LockVersion{ APIVersion: lockconfig.ImagesLockAPIVersion, @@ -144,25 +121,36 @@ func PrepareImagesLock(lock *imagelock.ImagesLock) (lockconfig.ImagesLock, error } for _, img := range lock.Images { // Carvel does not seem to support multi-arch. Grab amd64 digest + name := img.Image i := strings.LastIndex(img.Image, ":") if i > -1 { name = img.Image[0:i] - } - for _, digest := range img.Digests { - if digest.Arch == "linux/amd64" { - name = name + "@" + digest.Digest.String() - break - } + //TODO: Clarify with Carvel community their multi-arch support + //for the time being we stick to amd64 + imageWithDigest := getIntelImageWithDigest(name, img) + if imageWithDigest == "" { + // See above. Skip + break } imageRef := lockconfig.ImageRef{ - Image: name, + Image: imageWithDigest, Annotations: map[string]string{ - "kbld.carvel.dev/id": img.Image, + carvelID: img.Image, }, } imagesLock.AddImageRef(imageRef) } return imagesLock, nil } + +func getIntelImageWithDigest(name string, img *imagelock.ChartImage) string { + + for _, digest := range img.Digests { + if digest.Arch == "linux/amd64" { + return fmt.Sprintf("%s@%s", name, digest.Digest.String()) + } + } + return "" +} diff --git a/cmd/dt/carvelize.go b/cmd/dt/carvelize.go index 4905f53..1935e81 100644 --- a/cmd/dt/carvelize.go +++ b/cmd/dt/carvelize.go @@ -4,10 +4,11 @@ import ( "bytes" "fmt" "os" + "path/filepath" "github.com/spf13/cobra" + "github.com/vmware-labs/distribution-tooling-for-helm/carvel" "github.com/vmware-labs/distribution-tooling-for-helm/chartutils" - carvel "github.com/vmware-labs/distribution-tooling-for-helm/chartutils/carvel" "github.com/vmware-labs/distribution-tooling-for-helm/internal/log" "github.com/vmware-labs/distribution-tooling-for-helm/utils" ) @@ -63,6 +64,7 @@ func newCarvelizeCmd() *cobra.Command { if err := l.Section(fmt.Sprintf("Generating Carvel bundle for Helm chart %q", chartPath), func(childLog log.SectionLogger) error { if err := generateCarvelBundle( chartPath, + chartutils.WithAnnotationsKey(getAnnotationsKey()), chartutils.WithLog(childLog), ); err != nil { return childLog.Failf("%v", err) @@ -82,7 +84,6 @@ func newCarvelizeCmd() *cobra.Command { } func generateCarvelBundle(chartPath string, opts ...chartutils.Option) error { - cfg := chartutils.NewConfiguration(opts...) l := cfg.Log @@ -91,7 +92,7 @@ func generateCarvelBundle(chartPath string, opts ...chartutils.Option) error { return fmt.Errorf("failed to load Images.lock: %v", err) } - imgPkgPath := chartPath + "/.imgpkg" + imgPkgPath := filepath.Join(chartPath, ".imgpkg") if !utils.FileExists(imgPkgPath) { err := os.Mkdir(imgPkgPath, os.FileMode(0755)) if err != nil { @@ -99,29 +100,24 @@ func generateCarvelBundle(chartPath string, opts ...chartutils.Option) error { } } - _, _ = chartPath, l - if !utils.FileExists(chartPath) { - return fmt.Errorf("wrap file %q does not exist", chartPath) - } - - bundleMetadata, err := carvel.PrepareBundleMetadata(chartPath, lock) + bundleMetadata, err := carvel.CreateBundleMetadata(chartPath, lock, cfg) if err != nil { return fmt.Errorf("failed to prepare Carvel bundle: %w", err) } - imagesLock, err := carvel.PrepareImagesLock(lock) + carvelImagesLock, err := carvel.CreateImagesLock(lock) if err != nil { return fmt.Errorf("failed to prepare Carvel images lock: %w", err) } l.Infof("Validating Carvel images lock") - err = imagesLock.Validate() + err = carvelImagesLock.Validate() if err != nil { return fmt.Errorf("failed to validate Carvel images lock: %w", err) } - path := imgPkgPath + "/images.yml" - err = imagesLock.WriteToPath(path) + path := filepath.Join(imgPkgPath, "images.yml") + err = carvelImagesLock.WriteToPath(path) if err != nil { return fmt.Errorf("Could not write image lock: %v", err) } diff --git a/cmd/dt/carvelize_test.go b/cmd/dt/carvelize_test.go index be1c16b..f799458 100644 --- a/cmd/dt/carvelize_test.go +++ b/cmd/dt/carvelize_test.go @@ -6,7 +6,7 @@ import ( "path/filepath" "testing" - carvel "github.com/vmware-labs/distribution-tooling-for-helm/chartutils/carvel" + carvel "github.com/vmware-labs/distribution-tooling-for-helm/carvel" tu "github.com/vmware-labs/distribution-tooling-for-helm/internal/testutil" "gopkg.in/yaml.v3" ) @@ -68,7 +68,7 @@ func (suite *CmdSuite) TestCarvelizeCommand() { res.AssertSuccess(t) t.Run("Generates Carvel bundle", func(t *testing.T) { - newBundleData, err := os.ReadFile(filepath.Join(chartDir, ".imgpkg/bundle.yml")) + newBundleData, err := os.ReadFile(filepath.Join(chartDir, carvel.CarvelBundleFilePath)) require.NoError(err) var newBundle map[string]interface{} require.NoError(yaml.Unmarshal(newBundleData, &newBundle)) @@ -77,7 +77,7 @@ func (suite *CmdSuite) TestCarvelizeCommand() { }) t.Run("Generates Carvel images", func(t *testing.T) { - newImagesData, err := os.ReadFile(filepath.Join(chartDir, ".imgpkg/images.yml")) + newImagesData, err := os.ReadFile(filepath.Join(chartDir, carvel.CarvelImagesFilePath)) require.NoError(err) var newImagesLock map[string]interface{} require.NoError(yaml.Unmarshal(newImagesData, &newImagesLock)) diff --git a/cmd/dt/root.go b/cmd/dt/root.go index e3ee199..72ba31d 100644 --- a/cmd/dt/root.go +++ b/cmd/dt/root.go @@ -21,7 +21,7 @@ const ( terminalSpacer = "" ) -// Global falgs +// Global flags var ( insecure bool annotationsKey string = imagelock.DefaultAnnotationsKey diff --git a/cmd/dt/wrap.go b/cmd/dt/wrap.go index 737b624..54ee69b 100644 --- a/cmd/dt/wrap.go +++ b/cmd/dt/wrap.go @@ -94,6 +94,7 @@ func wrapChart(ctx context.Context, inputPath string, outputFile string, platfor if err := l.Section(fmt.Sprintf("Generating Carvel bundle for Helm chart %q", chartPath), func(childLog log.SectionLogger) error { if err := generateCarvelBundle( chartPath, + chartutils.WithAnnotationsKey(annotationsKey), chartutils.WithLog(childLog), ); err != nil { return childLog.Failf("%v", err) diff --git a/cmd/dt/wrap_test.go b/cmd/dt/wrap_test.go index b1d4dca..9ee4cf3 100644 --- a/cmd/dt/wrap_test.go +++ b/cmd/dt/wrap_test.go @@ -11,6 +11,7 @@ import ( "testing" "github.com/google/go-containerregistry/pkg/registry" + "github.com/vmware-labs/distribution-tooling-for-helm/carvel" tu "github.com/vmware-labs/distribution-tooling-for-helm/internal/testutil" "github.com/vmware-labs/distribution-tooling-for-helm/utils" "gopkg.in/yaml.v3" @@ -102,9 +103,9 @@ func (suite *CmdSuite) TestWrapCommand() { assert.FileExists(lockFile) if generateCarvelBundle { - carvelBundleFile := filepath.Join(tmpDir, ".imgpkg/bundle.yml") + carvelBundleFile := filepath.Join(tmpDir, carvel.CarvelBundleFilePath) assert.FileExists(carvelBundleFile) - carvelImagesLockFile := filepath.Join(tmpDir, ".imgpkg/images.yml") + carvelImagesLockFile := filepath.Join(tmpDir, carvel.CarvelImagesFilePath) assert.FileExists(carvelImagesLockFile) } diff --git a/relocator/chart.go b/relocator/chart.go index 738692c..4ef8f87 100644 --- a/relocator/chart.go +++ b/relocator/chart.go @@ -6,8 +6,10 @@ import ( "errors" "fmt" "os" + "path/filepath" "strings" + "github.com/vmware-labs/distribution-tooling-for-helm/carvel" cu "github.com/vmware-labs/distribution-tooling-for-helm/chartutils" "github.com/vmware-labs/distribution-tooling-for-helm/imagelock" "github.com/vmware-labs/distribution-tooling-for-helm/utils" @@ -79,9 +81,12 @@ func RelocateChartDir(chartPath string, prefix string, opts ...RelocateOption) e if err != nil { return err } - err = relocateCarvelBundle(chartPath, prefix) - if err != nil { - return err + if utils.FileExists(filepath.Join(chartPath, carvel.CarvelImagesFilePath)) { + err = relocateCarvelBundle(chartPath, prefix) + + if err != nil { + return err + } } var allErrors error @@ -99,13 +104,8 @@ func RelocateChartDir(chartPath string, prefix string, opts ...RelocateOption) e func relocateCarvelBundle(chartRoot string, prefix string) error { //TODO: Do better detection here, imgpkg probably has something - lockFile := chartRoot + "/.imgpkg/images.yml" - if !utils.FileExists(lockFile) { - fmt.Printf("Did not find Carvel images bundle at %s. Ignoring", lockFile) - return nil - } - - lock, err := lockconfig.NewImagesLockFromPath(lockFile) + carvelImagesFile := filepath.Join(chartRoot, carvel.CarvelImagesFilePath) + lock, err := lockconfig.NewImagesLockFromPath(carvelImagesFile) if err != nil { return fmt.Errorf("failed to load Carvel images lock: %v", err) } @@ -116,7 +116,7 @@ func relocateCarvelBundle(chartRoot string, prefix string) error { if result.Count == 0 { return nil } - if err := utils.SafeWriteFile(lockFile, result.Data, 0600); err != nil { + if err := utils.SafeWriteFile(carvelImagesFile, result.Data, 0600); err != nil { return fmt.Errorf("failed to overwrite Carvel images lock file: %v", err) } return nil