github.com/nycdavid/zeus@v0.0.0-20201208104106-9ba439429e03/go/config/config.go (about) 1 package config 2 3 import ( 4 "bufio" 5 "encoding/json" 6 "io/ioutil" 7 "os" 8 "path" 9 10 "github.com/burke/zeus/go/filemonitor" 11 "github.com/burke/zeus/go/processtree" 12 "github.com/burke/zeus/go/zerror" 13 ) 14 15 type config struct { 16 Command string 17 Plan interface{} 18 Items map[string]string 19 } 20 21 func BuildProcessTree(configFile string, monitor filemonitor.FileMonitor) *processtree.ProcessTree { 22 conf := parseConfig(configFile) 23 tree := &processtree.ProcessTree{} 24 tree.SlavesByName = make(map[string]*processtree.SlaveNode) 25 tree.StateChanged = make(chan bool, 16) 26 27 tree.ExecCommand = conf.Command 28 29 plan, ok := conf.Plan.(map[string]interface{}) 30 if !ok { 31 zerror.ErrorConfigFileInvalidFormat() 32 } 33 iteratePlan(tree, plan, monitor, nil) 34 35 return tree 36 } 37 38 func iteratePlan( 39 tree *processtree.ProcessTree, 40 plan map[string]interface{}, 41 monitor filemonitor.FileMonitor, 42 parent *processtree.SlaveNode, 43 ) { 44 for name, v := range plan { 45 if subPlan, ok := v.(map[string]interface{}); ok { 46 newNode := tree.NewSlaveNode(name, parent, monitor) 47 if parent == nil { 48 tree.Root = newNode 49 } else { 50 parent.Slaves = append(parent.Slaves, newNode) 51 } 52 iteratePlan(tree, subPlan, monitor, newNode) 53 } else { 54 var newNode *processtree.CommandNode 55 if aliases, ok := v.([]interface{}); ok { 56 strs := make([]string, len(aliases)) 57 for i, alias := range aliases { 58 strs[i] = alias.(string) 59 } 60 newNode = tree.NewCommandNode(name, strs, parent) 61 } else if v == nil { 62 newNode = tree.NewCommandNode(name, nil, parent) 63 } else { 64 zerror.ErrorConfigFileInvalidFormat() 65 } 66 parent.Commands = append(parent.Commands, newNode) 67 } 68 } 69 } 70 71 func defaultConfigPath() string { 72 binaryPath := os.Args[0] 73 gemDir := path.Dir(path.Dir(binaryPath)) 74 jsonpath := path.Join(gemDir, "examples/zeus.json") 75 return jsonpath 76 } 77 78 func readConfigFileOrDefault(configFile string) ([]byte, error) { 79 contents, err := readFile(configFile) 80 if err != nil { 81 switch err.(type) { 82 case *os.PathError: 83 return readFile(defaultConfigPath()) 84 default: 85 return contents, err 86 } 87 } 88 return contents, err 89 } 90 91 func parseConfig(configFile string) (c config) { 92 var conf config 93 94 contents, err := readConfigFileOrDefault(configFile) 95 if err != nil { 96 zerror.ErrorConfigFileInvalidJson() 97 } 98 99 json.Unmarshal(contents, &conf) 100 return conf 101 } 102 103 func readFile(path string) (contents []byte, err error) { 104 file, err := os.Open(path) 105 if err != nil { 106 return nil, err 107 } 108 reader := bufio.NewReader(file) 109 110 contents, err = ioutil.ReadAll(reader) 111 return 112 }