github.com/rancher/types@v0.0.0-20220328215343-4370ff10ecd5/mapper/namespace_reference.go (about)

     1  package mapper
     2  
     3  import (
     4  	"strings"
     5  
     6  	"fmt"
     7  
     8  	"github.com/rancher/norman/types"
     9  	"github.com/rancher/norman/types/convert"
    10  	"github.com/rancher/norman/types/definition"
    11  )
    12  
    13  type NamespaceReference struct {
    14  	fields      [][]string
    15  	VersionPath string
    16  }
    17  
    18  func (n *NamespaceReference) FromInternal(data map[string]interface{}) {
    19  	namespaceID, ok := data["namespaceId"]
    20  	if ok {
    21  		for _, path := range n.fields {
    22  			convert.Transform(data, path, func(input interface{}) interface{} {
    23  				parts := strings.SplitN(convert.ToString(input), ":", 2)
    24  				if len(parts) == 2 {
    25  					return input
    26  				}
    27  				return fmt.Sprintf("%s:%v", namespaceID, input)
    28  			})
    29  		}
    30  	}
    31  }
    32  
    33  func (n *NamespaceReference) ToInternal(data map[string]interface{}) error {
    34  	namespaceID, ok := data["namespaceId"]
    35  	for _, path := range n.fields {
    36  		convert.Transform(data, path, func(input interface{}) interface{} {
    37  			parts := strings.SplitN(convert.ToString(input), ":", 2)
    38  			if len(parts) == 2 && (!ok || parts[0] == namespaceID) {
    39  				return parts[1]
    40  			}
    41  			return input
    42  		})
    43  	}
    44  
    45  	return nil
    46  }
    47  
    48  func (n *NamespaceReference) ModifySchema(schema *types.Schema, schemas *types.Schemas) error {
    49  	_, hasNamespace := schema.ResourceFields["namespaceId"]
    50  	if schema.Version.Path != n.VersionPath || !hasNamespace {
    51  		return nil
    52  	}
    53  	n.fields = traverse(nil, schema, schemas)
    54  	return nil
    55  }
    56  
    57  func traverse(prefix []string, schema *types.Schema, schemas *types.Schemas) [][]string {
    58  	var result [][]string
    59  
    60  	for name, field := range schema.ResourceFields {
    61  		localPrefix := []string{name}
    62  		subType := field.Type
    63  		if definition.IsArrayType(field.Type) {
    64  			localPrefix = append(localPrefix, "{ARRAY}")
    65  			subType = definition.SubType(field.Type)
    66  		} else if definition.IsMapType(field.Type) {
    67  			localPrefix = append(localPrefix, "{MAP}")
    68  			subType = definition.SubType(field.Type)
    69  		}
    70  		if definition.IsReferenceType(subType) {
    71  			result = appendReference(result, prefix, localPrefix, field, schema, schemas)
    72  			continue
    73  		}
    74  
    75  		subSchema := schemas.Schema(&schema.Version, subType)
    76  		if subSchema != nil {
    77  			result = append(result, traverse(append(prefix, localPrefix...), subSchema, schemas)...)
    78  		}
    79  	}
    80  
    81  	return result
    82  }
    83  
    84  func appendReference(result [][]string, prefix []string, name []string, field types.Field, schema *types.Schema, schemas *types.Schemas) [][]string {
    85  	targetSchema := schemas.Schema(&schema.Version, definition.SubType(field.Type))
    86  	if targetSchema != nil && targetSchema.Scope == types.NamespaceScope {
    87  		result = append(result, append(prefix, name...))
    88  	}
    89  	return result
    90  }