Add subresource support to apply extract

This commit is contained in:
Joe Betz 2021-03-19 14:24:50 -07:00
parent 4925cb66c9
commit 59e717d503
2 changed files with 37 additions and 8 deletions

View File

@ -35,7 +35,22 @@ import (
// that no managed fields were found for the fieldManager because other field managers // that no managed fields were found for the fieldManager because other field managers
// have taken ownership of all the fields previously owned by the fieldManager. It is // have taken ownership of all the fields previously owned by the fieldManager. It is
// also possible the fieldManager never owned fields. // also possible the fieldManager never owned fields.
func ExtractInto(object runtime.Object, objectType typed.ParseableType, fieldManager string, applyConfiguration interface{}) error { //
// The provided object MUST bo a root resource object since subresource objects
// do not contain their own managed fields. For example, an autoscaling.Scale
// object read from a "scale" subresource does not have any managed fields and so
// cannot be used as the object.
//
// If the fields of a subresource are a subset of the fields of the root object,
// and their field paths and types are exactly the same, then ExtractInto can be
// called with the root resource as the object and the subresource as the
// applyConfiguration. This works for "status", obviously, because status is
// represented by the exact same object as the root resource. This this does NOT
// work, for example, with the "scale" subresources of Deployment, ReplicaSet and
// StatefulSet. While the spec.replicas, status.replicas fields are in the same
// exact field path locations as they are in autoscaling.Scale, the selector
// fields are in different locations, and are a different type.
func ExtractInto(object runtime.Object, objectType typed.ParseableType, fieldManager string, applyConfiguration interface{}, subresource string) error {
typedObj, err := toTyped(object, objectType) typedObj, err := toTyped(object, objectType)
if err != nil { if err != nil {
return fmt.Errorf("error converting obj to typed: %w", err) return fmt.Errorf("error converting obj to typed: %w", err)
@ -45,7 +60,7 @@ func ExtractInto(object runtime.Object, objectType typed.ParseableType, fieldMan
if err != nil { if err != nil {
return fmt.Errorf("error accessing metadata: %w", err) return fmt.Errorf("error accessing metadata: %w", err)
} }
fieldsEntry, ok := findManagedFields(accessor, fieldManager) fieldsEntry, ok := findManagedFields(accessor, fieldManager, subresource)
if !ok { if !ok {
return nil return nil
} }
@ -66,10 +81,10 @@ func ExtractInto(object runtime.Object, objectType typed.ParseableType, fieldMan
return nil return nil
} }
func findManagedFields(accessor metav1.Object, fieldManager string) (metav1.ManagedFieldsEntry, bool) { func findManagedFields(accessor metav1.Object, fieldManager string, subresource string) (metav1.ManagedFieldsEntry, bool) {
objManagedFields := accessor.GetManagedFields() objManagedFields := accessor.GetManagedFields()
for _, mf := range objManagedFields { for _, mf := range objManagedFields {
if mf.Manager == fieldManager && mf.Operation == metav1.ManagedFieldsOperationApply { if mf.Manager == fieldManager && mf.Operation == metav1.ManagedFieldsOperationApply && mf.Subresource == subresource {
return mf, true return mf, true
} }
} }

View File

@ -102,7 +102,7 @@ func (g *applyConfigurationGenerator) GenerateType(c *generator.Context, t *type
sw.Do(clientgenTypeConstructorNamespaced, typeParams) sw.Do(clientgenTypeConstructorNamespaced, typeParams)
} }
if typeParams.OpenAPIType != nil { if typeParams.OpenAPIType != nil {
g.generateClientgenExtract(sw, typeParams) g.generateClientgenExtract(sw, typeParams, !typeParams.Tags.NoStatus)
} }
} else { } else {
sw.Do(constructor, typeParams) sw.Do(constructor, typeParams)
@ -317,7 +317,7 @@ func $.ApplyConfig.Type|public$() *$.ApplyConfig.ApplyConfiguration|public$ {
} }
` `
func (g *applyConfigurationGenerator) generateClientgenExtract(sw *generator.SnippetWriter, typeParams TypeParams) { func (g *applyConfigurationGenerator) generateClientgenExtract(sw *generator.SnippetWriter, typeParams TypeParams, includeStatus bool) {
sw.Do(` sw.Do(`
// Extract$.ApplyConfig.Type|public$ extracts the applied configuration owned by fieldManager from // Extract$.ApplyConfig.Type|public$ extracts the applied configuration owned by fieldManager from
// $.Struct|private$. If no managedFields are found in $.Struct|private$ for fieldManager, a // $.Struct|private$. If no managedFields are found in $.Struct|private$ for fieldManager, a
@ -330,9 +330,23 @@ func (g *applyConfigurationGenerator) generateClientgenExtract(sw *generator.Sni
// Note that an extracted apply configuration will contain fewer fields than what the fieldManager previously // Note that an extracted apply configuration will contain fewer fields than what the fieldManager previously
// applied if another fieldManager has updated or force applied any of the previously applied fields. // applied if another fieldManager has updated or force applied any of the previously applied fields.
// Experimental! // Experimental!
func Extract$.ApplyConfig.Type|public$($.Struct|private$ *$.Struct|raw$, fieldManager string) (*$.ApplyConfig.ApplyConfiguration|public$ , error) { func Extract$.ApplyConfig.Type|public$($.Struct|private$ *$.Struct|raw$, fieldManager string) (*$.ApplyConfig.ApplyConfiguration|public$, error) {
return extract$.ApplyConfig.Type|public$($.Struct|private$, fieldManager, "")
}`, typeParams)
if includeStatus {
sw.Do(`
// Extract$.ApplyConfig.Type|public$Status is the same as Extract$.ApplyConfig.Type|public$ except
// that it extracts the status subresource applied configuration.
// Experimental!
func Extract$.ApplyConfig.Type|public$Status($.Struct|private$ *$.Struct|raw$, fieldManager string) (*$.ApplyConfig.ApplyConfiguration|public$, error) {
return extract$.ApplyConfig.Type|public$($.Struct|private$, fieldManager, "status")
}
`, typeParams)
}
sw.Do(`
func extract$.ApplyConfig.Type|public$($.Struct|private$ *$.Struct|raw$, fieldManager string, subresource string) (*$.ApplyConfig.ApplyConfiguration|public$, error) {
b := &$.ApplyConfig.ApplyConfiguration|public${} b := &$.ApplyConfig.ApplyConfiguration|public${}
err := $.ExtractInto|raw$($.Struct|private$, $.ParserFunc|raw$().Type("$.OpenAPIType$"), fieldManager, b) err := $.ExtractInto|raw$($.Struct|private$, $.ParserFunc|raw$().Type("$.OpenAPIType$"), fieldManager, b, subresource)
if err != nil { if err != nil {
return nil, err return nil, err
} }