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