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
4 changes: 2 additions & 2 deletions haproxy/haproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ type HAProxy struct {

func New(consulClient *api.Client, cfg chan consul.Config, opts Options) *HAProxy {
if opts.HAProxyBin == "" {
opts.HAProxyBin = "haproxy"
opts.HAProxyBin = haproxy_cmd.DefaultHAProxyBin
}
if opts.DataplaneBin == "" {
opts.DataplaneBin = "dataplaneapi"
opts.DataplaneBin = haproxy_cmd.DefaultDataplaneBin
}
return &HAProxy{
opts: opts,
Expand Down
57 changes: 57 additions & 0 deletions haproxy/haproxy_cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,23 @@ import (
"net"
"net/http"
"os"
"os/exec"
"regexp"
"strings"
"sync"
"time"

"github.com/haproxytech/haproxy-consul-connect/haproxy/dataplane"
"github.com/haproxytech/haproxy-consul-connect/lib"
)

const (
// DefaultDataplaneBin is the default dataplaneapi program name
DefaultDataplaneBin = "dataplaneapi"
// DefaultHAProxyBin is the default HAProxy program name
DefaultHAProxyBin = "haproxy"
)

type Config struct {
HAProxyPath string
HAProxyConfigPath string
Expand Down Expand Up @@ -93,3 +104,49 @@ func Start(sd *lib.Shutdown, cfg Config) (*dataplane.Dataplane, error) {

return dataplaneClient, nil
}

// execAndCapture Launch Help from program path and Find Version
// to capture the output and retrieve version information
func execAndCapture(path string, re *regexp.Regexp) (string, error) {
cmd := exec.Command(path, "-v")
out, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("Failed executing %s: %s", path, err.Error())
}
err = cmd.Run()
if err != nil {
return "", fmt.Errorf("Failed executing %s: %s", path, err)
}
return string(re.Find([]byte(out))), nil
}

// CheckEnvironment Verifies that all dependencies are correct
func CheckEnvironment(dataplaneapiBin, haproxyBin string) error {
errors := make([]error, 2)
wg := &sync.WaitGroup{}
wg.Add(2)
ensureVersion := func(path, rx, version string, idx int) {
r := regexp.MustCompile(rx)
v, e := execAndCapture(path, r)
if e != nil {
errors[idx] = e
} else if strings.Compare(v, "1.2") < 0 {
errors[idx] = fmt.Errorf("%s version must be > 1.2,, but is: %s", path, v)
}
wg.Done()
}
func() {
ensureVersion(haproxyBin, "^HA-Proxy version ([0-9]\\.[0-9]\\.[0-9])", "2.0", 0)
}()
func() {
ensureVersion(dataplaneapiBin, "^HAProxy Data Plane API v([0-9]\\.[0-9]\\.[0-9])", "1.2", 0)
}()

wg.Wait()
for _, err := range errors {
if err != nil {
return err
}
}
return nil
}
4 changes: 4 additions & 0 deletions haproxy/state/from_ha_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ RHmDi0qnL6qrKfjTOnfHgQPCgxAy9knMIiDzBRg=
}

func TestFromHA(t *testing.T) {
err := haproxy_cmd.CheckEnvironment(haproxy_cmd.DefaultDataplaneBin, haproxy_cmd.DefaultHAProxyBin)
if err != nil {
t.Skipf("CANNOT Run test because of missing requirement: %s", err.Error())
}
cfgDir, err := ioutil.TempDir("", fmt.Sprintf("%s_*", t.Name()))
require.NoError(t, err)

Expand Down
24 changes: 20 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
log "github.com/sirupsen/logrus"

haproxy "github.com/haproxytech/haproxy-consul-connect/haproxy"
"github.com/haproxytech/haproxy-consul-connect/haproxy/haproxy_cmd"
"github.com/haproxytech/haproxy-consul-connect/lib"

"github.com/hashicorp/consul/api"
Expand Down Expand Up @@ -47,24 +48,39 @@ func (consulLogger) Errorf(format string, args ...interface{}) {
log.Errorf(format, args...)
}

// validateRequirements Checks that dependencies are present
func validateRequirements(dataplaneBin, haproxyBin string) error {
err := haproxy_cmd.CheckEnvironment(dataplaneBin, haproxyBin)
if err != nil {
msg := fmt.Sprintf("Some external dependencies are missing: %s", err.Error())
os.Stderr.WriteString(fmt.Sprintf("%s\n", msg))
return err
}
return nil
}

func main() {
versionFlag := flag.Bool("version", false, "Show version and exit")
logLevel := flag.String("log-level", "INFO", "Log level")
consulAddr := flag.String("http-addr", "127.0.0.1:8500", "Consul agent address")
service := flag.String("sidecar-for", "", "The consul service id to proxy")
serviceTag := flag.String("sidecar-for-tag", "", "The consul service id to proxy")
haproxyBin := flag.String("haproxy", "haproxy", "Haproxy binary path")
dataplaneBin := flag.String("dataplane", "dataplane-api", "Dataplane binary path")
haproxyBin := flag.String("haproxy", haproxy_cmd.DefaultHAProxyBin, "Haproxy binary path")
dataplaneBin := flag.String("dataplane", haproxy_cmd.DefaultDataplaneBin, "Dataplane binary path")
haproxyCfgBasePath := flag.String("haproxy-cfg-base-path", "/tmp", "Haproxy binary path")
statsListenAddr := flag.String("stats-addr", "", "Listen addr for stats server")
statsServiceRegister := flag.Bool("stats-service-register", false, "Register a consul service for connect stats")
enableIntentions := flag.Bool("enable-intentions", false, "Enable Connect intentions")
token := flag.String("token", "", "Consul ACL token")
flag.Parse()

if versionFlag != nil && *versionFlag {
fmt.Printf("Version: %s ; BuildTime: %s ; GitHash: %s\n", Version, BuildTime, GitHash)
os.Exit(0)
status := 0
if err := validateRequirements(*dataplaneBin, *haproxyBin); err != nil {
fmt.Printf("ERROR: dataplane API / HAProxy dependencies are not satisfied: %s\n", err)
status = 4
}
os.Exit(status)
}

ll, err := log.ParseLevel(*logLevel)
Expand Down