Example #1
0
// 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
}
Example #2
0
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
}
Example #3
0
// 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
}
Example #4
0
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
}
Example #5
0
// 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 {}
}