Skip to content

Commit

Permalink
Consistent handling of spec versions (#364)
Browse files Browse the repository at this point in the history
* rework multiversion registries

* provide versionsupport for repos in all contexts

* generalize OCM repository spec factory delegation.

* simplify converter

* redesign runtime package and introduce clear consistent names

* improve conversion

* scheme support for types

* cleanup action interface

* get rid of scheme package

* mv action def to using context

* cv access for resource access

* get rid of prototypes in spec type object creation

* tweak type list in CLI  reference doc

* doc for runtime package

* docu for OCM delegation registry
  • Loading branch information
mandelsoft authored May 23, 2023
1 parent f2903dd commit 902e742
Show file tree
Hide file tree
Showing 183 changed files with 3,173 additions and 2,282 deletions.
8 changes: 4 additions & 4 deletions cmds/demoplugin/uploaders/demo.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ type TargetSpec struct {
Path string `json:"path"`
}

var types map[string]runtime.TypedObjectDecoder
var types ppi.UploadFormats

func init() {
decoder, err := runtime.NewDirectDecoder(&TargetSpec{})
decoder, err := runtime.NewDirectDecoder[runtime.TypedObject](&TargetSpec{})
if err != nil {
panic(err)
}
types = map[string]runtime.TypedObjectDecoder{NAME + runtime.VersionSeparator + VERSION: decoder}
types = ppi.UploadFormats{NAME + runtime.VersionSeparator + VERSION: decoder}
}

type Uploader struct {
Expand All @@ -56,7 +56,7 @@ func New() ppi.Uploader {
}
}

func (a *Uploader) Decoders() map[string]runtime.TypedObjectDecoder {
func (a *Uploader) Decoders() ppi.UploadFormats {
return types
}

Expand Down
2 changes: 1 addition & 1 deletion cmds/demoplugin/uploaders/writer.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func (w *Writer) Close() error {
}
}
w.spec = &accessmethods.AccessSpec{
ObjectVersionedType: runtime.NewVersionedObjectType(w.name, w.version),
ObjectVersionedType: runtime.NewVersionedTypedObject(w.name, w.version),
Path: n,
MediaType: w.media,
}
Expand Down
2 changes: 1 addition & 1 deletion cmds/ecrplugin/actions/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
"github.com/aws/aws-sdk-go-v2/service/ecr/types"

ocmcreds "github.com/open-component-model/ocm/pkg/contexts/credentials"
oci_repository_prepare "github.com/open-component-model/ocm/pkg/contexts/datacontext/action/types/oci-repository-prepare"
"github.com/open-component-model/ocm/pkg/contexts/oci/actions/oci-repository-prepare"
"github.com/open-component-model/ocm/pkg/contexts/ocm/accessmethods/s3/identity"
"github.com/open-component-model/ocm/pkg/contexts/ocm/plugin/ppi"
"github.com/open-component-model/ocm/pkg/errors"
Expand Down
2 changes: 1 addition & 1 deletion cmds/ocm/commands/misccmds/action/execute/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func (o *Command) Complete(args []string) error {
if err != nil {
return errors.Wrapf(err, "cannot marshal final spec")
}
o.Spec, err = action.DecodeActionSpec(data)
o.Spec, err = o.GetActions().GetActionTypes().DecodeActionSpec(data, runtime.DefaultYAMLEncoding)

if o.MatcherType != "" {
m := o.CredentialsContext().ConsumerIdentityMatchers().Get(o.MatcherType)
Expand Down
9 changes: 3 additions & 6 deletions cmds/ocm/commands/ocicmds/common/options/repooption/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package repooption
import (
"github.com/spf13/pflag"

"github.com/open-component-model/ocm/cmds/ocm/pkg/listformat"
"github.com/open-component-model/ocm/cmds/ocm/pkg/options"
"github.com/open-component-model/ocm/pkg/contexts/clictx"
"github.com/open-component-model/ocm/pkg/contexts/oci"
Expand Down Expand Up @@ -80,12 +81,8 @@ The <code>--repo</code> option takes a repository/OCI registry specification:
For the *Common Transport Format* the types <code>directory</code>,
<code>tar</code> or <code>tgz</code> are possible.
Using the JSON variant any repository type supported by the
Using the JSON variant any repository types supported by the
linked library can be used:
`
types := runtime.KindNames(oci.DefaultContext().RepositoryTypes())
for _, t := range types {
s += "- `" + t + "`\n"
}
return s
return s + listformat.FormatMapElements("", runtime.KindToVersionList(oci.DefaultContext().RepositoryTypes().KnownTypeNames()))
}
4 changes: 2 additions & 2 deletions cmds/ocm/commands/ocmcmds/common/addhdlrs/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ import (

"github.com/open-component-model/ocm/cmds/ocm/commands/ocmcmds/common/inputs"
"github.com/open-component-model/ocm/pkg/contexts/clictx"
"github.com/open-component-model/ocm/pkg/contexts/ocm/cpi"
"github.com/open-component-model/ocm/pkg/errors"
"github.com/open-component-model/ocm/pkg/runtime"
)

type ResourceInput struct {
Access *runtime.UnstructuredTypedObject `json:"access"`
Access *cpi.GenericAccessSpec `json:"access"`
// Input *inputs.BlobInput `json:"input,omitempty"`
Input *inputs.GenericInputSpec `json:"input,omitempty"`
}
Expand Down
4 changes: 2 additions & 2 deletions cmds/ocm/commands/ocmcmds/common/addhdlrs/srcs/elements.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,12 @@ func (r *ResourceSpec) Validate(ctx clictx.Context, input *addhdlrs.ResourceInpu
if r.Access.GetType() == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("access", "type"), "type of access required"))
} else {
acc, err := r.Access.Evaluate(ctx.OCMContext().AccessMethods())
acc, err := r.Access.Evaluate(ctx.OCMContext())
if err != nil {
raw, _ := r.Access.GetRaw()
allErrs = append(allErrs, field.Invalid(fldPath.Child("access"), string(raw), err.Error()))
} else if acc.(ocm.AccessSpec).IsLocal(ctx.OCMContext()) {
kind := runtime.ObjectVersionedType(r.Access.ObjectType).GetKind()
kind := runtime.GetKind(r.Access)
allErrs = append(allErrs, field.Invalid(fldPath.Child("access", "type"), kind, "local access no possible"))
}
}
Expand Down
4 changes: 2 additions & 2 deletions cmds/ocm/commands/ocmcmds/common/addhdlrs/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ func Validate(r *ResourceInput, ctx inputs.Context, inputFilePath string) error
if r.Access.GetType() == "" {
allErrs = append(allErrs, field.Required(fldPath.Child("access", "type"), "type of access required"))
} else {
acc, err := r.Access.Evaluate(ctx.OCMContext().AccessMethods())
acc, err := r.Access.Evaluate(ctx.OCMContext())
if err != nil {
if errors.IsErrUnknown(err) {
//nolint: errorlint // No way I can untagle this.
Expand All @@ -257,7 +257,7 @@ func Validate(r *ResourceInput, ctx inputs.Context, inputFilePath string) error
raw, _ := r.Access.GetRaw()
allErrs = append(allErrs, field.Invalid(fldPath.Child("access"), string(raw), err.Error()))
} else if acc.(ocm.AccessSpec).IsLocal(ctx.OCMContext()) {
kind := runtime.ObjectVersionedType(r.Access.ObjectType).GetKind()
kind := runtime.GetKind(r.Access)
allErrs = append(allErrs, field.Invalid(fldPath.Child("access", "type"), kind, "local access no possible"))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ func (h *TypeHandler) get(repo ocm.Repository, elemspec utils.ElemSpec) ([]outpu
if err != nil {
return nil, errors.Wrapf(err, "reference %q", name)
}
spec.UniformRepositorySpec = repo.GetSpecification().AsUniformSpec(h.octx.Context())
spec.UniformRepositorySpec = *repo.GetSpecification().AsUniformSpec(h.octx.Context())
spec.Component = comp.Component
spec.Version = comp.Version
}
Expand Down
58 changes: 21 additions & 37 deletions cmds/ocm/commands/ocmcmds/common/inputs/inputtype.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,14 @@ func (*InputSpecBase) GetInputVersion(ctx Context) string {
return ""
}

type (
InputSpecDecoder = runtime.TypedObjectDecoder[InputSpec]
_InputSpecDecoder = runtime.TypedObjectDecoder[InputSpec]
)

type InputType interface {
runtime.TypedObjectDecoder
runtime.VersionedTypedObject
runtime.VersionedTypeInfo
runtime.TypedObjectDecoder[InputSpec]

ConfigOptionTypeSetHandler() flagsets.ConfigOptionTypeSetHandler

Expand All @@ -110,7 +115,7 @@ type InputType interface {

type DefaultInputType struct {
runtime.ObjectVersionedType
runtime.TypedObjectDecoder
runtime.TypedObjectDecoder[InputSpec]
usage string
clihandler flagsets.ConfigOptionTypeSetHandler
}
Expand All @@ -121,8 +126,8 @@ func NewInputType(name string, proto InputSpec, usage string, cfg flagsets.Confi
t = t.Elem()
}
return &DefaultInputType{
ObjectVersionedType: runtime.NewVersionedObjectType(name),
TypedObjectDecoder: runtime.MustNewDirectDecoder(proto),
ObjectVersionedType: runtime.NewVersionedTypedObject(name),
TypedObjectDecoder: runtime.MustNewDirectDecoder[InputSpec](proto),
usage: usage,
clihandler: cfg,
}
Expand Down Expand Up @@ -155,35 +160,30 @@ func (t *DefaultInputType) ApplyConfig(opts flagsets.ConfigOptions, config flags
}

type InputTypeScheme interface {
runtime.Scheme
runtime.Scheme[InputSpec, InputType]

ConfigTypeSetConfigProvider() flagsets.ConfigTypeOptionSetConfigProvider
flagsets.ConfigProvider

GetInputType(name string) InputType
Register(name string, atype InputType)
Register(atype InputType)

DecodeInputSpec(data []byte, unmarshaler runtime.Unmarshaler) (InputSpec, error)
CreateInputSpec(obj runtime.TypedObject) (InputSpec, error)
}

type inputTypeScheme struct {
runtime.SchemeBase
runtime.Scheme[InputSpec, InputType]
optionTypes flagsets.ConfigTypeOptionSetConfigProvider
}

func NewInputTypeScheme(defaultRepoDecoder runtime.TypedObjectDecoder) InputTypeScheme {
var rt InputSpec
scheme := runtime.MustNewDefaultScheme(&rt, &UnknownInputSpec{}, false, defaultRepoDecoder)
func NewInputTypeScheme(defaultRepoDecoder runtime.TypedObjectDecoder[InputSpec]) InputTypeScheme {
scheme := runtime.MustNewDefaultScheme[InputSpec, InputType](&UnknownInputSpec{}, false, defaultRepoDecoder)
prov := flagsets.NewTypedConfigProvider("input", "blob input specification")
prov.AddGroups("Input Specification Options")
return &inputTypeScheme{scheme, prov}
}

func (t *inputTypeScheme) AddKnownTypes(s InputTypeScheme) {
t.SchemeBase.AddKnownTypes(s)
}

func (t *inputTypeScheme) ConfigTypeSetConfigProvider() flagsets.ConfigTypeOptionSetConfigProvider {
return t.optionTypes
}
Expand All @@ -204,37 +204,21 @@ func (t *inputTypeScheme) GetInputType(name string) InputType {
return d.(InputType)
}

func (t *inputTypeScheme) RegisterByDecoder(name string, decoder runtime.TypedObjectDecoder) error {
i, ok := decoder.(InputType)
if !ok {
return errors.ErrInvalid("GO type", reflect.TypeOf(decoder).String())
}
t.Register(name, i)
return nil
}

func (t *inputTypeScheme) Register(name string, rtype InputType) {
func (t *inputTypeScheme) Register(rtype InputType) {
if rtype == nil {
return
}
t.SchemeBase.RegisterByDecoder(name, rtype)
t.RegisterByDecoder(rtype.GetType(), rtype)
t.optionTypes.AddTypeSet(rtype.ConfigOptionTypeSetHandler())
}

func (t *inputTypeScheme) DecodeInputSpec(data []byte, unmarshaler runtime.Unmarshaler) (InputSpec, error) {
obj, err := t.Decode(data, unmarshaler)
if err != nil {
return nil, err
}
if spec, ok := obj.(InputSpec); ok {
return spec, nil
}
return nil, fmt.Errorf("invalid access spec type: yield %T instead of RepositorySpec", obj)
return t.Decode(data, unmarshaler)
}

func (t *inputTypeScheme) CreateInputSpec(obj runtime.TypedObject) (InputSpec, error) {
if s, ok := obj.(InputSpec); ok {
r, err := t.SchemeBase.Convert(s)
r, err := t.Convert(s)
if err != nil {
return nil, err
}
Expand All @@ -253,8 +237,8 @@ func (t *inputTypeScheme) CreateInputSpec(obj runtime.TypedObject) (InputSpec, e
// DefaultInputTypeScheme contains all globally known access serializer.
var DefaultInputTypeScheme = NewInputTypeScheme(nil)

func RegisterInputType(name string, atype InputType) {
DefaultInputTypeScheme.Register(name, atype)
func RegisterInputType(atype InputType) {
DefaultInputTypeScheme.Register(atype)
}

func CreateRepositorySpec(t runtime.TypedObject) (InputSpec, error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
const TYPE = "binary"

func init() {
inputs.DefaultInputTypeScheme.Register(TYPE, inputs.NewInputType(TYPE, &Spec{},
inputs.DefaultInputTypeScheme.Register(inputs.NewInputType(TYPE, &Spec{},
usage, ConfigHandler()))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
const TYPE = "dir"

func init() {
inputs.DefaultInputTypeScheme.Register(TYPE, inputs.NewInputType(TYPE, &Spec{}, usage, ConfigHandler()))
inputs.DefaultInputTypeScheme.Register(inputs.NewInputType(TYPE, &Spec{}, usage, ConfigHandler()))
}

const usage = `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
const TYPE = "docker"

func init() {
inputs.DefaultInputTypeScheme.Register(TYPE, inputs.NewInputType(TYPE, &Spec{}, usage, ConfigHandler()))
inputs.DefaultInputTypeScheme.Register(inputs.NewInputType(TYPE, &Spec{}, usage, ConfigHandler()))
}

const usage = `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
const TYPE = "dockermulti"

func init() {
inputs.DefaultInputTypeScheme.Register(TYPE, inputs.NewInputType(TYPE, &Spec{}, usage, ConfigHandler()))
inputs.DefaultInputTypeScheme.Register(inputs.NewInputType(TYPE, &Spec{}, usage, ConfigHandler()))
}

const usage = `
Expand Down
2 changes: 1 addition & 1 deletion cmds/ocm/commands/ocmcmds/common/inputs/types/file/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ import (
const TYPE = "file"

func init() {
inputs.DefaultInputTypeScheme.Register(TYPE, inputs.NewInputType(TYPE, &Spec{},
inputs.DefaultInputTypeScheme.Register(inputs.NewInputType(TYPE, &Spec{},
Usage("The path must denote a file relative the resources file. "), ConfigHandler()))
}
2 changes: 1 addition & 1 deletion cmds/ocm/commands/ocmcmds/common/inputs/types/helm/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
const TYPE = "helm"

func init() {
inputs.DefaultInputTypeScheme.Register(TYPE, inputs.NewInputType(TYPE, &Spec{}, usage, ConfigHandler()))
inputs.DefaultInputTypeScheme.Register(inputs.NewInputType(TYPE, &Spec{}, usage, ConfigHandler()))
}

const usage = `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import (
const TYPE = "ociImage"

func init() {
inputs.DefaultInputTypeScheme.Register(TYPE, inputs.NewInputType(TYPE, &Spec{}, usage, ConfigHandler()))
inputs.DefaultInputTypeScheme.Register(inputs.NewInputType(TYPE, &Spec{}, usage, ConfigHandler()))
}

const usage = `
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
const TYPE = "spiff"

func init() {
inputs.DefaultInputTypeScheme.Register(TYPE, inputs.NewInputType(TYPE, &Spec{}, usage(), ConfigHandler()))
inputs.DefaultInputTypeScheme.Register(inputs.NewInputType(TYPE, &Spec{}, usage(), ConfigHandler()))
}

func usage() string {
Expand Down
2 changes: 1 addition & 1 deletion cmds/ocm/commands/ocmcmds/common/inputs/types/utf8/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
const TYPE = "utf8"

func init() {
inputs.DefaultInputTypeScheme.Register(TYPE, inputs.NewInputType(TYPE, &Spec{},
inputs.DefaultInputTypeScheme.Register(inputs.NewInputType(TYPE, &Spec{},
usage, ConfigHandler()))
}

Expand Down
13 changes: 4 additions & 9 deletions cmds/ocm/commands/ocmcmds/common/options/repooption/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/spf13/pflag"

"github.com/open-component-model/ocm/cmds/ocm/commands/ocmcmds/common"
"github.com/open-component-model/ocm/cmds/ocm/pkg/listformat"
"github.com/open-component-model/ocm/cmds/ocm/pkg/options"
"github.com/open-component-model/ocm/pkg/contexts/clictx"
"github.com/open-component-model/ocm/pkg/contexts/oci"
Expand Down Expand Up @@ -87,23 +88,17 @@ The <code>--repo</code> option takes an OCM repository specification:
For the *Common Transport Format* the types <code>directory</code>,
<code>tar</code> or <code>tgz</code> is possible.
Using the JSON variant any repository type supported by the
Using the JSON variant any repository types supported by the
linked library can be used:
Dedicated OCM repository types:
`

types := runtime.KindNames(ocm.DefaultContext().RepositoryTypes())
for _, t := range types {
s += "- `" + t + "`\n"
}
s += listformat.FormatMapElements("", runtime.KindToVersionList(ocm.DefaultContext().RepositoryTypes().KnownTypeNames()))

s += `
OCI Repository types (using standard component repository to OCI mapping):
`
types = runtime.KindNames(oci.DefaultContext().RepositoryTypes())
for _, t := range types {
s += "- `" + t + "`\n"
}
s += listformat.FormatMapElements("", runtime.KindToVersionList(oci.DefaultContext().RepositoryTypes().KnownTypeNames()))
return s
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ const (
)

func init() {
cfgcpi.RegisterConfigType(ConfigType, cfgcpi.NewConfigType(ConfigType, &Config{}, usage))
cfgcpi.RegisterConfigType(ConfigTypeV1, cfgcpi.NewConfigType(ConfigTypeV1, &Config{}, usage))
cfgcpi.RegisterConfigType(cfgcpi.NewConfigType[*Config](ConfigType, usage))
cfgcpi.RegisterConfigType(cfgcpi.NewConfigType[*Config](ConfigTypeV1, usage))
}

// Config describes a memory based repository interface.
Expand All @@ -40,7 +40,7 @@ type ScriptSpec struct {
// NewConfig creates a new memory ConfigSpec.
func NewConfig() *Config {
return &Config{
ObjectVersionedType: runtime.NewVersionedObjectType(ConfigType),
ObjectVersionedType: runtime.NewVersionedTypedObject(ConfigType),
}
}

Expand Down
Loading

0 comments on commit 902e742

Please sign in to comment.