Skip to content
This repository has been archived by the owner on May 26, 2023. It is now read-only.

Commit

Permalink
add set command to modify comp desc
Browse files Browse the repository at this point in the history
  • Loading branch information
mandelsoft committed Jan 10, 2022
1 parent 4ff44b4 commit d9204c4
Show file tree
Hide file tree
Showing 6 changed files with 255 additions and 7 deletions.
3 changes: 3 additions & 0 deletions pkg/commands/componentarchive/componentarchive.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/gardener/component-cli/pkg/commands/componentarchive/componentreferences"
"github.com/gardener/component-cli/pkg/commands/componentarchive/remote"
"github.com/gardener/component-cli/pkg/commands/componentarchive/resources"
"github.com/gardener/component-cli/pkg/commands/componentarchive/set"
"github.com/gardener/component-cli/pkg/commands/componentarchive/sources"
ctfcmd "github.com/gardener/component-cli/pkg/commands/ctf"
"github.com/gardener/component-cli/pkg/componentarchive"
Expand Down Expand Up @@ -74,6 +75,7 @@ func NewComponentArchiveCommand(ctx context.Context) *cobra.Command {
cmd.AddCommand(resources.NewResourcesCommand(ctx))
cmd.AddCommand(componentreferences.NewCompRefCommand(ctx))
cmd.AddCommand(sources.NewSourcesCommand(ctx))
cmd.AddCommand(set.NewSetCommand(ctx))
return cmd
}

Expand Down Expand Up @@ -110,6 +112,7 @@ func (o *ComponentArchiveOptions) Run(ctx context.Context, log logr.Logger, fs v
return fmt.Errorf("unable to add component archive to ctf: %w", err)
}
log.Info("Successfully added ctf\n")
return nil
}

// only copy essential files to the temp dir
Expand Down
6 changes: 6 additions & 0 deletions pkg/commands/componentarchive/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package componentarchive

