vendor: Update vendor logic

This commit is contained in:
Clayton Coleman 2020-04-08 14:34:43 -04:00
parent c6ac5cbc87
commit 4ca64b85f0
No known key found for this signature in database
GPG key ID: 3D16906B4F1C5CB3
1540 changed files with 265304 additions and 91616 deletions

View file

@ -16,9 +16,17 @@ limitations under the License.
package schema
import "sync"
// Schema is a list of named types.
//
// Schema types are indexed in a map before the first search so this type
// should be considered immutable.
type Schema struct {
Types []TypeDef `yaml:"types,omitempty"`
once sync.Once
m map[string]TypeDef
}
// A TypeSpecifier references a particular type in a schema.
@ -43,13 +51,12 @@ type TypeRef struct {
}
// Atom represents the smallest possible pieces of the type system.
// Each set field in the Atom represents a possible type for the object.
// If none of the fields are set, any object will fail validation against the atom.
type Atom struct {
// Exactly one of the below must be set.
*Scalar `yaml:"scalar,omitempty"`
*Struct `yaml:"struct,omitempty"`
*List `yaml:"list,omitempty"`
*Map `yaml:"map,omitempty"`
*Untyped `yaml:"untyped,omitempty"`
*Scalar `yaml:"scalar,omitempty"`
*List `yaml:"list,omitempty"`
*Map `yaml:"map,omitempty"`
}
// Scalar (AKA "primitive") represents a type which has a single value which is
@ -65,45 +72,122 @@ const (
)
// ElementRelationship is an enum of the different possible relationships
// between the elements of container types (maps, lists, structs, untyped).
// between the elements of container types (maps, lists).
type ElementRelationship string
const (
// Associative only applies to lists (see the documentation there).
Associative = ElementRelationship("associative")
// Atomic makes container types (lists, maps, structs, untyped) behave
// as scalars / leaf fields (which is the default for untyped data).
// Atomic makes container types (lists, maps) behave
// as scalars / leaf fields
Atomic = ElementRelationship("atomic")
// Separable means the items of the container type have no particular
// relationship (default behavior for maps and structs).
// relationship (default behavior for maps).
Separable = ElementRelationship("separable")
)
// Struct represents a type which is composed of a number of different fields.
// Map is a key-value pair. Its default semantics are the same as an
// associative list, but:
// * It is serialized differently:
// map: {"k": {"value": "v"}}
// list: [{"key": "k", "value": "v"}]
// * Keys must be string typed.
// * Keys can't have multiple components.
//
// Optionally, maps may be atomic (for example, imagine representing an RGB
// color value--it doesn't make sense to have different actors own the R and G
// values).
//
// Maps may also represent a type which is composed of a number of different fields.
// Each field has a name and a type.
//
// TODO: in the future, we will add one-of groups (sometimes called unions).
type Struct struct {
// Fields are indexed in a map before the first search so this type
// should be considered immutable.
type Map struct {
// Each struct field appears exactly once in this list. The order in
// this list defines the canonical field ordering.
Fields []StructField `yaml:"fields,omitempty"`
// TODO: Implement unions, either this way or by inlining.
// Unions are groupings of fields with special rules. They may refer to
// A Union is a grouping of fields with special rules. It may refer to
// one or more fields in the above list. A given field from the above
// list may be referenced in exactly 0 or 1 places in the below list.
// Unions []Union `yaml:"unions,omitempty"`
// One can have multiple unions in the same struct, but the fields can't
// overlap between unions.
Unions []Union `yaml:"unions,omitempty"`
// ElementRelationship states the relationship between the struct's items.
// ElementType is the type of the structs's unknown fields.
ElementType TypeRef `yaml:"elementType,omitempty"`
// ElementRelationship states the relationship between the map's items.
// * `separable` (or unset) implies that each element is 100% independent.
// * `atomic` implies that all elements depend on each other, and this
// is effectively a scalar / leaf field; it doesn't make sense for
// separate actors to set the elements. Example: an RGB color struct;
// it would never make sense to "own" only one component of the
// color.
// The default behavior for structs is `separable`; it's permitted to
// The default behavior for maps is `separable`; it's permitted to
// leave this unset to get the default behavior.
ElementRelationship ElementRelationship `yaml:"elementRelationship,omitempty"`
once sync.Once
m map[string]StructField
}
// FindField is a convenience function that returns the referenced StructField,
// if it exists, or (nil, false) if it doesn't.
func (m *Map) FindField(name string) (StructField, bool) {
m.once.Do(func() {
m.m = make(map[string]StructField, len(m.Fields))
for _, field := range m.Fields {
m.m[field.Name] = field
}
})
sf, ok := m.m[name]
return sf, ok
}
// UnionFields are mapping between the fields that are part of the union and
// their discriminated value. The discriminated value has to be set, and
// should not conflict with other discriminated value in the list.
type UnionField struct {
// FieldName is the name of the field that is part of the union. This
// is the serialized form of the field.
FieldName string `yaml:"fieldName"`
// Discriminatorvalue is the value of the discriminator to
// select that field. If the union doesn't have a discriminator,
// this field is ignored.
DiscriminatorValue string `yaml:"discriminatorValue"`
}
// Union, or oneof, means that only one of multiple fields of a structure can be
// set at a time. Setting the discriminator helps clearing oher fields:
// - If discriminator changed to non-nil, and a new field has been added
// that doesn't match, an error is returned,
// - If discriminator hasn't changed and two fields or more are set, an
// error is returned,
// - If discriminator changed to non-nil, all other fields but the
// discriminated one will be cleared,
// - Otherwise, If only one field is left, update discriminator to that value.
type Union struct {
// Discriminator, if present, is the name of the field that
// discriminates fields in the union. The mapping between the value of
// the discriminator and the field is done by using the Fields list
// below.
Discriminator *string `yaml:"discriminator,omitempty"`
// DeduceInvalidDiscriminator indicates if the discriminator
// should be updated automatically based on the fields set. This
// typically defaults to false since we don't want to deduce by
// default (the behavior exists to maintain compatibility on
// existing types and shouldn't be used for new types).
DeduceInvalidDiscriminator bool `yaml:"deduceInvalidDiscriminator,omitempty"`
// This is the list of fields that belong to this union. All the
// fields present in here have to be part of the parent
// structure. Discriminator (if oneOf has one), is NOT included in
// this list. The value for field is how we map the name of the field
// to actual value for discriminator.
Fields []UnionField `yaml:"fields,omitempty"`
}
// StructField pairs a field name with a field type.
@ -129,15 +213,14 @@ type List struct {
// * `atomic`: the list is treated as a single entity, like a scalar.
// * `associative`:
// - If the list element is a scalar, the list is treated as a set.
// - If the list element is a struct, the list is treated as a map.
// - The list element must not be a map or a list itself.
// - If the list element is a map, the list is treated as a map.
// There is no default for this value for lists; all schemas must
// explicitly state the element relationship for all lists.
ElementRelationship ElementRelationship `yaml:"elementRelationship,omitempty"`
// Iff ElementRelationship is `associative`, and the element type is
// struct, then Keys must have non-zero length, and it lists the fields
// of the element's struct type which are to be used as the keys of the
// map, then Keys must have non-zero length, and it lists the fields
// of the element's map type which are to be used as the keys of the
// list.
//
// TODO: change this to "non-atomic struct" above and make the code reflect this.
@ -146,60 +229,17 @@ type List struct {
Keys []string `yaml:"keys,omitempty"`
}
// Map is a key-value pair. Its default semantics are the same as an
// associative list, but:
// * It is serialized differently:
// map: {"k": {"value": "v"}}
// list: [{"key": "k", "value": "v"}]
// * Keys must be string typed.
// * Keys can't have multiple components.
//
// Although serialized the same, maps are different from structs in that each
// map item must have the same type.
//
// Optionally, maps may be atomic (for example, imagine representing an RGB
// color value--it doesn't make sense to have different actors own the R and G
// values).
type Map struct {
// ElementType is the type of the list's elements.
ElementType TypeRef `yaml:"elementType,omitempty"`
// ElementRelationship states the relationship between the map's items.
// * `separable` implies that each element is 100% independent.
// * `atomic` implies that all elements depend on each other, and this
// is effectively a scalar / leaf field; it doesn't make sense for
// separate actors to set the elements.
// TODO: find a simple example.
// The default behavior for maps is `separable`; it's permitted to
// leave this unset to get the default behavior.
ElementRelationship ElementRelationship `yaml:"elementRelationship,omitempty"`
}
// Untyped represents types that allow arbitrary content. (Think: plugin
// objects.)
type Untyped struct {
// ElementRelationship states the relationship between the items, if
// container-typed data happens to be present here.
// * `atomic` implies that all elements depend on each other, and this
// is effectively a scalar / leaf field; it doesn't make sense for
// separate actors to set the elements.
// TODO: support "guess" (guesses at associative list keys)
// TODO: support "lookup" (calls a lookup function to figure out the
// schema based on the data)
// The default behavior for untyped data is `atomic`; it's permitted to
// leave this unset to get the default behavior.
ElementRelationship ElementRelationship `yaml:"elementRelationship,omitempty"`
}
// FindNamedType is a convenience function that returns the referenced TypeDef,
// if it exists, or (nil, false) if it doesn't.
func (s Schema) FindNamedType(name string) (TypeDef, bool) {
for _, t := range s.Types {
if t.Name == name {
return t, true
func (s *Schema) FindNamedType(name string) (TypeDef, bool) {
s.once.Do(func() {
s.m = make(map[string]TypeDef, len(s.Types))
for _, t := range s.Types {
s.m[t.Name] = t
}
}
return TypeDef{}, false
})
t, ok := s.m[name]
return t, ok
}
// Resolve is a convenience function which returns the atom referenced, whether

View file

@ -0,0 +1,166 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package schema
// Equals returns true iff the two Schemas are equal.
func (a Schema) Equals(b Schema) bool {
if len(a.Types) != len(b.Types) {
return false
}
for i := range a.Types {
if !a.Types[i].Equals(b.Types[i]) {
return false
}
}
return true
}
// Equals returns true iff the two TypeRefs are equal.
//
// Note that two typerefs that have an equivalent type but where one is
// inlined and the other is named, are not considered equal.
func (a TypeRef) Equals(b TypeRef) bool {
if (a.NamedType == nil) != (b.NamedType == nil) {
return false
}
if a.NamedType != nil {
if *a.NamedType != *b.NamedType {
return false
}
//return true
}
return a.Inlined.Equals(b.Inlined)
}
// Equals returns true iff the two TypeDefs are equal.
func (a TypeDef) Equals(b TypeDef) bool {
if a.Name != b.Name {
return false
}
return a.Atom.Equals(b.Atom)
}
// Equals returns true iff the two Atoms are equal.
func (a Atom) Equals(b Atom) bool {
if (a.Scalar == nil) != (b.Scalar == nil) {
return false
}
if (a.List == nil) != (b.List == nil) {
return false
}
if (a.Map == nil) != (b.Map == nil) {
return false
}
switch {
case a.Scalar != nil:
return *a.Scalar == *b.Scalar
case a.List != nil:
return a.List.Equals(*b.List)
case a.Map != nil:
return a.Map.Equals(*b.Map)
}
return true
}
// Equals returns true iff the two Maps are equal.
func (a Map) Equals(b Map) bool {
if !a.ElementType.Equals(b.ElementType) {
return false
}
if a.ElementRelationship != b.ElementRelationship {
return false
}
if len(a.Fields) != len(b.Fields) {
return false
}
for i := range a.Fields {
if !a.Fields[i].Equals(b.Fields[i]) {
return false
}
}
if len(a.Unions) != len(b.Unions) {
return false
}
for i := range a.Unions {
if !a.Unions[i].Equals(b.Unions[i]) {
return false
}
}
return true
}
// Equals returns true iff the two Unions are equal.
func (a Union) Equals(b Union) bool {
if (a.Discriminator == nil) != (b.Discriminator == nil) {
return false
}
if a.Discriminator != nil {
if *a.Discriminator != *b.Discriminator {
return false
}
}
if a.DeduceInvalidDiscriminator != b.DeduceInvalidDiscriminator {
return false
}
if len(a.Fields) != len(b.Fields) {
return false
}
for i := range a.Fields {
if !a.Fields[i].Equals(b.Fields[i]) {
return false
}
}
return true
}
// Equals returns true iff the two UnionFields are equal.
func (a UnionField) Equals(b UnionField) bool {
if a.FieldName != b.FieldName {
return false
}
if a.DiscriminatorValue != b.DiscriminatorValue {
return false
}
return true
}
// Equals returns true iff the two StructFields are equal.
func (a StructField) Equals(b StructField) bool {
if a.Name != b.Name {
return false
}
return a.Type.Equals(b.Type)
}
// Equals returns true iff the two Lists are equal.
func (a List) Equals(b List) bool {
if !a.ElementType.Equals(b.ElementType) {
return false
}
if a.ElementRelationship != b.ElementRelationship {
return false
}
if len(a.Keys) != len(b.Keys) {
return false
}
for i := range a.Keys {
if a.Keys[i] != b.Keys[i] {
return false
}
}
return true
}

View file

@ -1,57 +0,0 @@
/*
Copyright 2019 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package schema
import (
"sigs.k8s.io/structured-merge-diff/value"
)
// TypeRefFromValue creates an inlined type from a value v
func TypeRefFromValue(v value.Value) TypeRef {
atom := atomFor(v)
return TypeRef{
Inlined: atom,
}
}
func atomFor(v value.Value) Atom {
switch {
// Untyped cases (handled at the bottom of this function)
case v.Null:
case v.ListValue != nil:
case v.FloatValue != nil:
case v.IntValue != nil:
case v.StringValue != nil:
case v.BooleanValue != nil:
// Recursive case
case v.MapValue != nil:
s := Struct{}
for i := range v.MapValue.Items {
child := v.MapValue.Items[i]
field := StructField{
Name: child.Name,
Type: TypeRef{
Inlined: atomFor(child.Value),
},
}
s.Fields = append(s.Fields, field)
}
return Atom{Struct: &s}
}
return Atom{Untyped: &Untyped{}}
}

View file

@ -20,7 +20,7 @@ package schema
// It will validate itself. It can be unmarshalled into a Schema type.
var SchemaSchemaYAML = `types:
- name: schema
struct:
map:
fields:
- name: types
type:
@ -31,7 +31,7 @@ var SchemaSchemaYAML = `types:
keys:
- name
- name: typeDef
struct:
map:
fields:
- name: name
type:
@ -39,20 +39,17 @@ var SchemaSchemaYAML = `types:
- name: scalar
type:
scalar: string
- name: struct
type:
namedType: struct
- name: list
type:
namedType: list
- name: map
type:
namedType: map
- name: list
type:
namedType: list
- name: untyped
type:
namedType: untyped
- name: typeRef
struct:
map:
fields:
- name: namedType
type:
@ -60,22 +57,19 @@ var SchemaSchemaYAML = `types:
- name: scalar
type:
scalar: string
- name: struct
type:
namedType: struct
- name: list
type:
namedType: list
- name: map
type:
namedType: map
- name: list
type:
namedType: list
- name: untyped
type:
namedType: untyped
- name: scalar
scalar: string
- name: struct
struct:
- name: map
map:
fields:
- name: fields
type:
@ -84,11 +78,46 @@ var SchemaSchemaYAML = `types:
namedType: structField
elementRelationship: associative
keys: [ "name" ]
- name: unions
type:
list:
elementType:
namedType: union
elementRelationship: atomic
- name: elementType
type:
namedType: typeRef
- name: elementRelationship
type:
scalar: string
- name: unionField
map:
fields:
- name: fieldName
type:
scalar: string
- name: discriminatorValue
type:
scalar: string
- name: union
map:
fields:
- name: discriminator
type:
scalar: string
- name: deduceInvalidDiscriminator
type:
scalar: bool
- name: fields
type:
list:
elementRelationship: associative
elementType:
namedType: unionField
keys:
- fieldName
- name: structField
struct:
map:
fields:
- name: name
type:
@ -97,7 +126,7 @@ var SchemaSchemaYAML = `types:
type:
namedType: typeRef
- name: list
struct:
map:
fields:
- name: elementType
type:
@ -110,17 +139,8 @@ var SchemaSchemaYAML = `types:
list:
elementType:
scalar: string
- name: map
struct:
fields:
- name: elementType
type:
namedType: typeRef
- name: elementRelationship
type:
scalar: string
- name: untyped
struct:
map:
fields:
- name: elementRelationship
type: