// Upload the i18n file for specific language // and save into pool func (self pool) save(lang string) error { filename := path.Join(folder, lang+iniExtension) f, err := ini.LoadFile(filename) if err != nil { return err } self[lang] = f return nil }
func GetConfig(configFilePath string) (ini.File, error) { appConfig, err := ini.LoadFile(configFilePath) if err != nil { return nil, err } ok, err := testConfig(appConfig) if !ok { return nil, err } return appConfig, nil }
// Load the ~/.pstoprc regexp expressions in section [munge] func loadRegexps() { if loadedRegexps { return } loadedRegexps = true logger.Println("rc.loadRegexps()") haveRegexps = false filename := convertFilename(pstoprc) // Is the file is there? f, err := os.Open(filename) if err != nil { logger.Println("- unable to open " + filename + ", nothing to munge") return // can't open file. This is not fatal. We just can't do anything useful. } // If we get here the file is readable, so close it again. err = f.Close() if err != nil { // Do nothing. What can we do? Do we care? } // Load and process the ini file. i, err := go_ini.LoadFile(filename) if err != nil { log.Fatal("Could not load ~/.pstoprc", filename, ":", err) } // Note: This is wrong if I want to have an _ordered_ list of regexps // as go-ini provides me a hash so I lose the ordering. This may not // be desirable but as a first step accept this is broken. section := i.Section("munge") regexps = make(mungeRegexps, 0, len(section)) // now look for regexps and load them in... for k, v := range section { var m mungeRegexp var err error m.pattern, m.replace = k, v m.re, err = regexp.Compile(m.pattern) if err == nil { m.valid = true } regexps = append(regexps, m) } if len(regexps) > 0 { haveRegexps = true } logger.Println("- found", len(regexps), "regexps to use to munge output") }
// Ini creates a backing config reader that reads properties from an Ini file func Ini(filename string) (Reader, error) { file, err := ini.LoadFile(filename) if err != nil { return nil, errors.Annotatef(err, "Unable to open file %s", filename) } return &propertyFileDisco{ filename: filename, file: file, }, nil }
// ParseSubmodules returns all submodule definitions given a .gitmodules // configuration. func ParseSubmodules(filename string) ([]Submodule, error) { config, err := ini.LoadFile(filename) if err != nil { return nil, err } var submodules []Submodule for section := range config { if !strings.HasPrefix(section, "submodule") { continue } submodules = append(submodules, Submodule{ Path: config.Section(section)["path"], URL: config.Section(section)["url"], }) } return submodules, nil }
func loadKeys() (pub, prv string, err error) { var file ini.File file, err = ini.LoadFile("keys.ini") if err != nil { return } var ok bool pub, ok = file.Get("keys", "public") if !ok { err = errors.New("pubkey missed") return } prv, ok = file.Get("keys", "private") if !ok { err = errors.New("privkey missed") return } return }
func loadAWSConfigFile(fileName string, profileName string) (aws.Auth, aws.Region, error) { var auth aws.Auth var region aws.Region conf, err := ini.LoadFile(fileName) if err != nil { return auth, region, err } log.Printf("Loading file %s [%s]", fileName, profileName) for key, value := range conf[profileName] { switch key { case "aws_access_key_id": auth.AccessKey = value case "aws_secret_access_key": auth.SecretKey = value case "region": region = aws.GetRegion(value) } } return auth, region, nil }
func main() { confs := flag.String("conf", "monitor.ini", "Monitor configuration file.") logfile := flag.String("log", "", "Log file.") version := flag.Bool("version", false, "Monitor version number.") flag.Parse() if *version { fmt.Println("Monitor version is:", definitions.Version) os.Exit(0) } pid := os.Getpid() pidstr := strconv.FormatInt(int64(pid), 10) log.SetPrefix("monitor (" + pidstr + ") ") if *logfile != "" { file := logToFile(*logfile) sig := make(chan os.Signal) signal.Notify(sig, syscall.SIGHUP) go func() { for { select { case <-sig: log.Println("Closing log...") oldfile := file file = logToFile(*logfile) oldfile.Close() log.Println("Log restarted.") } } }() } log.Println("Starting...") file, err := ini.LoadFile(*confs) if err != nil { log.Fatal("Open failed with error:", err) } var em *mail.Email if section, ok := file["smtp"]; ok { tos := strings.Split(strings.Trim(section["to"], "\""), ",") for i, to := range tos { tos[i] = strings.TrimSpace(to) } skipVerify := false if section["skip_verify"] == "true" { skipVerify = true } var timeout int64 = 30 if section["timeout"] != "" { timeout, err = strconv.ParseInt(section["timeout"], 10, 64) if err != nil { log.Fatal("Invalid smtp timeout.") } } em = &mail.Email{ Smtp: strings.Trim(section["smtp"], "\""), From: strings.Trim(section["from"], "\""), To: tos, Hello: strings.Trim(section["hello"], "\""), User: strings.Trim(section["user"], "\""), Pass: strings.Trim(section["pass"], "\""), Timeout: time.Duration(timeout) * time.Second, InsecureSkipVerify: skipVerify, } } status.Name = "monitor" status.Email = em status.Debug = status.Normal if section, ok := file["debug"]; ok { if l, err := strconv.ParseInt(section["level"], 10, 8); err == nil { status.Debug = status.DebugLevel(l) } } wait := definitions.WaitDefault conntries := definitions.ConnTriesDefault if section, ok := file["connections"]; ok { if w, err := strconv.ParseInt(section["wait"], 10, 32); err == nil { wait = time.Duration(w) * time.Second } if r, err := strconv.ParseInt(section["retries"], 10, 32); err == nil { conntries = int(r) } if t, ok := section["TLSChecks"]; ok { if t == "false" { ping.SkipSecurityChecksTLS(true) } else if t == "true" { ping.SkipSecurityChecksTLS(false) } else { ping.SkipSecurityChecksTLS(false) log.Println("TLSChecks option is invalid.") } } if r, err := strconv.ParseInt(section["DialTimeout"], 10, 32); err == nil { ping.DialTimeout = time.Duration(r) * time.Second } if r, err := strconv.ParseInt(section["TLSHandshakeTimeout"], 10, 32); err == nil { ping.TLSHandshakeTimeout = time.Duration(r) * time.Second } if r, err := strconv.ParseInt(section["HttpResponseHeaderTimeout"], 10, 32); err == nil { ping.ResponseHeaderTimeout = time.Duration(r) * time.Second } if r, err := strconv.ParseInt(section["HttpTimeout"], 10, 32); err == nil { ping.HttpTimeout = time.Duration(r) * time.Second } } monitors := make([]monitors.Monitor, 0, len(file)) var numQueues uint64 = 1<<64 - 1 serversQueue := queue.NewPriority(numQueues, func() (queue.Queue, error) { return queue.NewSimple(10, 1), nil }) defer serversQueue.Stop() monitorsQueue := queue.NewPriority(numQueues, func() (queue.Queue, error) { return queue.NewSimple(10, 1), nil }) defer monitorsQueue.Stop() serversQueue.Process() monitorsQueue.Process() for name, section := range file { switch { case strings.Contains(name, "server:"): if em == nil { log.Fatal("smtp section not found") } d := new(daemon.Daemon) d.DaemonName = strings.TrimPrefix(name, "server:") cmd, args := util.SplitCmd(strings.Trim(section["cmd"], "\"")) d.RestartCmd = cmd d.RestartArgs = args forcekillcmd, forcekillargs := util.SplitCmd(strings.Trim(section["forcekill"], "\"")) d.ForceKillCmd = forcekillcmd d.ForceKillArgs = forcekillargs urls := strings.Split(strings.Trim(section["urls"], "\""), " ") d.Urls = make([]*url.URL, len(urls)) j := 0 for i, u := range urls { u = strings.TrimSpace(u) if u == "" { continue } d.Urls[i], err = utilUrl.ParseWithSocket(u) if err != nil { err = e.Push(e.Forward(err), e.New("url [%v] is invalid", u)) log.Fatal("Url in", d.DaemonName, "is invalid:", e.Trace(e.Forward(err))) } j++ } d.Urls = d.Urls[:j] sleep, err := strconv.ParseInt(section["sleep"], 10, 32) if err != nil { log.Fatal("sleep value for", d.DaemonName, "is invalid:", e.Trace(e.Forward(err))) } d.Sleep = time.Duration(sleep) * time.Second tries64, _ := strconv.ParseInt(section["tries"], 10, 32) d.Tries = int(tries64) d.PidFile = strings.Trim(section["pidFile"], "\"") d.Prio = numQueues - 1 if p, err := strconv.ParseUint(section["prio"], 10, 32); err == nil { d.Prio = uint64(p) } d.Queue = serversQueue d.ExecTimeout = 4 * time.Minute monitor, err := daemon.Init(d) if err != nil { log.Fatal("New daemon for "+d.DaemonName+" failed with error ", e.Trace(e.Forward(err))) } log.Println("Monitor installed for " + d.DaemonName + ".") defer monitor.Close() monitors = append(monitors, monitor) case strings.Contains(name, "monitor:"): if em == nil { log.Fatal("smtp section not found") } vs := new(virtualserver.VirtualServer) vs.VirtualServerName = strings.TrimPrefix(name, "monitor:") vs.PidFile = strings.Trim(section["pidFile"], "\"") cmdargs := strings.Split(strings.Trim(section["cmd"], "\""), " ") if len(cmdargs) == 0 { log.Fatal("cmd value for", vs.VirtualServerName, "is invalid.") } vs.RestartCmd = cmdargs[0] vs.RestartArgs = make([]string, 0) if len(cmdargs) > 1 { vs.RestartArgs = cmdargs[1:] } net := strings.Trim(section["net"], "\"") if net == "" { log.Fatal("net value for", vs.VirtualServerName, "is invalid.") } vs.MonitorUrl, err = utilUrl.ParseWithSocket(net) if err != nil { log.Fatal("net value for", vs.VirtualServerName, "is invalid:", e.Trace(e.Forward(err))) } sleep, err := strconv.ParseInt(section["sleep"], 10, 32) if err != nil { log.Fatal("sleep value for", vs.VirtualServerName, "is invalid:", e.Trace(e.Forward(err))) } vs.Sleep = time.Duration(sleep) * time.Second tries64, _ := strconv.ParseInt(section["tries"], 10, 32) vs.Tries = int(tries64) forcekill := strings.Trim(section["forcekill"], "\"") if forcekill == "" { log.Fatal("forcekill value for", vs.VirtualServerName, "is invalid:", e.Trace(e.Forward(err))) } vs.ForceKillCmd, vs.ForceKillArgs = util.SplitCmd(forcekill) beforestart := strings.Trim(section["beforestart"], "\"") if beforestart == "" { log.Fatal("beforestart value for", vs.VirtualServerName, "is invalid:", e.Trace(e.Forward(err))) } vs.BeforeStartCmd, vs.BeforeStartArgs = util.SplitCmd(beforestart) vs.Prio = numQueues - 1 if p, err := strconv.ParseUint(section["prio"], 10, 32); err == nil { vs.Prio = uint64(p) } vs.ConnWait = wait vs.ConnTries = conntries vs.Email = em vs.Queue = monitorsQueue vs.ExecTimeout = 6 * time.Minute monitor, err := virtualserver.Init(vs) if err != nil { log.Fatal("NewMetaMonitor for "+vs.VirtualServerName+" failed with error ", e.Trace(e.Forward(err))) } defer monitor.Close() log.Println("Meta monitor installed for " + vs.VirtualServerName + ".") monitors = append(monitors, monitor) case strings.Contains(name, "disk:"): if em == nil { log.Fatal("smtp section not found") } name := strings.TrimPrefix(name, "disk:") if name == "" { continue } sleep, err := strconv.ParseInt(section["sleep"], 10, 32) if err != nil { log.Fatal("sleep value for", name, "is invalid:", e.Trace(e.Forward(err))) continue } minfree, err := strconv.ParseFloat(section["min"], 32) if err != nil { log.Fatal("min value for", name, "is invalid:", e.Trace(e.Forward(err))) continue } var alarm time.Duration if alarmInt, err := strconv.ParseInt(section["alarm"], 10, 32); err == nil { alarm = time.Duration(alarmInt) * time.Second } dm := disk.New(name, strings.Trim(section["mount"], "\""), int(sleep), float32(minfree), em, alarm) defer dm.Close() log.Println("Disk monitor installed for " + name + ".") monitors = append(monitors, dm) } } if section, ok := file["alive"]; ok { if em == nil { log.Fatal("smtp section not found") } urlStr, ok := section["url"] if !ok { log.Fatal("Alive section doesn't have the url entry.") } urlStr = strings.Trim(urlStr, "\"") url, err := utilUrl.ParseWithSocket(urlStr) if err != nil { log.Fatal("Invalid url:", e.Trace(e.Forward(err))) } a, err := alive.New(url.Scheme, url.Host, em, monitors) if err != nil { log.Fatal("Can't start alive:", e.Trace(e.Forward(err))) } defer a.Close() monitors = append(monitors, a) log.Println("Alive server installed.") } if len(monitors) > 0 { time := time.Now().Format("jan 2, 2006 at 3:04pm (MST)") msg := "Monitor, pid " + pidstr + ", started at " + time + " monitoring this:\n\n" for _, m := range monitors { msg += "\t- " + m.Type().String() + " " + m.Name() + "\n" } err := em.Send("Monitor started ("+pidstr+").", msg) if err != nil { log.Println("Can't send the email informing the start of the monitors, error:", e.Trace(e.Forward(err))) } // Termination signal stuff sig := make(chan os.Signal) signal.Notify(sig, syscall.SIGINT, syscall.SIGKILL, syscall.SIGTERM) <-sig err = em.Send("Monitor stoped ("+pidstr+").", "") if err != nil { log.Println("Can't send the email informing the end of the monitors, error:", e.Trace(e.Forward(err))) } } // End defer log.Println("End.") }
func LoadConf(confFile string) (err error) { var tmpStr string var ok bool conf, err := ini.LoadFile(confFile) if err != nil { return err } // common tmpStr, ok = conf.Get("common", "server_addr") if ok { ServerAddr = tmpStr } tmpStr, ok = conf.Get("common", "server_port") if ok { ServerPort, _ = strconv.ParseInt(tmpStr, 10, 64) } tmpStr, ok = conf.Get("common", "log_file") if ok { LogFile = tmpStr if LogFile == "console" { LogWay = "console" } else { LogWay = "file" } } tmpStr, ok = conf.Get("common", "log_level") if ok { LogLevel = tmpStr } tmpStr, ok = conf.Get("common", "log_max_days") if ok { LogMaxDays, _ = strconv.ParseInt(tmpStr, 10, 64) } tmpStr, ok = conf.Get("common", "privilege_token") if ok { PrivilegeToken = tmpStr } var authToken string tmpStr, ok = conf.Get("common", "auth_token") if ok { authToken = tmpStr } // proxies for name, section := range conf { if name != "common" { proxyClient := &ProxyClient{} // name proxyClient.Name = name // auth_token proxyClient.AuthToken = authToken // local_ip proxyClient.LocalIp, ok = section["local_ip"] if !ok { // use 127.0.0.1 as default proxyClient.LocalIp = "127.0.0.1" } // local_port tmpStr, ok = section["local_port"] if ok { proxyClient.LocalPort, err = strconv.ParseInt(tmpStr, 10, 64) if err != nil { return fmt.Errorf("Parse conf error: proxy [%s] local_port error", proxyClient.Name) } } else { return fmt.Errorf("Parse conf error: proxy [%s] local_port not found", proxyClient.Name) } // type proxyClient.Type = "tcp" tmpStr, ok = section["type"] if ok { if tmpStr != "tcp" && tmpStr != "http" && tmpStr != "https" { return fmt.Errorf("Parse conf error: proxy [%s] type error", proxyClient.Name) } proxyClient.Type = tmpStr } // use_encryption proxyClient.UseEncryption = false tmpStr, ok = section["use_encryption"] if ok && tmpStr == "true" { proxyClient.UseEncryption = true } // use_gzip proxyClient.UseGzip = false tmpStr, ok = section["use_gzip"] if ok && tmpStr == "true" { proxyClient.UseGzip = true } // privilege_mode proxyClient.PrivilegeMode = false tmpStr, ok = section["privilege_mode"] if ok && tmpStr == "true" { proxyClient.PrivilegeMode = true } // configures used in privilege mode if proxyClient.PrivilegeMode == true { if PrivilegeToken == "" { return fmt.Errorf("Parse conf error: proxy [%s] privilege_key must be set when privilege_mode = true", proxyClient.Name) } else { proxyClient.PrivilegeToken = PrivilegeToken } if proxyClient.Type == "tcp" { // remote_port tmpStr, ok = section["remote_port"] if ok { proxyClient.RemotePort, err = strconv.ParseInt(tmpStr, 10, 64) if err != nil { return fmt.Errorf("Parse conf error: proxy [%s] remote_port error", proxyClient.Name) } } else { return fmt.Errorf("Parse conf error: proxy [%s] remote_port not found", proxyClient.Name) } } else if proxyClient.Type == "http" { domainStr, ok := section["custom_domains"] if ok { proxyClient.CustomDomains = strings.Split(domainStr, ",") if len(proxyClient.CustomDomains) == 0 { return fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals http", proxyClient.Name) } for i, domain := range proxyClient.CustomDomains { proxyClient.CustomDomains[i] = strings.ToLower(strings.TrimSpace(domain)) } } else { return fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals http", proxyClient.Name) } } else if proxyClient.Type == "https" { domainStr, ok := section["custom_domains"] if ok { proxyClient.CustomDomains = strings.Split(domainStr, ",") if len(proxyClient.CustomDomains) == 0 { return fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals https", proxyClient.Name) } for i, domain := range proxyClient.CustomDomains { proxyClient.CustomDomains[i] = strings.ToLower(strings.TrimSpace(domain)) } } else { return fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals http", proxyClient.Name) } } } ProxyClients[proxyClient.Name] = proxyClient } } if len(ProxyClients) == 0 { return fmt.Errorf("Parse conf error: no proxy config found") } return nil }
func loadCommonConf(confFile string) error { var tmpStr string var ok bool conf, err := ini.LoadFile(confFile) if err != nil { return err } // common tmpStr, ok = conf.Get("common", "bind_addr") if ok { BindAddr = tmpStr } tmpStr, ok = conf.Get("common", "bind_port") if ok { v, err := strconv.ParseInt(tmpStr, 10, 64) if err == nil { BindPort = v } } tmpStr, ok = conf.Get("common", "vhost_http_port") if ok { VhostHttpPort, _ = strconv.ParseInt(tmpStr, 10, 64) } else { VhostHttpPort = 0 } tmpStr, ok = conf.Get("common", "vhost_https_port") if ok { VhostHttpsPort, _ = strconv.ParseInt(tmpStr, 10, 64) } else { VhostHttpsPort = 0 } tmpStr, ok = conf.Get("common", "dashboard_port") if ok { DashboardPort, _ = strconv.ParseInt(tmpStr, 10, 64) } else { DashboardPort = 0 } tmpStr, ok = conf.Get("common", "log_file") if ok { LogFile = tmpStr if LogFile == "console" { LogWay = "console" } else { LogWay = "file" } } tmpStr, ok = conf.Get("common", "log_level") if ok { LogLevel = tmpStr } tmpStr, ok = conf.Get("common", "log_max_days") if ok { v, err := strconv.ParseInt(tmpStr, 10, 64) if err == nil { LogMaxDays = v } } tmpStr, ok = conf.Get("common", "privilege_mode") if ok { if tmpStr == "true" { PrivilegeMode = true } } if PrivilegeMode == true { tmpStr, ok = conf.Get("common", "privilege_token") if ok { if tmpStr == "" { return fmt.Errorf("Parse conf error: privilege_token can not be null") } PrivilegeToken = tmpStr } else { return fmt.Errorf("Parse conf error: privilege_token must be set if privilege_mode is enabled") } } return nil }
func loadProxyConf(confFile string) (proxyServers map[string]*ProxyServer, err error) { var ok bool proxyServers = make(map[string]*ProxyServer) conf, err := ini.LoadFile(confFile) if err != nil { return proxyServers, err } // servers for name, section := range conf { if name != "common" { proxyServer := NewProxyServer() proxyServer.Name = name proxyServer.Type, ok = section["type"] if ok { if proxyServer.Type != "tcp" && proxyServer.Type != "http" && proxyServer.Type != "https" { return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] type error", proxyServer.Name) } } else { proxyServer.Type = "tcp" } proxyServer.AuthToken, ok = section["auth_token"] if !ok { return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] no auth_token found", proxyServer.Name) } // for tcp if proxyServer.Type == "tcp" { proxyServer.BindAddr, ok = section["bind_addr"] if !ok { proxyServer.BindAddr = "0.0.0.0" } portStr, ok := section["listen_port"] if ok { proxyServer.ListenPort, err = strconv.ParseInt(portStr, 10, 64) if err != nil { return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] listen_port error", proxyServer.Name) } } else { return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] listen_port not found", proxyServer.Name) } } else if proxyServer.Type == "http" { // for http domainStr, ok := section["custom_domains"] if ok { proxyServer.CustomDomains = strings.Split(domainStr, ",") if len(proxyServer.CustomDomains) == 0 { return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals http", proxyServer.Name) } for i, domain := range proxyServer.CustomDomains { proxyServer.CustomDomains[i] = strings.ToLower(strings.TrimSpace(domain)) } } else { return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals http", proxyServer.Name) } } else if proxyServer.Type == "https" { // for https domainStr, ok := section["custom_domains"] if ok { proxyServer.CustomDomains = strings.Split(domainStr, ",") if len(proxyServer.CustomDomains) == 0 { return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals https", proxyServer.Name) } for i, domain := range proxyServer.CustomDomains { proxyServer.CustomDomains[i] = strings.ToLower(strings.TrimSpace(domain)) } } else { return proxyServers, fmt.Errorf("Parse conf error: proxy [%s] custom_domains must be set when type equals https", proxyServer.Name) } } proxyServers[proxyServer.Name] = proxyServer } } return proxyServers, nil }
func getProfile(filename string) (*Profile, error) { f, err := ini.LoadFile(filename) return &Profile{f}, err }
func LoadConf(confFile string) (err error) { var tmpStr string var ok bool conf, err := ini.LoadFile(confFile) if err != nil { return err } // common tmpStr, ok = conf.Get("common", "server_addr") if ok { ServerAddr = tmpStr } tmpStr, ok = conf.Get("common", "server_port") if ok { ServerPort, _ = strconv.ParseInt(tmpStr, 10, 64) } tmpStr, ok = conf.Get("common", "log_file") if ok { LogFile = tmpStr if LogFile == "console" { LogWay = "console" } else { LogWay = "file" } } tmpStr, ok = conf.Get("common", "log_level") if ok { LogLevel = tmpStr } tmpStr, ok = conf.Get("common", "log_max_days") if ok { LogMaxDays, _ = strconv.ParseInt(tmpStr, 10, 64) } var authToken string tmpStr, ok = conf.Get("common", "auth_token") if ok { authToken = tmpStr } else { return fmt.Errorf("auth_token not found") } // proxies for name, section := range conf { if name != "common" { proxyClient := &ProxyClient{} // name proxyClient.Name = name // auth_token proxyClient.AuthToken = authToken // local_ip proxyClient.LocalIp, ok = section["local_ip"] if !ok { // use 127.0.0.1 as default proxyClient.LocalIp = "127.0.0.1" } // local_port portStr, ok := section["local_port"] if ok { proxyClient.LocalPort, err = strconv.ParseInt(portStr, 10, 64) if err != nil { return fmt.Errorf("Parse ini file error: proxy [%s] local_port error", proxyClient.Name) } } else { return fmt.Errorf("Parse ini file error: proxy [%s] local_port not found", proxyClient.Name) } // type proxyClient.Type = "tcp" typeStr, ok := section["type"] if ok { if typeStr != "tcp" && typeStr != "http" { return fmt.Errorf("Parse ini file error: proxy [%s] type error", proxyClient.Name) } proxyClient.Type = typeStr } // use_encryption proxyClient.UseEncryption = false useEncryptionStr, ok := section["use_encryption"] if ok && useEncryptionStr == "true" { proxyClient.UseEncryption = true } ProxyClients[proxyClient.Name] = proxyClient } } if len(ProxyClients) == 0 { return fmt.Errorf("Parse ini file error: no proxy config found") } return nil }