diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2022-10-25 17:35:25 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-25 17:35:25 +0200 |
commit | 373c68b2955c8a9ef77daa4e38622eec274b54ea (patch) | |
tree | 5c1b8e6aab71b25046688b0d8b8477dbadca9082 /client/go | |
parent | 866d45ec6b8a6d0f014f4a5cfb45204a2e215e25 (diff) | |
parent | 93cc378ab973517700263b629f11381e79cfff81 (diff) |
Merge pull request #24549 from vespa-engine/arnej/defaults-for-go
add go code wih API similar to defaults.cpp
Diffstat (limited to 'client/go')
-rw-r--r-- | client/go/defaults/defaults.go | 221 | ||||
-rw-r--r-- | client/go/defaults/defaults_test.go | 194 |
2 files changed, 415 insertions, 0 deletions
diff --git a/client/go/defaults/defaults.go b/client/go/defaults/defaults.go new file mode 100644 index 00000000000..b67900e84be --- /dev/null +++ b/client/go/defaults/defaults.go @@ -0,0 +1,221 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Author: arnej + +package defaults + +import ( + "fmt" + "os" + "strconv" + "strings" + + "github.com/vespa-engine/vespa/client/go/trace" +) + +const ( + ENV_VESPA_HOME = "VESPA_HOME" + ENV_VESPA_USER = "VESPA_USER" + ENV_VESPA_HOST = "VESPA_HOSTNAME" + + ENV_CONFIGSERVERS = "VESPA_CONFIGSERVERS" + ENV_ADDR_CONFIGSERVER = "addr_configserver" + + DEFAULT_VESPA_HOME = "/opt/vespa" + DEFAULT_VESPA_USER = "vespa" + DEFAULT_VESPA_HOST = "localhost" + + DEFAULT_VESPA_PORT_BASE = 19000 + ENV_VESPA_PORT_BASE = "VESPA_PORT_BASE" + + CONFIGSERVER_RPC_PORT_OFFSET = 70 + ENV_CONFIGSERVER_RPC_PORT = "port_configserver_rpc" + + CONFIGPROXY_RPC_PORT_OFFSET = 90 + ENV_CONFIGPROXY_RPC_PORT = "port_configproxy_rpc" + + DEFAULT_WEB_SERVICE_PORT = 8080 + ENV_WEB_SERVICE_PORT = "VESPA_WEB_SERVICE_PORT" +) + +// Compute the path prefix where Vespa files will live. +// Note: does not end with "/" +func VespaHome() string { + if env := os.Getenv(ENV_VESPA_HOME); env != "" { + return env + } + return DEFAULT_VESPA_HOME +} + +func UnderVespaHome(p string) string { + if strings.HasPrefix(p, "/") || strings.HasPrefix(p, "./") { + return p + } + return fmt.Sprintf("%s/%s", VespaHome(), p) +} + +// Compute the user name to own directories and run processes. +func VespaUser() string { + if env := os.Getenv(ENV_VESPA_USER); env != "" { + return env + } + return DEFAULT_VESPA_USER +} + +// Compute the host name that identifies myself. +// Detection of the hostname is now done before starting any Vespa +// programs and provided in the environment variable VESPA_HOSTNAME; +// if that variable isn't set a default of "localhost" is always returned. +func VespaHostname() string { + if env := os.Getenv(ENV_VESPA_HOST); env != "" { + return env + } + return DEFAULT_VESPA_HOST +} + +// Compute the port number where the Vespa webservice +// container should be available. +func VespaContainerWebServicePort() int { + p := getNumFromEnv(ENV_WEB_SERVICE_PORT) + if p > 0 { + trace.Debug(ENV_WEB_SERVICE_PORT, p) + return p + } + return DEFAULT_WEB_SERVICE_PORT +} + +// Compute the base for port numbers where the Vespa services should listen. +func VespaPortBase() int { + p := getNumFromEnv(ENV_VESPA_PORT_BASE) + if p > 0 { + trace.Debug(ENV_VESPA_PORT_BASE, p) + return p + } + return DEFAULT_VESPA_PORT_BASE +} + +// Find the hostnames of configservers that are configured. +func VespaConfigserverHosts() []string { + parts := splitVespaConfigservers() + rv := make([]string, len(parts)) + for idx, part := range parts { + if colon := strings.Index(part, ":"); colon > 0 { + rv[idx] = part[0:colon] + } else { + rv[idx] = part + } + trace.Debug("config server host:", rv[idx]) + } + return rv +} + +func findConfigserverHttpPort() int { + return findConfigserverRpcPort() + 1 +} + +// Find the RPC addresses to configservers that are configured. +// Returns a list of RPC specs in the format tcp/{hostname}:{portnumber} +func VespaConfigserverRpcAddrs() []string { + parts := splitVespaConfigservers() + rv := make([]string, len(parts)) + for idx, part := range parts { + if colon := strings.Index(part, ":"); colon > 0 { + rv[idx] = fmt.Sprintf("tcp/%s", part) + } else { + rv[idx] = fmt.Sprintf("tcp/%s:%d", part, findConfigserverRpcPort()) + } + trace.Debug("config server rpc addr:", rv[idx]) + } + return rv +} + +// Find the URLs to the REST api on configservers +// Returns a list of URLS in the format http://{hostname}:{portnumber}/ +func VespaConfigserverRestUrls() []string { + parts := splitVespaConfigservers() + rv := make([]string, len(parts)) + for idx, hostnm := range parts { + port := findConfigserverHttpPort() + if colon := strings.Index(hostnm, ":"); colon > 0 { + p, err := strconv.Atoi(hostnm[colon+1:]) + if err == nil && p > 0 { + port = p + 1 + } + hostnm = hostnm[:colon] + } + rv[idx] = fmt.Sprintf("http://%s:%d", hostnm, port) + trace.Debug("config server rest url:", rv[idx]) + } + return rv +} + +// Find the RPC address to the local config proxy +// Returns one RPC spec in the format tcp/{hostname}:{portnumber} +func VespaConfigProxyRpcAddr() string { + return fmt.Sprintf("tcp/localhost:%d", findConfigproxyRpcPort()) +} + +// Get the RPC addresses to all known config sources +// Returns same as vespaConfigProxyRpcAddr + vespaConfigserverRpcAddrs +func VespaConfigSourcesRpcAddrs() []string { + cs := VespaConfigserverRpcAddrs() + rv := make([]string, 0, len(cs)+1) + rv = append(rv, VespaConfigProxyRpcAddr()) + for _, addr := range cs { + rv = append(rv, addr) + } + return rv +} + +func splitVespaConfigservers() []string { + env := os.Getenv(ENV_CONFIGSERVERS) + if env == "" { + env = os.Getenv(ENV_ADDR_CONFIGSERVER) + } + parts := make([]string, 0, 3) + for { + idx := strings.IndexAny(env, " ,") + if idx < 0 { + break + } + if idx > 0 { + parts = append(parts, env[:idx]) + } + env = env[idx+1:] + } + if env != "" { + parts = append(parts, env) + } + if len(parts) == 0 { + parts = append(parts, "localhost") + } + return parts +} + +func findConfigproxyRpcPort() int { + p := getNumFromEnv(ENV_CONFIGPROXY_RPC_PORT) + if p > 0 { + return p + } + return VespaPortBase() + CONFIGPROXY_RPC_PORT_OFFSET +} + +func findConfigserverRpcPort() int { + p := getNumFromEnv(ENV_CONFIGSERVER_RPC_PORT) + if p > 0 { + trace.Debug(ENV_CONFIGSERVER_RPC_PORT, p) + return p + } + return VespaPortBase() + CONFIGSERVER_RPC_PORT_OFFSET +} + +func getNumFromEnv(vn string) int { + env := os.Getenv(vn) + if env != "" { + p, err := strconv.Atoi(env) + if err == nil { + return p + } + trace.Debug("env var", vn, "is:", env, "parse error:", err) + } + return -1 +} diff --git a/client/go/defaults/defaults_test.go b/client/go/defaults/defaults_test.go new file mode 100644 index 00000000000..3a566052797 --- /dev/null +++ b/client/go/defaults/defaults_test.go @@ -0,0 +1,194 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package defaults + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/vespa-engine/vespa/client/go/trace" +) + +func setup(t *testing.T) { + t.Setenv("VESPA_HOME", "/home/v/1") + t.Setenv("VESPA_USER", "somebody") + t.Setenv("VESPA_HOSTNAME", "foo.bar.local") + t.Setenv("VESPA_CONFIGSERVERS", "foo1.local, bar2.local, baz3.local") + t.Setenv("VESPA_PORT_BASE", "17000") + t.Setenv("port_configserver_rpc", "") + t.Setenv("port_configproxy_rpc", "") + t.Setenv("VESPA_WEB_SERVICE_PORT", "") +} + +func TestWebServicePort(t *testing.T) { + trace.AdjustVerbosity(1) + setup(t) + ws := VespaContainerWebServicePort() + assert.Equal(t, 8080, ws) + + t.Setenv("VESPA_WEB_SERVICE_PORT", "4488") + ws = VespaContainerWebServicePort() + assert.Equal(t, 4488, ws) +} + +func TestConfigProxyRpcAddr(t *testing.T) { + setup(t) + addr := VespaConfigProxyRpcAddr() + assert.Equal(t, "tcp/localhost:17090", addr) + t.Setenv("VESPA_PORT_BASE", "") + addr = VespaConfigProxyRpcAddr() + assert.Equal(t, "tcp/localhost:19090", addr) + t.Setenv("port_configproxy_rpc", "16066") + addr = VespaConfigProxyRpcAddr() + assert.Equal(t, "tcp/localhost:16066", addr) +} + +func TestConfigSourcesRpcAddrs(t *testing.T) { + setup(t) + cs := VespaConfigSourcesRpcAddrs() + assert.Equal(t, len(cs), 4) + assert.Equal(t, cs[0], "tcp/localhost:17090") + assert.Equal(t, cs[1], "tcp/foo1.local:17070") + t.Setenv("port_configserver_rpc", "12345") + cs = VespaConfigSourcesRpcAddrs() + assert.Equal(t, len(cs), 4) + assert.Equal(t, cs[1], "tcp/foo1.local:12345") +} + +func TestConfigserverHosts(t *testing.T) { + setup(t) + var cs []string + t.Setenv("VESPA_CONFIGSERVERS", "foo.bar") + cs = VespaConfigserverHosts() + assert.Equal(t, len(cs), 1) + assert.Equal(t, cs[0], "foo.bar") + cs = VespaConfigserverRpcAddrs() + assert.Equal(t, len(cs), 1) + assert.Equal(t, cs[0], "tcp/foo.bar:17070") + cs = VespaConfigserverRestUrls() + assert.Equal(t, len(cs), 1) + assert.Equal(t, cs[0], "http://foo.bar:17071") + + t.Setenv("VESPA_CONFIGSERVERS", "foo.bar:18080") + cs = VespaConfigserverHosts() + assert.Equal(t, len(cs), 1) + assert.Equal(t, cs[0], "foo.bar") + cs = VespaConfigserverRpcAddrs() + assert.Equal(t, len(cs), 1) + assert.Equal(t, cs[0], "tcp/foo.bar:18080") + cs = VespaConfigserverRestUrls() + assert.Equal(t, len(cs), 1) + assert.Equal(t, cs[0], "http://foo.bar:18081") + + t.Setenv("VESPA_CONFIGSERVERS", "foo.local, bar.local") + cs = VespaConfigserverHosts() + assert.Equal(t, len(cs), 2) + assert.Equal(t, cs[0], "foo.local") + assert.Equal(t, cs[1], "bar.local") + cs = VespaConfigserverRpcAddrs() + assert.Equal(t, len(cs), 2) + assert.Equal(t, cs[0], "tcp/foo.local:17070") + assert.Equal(t, cs[1], "tcp/bar.local:17070") + cs = VespaConfigserverRestUrls() + assert.Equal(t, len(cs), 2) + assert.Equal(t, cs[0], "http://foo.local:17071") + assert.Equal(t, cs[1], "http://bar.local:17071") + + t.Setenv("VESPA_CONFIGSERVERS", "foo bar") + cs = VespaConfigserverHosts() + assert.Equal(t, len(cs), 2) + assert.Equal(t, cs[0], "foo") + assert.Equal(t, cs[1], "bar") + cs = VespaConfigserverRpcAddrs() + assert.Equal(t, len(cs), 2) + assert.Equal(t, cs[0], "tcp/foo:17070") + assert.Equal(t, cs[1], "tcp/bar:17070") + cs = VespaConfigserverRestUrls() + assert.Equal(t, len(cs), 2) + assert.Equal(t, cs[0], "http://foo:17071") + assert.Equal(t, cs[1], "http://bar:17071") + + t.Setenv("VESPA_CONFIGSERVERS", "foo,bar") + cs = VespaConfigserverHosts() + assert.Equal(t, len(cs), 2) + assert.Equal(t, cs[0], "foo") + assert.Equal(t, cs[1], "bar") + cs = VespaConfigserverRpcAddrs() + assert.Equal(t, len(cs), 2) + assert.Equal(t, cs[0], "tcp/foo:17070") + assert.Equal(t, cs[1], "tcp/bar:17070") + cs = VespaConfigserverRestUrls() + assert.Equal(t, len(cs), 2) + assert.Equal(t, cs[0], "http://foo:17071") + assert.Equal(t, cs[1], "http://bar:17071") + + t.Setenv("VESPA_CONFIGSERVERS", " foo , bar, ") + cs = VespaConfigserverHosts() + assert.Equal(t, len(cs), 2) + assert.Equal(t, cs[0], "foo") + assert.Equal(t, cs[1], "bar") + cs = VespaConfigserverRpcAddrs() + assert.Equal(t, len(cs), 2) + assert.Equal(t, cs[0], "tcp/foo:17070") + assert.Equal(t, cs[1], "tcp/bar:17070") + cs = VespaConfigserverRestUrls() + assert.Equal(t, len(cs), 2) + assert.Equal(t, cs[0], "http://foo:17071") + assert.Equal(t, cs[1], "http://bar:17071") + + os.Unsetenv("VESPA_CONFIGSERVERS") + cs = VespaConfigserverHosts() + assert.Equal(t, len(cs), 1) + assert.Equal(t, cs[0], "localhost") + cs = VespaConfigserverRpcAddrs() + assert.Equal(t, len(cs), 1) + assert.Equal(t, cs[0], "tcp/localhost:17070") + cs = VespaConfigserverRestUrls() + assert.Equal(t, len(cs), 1) + assert.Equal(t, cs[0], "http://localhost:17071") + + t.Setenv("VESPA_PORT_BASE", "") + cs = VespaConfigserverRpcAddrs() + assert.Equal(t, len(cs), 1) + assert.Equal(t, cs[0], "tcp/localhost:19070") +} + +func TestConfigserverHostsWithPortOverride(t *testing.T) { + setup(t) + var cs []string + t.Setenv("VESPA_CONFIGSERVERS", "foo.bar") + t.Setenv("port_configserver_rpc", "12345") + cs = VespaConfigserverRpcAddrs() + assert.Equal(t, len(cs), 1) + assert.Equal(t, cs[0], "tcp/foo.bar:12345") + cs = VespaConfigserverRestUrls() + assert.Equal(t, len(cs), 1) + assert.Equal(t, cs[0], "http://foo.bar:12346") +} + +func TestUser(t *testing.T) { + setup(t) + user := VespaUser() + assert.Equal(t, "somebody", user) + t.Setenv("VESPA_USER", "") + user = VespaUser() + assert.Equal(t, "vespa", user) +} + +func TestHome(t *testing.T) { + setup(t) + home := VespaHome() + assert.Equal(t, "/home/v/1", home) + t.Setenv("VESPA_HOME", "") + home = VespaHome() + assert.Equal(t, "/opt/vespa", home) +} + +func TestHost(t *testing.T) { + setup(t) + host := VespaHostname() + assert.Equal(t, "foo.bar.local", host) + t.Setenv("VESPA_HOSTNAME", "") + host = VespaHostname() + assert.Equal(t, "localhost", host) +} |