Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions cmd/boulder-observer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import (
"flag"
"os"

"github.com/letsencrypt/validator/v10"

"github.com/letsencrypt/boulder/cmd"
"github.com/letsencrypt/boulder/config"
"github.com/letsencrypt/boulder/observer"
"github.com/letsencrypt/boulder/strictyaml"
)
Expand All @@ -19,25 +22,33 @@ func main() {
cmd.FailOnError(err, "failed to read config file")

// Parse the YAML config file.
var config observer.ObsConf
err = strictyaml.Unmarshal(configYAML, &config)
var obsConf observer.ObsConf
err = strictyaml.Unmarshal(configYAML, &obsConf)

if *debugAddr != "" {
config.DebugAddr = *debugAddr
obsConf.DebugAddr = *debugAddr
}

if err != nil {
cmd.FailOnError(err, "failed to parse YAML config")
}

// Validate config using struct tags.
validate := validator.New()
validate.RegisterCustomTypeFunc(config.DurationCustomTypeFunc, config.Duration{})
err = validate.Struct(obsConf)
if err != nil {
cmd.FailOnError(err, "config validation failed")
}

// Make an `Observer` object.
observer, err := config.MakeObserver()
obs, err := obsConf.MakeObserver()
if err != nil {
cmd.FailOnError(err, "config failed validation")
}

// Start the `Observer` daemon.
observer.Start()
obs.Start()
}

func init() {
Expand Down
46 changes: 0 additions & 46 deletions observer/obs_conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package observer
import (
"errors"
"fmt"
"net"
"strconv"

"github.com/prometheus/client_golang/prometheus"
Expand Down Expand Up @@ -32,33 +31,6 @@ type ObsConf struct {
MonConfs []*MonConf `yaml:"monitors" validate:"min=1,dive"`
}

// validateSyslog ensures the `Syslog` field received by `ObsConf`
// contains valid log levels.
func (c *ObsConf) validateSyslog() error {
syslog, stdout := c.Syslog.SyslogLevel, c.Syslog.StdoutLevel
if stdout < 0 || stdout > 7 || syslog < 0 || syslog > 7 {
return fmt.Errorf(
"invalid 'syslog', '%+v', valid log levels are 0-7", c.Syslog)
}
return nil
}

// validateDebugAddr ensures the `debugAddr` received by `ObsConf` is
// properly formatted and a valid port.
func (c *ObsConf) validateDebugAddr() error {
_, p, err := net.SplitHostPort(c.DebugAddr)
if err != nil {
return fmt.Errorf(
"invalid 'debugaddr', %q, not expected format", c.DebugAddr)
}
port, _ := strconv.Atoi(p)
if port <= 0 || port > 65535 {
return fmt.Errorf(
"invalid 'debugaddr','%d' is not a valid port", port)
}
return nil
}

func (c *ObsConf) makeMonitors(metrics prometheus.Registerer) ([]*monitor, []error, error) {
var errs []error
var monitors []*monitor
Expand Down Expand Up @@ -117,24 +89,6 @@ func (c *ObsConf) makeMonitors(metrics prometheus.Registerer) ([]*monitor, []err
// bound `ObsConf`. If the `ObsConf` cannot be validated, an error
// appropriate for end-user consumption is returned instead.
func (c *ObsConf) MakeObserver() (*Observer, error) {
err := c.validateSyslog()
if err != nil {
return nil, err
}

err = c.validateDebugAddr()
if err != nil {
return nil, err
}

if len(c.MonConfs) == 0 {
return nil, errors.New("no monitors provided")
}

if len(c.Buckets) == 0 {
return nil, errors.New("no histogram buckets provided")
}

// Start monitoring and logging.
metrics, logger, shutdown := cmd.StatsAndLogging(c.Syslog, c.OpenTelemetry, c.DebugAddr)
histObservations = prometheus.NewHistogramVec(
Expand Down
70 changes: 0 additions & 70 deletions observer/obs_conf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"github.com/letsencrypt/boulder/metrics"
"github.com/letsencrypt/boulder/observer/probers"
_ "github.com/letsencrypt/boulder/observer/probers/mock"
"github.com/letsencrypt/boulder/test"
)

const (
Expand Down Expand Up @@ -71,72 +70,3 @@ func TestObsConf_makeMonitors(t *testing.T) {
})
}
}

func TestObsConf_ValidateDebugAddr(t *testing.T) {
type fields struct {
DebugAddr string
}
tests := []struct {
name string
fields fields
wantErr bool
}{
// valid
{"max len and range", fields{":65535"}, false},
{"min len and range", fields{":1"}, false},
{"2 digits", fields{":80"}, false},
// invalid
{"out of range high", fields{":65536"}, true},
{"out of range low", fields{":0"}, true},
{"not even a port", fields{":foo"}, true},
{"missing :", fields{"foo"}, true},
{"missing port", fields{"foo:"}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &ObsConf{
DebugAddr: tt.fields.DebugAddr,
}
err := c.validateDebugAddr()
if tt.wantErr {
test.AssertError(t, err, "ObsConf.ValidateDebugAddr() should have errored")
} else {
test.AssertNotError(t, err, "ObsConf.ValidateDebugAddr() shouldn't have errored")
}
})
}
}

func TestObsConf_validateSyslog(t *testing.T) {
type fields struct {
Syslog cmd.SyslogConfig
}
tests := []struct {
name string
fields fields
wantErr bool
}{
// valid
{"valid", fields{cmd.SyslogConfig{StdoutLevel: 6, SyslogLevel: 6}}, false},
// invalid
{"both too high", fields{cmd.SyslogConfig{StdoutLevel: 9, SyslogLevel: 9}}, true},
{"stdout too high", fields{cmd.SyslogConfig{StdoutLevel: 9, SyslogLevel: 6}}, true},
{"syslog too high", fields{cmd.SyslogConfig{StdoutLevel: 6, SyslogLevel: 9}}, true},
{"both too low", fields{cmd.SyslogConfig{StdoutLevel: -1, SyslogLevel: -1}}, true},
{"stdout too low", fields{cmd.SyslogConfig{StdoutLevel: -1, SyslogLevel: 6}}, true},
{"syslog too low", fields{cmd.SyslogConfig{StdoutLevel: 6, SyslogLevel: -1}}, true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
c := &ObsConf{
Syslog: tt.fields.Syslog,
}
err := c.validateSyslog()
if tt.wantErr {
test.AssertError(t, err, "ObsConf.validateSyslog() should have errored")
} else {
test.AssertNotError(t, err, "ObsConf.validateSyslog() shouldn't have errored")
}
})
}
}
Loading