in pkg/cloud/api/copy.go [271:318]
func (c *copier) doMetaFields(p Path, destField, srcField, destStruct, srcStruct reflect.Value) error {
if !isSliceOfStringV(destField) || !isSliceOfStringV(srcField) {
return fmt.Errorf("copyMetaFields: invalid type (destField: %T, srcField: %T)", destField.Interface(), srcField.Interface())
}
destMetaFields := destField.Interface().([]string)
// MetaFields already present in the destination list.
exists := map[string]bool{}
for _, v := range destMetaFields {
exists[v] = true
}
c.logS("copyMetaFields dest", "path", p, "destFields", exists)
for _, fn := range srcField.Interface().([]string) {
if _, ok := srcStruct.Type().FieldByName(fn); !ok {
return fmt.Errorf("copyMetaFields: %s refers to field %q that doesn't exist (type %T)", p, fn, srcStruct.Interface())
}
_, destHasField := destStruct.Type().FieldByName(fn)
// We only need to add to destMetaFields if it exists
// in the dest struct and hasn't already been added to
// the list.
if destHasField && !exists[fn] {
destMetaFields = append(destMetaFields, fn)
c.logS("copyMetaFields add", "path", p, "fieldName", fn)
} else if !destHasField {
// Record that the metafield referenced a
// field that didn't exist on the dest
// version.
c.missing = append(c.missing, missingFieldOnCopy{
Path: p.Field(fn),
Value: srcField.Interface(),
})
c.logS("copyMetaFields missing field", "path", p, "fieldName", fn)
}
}
if !destField.CanSet() {
return fmt.Errorf("cannot set destField (%s)", p)
}
sort.Strings(destMetaFields)
destField.Set(reflect.ValueOf(destMetaFields))
return nil
}