Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

priority for CLI registration options #1045

Merged
merged 3 commits into from
Nov 5, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions api/ocm/extensions/blobhandler/registration.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import (
"fmt"

"ocm.software/ocm/api/ocm/cpi"
"ocm.software/ocm/api/ocm/internal"
)

const DEFAULT_BLOBHANDLER_PRIO = internal.DEFAULT_BLOBHANDLER_PRIO

func RegisterHandlerByName(ctx cpi.ContextProvider, name string, config HandlerConfig, opts ...HandlerOption) error {
o, err := For(ctx).RegisterByName(name, ctx.OCMContext(), config, opts...)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type Option struct {
func (o *Option) Register(ctx ocm.ContextProvider) error {
for _, s := range o.Registrations {
err := download.RegisterHandlerByName(ctx.OCMContext(), s.Name, s.Config,
download.ForArtifactType(s.ArtifactType), download.ForMimeType(s.MediaType))
download.ForArtifactType(s.ArtifactType), download.ForMimeType(s.MediaType), download.WithPrio(s.GetPriority(download.DEFAULT_BLOBHANDLER_PRIO*2)))
if err != nil {
return err
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package downloaderoption_test

import (
. "github.com/mandelsoft/goutils/testutils"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/mandelsoft/goutils/generics"
"github.com/spf13/pflag"

"ocm.software/ocm/api/ocm"
me "ocm.software/ocm/cmds/ocm/commands/ocmcmds/common/options/downloaderoption"
)

var _ = Describe("Downloader Option Test Environment", func() {
var o *me.Option
var fs *pflag.FlagSet

BeforeEach(func() {
o = me.New(ocm.DefaultContext())
fs = &pflag.FlagSet{}
o.AddFlags(fs)
})

It("handles all parts", func() {
MustBeSuccessful(fs.Parse([]string{"--downloader", `bla/blub:a:b:10={"k":"v"}`}))
MustBeSuccessful(o.Configure(nil))
Expect(len(o.Registrations)).To(Equal(1))
Expect(o.Registrations[0].Prio).To(Equal(generics.Pointer(10)))
Expect(o.Registrations[0].Name).To(Equal("bla/blub"))
Expect(o.Registrations[0].ArtifactType).To(Equal("a"))
Expect(o.Registrations[0].MediaType).To(Equal("b"))
Expect(o.Registrations[0].Config).To(Equal([]byte(`{"k":"v"}`)))
Expect("").To(Equal(""))
})

It("handles empty parts", func() {
MustBeSuccessful(fs.Parse([]string{"--downloader", `bla/blub:::10={"k":"v"}`}))
MustBeSuccessful(o.Configure(nil))
Expect(len(o.Registrations)).To(Equal(1))
Expect(o.Registrations[0].Prio).To(Equal(generics.Pointer(10)))
Expect(o.Registrations[0].Name).To(Equal("bla/blub"))
Expect(o.Registrations[0].ArtifactType).To(Equal(""))
Expect(o.Registrations[0].MediaType).To(Equal(""))
Expect(o.Registrations[0].Config).To(Equal([]byte(`{"k":"v"}`)))
})

It("handles art/media/config", func() {
MustBeSuccessful(fs.Parse([]string{"--downloader", `bla/blub:a:b={"k":"v"}`}))
MustBeSuccessful(o.Configure(nil))
Expect(len(o.Registrations)).To(Equal(1))
Expect(o.Registrations[0].Prio).To(BeNil())
Expect(o.Registrations[0].Name).To(Equal("bla/blub"))
Expect(o.Registrations[0].ArtifactType).To(Equal("a"))
Expect(o.Registrations[0].MediaType).To(Equal("b"))
Expect(o.Registrations[0].Config).To(Equal([]byte(`{"k":"v"}`)))
})

It("handles art/media/empty config", func() {
MustBeSuccessful(fs.Parse([]string{"--downloader", `bla/blub:a:b`}))
MustBeSuccessful(o.Configure(nil))
Expect(len(o.Registrations)).To(Equal(1))
Expect(o.Registrations[0].Prio).To(BeNil())
Expect(o.Registrations[0].Name).To(Equal("bla/blub"))
Expect(o.Registrations[0].ArtifactType).To(Equal("a"))
Expect(o.Registrations[0].MediaType).To(Equal("b"))
Expect(o.Registrations[0].Config).To(BeNil())
})

It("handles empty config", func() {
MustBeSuccessful(fs.Parse([]string{"--downloader", `bla/blub`}))
MustBeSuccessful(o.Configure(nil))
Expect(len(o.Registrations)).To(Equal(1))
Expect(o.Registrations[0].Prio).To(BeNil())
Expect(o.Registrations[0].Name).To(Equal("bla/blub"))
Expect(o.Registrations[0].ArtifactType).To(Equal(""))
Expect(o.Registrations[0].MediaType).To(Equal(""))
Expect(o.Registrations[0].Config).To(BeNil())
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package downloaderoption_test

import (
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestConfig(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "downloader option Test Suite")
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ package optutils
import (
"encoding/json"
"fmt"
"strconv"
"strings"

"github.com/mandelsoft/goutils/errors"
"github.com/mandelsoft/goutils/generics"
"github.com/spf13/pflag"
"sigs.k8s.io/yaml"

Expand All @@ -18,9 +20,17 @@ type Registration struct {
Name string
ArtifactType string
MediaType string
Prio *int
Config interface{}
}

func (r *Registration) GetPriority(def int) int {
if r.Prio != nil {
return *r.Prio
}
return def
}

func NewRegistrationOption(name, short, desc, usage string) RegistrationOption {
return RegistrationOption{name: name, short: short, desc: desc, usage: usage}
}
Expand All @@ -34,7 +44,7 @@ type RegistrationOption struct {
Registrations []*Registration
}

const RegistrationFormat = "<name>[:<artifact type>[:<media type>]]=<JSON target config"
const RegistrationFormat = "<name>[:<artifact type>[:<media type>[:<prio>]]]=<JSON target config>"
hilmarf marked this conversation as resolved.
Show resolved Hide resolved

func (o *RegistrationOption) AddFlags(fs *pflag.FlagSet) {
flag.StringToStringVarP(fs, &o.spec, o.name, o.short, nil, fmt.Sprintf("%s (%s)", o.desc, RegistrationFormat))
Expand All @@ -46,22 +56,34 @@ func (o *RegistrationOption) HasRegistrations() bool {

func (o *RegistrationOption) Configure(ctx clictx.Context) error {
for n, v := range o.spec {
var prio *int
nam := n
art := ""
med := ""
i := strings.Index(nam, ":")
if i >= 0 {
art = nam[i+1:]
nam = nam[:i]
i = strings.Index(art, ":")
if i >= 0 {
med = art[i+1:]
art = art[:i]
i = strings.Index(med, ":")
if i >= 0 {
return fmt.Errorf("invalid %s registration %s must be of %s", o.name, n, RegistrationFormat)
}
}
i = strings.Index(art, ":")
if i >= 0 {
med = art[i+1:]
art = art[:i]
}
i = strings.Index(med, ":")
if i >= 0 {
p := med[i+1:]
med = med[:i]

v, err := strconv.ParseInt(p, 10, 32)
if err != nil {
return fmt.Errorf("invalid %s registration %s (invalid priority) must be of %s", o.name, n, RegistrationFormat)
}
prio = generics.Pointer(int(v))
}
i = strings.Index(med, ":")
if i >= 0 {
return fmt.Errorf("invalid %s registration %s must be of %s", o.name, n, RegistrationFormat)
}

var data interface{}
Expand Down Expand Up @@ -93,6 +115,7 @@ func (o *RegistrationOption) Configure(ctx clictx.Context) error {
Name: nam,
ArtifactType: art,
MediaType: med,
Prio: prio,
Config: data,
})
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type Option struct {
func (o *Option) Register(ctx ocm.ContextProvider) error {
for _, s := range o.Registrations {
err := blobhandler.RegisterHandlerByName(ctx.OCMContext(), s.Name, s.Config,
blobhandler.ForArtifactType(s.ArtifactType), blobhandler.ForMimeType(s.MediaType))
blobhandler.ForArtifactType(s.ArtifactType), blobhandler.ForMimeType(s.MediaType), blobhandler.WithPrio(s.GetPriority(blobhandler.DEFAULT_BLOBHANDLER_PRIO*2)))
if err != nil {
return err
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package uploaderoption_test

import (
. "github.com/mandelsoft/goutils/testutils"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/mandelsoft/goutils/generics"
"github.com/spf13/pflag"

"ocm.software/ocm/api/ocm"
me "ocm.software/ocm/cmds/ocm/commands/ocmcmds/common/options/uploaderoption"
)

var _ = Describe("Downloader Option Test Environment", func() {
var o *me.Option
var fs *pflag.FlagSet

BeforeEach(func() {
o = me.New(ocm.DefaultContext())
fs = &pflag.FlagSet{}
o.AddFlags(fs)
})

It("handles all parts", func() {
MustBeSuccessful(fs.Parse([]string{"--uploader", `bla/blub:a:b:10={"k":"v"}`}))
MustBeSuccessful(o.Configure(nil))
Expect(len(o.Registrations)).To(Equal(1))
Expect(o.Registrations[0].Prio).To(Equal(generics.Pointer(10)))
Expect(o.Registrations[0].Name).To(Equal("bla/blub"))
Expect(o.Registrations[0].ArtifactType).To(Equal("a"))
Expect(o.Registrations[0].MediaType).To(Equal("b"))
Expect(o.Registrations[0].Config).To(Equal([]byte(`{"k":"v"}`)))
Expect("").To(Equal(""))
})

It("handles empty parts", func() {
MustBeSuccessful(fs.Parse([]string{"--uploader", `bla/blub:::10={"k":"v"}`}))
MustBeSuccessful(o.Configure(nil))
Expect(len(o.Registrations)).To(Equal(1))
Expect(o.Registrations[0].Prio).To(Equal(generics.Pointer(10)))
Expect(o.Registrations[0].Name).To(Equal("bla/blub"))
Expect(o.Registrations[0].ArtifactType).To(Equal(""))
Expect(o.Registrations[0].MediaType).To(Equal(""))
Expect(o.Registrations[0].Config).To(Equal([]byte(`{"k":"v"}`)))
})

It("handles art/media/config", func() {
MustBeSuccessful(fs.Parse([]string{"--uploader", `bla/blub:a:b={"k":"v"}`}))
MustBeSuccessful(o.Configure(nil))
Expect(len(o.Registrations)).To(Equal(1))
Expect(o.Registrations[0].Prio).To(BeNil())
Expect(o.Registrations[0].Name).To(Equal("bla/blub"))
Expect(o.Registrations[0].ArtifactType).To(Equal("a"))
Expect(o.Registrations[0].MediaType).To(Equal("b"))
Expect(o.Registrations[0].Config).To(Equal([]byte(`{"k":"v"}`)))
})

It("handles art/media/empty config", func() {
MustBeSuccessful(fs.Parse([]string{"--uploader", `bla/blub:a:b`}))
MustBeSuccessful(o.Configure(nil))
Expect(len(o.Registrations)).To(Equal(1))
Expect(o.Registrations[0].Prio).To(BeNil())
Expect(o.Registrations[0].Name).To(Equal("bla/blub"))
Expect(o.Registrations[0].ArtifactType).To(Equal("a"))
Expect(o.Registrations[0].MediaType).To(Equal("b"))
Expect(o.Registrations[0].Config).To(BeNil())
})

It("handles empty config", func() {
MustBeSuccessful(fs.Parse([]string{"--uploader", `bla/blub`}))
MustBeSuccessful(o.Configure(nil))
Expect(len(o.Registrations)).To(Equal(1))
Expect(o.Registrations[0].Prio).To(BeNil())
Expect(o.Registrations[0].Name).To(Equal("bla/blub"))
Expect(o.Registrations[0].ArtifactType).To(Equal(""))
Expect(o.Registrations[0].MediaType).To(Equal(""))
Expect(o.Registrations[0].Config).To(BeNil())
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ var _ = Describe("uploader option", func() {
})

It("fails", func() {
MustBeSuccessful(flags.Parse([]string{`--uploader`, `plugin/name:::=Name`}))
MustFailWithMessage(opt.Configure(ctx), "invalid uploader registration plugin/name::: must be of "+optutils.RegistrationFormat)
MustBeSuccessful(flags.Parse([]string{`--uploader`, `plugin/name:::0:=Name`}))
MustFailWithMessage(opt.Configure(ctx), "invalid uploader registration plugin/name:::0: (invalid priority) must be of "+optutils.RegistrationFormat)
})
})
2 changes: 1 addition & 1 deletion docs/reference/ocm_add_componentversions.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ componentversions, componentversion, cv, components, component, comps, comp, c
-s, --settings stringArray settings file with variable settings (yaml)
--templater string templater to use (go, none, spiff, subst) (default "subst")
-t, --type string archive format (directory, tar, tgz) (default "directory")
--uploader <name>=<value> repository uploader (<name>[:<artifact type>[:<media type>]]=<JSON target config) (default [])
--uploader <name>=<value> repository uploader (<name>[:<artifact type>[:<media type>[:<prio>]]]=<JSON target config>) (default [])
-v, --version string default version for components
```

Expand Down
2 changes: 1 addition & 1 deletion docs/reference/ocm_download_resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ resources, resource, res, r
--check-verified enable verification store
-c, --constraints constraints version constraint
-d, --download-handlers use download handler if possible
--downloader <name>=<value> artifact downloader (<name>[:<artifact type>[:<media type>]]=<JSON target config) (default [])
--downloader <name>=<value> artifact downloader (<name>[:<artifact type>[:<media type>[:<prio>]]]=<JSON target config>) (default [])
-x, --executable download executable for local platform
-h, --help help for resources
--latest restrict component versions to latest
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/ocm_transfer_commontransportarchive.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ commontransportarchive, ctf
-s, --scriptFile string filename of transfer handler script
-E, --stop-on-existing stop on existing component version in target repository
-t, --type string archive format (directory, tar, tgz) (default "directory")
--uploader <name>=<value> repository uploader (<name>[:<artifact type>[:<media type>]]=<JSON target config) (default [])
--uploader <name>=<value> repository uploader (<name>[:<artifact type>[:<media type>[:<prio>]]]=<JSON target config>) (default [])
```

### Description
Expand Down
2 changes: 1 addition & 1 deletion docs/reference/ocm_transfer_componentversions.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ componentversions, componentversion, cv, components, component, comps, comp, c
-s, --scriptFile string filename of transfer handler script
-E, --stop-on-existing stop on existing component version in target repository
-t, --type string archive format (directory, tar, tgz) (default "directory")
--uploader <name>=<value> repository uploader (<name>[:<artifact type>[:<media type>]]=<JSON target config) (default [])
--uploader <name>=<value> repository uploader (<name>[:<artifact type>[:<media type>[:<prio>]]]=<JSON target config>) (default [])
```

### Description
Expand Down
Loading