summaryrefslogtreecommitdiffstats
path: root/client
diff options
context:
space:
mode:
authorArne Juul <arnej@yahooinc.com>2022-10-24 10:53:44 +0000
committerArne Juul <arnej@yahooinc.com>2022-10-24 10:53:44 +0000
commitfae3786542ed48d41e8dacf02f282a849518463b (patch)
treec26e769a5c00c5ce85005f2f6a898b4f7b934498 /client
parentfa29e75a71b49fc3925349457bb43de03b6d60d8 (diff)
add go code wih API similar to defaults.cpp
Diffstat (limited to 'client')
-rw-r--r--client/go/defaults/defaults.go251
-rw-r--r--client/go/defaults/defaults_test.go194
2 files changed, 445 insertions, 0 deletions
diff --git a/client/go/defaults/defaults.go b/client/go/defaults/defaults.go
new file mode 100644
index 00000000000..c4abaacff96
--- /dev/null
+++ b/client/go/defaults/defaults.go
@@ -0,0 +1,251 @@
+// 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
+}
+
+/**
+ * Find the HTTP port for talking to configservers
+ **/
+func findConfigserverHttpPort() int {
+ return findConfigserverRpcPort() + 1
+}
+
+/**
+ * Find the RPC addresses to configservers that are configured
+ * @return 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
+ * @return 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
+ * @return 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
+ * @return 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
+}
+
+/**
+ * Find the RPC port for talking to config proxy
+ **/
+func findConfigproxyRpcPort() int {
+ p := getNumFromEnv(ENV_CONFIGPROXY_RPC_PORT)
+ if p > 0 {
+ return p
+ }
+ return VespaPortBase() + CONFIGPROXY_RPC_PORT_OFFSET
+}
+
+/**
+ * Find the RPC port for talking to configservers
+ **/
+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)
+}