Skip to content
This repository has been archived by the owner on Feb 12, 2024. It is now read-only.

Commit

Permalink
Fix overwritten changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim Schrodi authored and ccwienk committed Sep 25, 2020
1 parent 4bd928e commit 816233f
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 75 deletions.
77 changes: 76 additions & 1 deletion bindings-go/apis/v2/componentdescriptor.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ type ComponentSpec struct {
// Sources defines sources that produced the component
Sources []Source `json:"sources"`
// ComponentReferences references component dependencies that can be resolved in the current context.
ComponentReferences []ObjectMeta `json:"componentReferences"`
ComponentReferences []ComponentReference `json:"componentReferences"`
// LocalResources defines internal resources that are created by the component
LocalResources []Resource `json:"localResources"`
// ExternalResources defines external resources that are not produced by a third party.
Expand All @@ -85,6 +85,10 @@ type ObjectMeta struct {
Name string `json:"name"`
// Version is the semver version of the object.
Version string `json:"version"`
// Labels defines an optional set of additional labels
// describing the object.
// +optional
Labels []Label `json:"labels,omitempty"`
}

// GetName returns the name of the object.
Expand All @@ -107,6 +111,16 @@ func (o *ObjectMeta) SetVersion(version string) {
o.Version = version
}

// GetLabels returns the label of the object.
func (o ObjectMeta) GetLabels() []Label {
return o.Labels
}

// SetLabels sets the labels of the object.
func (o *ObjectMeta) SetLabels(labels []Label) {
o.Labels = labels
}

// ObjectType describes the type of a object
type ObjectType struct {
// Type describes the type of the object.
Expand All @@ -123,6 +137,58 @@ func (t *ObjectType) SetType(ttype string) {
t.Type = ttype
}

// Label is a label that can be set on objects.
type Label struct {
// Name is the unique name of the label.
Name string `json:"name"`
// Value is the json/yaml data of the label
Value json.RawMessage `json:"value"`
}

// ComponentReference describes the reference to another component in the registry. // Source is the definition of a component's source.
type ComponentReference struct {
// Name is the context unique name of the object.
Name string `json:"name"`
// ComponentName describes the remote name of the referenced object
ComponentName string `json:"componentName"`
// Version is the semver version of the object.
Version string `json:"version"`
// Labels defines an optional set of additional labels
// describing the object.
// +optional
Labels []Label `json:"labels,omitempty"`
}

// GetName returns the name of the object.
func (o ComponentReference) GetName() string {
return o.Name
}

// SetName sets the name of the object.
func (o *ComponentReference) SetName(name string) {
o.Name = name
}

// GetVersion returns the version of the object.
func (o ComponentReference) GetVersion() string {
return o.Version
}

// SetVersion sets the version of the object.
func (o *ComponentReference) SetVersion(version string) {
o.Version = version
}

// GetLabels returns the label of the object.
func (o ComponentReference) GetLabels() []Label {
return o.Labels
}

// SetLabels sets the labels of the object.
func (o *ComponentReference) SetLabels(labels []Label) {
o.Labels = labels
}

// NameAccessor describes a accessor for a named object.
type NameAccessor interface {
// GetName returns the name of the object.
Expand All @@ -139,10 +205,19 @@ type VersionAccessor interface {
SetVersion(version string)
}

// LabelsAccessor describes a accessor for a labeled object.
type LabelsAccessor interface {
// GetLabels returns the labels of the object.
GetLabels() []Label
// SetLabels sets the labels of the object.
SetLabels(labels []Label)
}

// ObjectMetaAccessor describes a accessor for named and versioned object.
type ObjectMetaAccessor interface {
NameAccessor
VersionAccessor
LabelsAccessor
}

// TypedObjectAccessor defines the accessor for a typed component with additional data.
Expand Down
125 changes: 99 additions & 26 deletions bindings-go/apis/v2/validation/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,63 +51,69 @@ func validate(fldPath *field.Path, component *v2.ComponentDescriptor) field.Erro
allErrs = append(allErrs, err)
}

allErrs = append(allErrs, validateObjectMeta(compPath, component.ObjectMeta)...)
allErrs = append(allErrs, validateObjectMeta(compPath, component)...)

srcPath := compPath.Child("sources")
for i, src := range component.Sources {
allErrs = append(allErrs, validateSource(srcPath.Index(i), src)...)
}
allErrs = append(allErrs, validateSources(srcPath, component.Sources)...)

refPath := compPath.Child("componentReferences")
for i, ref := range component.ComponentReferences {
allErrs = append(allErrs, validateObjectMeta(refPath.Index(i), ref)...)
}
allErrs = append(allErrs, validateComponentReferences(refPath, component.ComponentReferences)...)

localPath := compPath.Child("localResources")
for i, res := range component.LocalResources {
allErrs = append(allErrs, validateResource(localPath.Index(i), res)...)
if res.GetVersion() != component.GetVersion() {
allErrs = append(allErrs, field.Invalid(localPath.Index(i).Child("version"), "invalid version",
"version of local resources must match the component version"))
}
}
allErrs = append(allErrs, validateResources(localPath, component.LocalResources, component.GetVersion())...)

extPath := compPath.Child("externalResources")
for i, res := range component.ExternalResources {
allErrs = append(allErrs, validateResource(extPath.Index(i), res)...)
}
allErrs = append(allErrs, validateResources(extPath, component.ExternalResources, "")...)

return allErrs
}

func validateObjectMeta(fldPath *field.Path, om v2.ObjectMeta) field.ErrorList {
func validateObjectMeta(fldPath *field.Path, om v2.ObjectMetaAccessor) field.ErrorList {
allErrs := field.ErrorList{}
if len(om.Name) == 0 {
if len(om.GetName()) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("name"), "must specify a name"))
}
if len(om.Version) == 0 {
if len(om.GetVersion()) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("version"), "must specify a version"))
}
if len(om.GetLabels()) != 0 {
allErrs = append(allErrs, validateLabels(fldPath.Child("labels"), om.GetLabels())...)
}
return allErrs
}

