Skip to content

Commit

Permalink
feat: parse expressions in x-kubernetes-preserve-unknown fields
Browse files Browse the repository at this point in the history
Previously, fields marked with `x-kubernetes-preserve-unknown-fields` were skipped
during parsing. Now these fields are parsed to extract expressions, allowing for
variable substitution in schemaless fields while still preserving unknown fields
as specified by the k8s-open-api extension.
  • Loading branch information
a-hilaly committed Dec 23, 2024
1 parent 335ad25 commit 929a161
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 1 deletion.
6 changes: 5 additions & 1 deletion pkg/graph/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ func parseObject(field map[string]interface{}, schema *spec.Schema, path, expect
// If the schema has the x-kubernetes-preserve-unknown-fields extension, we should not
// parse the object and return an empty list of expressions.
if enabled, ok := schema.VendorExtensible.Extensions[xKubernetesPreserveUnknownFields]; ok && enabled.(bool) {
return nil, nil
expressions, err := parseSchemalessResource(field, path)
if err != nil {
return nil, err
}
return expressions, nil
}
}

Expand Down
45 changes: 45 additions & 0 deletions pkg/graph/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ func TestParseResource(t *testing.T) {
"${value}",
},
},
"schemalessField": map[string]interface{}{
"key": "value",
"something": "${schemaless.value}",
"nestedSomething": map[string]interface{}{
"key": "value",
"nested": "${schemaless.nested.value}",
},
},
}

schema := &spec.Schema{
Expand Down Expand Up @@ -107,6 +115,16 @@ func TestParseResource(t *testing.T) {
},
},
},
"schemalessField": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
},
VendorExtensible: spec.VendorExtensible{
Extensions: spec.Extensions{
"x-kubernetes-preserve-unknown-fields": true,
},
},
},
},
},
}
Expand All @@ -125,6 +143,8 @@ func TestParseResource(t *testing.T) {
{Path: "specialCharacters[\"doted.annotation.key\"]", Expressions: []string{"dotedannotationvalue"}, ExpectedType: "string", StandaloneExpression: true},
{Path: "specialCharacters[\"\"]", Expressions: []string{"emptyannotation"}, ExpectedType: "string", StandaloneExpression: true},
{Path: "specialCharacters[\"array.name.with.dots\"][0]", Expressions: []string{"value"}, ExpectedType: "string", StandaloneExpression: true},
{Path: "schemalessField.something", Expressions: []string{"schemaless.value"}, ExpectedType: "string", StandaloneExpression: true},
{Path: "schemalessField.nestedSomething.nested", Expressions: []string{"schemaless.nested.value"}, ExpectedType: "string", StandaloneExpression: true},
}

expressions, err := ParseResource(resource, schema)
Expand Down Expand Up @@ -618,6 +638,31 @@ func TestParserEdgeCases(t *testing.T) {
resource: map[string]interface{}{"name": "John", "age": 30},
expectedError: "",
},
{
name: "structured object with nested x-kubernetes-preserve-unknown-fields",
schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
Properties: map[string]spec.Schema{
"id": {SchemaProps: spec.SchemaProps{Type: []string{"string"}}},
"metadata": {
SchemaProps: spec.SchemaProps{
Type: []string{"object"},
},
VendorExtensible: spec.VendorExtensible{
Extensions: spec.Extensions{
"x-kubernetes-preserve-unknown-fields": true,
},
},
},
},
},
},
resource: map[string]interface{}{"id": "123", "metadata": map[string]interface{}{
"name": "John", "age": 30, "test": "${test.value}",
}},
expectedError: "",
},
}

for _, tc := range testCases {
Expand Down

0 comments on commit 929a161

Please sign in to comment.