func GetConfigValue(session *ini.Section, key string) (string, error) { if session.HasKey(key) { return session.Key(key).String(), nil } else { return "", fmt.Errorf("Can not find %s configuration", key) } }
// Currently supported: []string, []int (32 bit). // TODO: struct tags for int size, struct tags for separator, more types. func processSliceField(field reflect.Value, section *ini.Section, kvName string) reflect.Value { // Prepare list: stringList := strings.Split(section.Key(kvName).String(), ",") for idx, val := range stringList { stringList[idx] = strings.TrimSpace(val) } // Get contained type: fieldKind := field.Type().Elem().Kind() // Handle each type differently. // Strings are just returned. if fieldKind == reflect.String { return reflect.ValueOf(stringList) // Ints are converted by base 10, length 32 bits. } else if fieldKind == reflect.Int { intList := []int{} for _, str := range stringList { i, err := strconv.ParseInt(str, 10, 32) if err != nil { infoLogger.Fatalln("Error parsing 32 bit integer for field "+ string(kvName), err) } intList = append(intList, int(i)) } return reflect.ValueOf(intList) // Everything else should trigger an error. } else { infoLogger.Fatalln("Do not know what to do with slice of " + string(fieldKind)) } // Failsafe if the error fails: Empty new iface satisfying the type. return reflect.New(field.Type()).Elem() }
func execCommand(log *logging.Logger, section *ini.Section, command string) error { var buff *bufio.Reader var conn net.Conn var cmd common.JSONMessage var res common.JSONResult var err error var result []byte if section.Key(command).String() != "" { conn, err = network.GetSocket(section) if err != nil { return errorMsg(log, 1, "Connection with "+command+" failed: "+err.Error()) } defer conn.Close() buff = bufio.NewReader(conn) cmd = common.JSONMessage{} cmd.Context = "system" cmd.Command.Name = "exec" cmd.Command.Cmd = section.Key(command).String() if err = cmd.Send(conn); err != nil { return errorMsg(log, 2, "Sending "+command+" failed: "+err.Error()) } else { result, err = buff.ReadBytes('\n') if err != nil { log.Error("Receive " + command + " result failed: " + err.Error()) } err = json.Unmarshal(result, &res) if err != nil { msg := "Response result for " + command + " failed: " + err.Error() log.Error(msg) return errorMsg(log, 3, msg) } if res.Result == "ok" { log.Debug("Executed " + command) return nil } else { return errorMsg(log, 4, "Error in "+command+" execution: "+res.Message) } } } else { return nil } }
func GetSocket(cfg *ini.Section) (net.Conn, error) { var conn net.Conn var err error host := cfg.Key("host").String() port := cfg.Key("port").String() address := host + ":" + port if _, err = net.ResolveTCPAddr("tcp", address); err != nil { return nil, err } if cfg.Key("ssl").MustBool() { key := cfg.Key("sslcert").String() private := cfg.Key("sslkey").String() cert, err := tls.LoadX509KeyPair(key, private) if err != nil { err = errors.New("Error when loading SSL certificate: " + err.Error()) return nil, err } caCert, err := ioutil.ReadFile(key) if err != nil { return nil, err } caCertPool := x509.NewCertPool() caCertPool.AppendCertsFromPEM(caCert) config := tls.Config{ RootCAs: caCertPool, Certificates: []tls.Certificate{cert}, } now := time.Now() config.Time = func() time.Time { return now } config.Rand = rand.Reader conn, err = tls.Dial("tcp", address, &config) if err != nil { return nil, err } } else { conn, err = net.Dial("tcp", address) if err != nil { return nil, err } } return conn, err }
// Currently supported: string, int. // TODO: struct tags for int size, more types. func processField(field reflect.Value, section *ini.Section, kvName string) reflect.Value { // Get contained type: fieldKind := field.Kind() // Per type treatment: // Strings are trimmed then assigned directly. if fieldKind == reflect.String { strVal := strings.TrimSpace(section.Key(kvName).String()) return reflect.ValueOf(strVal) // Integers are converted by base 10, length 32 bits. } else if fieldKind == reflect.Int { intVal, err := section.Key(kvName).Int() if err != nil { infoLogger.Fatalf("Unable to parse %s='%s' as int.", kvName, section.Key(kvName).String()) } return reflect.ValueOf(intVal) } else { infoLogger.Fatalln("Do not know what to do with type " + string(fieldKind)) } // Failsafe if the error fails: Empty new iface satisfying the type. return reflect.New(field.Type()).Elem() }
// Receives a list of Container INI configuration files and load them into // "Container" section of primary Config instance. func (cfg *Config) loadIniConfigs(cfgPaths []string) error { var err error var iniCfg *ini.File var section *ini.Section var sectionName string var cfgPath string var serviceCfg *ServiceConfig var containerCfg *ContainerConfig var name string var match bool for _, cfgPath = range cfgPaths { log.Printf("[Config] Loading: '%s'", cfgPath) // avoiding dummy files if match, _ = path.Match("\\.\\#*\\.ini", path.Base(cfgPath)); match { log.Printf("[Config] Ignoring config file: '%s'", cfgPath) continue } if iniCfg, err = ini.Load(cfgPath); err != nil { log.Println("[Config] Config load error:", err) return err } // the section names will determine witch kind of configuratio this is for _, sectionName = range iniCfg.SectionStrings() { section = iniCfg.Section(sectionName) switch sectionName { case "Service": serviceCfg = new(ServiceConfig) if err = section.MapTo(serviceCfg); err != nil { log.Println("[Config] Error on mapTo ServiceConfig:", err) return err } if name, err = sanitizeName(serviceCfg.Name); err != nil { log.Println("[Config] Error on sanitize name:", err) return err } log.Printf("[Config] Adding service: '%s'", name) serviceCfg.Name = name cfg.Service[name] = serviceCfg log.Printf("[Config] DEBUG serviceCfg: '%+v'", serviceCfg) case "Container": containerCfg = new(ContainerConfig) if err = section.MapTo(containerCfg); err != nil { log.Println("[Config] Error on mapTo Container:", err) return err } if name, err = sanitizeName(containerCfg.Name); err != nil { log.Println("[Config] Error on sanitize name:", err) return err } log.Printf("[Config] Adding container: '%s'", name) containerCfg.Name = name cfg.Container[name] = containerCfg log.Printf("[Config] DEBUG containerCfg: '%+v'", containerCfg) case "DEFAULT": continue default: log.Printf("[Config] Ignored section: '%s'", sectionName) } } } return nil }