func validateSources(fldPath *field.Path, sources []v2.Source) field.ErrorList {
allErrs := field.ErrorList{}
srcNames := make(map[string]struct{})
for i, src := range sources {
srcPath := fldPath.Index(i)
allErrs = append(allErrs, validateSource(srcPath, src)...)

if _, ok := srcNames[src.Name]; ok {
allErrs = append(allErrs, field.Duplicate(srcPath, "duplicate source"))
continue
}
srcNames[src.Name] = struct{}{}
}
return allErrs
}

func validateSource(fldPath *field.Path, res v2.Source) field.ErrorList {
func validateSource(fldPath *field.Path, src v2.Source) field.ErrorList {
allErrs := field.ErrorList{}
if len(res.GetName()) == 0 {
if len(src.GetName()) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("name"), "must specify a name"))
}
if len(res.GetType()) == 0 {
if len(src.GetType()) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("type"), "must specify a type"))
}

return allErrs
}

func validateResource(fldPath *field.Path, res v2.Resource) field.ErrorList {
allErrs := field.ErrorList{}
allErrs = append(allErrs, validateObjectMeta(fldPath, res.ObjectMeta)...)
allErrs = append(allErrs, validateObjectMeta(fldPath, &res)...)

if len(res.GetType()) == 0 {
if res.TypedObjectAccessor == nil || len(res.GetType()) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("type"), "must specify a type"))
}

Expand All @@ -123,3 +129,70 @@ func validateProvider(fldPath *field.Path, provider v2.ProviderType) *field.Erro
}
return nil
}

func validateLabels(fldPath *field.Path, labels []v2.Label) field.ErrorList {
allErrs := field.ErrorList{}
labelNames := make(map[string]struct{})
for i, label := range labels {
labelPath := fldPath.Index(i)
if len(label.Name) == 0 {
allErrs = append(allErrs, field.Required(labelPath.Child("name"), "must specify a name"))
continue
}

if _, ok := labelNames[label.Name]; ok {
allErrs = append(allErrs, field.Duplicate(labelPath, "duplicate label name"))
continue
}
labelNames[label.Name] = struct{}{}
}
return allErrs
}

func validateComponentReference(fldPath *field.Path, cr v2.ComponentReference) field.ErrorList {
allErrs := field.ErrorList{}
if len(cr.ComponentName) == 0 {
allErrs = append(allErrs, field.Required(fldPath.Child("componentName"), "must specify a component name"))
}
allErrs = append(allErrs, validateObjectMeta(fldPath, &cr)...)
return allErrs
}

func validateComponentReferences(fldPath *field.Path, refs []v2.ComponentReference) field.ErrorList {
allErrs := field.ErrorList{}
refNames := make(map[string]struct{})
for i, ref := range refs {
refPath := fldPath.Index(i)
allErrs = append(allErrs, validateComponentReference(refPath, ref)...)

if _, ok := refNames[ref.Name]; ok {
allErrs = append(allErrs, field.Duplicate(refPath, "duplicate component reference name"))
continue
}
refNames[ref.Name] = struct{}{}
}
return allErrs
}

func validateResources(fldPath *field.Path, resources []v2.Resource, componentVersion string) field.ErrorList {
allErrs := field.ErrorList{}
resourceNames := make(map[string]struct{})
for i, res := range resources {
localPath := fldPath.Index(i)
allErrs = append(allErrs, validateResource(localPath, res)...)

// only validate the component version if it is defined
if len(componentVersion) != 0 {
if res.GetVersion() != componentVersion {
allErrs = append(allErrs, field.Invalid(localPath.Child("version"), "invalid version",
"version of local resources must match the component version"))
}
}
if _, ok := resourceNames[res.Name]; ok {
allErrs = append(allErrs, field.Duplicate(localPath, "duplicated local resource"))
continue
}
resourceNames[res.Name] = struct{}{}
}
return allErrs
}
Loading

0 comments on commit 816233f

Please sign in to comment.