github.com/Cloud-Foundations/Dominator@v0.3.4/lib/filegen/mdbFieldDirectory.go (about) 1 package filegen 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "os" 7 "path/filepath" 8 "reflect" 9 "strings" 10 "time" 11 12 "github.com/Cloud-Foundations/Dominator/lib/log" 13 "github.com/Cloud-Foundations/Dominator/lib/mdb" 14 ) 15 16 var ( 17 machineType = reflect.TypeOf(mdb.Machine{}) 18 ) 19 20 type mdbFieldDirectoryType struct { 21 directory string 22 index []int 23 tagKey string 24 } 25 26 func makeGenerator(field string) (*mdbFieldDirectoryType, error) { 27 if fParts := strings.Split(field, "."); len(fParts) == 2 { 28 if fParts[0] == "Tags" { 29 return &mdbFieldDirectoryType{tagKey: fParts[1]}, nil 30 } 31 } 32 structField, found := machineType.FieldByName(field) 33 if !found { 34 return nil, fmt.Errorf( 35 "field: \"%s\" not found in mdb.Machine type", field) 36 } 37 if structField.Type.Kind() != reflect.String { 38 return nil, fmt.Errorf( 39 "field: \"%s\" is not string type", field) 40 } 41 return &mdbFieldDirectoryType{index: structField.Index}, nil 42 } 43 44 func sendNotifications(notifierChannel chan<- string, 45 interval time.Duration) { 46 for ; ; time.Sleep(interval) { 47 notifierChannel <- "" 48 } 49 } 50 51 func (m *Manager) registerMdbFieldDirectoryForPath(pathname string, 52 field, directory string, interval time.Duration) error { 53 generator, err := makeGenerator(field) 54 if err != nil { 55 return err 56 } 57 generator.directory = directory 58 notifierChannel := m.RegisterGeneratorForPath(pathname, 59 generator) 60 if interval <= 0 { 61 close(notifierChannel) 62 return nil 63 } 64 go sendNotifications(notifierChannel, interval) 65 return nil 66 } 67 68 func (g *mdbFieldDirectoryType) Generate(machine mdb.Machine, 69 logger log.Logger) ([]byte, time.Time, error) { 70 var fieldValue string 71 if g.tagKey != "" { 72 fieldValue = machine.Tags[g.tagKey] 73 } else { 74 fieldValue = reflect.ValueOf(machine).FieldByIndex( 75 g.index).String() 76 } 77 if fieldValue == "" { 78 fieldValue = "*" 79 } 80 pathname := filepath.Join(g.directory, 81 filepath.Clean(fieldValue)) 82 if data, err := ioutil.ReadFile(pathname); err != nil { 83 if os.IsNotExist(err) && fieldValue != "*" { 84 data, err := ioutil.ReadFile(filepath.Join(g.directory, 85 "*")) 86 if err == nil { 87 return data, time.Time{}, nil 88 } 89 } 90 return nil, time.Time{}, err 91 } else { 92 return data, time.Time{}, nil 93 } 94 }