diff --git a/docs/content/en/docs/references/yaml/main.js b/docs/content/en/docs/references/yaml/main.js index 6f850275472..fc9e106659e 100644 --- a/docs/content/en/docs/references/yaml/main.js +++ b/docs/content/en/docs/references/yaml/main.js @@ -193,9 +193,14 @@ function* template(definitions, parentDefinition, ref, ident, parent) { // This definition is an array if (definition.items && definition.items.$ref) { - yield html` - ${template(definitions, definition, definition.items.$ref, ident + 1, path)} - `; + // don't infinitely recurse into nested tagger components + if (definition.items.$ref === "#/definitions/TaggerComponent") { + yield html ``; + } else { + yield html` + ${template(definitions, definition, definition.items.$ref, ident + 1, path)} + `; + } } } } diff --git a/docs/content/en/schemas/v2beta6.json b/docs/content/en/schemas/v2beta6.json index 74046c58b32..32438e34588 100755 --- a/docs/content/en/schemas/v2beta6.json +++ b/docs/content/en/schemas/v2beta6.json @@ -2117,6 +2117,45 @@ "description": "specifies which local files to sync to remote folders.", "x-intellij-html-description": "specifies which local files to sync to remote folders." }, + "TagPolicy": { + "properties": { + "customTemplate": { + "$ref": "#/definitions/CustomTemplateTagger", + "description": "*beta* tags images with a configurable template string *composed of other taggers*.", + "x-intellij-html-description": "beta tags images with a configurable template string composed of other taggers." + }, + "dateTime": { + "$ref": "#/definitions/DateTimeTagger", + "description": "*beta* tags images with the build timestamp.", + "x-intellij-html-description": "beta tags images with the build timestamp." + }, + "envTemplate": { + "$ref": "#/definitions/EnvTemplateTagger", + "description": "*beta* tags images with a configurable template string.", + "x-intellij-html-description": "beta tags images with a configurable template string." + }, + "gitCommit": { + "$ref": "#/definitions/GitTagger", + "description": "*beta* tags images with the git tag or commit of the artifact's workspace.", + "x-intellij-html-description": "beta tags images with the git tag or commit of the artifact's workspace." + }, + "sha256": { + "$ref": "#/definitions/ShaTagger", + "description": "*beta* tags images with their sha256 digest.", + "x-intellij-html-description": "beta tags images with their sha256 digest." + } + }, + "preferredOrder": [ + "gitCommit", + "sha256", + "envTemplate", + "dateTime", + "customTemplate" + ], + "additionalProperties": false, + "description": "contains all the configuration for the tagging step.", + "x-intellij-html-description": "contains all the configuration for the tagging step." + }, "TaggerComponent": { "anyOf": [ { diff --git a/hack/schemas/main.go b/hack/schemas/main.go index ecefc3a9948..3e02cb64a86 100644 --- a/hack/schemas/main.go +++ b/hack/schemas/main.go @@ -77,8 +77,9 @@ type Definition struct { Examples []string `json:"examples,omitempty"` Enum []string `json:"enum,omitempty"` - inlines []*Definition - tags string + inlines []*Definition + tags string + skipTrim bool } func main() { @@ -238,7 +239,8 @@ func (g *schemaGenerator) newDefinition(name string, t ast.Expr, comment string, if strings.Contains(field.Tag.Value, "inline") { def.PreferredOrder = append(def.PreferredOrder, "") def.inlines = append(def.inlines, &Definition{ - Ref: defPrefix + field.Type.(*ast.Ident).Name, + Ref: defPrefix + field.Type.(*ast.Ident).Name, + skipTrim: strings.Contains(field.Tag.Value, "skipTrim"), }) continue } @@ -354,6 +356,9 @@ func (g *schemaGenerator) Apply(inputPath string) ([]byte, error) { } for _, inlineStruct := range def.inlines { + if inlineStruct.skipTrim { + continue + } ref := strings.TrimPrefix(inlineStruct.Ref, defPrefix) inlines = append(inlines, ref) } @@ -435,7 +440,13 @@ func (g *schemaGenerator) Apply(inputPath string) ([]byte, error) { } for _, ref := range inlines { - delete(definitions, ref) + existingDef, ok := definitions[ref] + if !ok { + continue + } + if !existingDef.skipTrim { + delete(definitions, ref) + } } schema := Schema{ diff --git a/pkg/skaffold/schema/latest/config.go b/pkg/skaffold/schema/latest/config.go index 9ead532f4dd..d5cc062d6a1 100644 --- a/pkg/skaffold/schema/latest/config.go +++ b/pkg/skaffold/schema/latest/config.go @@ -191,7 +191,7 @@ type TaggerComponent struct { Name string `yaml:"name,omitempty"` // Component is a tagging strategy to be used in CustomTemplateTagger. - Component TagPolicy `yaml:",inline"` + Component TagPolicy `yaml:",inline" yamltags:"skipTrim"` } // BuildType contains the specific implementation and parameters needed diff --git a/pkg/skaffold/yamltags/tags.go b/pkg/skaffold/yamltags/tags.go index b3c4c7cbbaf..35a4869d2b9 100644 --- a/pkg/skaffold/yamltags/tags.go +++ b/pkg/skaffold/yamltags/tags.go @@ -72,6 +72,10 @@ func processTags(yamltags string, val reflect.Value, parentStruct reflect.Value, Field: field, Parent: parentStruct, } + case "skipTrim": + yt = &skipTrimTag{ + Field: field, + } default: logrus.Panicf("unknown yaml tag in %s", yamltags) } @@ -166,6 +170,24 @@ func (oot *oneOfTag) Process(val reflect.Value) error { return nil } +type skipTrimTag struct { + Field reflect.StructField +} + +func (tag *skipTrimTag) Load(s []string) error { + return nil +} + +func (tag *skipTrimTag) Process(val reflect.Value) error { + if isZeroValue(val) { + if tags, ok := tag.Field.Tag.Lookup("yaml"); ok { + return fmt.Errorf("skipTrim value not set: %s", strings.Split(tags, ",")[0]) + } + return fmt.Errorf("skipTrim value not set: %s", tag.Field.Name) + } + return nil +} + func isZeroValue(val reflect.Value) bool { if val.Kind() == reflect.Invalid { return true