mirror of
https://github.com/kubernetes-sigs/kustomize.git
synced 2026-06-12 01:14:22 +00:00
Use OpenAPI when merging (3way) resources
- When merging (3way) resources use the patch strategy from the openAPI if the definition exists for the field - Allow disabling of guessing patch strategy merge keys when no definition exists - Support defining strategy and key directly on configuration fields through line and header coments - Support attaching schema to parent fields of lists, and propagating -- e.g. that a field is a PodTemplate
This commit is contained in:
@@ -8,20 +8,30 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"sigs.k8s.io/kustomize/kyaml/fieldmeta"
|
||||
"sigs.k8s.io/kustomize/kyaml/openapi"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml"
|
||||
"sigs.k8s.io/kustomize/kyaml/yaml/schema"
|
||||
)
|
||||
|
||||
// Filter walks the Source RNode and modifies the RNode provided to GrepFilter.
|
||||
// Walker walks the Source RNode and modifies the RNode provided to GrepFilter.
|
||||
type Walker struct {
|
||||
// Visitor is invoked by GrepFilter
|
||||
Visitor
|
||||
|
||||
Schema *openapi.ResourceSchema
|
||||
|
||||
// Source is the RNode to walk. All Source fields and associative list elements
|
||||
// will be visited.
|
||||
Sources Sources
|
||||
|
||||
// Path is the field path to the current Source Node.
|
||||
Path []string
|
||||
|
||||
// InferAssociativeLists if set to true will infer merge strategies for
|
||||
// fields which it doesn't have the schema based on the fields in the
|
||||
// list elements.
|
||||
InferAssociativeLists bool
|
||||
}
|
||||
|
||||
func (l Walker) Kind() yaml.Kind {
|
||||
@@ -35,6 +45,8 @@ func (l Walker) Kind() yaml.Kind {
|
||||
|
||||
// GrepFilter implements yaml.GrepFilter
|
||||
func (l Walker) Walk() (*yaml.RNode, error) {
|
||||
l.Schema = l.GetSchema()
|
||||
|
||||
// invoke the handler for the corresponding node type
|
||||
switch l.Kind() {
|
||||
case yaml.MappingNode:
|
||||
@@ -46,7 +58,7 @@ func (l Walker) Walk() (*yaml.RNode, error) {
|
||||
if err := yaml.ErrorIfAnyInvalidAndNonNull(yaml.SequenceNode, l.Sources...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if yaml.IsAssociative(l.Sources) {
|
||||
if schema.IsAssociative(l.Schema, l.Sources, l.InferAssociativeLists) {
|
||||
return l.walkAssociativeSequence()
|
||||
}
|
||||
return l.walkNonAssociativeSequence()
|
||||
@@ -64,6 +76,49 @@ func (l Walker) Walk() (*yaml.RNode, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func (l Walker) GetSchema() *openapi.ResourceSchema {
|
||||
for i := range l.Sources {
|
||||
r := l.Sources[i]
|
||||
if yaml.IsEmpty(r) {
|
||||
continue
|
||||
}
|
||||
|
||||
fm := fieldmeta.FieldMeta{}
|
||||
if err := fm.Read(r); err == nil && !fm.IsEmpty() {
|
||||
// per-field schema, this is fine
|
||||
if fm.Schema.Ref.String() != "" {
|
||||
// resolve the reference
|
||||
s, err := openapi.Resolve(&fm.Schema.Ref)
|
||||
if err == nil && s != nil {
|
||||
fm.Schema = *s
|
||||
}
|
||||
}
|
||||
return &openapi.ResourceSchema{Schema: &fm.Schema}
|
||||
}
|
||||
}
|
||||
|
||||
if l.Schema != nil {
|
||||
return l.Schema
|
||||
}
|
||||
for i := range l.Sources {
|
||||
r := l.Sources[i]
|
||||
if yaml.IsEmpty(r) {
|
||||
continue
|
||||
}
|
||||
|
||||
m, _ := r.GetMeta()
|
||||
if m.Kind == "" || m.APIVersion == "" {
|
||||
continue
|
||||
}
|
||||
|
||||
s := openapi.SchemaForResourceType(yaml.TypeMeta{Kind: m.Kind, APIVersion: m.APIVersion})
|
||||
if s != nil {
|
||||
return s
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
DestIndex = iota
|
||||
OriginIndex
|
||||
|
||||
Reference in New Issue
Block a user