// NewBackends creates a new backend from a raw config structure func NewBackends(raw []interface{}, disc discovery.ServiceBackend) ([]*Backend, error) { if raw == nil { return []*Backend{}, nil } var backends []*Backend if err := utils.DecodeRaw(raw, &backends); err != nil { return nil, fmt.Errorf("Backend configuration error: %v", err) } for _, b := range backends { if err := utils.ValidateServiceName(b.Name); err != nil { return nil, err } cmd, err := utils.ParseCommandArgs(b.OnChangeExec) if err != nil { return nil, fmt.Errorf("Could not parse `onChange` in backend %s: %s", b.Name, err) } if cmd == nil { return nil, fmt.Errorf("`onChange` is required in backend %s", b.Name) } if b.Poll < 1 { return nil, fmt.Errorf("`poll` must be > 0 in backend %s", b.Name) } b.onChangeCmd = cmd b.discoveryService = disc } return backends, nil }
func parseCommand(name string, args interface{}) (*exec.Cmd, error) { cmd, err := utils.ParseCommandArgs(args) if err != nil { return nil, fmt.Errorf("Could not parse `%s`: %s", name, err) } return cmd, nil }
// NewSensors creates new sensors from a raw config func NewSensors(raw []interface{}) ([]*Sensor, error) { var sensors []*Sensor if err := utils.DecodeRaw(raw, &sensors); err != nil { return nil, fmt.Errorf("Sensor configuration error: %v", err) } for _, s := range sensors { check, err := utils.ParseCommandArgs(s.CheckExec) if err != nil { return nil, err } s.checkCmd = check // the prometheus client lib's API here is baffling... they don't expose // an interface or embed their Opts type in each of the Opts "subtypes", // so we can't share the initialization. switch { case s.Type == "counter": s.collector = prometheus.NewCounter(prometheus.CounterOpts{ Namespace: s.Namespace, Subsystem: s.Subsystem, Name: s.Name, Help: s.Help, }) case s.Type == "gauge": s.collector = prometheus.NewGauge(prometheus.GaugeOpts{ Namespace: s.Namespace, Subsystem: s.Subsystem, Name: s.Name, Help: s.Help, }) case s.Type == "histogram": s.collector = prometheus.NewHistogram(prometheus.HistogramOpts{ Namespace: s.Namespace, Subsystem: s.Subsystem, Name: s.Name, Help: s.Help, }) case s.Type == "summary": s.collector = prometheus.NewSummary(prometheus.SummaryOpts{ Namespace: s.Namespace, Subsystem: s.Subsystem, Name: s.Name, Help: s.Help, }) default: return nil, fmt.Errorf("Invalid sensor type: %s\n", s.Type) } // we're going to unregister before every attempt to register // so that we can reload config prometheus.Unregister(s.collector) if err := prometheus.Register(s.collector); err != nil { return nil, err } } return sensors, nil }
func parseService(s *Service, disc discovery.ServiceBackend) error { if err := utils.ValidateServiceName(s.Name); err != nil { return err } hostname, _ := os.Hostname() s.ID = fmt.Sprintf("%s-%s", s.Name, hostname) s.discoveryService = disc if s.Poll < 1 { return fmt.Errorf("`poll` must be > 0 in service %s", s.Name) } if s.TTL < 1 { return fmt.Errorf("`ttl` must be > 0 in service %s", s.Name) } if s.Port < 1 { return fmt.Errorf("`port` must be > 0 in service %s", s.Name) } // if the HealthCheckExec is nil then we'll have no health check // command; this is useful for the telemetry service cmd, err := utils.ParseCommandArgs(s.HealthCheckExec) if err != nil { return fmt.Errorf("Could not parse `health` in service %s: %s", s.Name, err) } s.healthCheckCmd = cmd interfaces, ifaceErr := utils.ToStringArray(s.Interfaces) if ifaceErr != nil { return ifaceErr } ipAddress, err := utils.GetIP(interfaces) if err != nil { return err } s.IPAddress = ipAddress s.definition = &discovery.ServiceDefinition{ ID: s.ID, Name: s.Name, Port: s.Port, TTL: s.TTL, Tags: s.Tags, IPAddress: s.IPAddress, } return nil }
// Run starts the application and blocks until finished func (a *App) Run() { // Set up handlers for polling and to accept signal interrupts if 1 == os.Getpid() { reapChildren() } args := getArgs(flag.Args()) command, err := utils.ParseCommandArgs(args) if err != nil { log.Errorf("Unable to parse command arguments: %v", err) } a.handleSignals() // Run the preStart handler, if any, and exit if it returns an error if preStartCode, err := utils.RunWithFields(a.PreStartCmd, log.Fields{"process": "PreStart"}); err != nil { os.Exit(preStartCode) } a.handleCoprocesses() a.handlePolling() if len(args) != 0 { // Run our main application and capture its stdout/stderr. // This will block until the main application exits and then os.Exit // with the exit code of that application. a.Command = command command.Stderr = os.Stderr command.Stdout = os.Stdout code, err := utils.ExecuteAndWait(command) if err != nil { log.Println(err) } // Run the PostStop handler, if any, and exit if it returns an error if postStopCode, err := utils.RunWithFields(a.PostStopCmd, log.Fields{"process": "PostStop"}); err != nil { os.Exit(postStopCode) } os.Exit(code) } // block forever, as we're polling in the two polling functions and // did not os.Exit by waiting on an external application. select {} }