github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/nomad/structs/extensions.go (about) 1 package structs 2 3 import ( 4 "reflect" 5 ) 6 7 var ( 8 // extendedTypes is a mapping of extended types to their extension function 9 // TODO: the duplicates could be simplified by looking up the base type in the case of a pointer type in ConvertExt 10 extendedTypes = map[reflect.Type]extendFunc{ 11 reflect.TypeOf(Node{}): nodeExt, 12 reflect.TypeOf(&Node{}): nodeExt, 13 reflect.TypeOf(CSIVolume{}): csiVolumeExt, 14 reflect.TypeOf(&CSIVolume{}): csiVolumeExt, 15 } 16 ) 17 18 // nodeExt ensures the node is sanitized and adds the legacy field .Drain back to encoded Node objects 19 func nodeExt(v interface{}) interface{} { 20 node := v.(*Node).Sanitize() 21 // transform to a struct with inlined Node fields plus the Drain field 22 // - using defined type (not an alias!) EmbeddedNode gives us free conversion to a distinct type 23 // - distinct type prevents this encoding extension from being called recursively/infinitely on the embedding 24 // - pointers mean the conversion function doesn't have to make a copy during conversion 25 type EmbeddedNode Node 26 return &struct { 27 *EmbeddedNode 28 Drain bool 29 }{ 30 EmbeddedNode: (*EmbeddedNode)(node), 31 Drain: node != nil && node.DrainStrategy != nil, 32 } 33 } 34 35 func csiVolumeExt(v interface{}) interface{} { 36 vol := v.(*CSIVolume) 37 type EmbeddedCSIVolume CSIVolume 38 39 allocCount := len(vol.ReadAllocs) + len(vol.WriteAllocs) 40 41 apiVol := &struct { 42 *EmbeddedCSIVolume 43 Allocations []*AllocListStub 44 }{ 45 EmbeddedCSIVolume: (*EmbeddedCSIVolume)(vol), 46 Allocations: make([]*AllocListStub, 0, allocCount), 47 } 48 49 // WriteAllocs and ReadAllocs will only ever contain the Allocation ID, 50 // with a null value for the Allocation; these IDs are mapped to 51 // allocation stubs in the Allocations field. This indirection is so the 52 // API can support both the UI and CLI consumer in a safely backwards 53 // compatible way 54 for _, a := range vol.ReadAllocs { 55 if a != nil { 56 apiVol.ReadAllocs[a.ID] = nil 57 apiVol.Allocations = append(apiVol.Allocations, a.Stub(nil)) 58 } 59 } 60 for _, a := range vol.WriteAllocs { 61 if a != nil { 62 apiVol.WriteAllocs[a.ID] = nil 63 apiVol.Allocations = append(apiVol.Allocations, a.Stub(nil)) 64 } 65 } 66 67 // MountFlags can contain secrets, so we always redact it but want 68 // to show the user that we have the value 69 if vol.MountOptions != nil && len(vol.MountOptions.MountFlags) > 0 { 70 apiVol.MountOptions.MountFlags = []string{"[REDACTED]"} 71 } 72 73 // would be better not to have at all but left in and redacted for 74 // backwards compatibility with the existing API 75 apiVol.Secrets = nil 76 77 return apiVol 78 }