import (
"context"
"errors"
"fmt"
"os"

Expand Down Expand Up @@ -70,6 +71,11 @@ func (o *CreateOptions) Complete(args []string) error {
}

func (o *CreateOptions) validate() error {
if len(o.Name) != 0 {
if len(o.Version) == 0 {
return errors.New("a version has to be provided for a minimal component descriptor")
}
}
return o.BuilderOptions.Validate()
}

Expand Down
114 changes: 114 additions & 0 deletions pkg/commands/componentarchive/set/set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// SPDX-FileCopyrightText: 2020 SAP SE or an SAP affiliate company and Gardener contributors.
//
// SPDX-License-Identifier: Apache-2.0

package set

import (
"context"
"errors"
"fmt"
"os"
"path/filepath"

cdvalidation "github.com/gardener/component-spec/bindings-go/apis/v2/validation"
"github.com/gardener/component-spec/bindings-go/ctf"
"github.com/go-logr/logr"
"github.com/mandelsoft/vfs/pkg/osfs"
"github.com/mandelsoft/vfs/pkg/vfs"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"sigs.k8s.io/yaml"

"github.com/gardener/component-cli/pkg/componentarchive"
"github.com/gardener/component-cli/pkg/logger"
"github.com/gardener/component-cli/pkg/template"
)

// Options defines the options that are used to add resources to a component descriptor
type Options struct {
componentarchive.BuilderOptions
TemplateOptions template.Options
}

// NewAddCommand creates a command to add additional resources to a component descriptor.
func NewSetCommand(ctx context.Context) *cobra.Command {
opts := &Options{}
cmd := &cobra.Command{
Use: "set COMPONENT_ARCHIVE_PATH [options...]",
Args: cobra.MinimumNArgs(0),
Short: "set some component descriptor properties",
Long: fmt.Sprintf(`
the set command sets some component descriptor properies like the component name and/or version.
The component archive can be specified by the first argument, the flag "--archive" or as env var "COMPONENT_ARCHIVE_PATH".
The component archive is expected to be a filesystem archive.
`),
Run: func(cmd *cobra.Command, args []string) {
if err := opts.Complete(args); err != nil {
fmt.Println(err.Error())
os.Exit(1)
}

if err := opts.Run(ctx, logger.Log, osfs.New()); err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
},
}

opts.AddFlags(cmd.Flags())

return cmd
}

func (o *Options) Run(ctx context.Context, log logr.Logger, fs vfs.FileSystem) error {
compDescFilePath := filepath.Join(o.ComponentArchivePath, ctf.ComponentDescriptorFileName)

o.Modify = true
archive, err := o.BuilderOptions.Build(fs)
if err != nil {
return err
}

if len(o.Name) != 0 {
archive.ComponentDescriptor.Name = o.Name
}
if len(o.Version) != 0 {
archive.ComponentDescriptor.Version = o.Version
}

if err := cdvalidation.Validate(archive.ComponentDescriptor); err != nil {
return fmt.Errorf("invalid component descriptor: %w", err)
}

data, err := yaml.Marshal(archive.ComponentDescriptor)
if err != nil {
return fmt.Errorf("unable to encode component descriptor: %w", err)
}
if err := vfs.WriteFile(fs, compDescFilePath, data, 0664); err != nil {
return fmt.Errorf("unable to write modified comonent descriptor: %w", err)
}
log.V(2).Info(fmt.Sprintf("Successfully changed component descriptor"))
return nil
}

func (o *Options) Complete(args []string) error {
args = o.TemplateOptions.Parse(args)

if len(args) == 0 {
return errors.New("at least a component archive path argument has to be defined")
}
o.BuilderOptions.ComponentArchivePath = args[0]
o.BuilderOptions.Default()

return o.validate()
}

func (o *Options) validate() error {
return o.BuilderOptions.Validate()
}

func (o *Options) AddFlags(fs *pflag.FlagSet) {
o.BuilderOptions.AddFlags(fs)
}
110 changes: 110 additions & 0 deletions pkg/commands/componentarchive/set/set_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// SPDX-FileCopyrightText: 2020 SAP SE or an SAP affiliate company and Gardener contributors.
//
// SPDX-License-Identifier: Apache-2.0

package set_test

import (
"context"
"path/filepath"
"testing"

cdv2 "github.com/gardener/component-spec/bindings-go/apis/v2"
"github.com/gardener/component-spec/bindings-go/codec"
"github.com/gardener/component-spec/bindings-go/ctf"
"github.com/go-logr/logr"
"github.com/mandelsoft/vfs/pkg/layerfs"
"github.com/mandelsoft/vfs/pkg/memoryfs"
"github.com/mandelsoft/vfs/pkg/osfs"
"github.com/mandelsoft/vfs/pkg/projectionfs"
"github.com/mandelsoft/vfs/pkg/vfs"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
. "github.com/onsi/gomega/gstruct"

"github.com/gardener/component-cli/pkg/commands/componentarchive/set"
"github.com/gardener/component-cli/pkg/componentarchive"
)

func TestConfig(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Resources Test Suite")
}

var _ = Describe("Set", func() {

var testdataFs vfs.FileSystem

BeforeEach(func() {
fs, err := projectionfs.New(osfs.New(), "./testdata")
Expect(err).ToNot(HaveOccurred())
testdataFs = layerfs.New(memoryfs.New(), fs)
})

It("should set name", func() {
opts := &set.Options{
BuilderOptions: componentarchive.BuilderOptions{
ComponentArchivePath: "./00-component",
Name: "xxxx.xx/name",
},
}

Expect(opts.Run(context.TODO(), logr.Discard(), testdataFs)).To(Succeed())

data, err := vfs.ReadFile(testdataFs, filepath.Join(opts.ComponentArchivePath, ctf.ComponentDescriptorFileName))
Expect(err).ToNot(HaveOccurred())

cd := &cdv2.ComponentDescriptor{}
Expect(codec.Decode(data, cd)).To(Succeed())

Expect(cd.Resources).To(HaveLen(1))
Expect(cd.Resources[0].IdentityObjectMeta).To(MatchFields(IgnoreExtras, Fields{
"Name": Equal("ubuntu"),
"Version": Equal("v0.0.1"),
"Type": Equal("ociImage"),
"ExtraIdentity": HaveLen(0),
}))
Expect(cd.Resources[0]).To(MatchFields(IgnoreExtras, Fields{
"Relation": Equal(cdv2.ResourceRelation("external")),
}))
Expect(cd.Resources[0].Access.Object).To(HaveKeyWithValue("type", "ociRegistry"))
Expect(cd.Resources[0].Access.Object).To(HaveKeyWithValue("imageReference", "ubuntu:18.0"))

Expect(cd.Name).To(Equal("xxxx.xx/name"))
Expect(cd.Version).To(Equal("v0.0.0"))
})

It("should set version", func() {
opts := &set.Options{
BuilderOptions: componentarchive.BuilderOptions{
ComponentArchivePath: "./00-component",
Version: "v1",
},
}

Expect(opts.Run(context.TODO(), logr.Discard(), testdataFs)).To(Succeed())

data, err := vfs.ReadFile(testdataFs, filepath.Join(opts.ComponentArchivePath, ctf.ComponentDescriptorFileName))
Expect(err).ToNot(HaveOccurred())

cd := &cdv2.ComponentDescriptor{}
Expect(codec.Decode(data, cd)).To(Succeed())

Expect(cd.Resources).To(HaveLen(1))
Expect(cd.Resources[0].IdentityObjectMeta).To(MatchFields(IgnoreExtras, Fields{
"Name": Equal("ubuntu"),
"Version": Equal("v0.0.1"),
"Type": Equal("ociImage"),
"ExtraIdentity": HaveLen(0),
}))
Expect(cd.Resources[0]).To(MatchFields(IgnoreExtras, Fields{
"Relation": Equal(cdv2.ResourceRelation("external")),
}))
Expect(cd.Resources[0].Access.Object).To(HaveKeyWithValue("type", "ociRegistry"))
Expect(cd.Resources[0].Access.Object).To(HaveKeyWithValue("imageReference", "ubuntu:18.0"))

Expect(cd.Name).To(Equal("example.com/component"))
Expect(cd.Version).To(Equal("v1"))
})

})
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
component:
componentReferences: []
name: example.com/component
provider: internal
repositoryContexts:
- baseUrl: eu.gcr.io/gardener-project/components/dev
type: ociRegistry
resources:
- name: 'ubuntu'
version: 'v0.0.1'
type: 'ociImage'
relation: 'external'
access:
type: 'ociRegistry'
imageReference: 'ubuntu:18.0'
sources: []
version: v0.0.0
meta:
schemaVersion: v2
10 changes: 3 additions & 7 deletions pkg/componentarchive/archive.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type BuilderOptions struct {
ComponentNameMapping string

Overwrite bool
Modify bool
}

func (o *BuilderOptions) AddFlags(fs *pflag.FlagSet) {
Expand All @@ -58,11 +59,6 @@ func (o *BuilderOptions) Validate() error {
return errors.New("a component archive path must be defined")
}

if len(o.Name) != 0 {
if len(o.Version) == 0 {
return errors.New("a version has to be provided for a minimal component descriptor")
}
}
if len(o.ComponentNameMapping) != 0 {
if o.ComponentNameMapping != string(cdv2.OCIRegistryURLPathMapping) &&
o.ComponentNameMapping != string(cdv2.OCIRegistryDigestMapping) {
Expand Down Expand Up @@ -100,14 +96,14 @@ func (o *BuilderOptions) Build(fs vfs.FileSystem) (*ctf.ComponentArchive, error)
cd := archive.ComponentDescriptor

if o.Name != "" {
if cd.Name != "" && cd.Name != o.Name {
if !o.Modify && cd.Name != "" && cd.Name != o.Name {
return nil, errors.New("unable to overwrite the existing component name: forbidden")
}
cd.Name = o.Name
}

if o.Version != "" {
if cd.Version != "" && cd.Version != o.Version {
if !o.Modify && cd.Version != "" && cd.Version != o.Version {
return nil, errors.New("unable to overwrite the existing component version: forbidden")
}
cd.Version = o.Version
Expand Down

0 comments on commit d9204c4

Please sign in to comment.