From 5a2ca8bb50a8ec34f5834851fb06e4cdc7e253cd Mon Sep 17 00:00:00 2001 From: Christian Schefuss Date: Thu, 21 Dec 2023 19:15:57 +0100 Subject: [PATCH 1/3] improve URI parsing for elasticsearch bindings * alternative determination of port based on URI scheme swisscom/backman#83 --- service/service.go | 10 ++++++++++ service/service_bindings_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/service/service.go b/service/service.go index a6e7203..385a2f8 100644 --- a/service/service.go +++ b/service/service.go @@ -137,6 +137,16 @@ func enrichBinding(binding config.ServiceBinding) config.ServiceBinding { binding.Port, _ = strconv.Atoi(p) } + // set well-known port based on scheme if still missing + if binding.Port == 0 { + if strings.EqualFold(u.Scheme, "https") { + binding.Port = 443 + } + if strings.EqualFold(u.Scheme, "http") { + binding.Port = 80 + } + } + // set database if not defined yet but can be found in URI if len(binding.Database) == 0 { binding.Database = strings.TrimPrefix(u.Path, "/") diff --git a/service/service_bindings_test.go b/service/service_bindings_test.go index 7e45b03..1b29fcc 100644 --- a/service/service_bindings_test.go +++ b/service/service_bindings_test.go @@ -46,3 +46,31 @@ func Test_Service_ParseServiceBindings(t *testing.T) { assert.Equal(t, "dev-secret", c.Services["my_postgres_db"].Binding.Password) // from service_binding_root/* assert.Equal(t, "postgres://dev-user:dev-secret@127.0.0.1:5432/my_postgres_db?sslmode=disable", c.Services["my_postgres_db"].Binding.URI) // from service_binding_root/* } + +func Test_Service_MergeVCAPServices(t *testing.T) { + config.SetConfigFile("_fixtures/config_without_bindings.json") + + c := config.Get() + mergeVCAPServices() + + assert.Equal(t, "postgres", c.Services["my_postgres_db"].Binding.Type) + assert.Equal(t, "127.0.0.1", c.Services["my_postgres_db"].Binding.Host) + assert.Equal(t, 5432, c.Services["my_postgres_db"].Binding.Port) + assert.Equal(t, "dev-user", c.Services["my_postgres_db"].Binding.Username) + assert.Equal(t, "dev-secret", c.Services["my_postgres_db"].Binding.Password) + assert.Equal(t, "postgres://dev-user:dev-secret@127.0.0.1:5432/my_postgres_db?sslmode=disable", c.Services["my_postgres_db"].Binding.URI) + assert.Equal(t, "https://0c061730-1b19-424b-8efd-349fd40957a0.yolo.elasticsearch.lyra-836.appcloud.swisscom.com:443", c.Services["my-elasticsearch"].Binding.URI) + + elasticsearchServiceConfig := c.Services["my-elasticsearch"] + // without enrichBinding is port undefined + assert.Equal(t, 0, elasticsearchServiceConfig.Binding.Port) + // if port is defined in uri, it is determined from there + elasticsearchServiceConfig.Binding = enrichBinding(elasticsearchServiceConfig.Binding) + assert.Equal(t, 443, elasticsearchServiceConfig.Binding.Port) + // if no port is defined in uri, it is determined by schema/protocol + elasticsearchServiceConfig.Binding.Host = "https://0c061730-1b19-424b-8efd-349fd40957a0.yolo.elasticsearch.lyra-836.appcloud.swisscom.com" + elasticsearchServiceConfig.Binding.URI = elasticsearchServiceConfig.Binding.Host + elasticsearchServiceConfig.Binding.Port = 0 + elasticsearchServiceConfig.Binding = enrichBinding(elasticsearchServiceConfig.Binding) + assert.Equal(t, 443, elasticsearchServiceConfig.Binding.Port) +} From 1562003756bd98c0ef4581099d44bf37b2297807 Mon Sep 17 00:00:00 2001 From: Christian Schefuss Date: Wed, 27 Dec 2023 09:46:25 +0100 Subject: [PATCH 2/3] improve URI parsing for elasticsearch bindings * more elegant alternative determination of port based on URI scheme swisscom/backman#83 --- service/service.go | 27 ++++++++++------- service/service_bindings_test.go | 28 ------------------ service/service_test.go | 50 ++++++++++++++++++++++++++++++++ service/vcap_services_test.go | 28 ++++++++++++++++++ 4 files changed, 94 insertions(+), 39 deletions(-) create mode 100644 service/service_test.go create mode 100644 service/vcap_services_test.go diff --git a/service/service.go b/service/service.go index 385a2f8..34389f3 100644 --- a/service/service.go +++ b/service/service.go @@ -129,7 +129,7 @@ func enrichBinding(binding config.ServiceBinding) config.ServiceBinding { } // set host and port too if still missing - h, p, _ := net.SplitHostPort(u.Host) + h, p, _ := net.SplitHostPort(canonicalHost(u)) if len(binding.Host) == 0 { binding.Host = h } @@ -137,16 +137,6 @@ func enrichBinding(binding config.ServiceBinding) config.ServiceBinding { binding.Port, _ = strconv.Atoi(p) } - // set well-known port based on scheme if still missing - if binding.Port == 0 { - if strings.EqualFold(u.Scheme, "https") { - binding.Port = 443 - } - if strings.EqualFold(u.Scheme, "http") { - binding.Port = 80 - } - } - // set database if not defined yet but can be found in URI if len(binding.Database) == 0 { binding.Database = strings.TrimPrefix(u.Path, "/") @@ -196,3 +186,18 @@ func GetService(serviceType, serviceName string) config.Service { } return config.Service{} } + +// canonicalHost returns url.Host but always with a ":port" suffix +// adapted from net/http/transport canonicalAddr +func canonicalHost(url *url.URL) string { + portMap := map[string]string{ + "http": "80", + "https": "443", + } + addr := url.Hostname() + port := url.Port() + if port == "" { + port = portMap[url.Scheme] + } + return net.JoinHostPort(addr, port) +} diff --git a/service/service_bindings_test.go b/service/service_bindings_test.go index 1b29fcc..7e45b03 100644 --- a/service/service_bindings_test.go +++ b/service/service_bindings_test.go @@ -46,31 +46,3 @@ func Test_Service_ParseServiceBindings(t *testing.T) { assert.Equal(t, "dev-secret", c.Services["my_postgres_db"].Binding.Password) // from service_binding_root/* assert.Equal(t, "postgres://dev-user:dev-secret@127.0.0.1:5432/my_postgres_db?sslmode=disable", c.Services["my_postgres_db"].Binding.URI) // from service_binding_root/* } - -func Test_Service_MergeVCAPServices(t *testing.T) { - config.SetConfigFile("_fixtures/config_without_bindings.json") - - c := config.Get() - mergeVCAPServices() - - assert.Equal(t, "postgres", c.Services["my_postgres_db"].Binding.Type) - assert.Equal(t, "127.0.0.1", c.Services["my_postgres_db"].Binding.Host) - assert.Equal(t, 5432, c.Services["my_postgres_db"].Binding.Port) - assert.Equal(t, "dev-user", c.Services["my_postgres_db"].Binding.Username) - assert.Equal(t, "dev-secret", c.Services["my_postgres_db"].Binding.Password) - assert.Equal(t, "postgres://dev-user:dev-secret@127.0.0.1:5432/my_postgres_db?sslmode=disable", c.Services["my_postgres_db"].Binding.URI) - assert.Equal(t, "https://0c061730-1b19-424b-8efd-349fd40957a0.yolo.elasticsearch.lyra-836.appcloud.swisscom.com:443", c.Services["my-elasticsearch"].Binding.URI) - - elasticsearchServiceConfig := c.Services["my-elasticsearch"] - // without enrichBinding is port undefined - assert.Equal(t, 0, elasticsearchServiceConfig.Binding.Port) - // if port is defined in uri, it is determined from there - elasticsearchServiceConfig.Binding = enrichBinding(elasticsearchServiceConfig.Binding) - assert.Equal(t, 443, elasticsearchServiceConfig.Binding.Port) - // if no port is defined in uri, it is determined by schema/protocol - elasticsearchServiceConfig.Binding.Host = "https://0c061730-1b19-424b-8efd-349fd40957a0.yolo.elasticsearch.lyra-836.appcloud.swisscom.com" - elasticsearchServiceConfig.Binding.URI = elasticsearchServiceConfig.Binding.Host - elasticsearchServiceConfig.Binding.Port = 0 - elasticsearchServiceConfig.Binding = enrichBinding(elasticsearchServiceConfig.Binding) - assert.Equal(t, 443, elasticsearchServiceConfig.Binding.Port) -} diff --git a/service/service_test.go b/service/service_test.go new file mode 100644 index 0000000..7695c7f --- /dev/null +++ b/service/service_test.go @@ -0,0 +1,50 @@ +package service + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/swisscom/backman/config" +) + +func init() { + _ = os.Chdir("../") +} + +func Test_Service_EnrichBinding(t *testing.T) { + config.SetConfigFile("_fixtures/config_without_bindings.json") + + c := config.Get() + mergeVCAPServices() + + elasticsearchServiceConfig := c.Services["my-elasticsearch"] + + // without enrichBinding is port undefined + assert.Equal(t, 0, elasticsearchServiceConfig.Binding.Port) + + // if port is defined in uri, it is determined from there + elasticsearchServiceConfig.Binding = enrichBinding(elasticsearchServiceConfig.Binding) + assert.Equal(t, 443, elasticsearchServiceConfig.Binding.Port) + + // if no port is defined in uri, it is determined by schema/protocol + elasticsearchServiceConfig.Binding.Host = "https://0c061730-1b19-424b-8efd-349fd40957a0.yolo.elasticsearch.lyra-836.appcloud.swisscom.com" + elasticsearchServiceConfig.Binding.URI = elasticsearchServiceConfig.Binding.Host + elasticsearchServiceConfig.Binding.Port = 0 + elasticsearchServiceConfig.Binding = enrichBinding(elasticsearchServiceConfig.Binding) + assert.Equal(t, 443, elasticsearchServiceConfig.Binding.Port) + + // if no port is defined in uri, it is determined by schema/protocol + elasticsearchServiceConfig.Binding.Host = "http://0c061730-1b19-424b-8efd-349fd40957a0.yolo.elasticsearch.lyra-836.appcloud.swisscom.com" + elasticsearchServiceConfig.Binding.URI = elasticsearchServiceConfig.Binding.Host + elasticsearchServiceConfig.Binding.Port = 0 + elasticsearchServiceConfig.Binding = enrichBinding(elasticsearchServiceConfig.Binding) + assert.Equal(t, 80, elasticsearchServiceConfig.Binding.Port) + + // if no port is defined in uri, it is determined by schema/protocol + elasticsearchServiceConfig.Binding.Host = "nonehttp://0c061730-1b19-424b-8efd-349fd40957a0.yolo.elasticsearch.lyra-836.appcloud.swisscom.com" + elasticsearchServiceConfig.Binding.URI = elasticsearchServiceConfig.Binding.Host + elasticsearchServiceConfig.Binding.Port = 0 + elasticsearchServiceConfig.Binding = enrichBinding(elasticsearchServiceConfig.Binding) + assert.Equal(t, 0, elasticsearchServiceConfig.Binding.Port) +} diff --git a/service/vcap_services_test.go b/service/vcap_services_test.go new file mode 100644 index 0000000..2cdb1cc --- /dev/null +++ b/service/vcap_services_test.go @@ -0,0 +1,28 @@ +package service + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/swisscom/backman/config" +) + +func init() { + _ = os.Chdir("../") +} + +func Test_Service_MergeVCAPServices(t *testing.T) { + config.SetConfigFile("_fixtures/config_without_bindings.json") + + c := config.Get() + mergeVCAPServices() + + assert.Equal(t, "postgres", c.Services["my_postgres_db"].Binding.Type) + assert.Equal(t, "127.0.0.1", c.Services["my_postgres_db"].Binding.Host) + assert.Equal(t, 5432, c.Services["my_postgres_db"].Binding.Port) + assert.Equal(t, "dev-user", c.Services["my_postgres_db"].Binding.Username) + assert.Equal(t, "dev-secret", c.Services["my_postgres_db"].Binding.Password) + assert.Equal(t, "postgres://dev-user:dev-secret@127.0.0.1:5432/my_postgres_db?sslmode=disable", c.Services["my_postgres_db"].Binding.URI) + assert.Equal(t, "https://0c061730-1b19-424b-8efd-349fd40957a0.yolo.elasticsearch.lyra-836.appcloud.swisscom.com:443", c.Services["my-elasticsearch"].Binding.URI) +} From e7c6f38d283fe28e7c93ecd589215d8068bf1e2f Mon Sep 17 00:00:00 2001 From: Christian Schefuss Date: Wed, 27 Dec 2023 11:09:49 +0100 Subject: [PATCH 3/3] improve URI parsing for elasticsearch bindings * fix testcases swisscom/backman#83 --- service/service_test.go | 8 +++----- service/vcap_services_test.go | 6 ++---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/service/service_test.go b/service/service_test.go index 7695c7f..f59557c 100644 --- a/service/service_test.go +++ b/service/service_test.go @@ -8,13 +8,11 @@ import ( "github.com/swisscom/backman/config" ) -func init() { - _ = os.Chdir("../") -} - func Test_Service_EnrichBinding(t *testing.T) { config.SetConfigFile("_fixtures/config_without_bindings.json") + os.Unsetenv("SERVICE_BINDING_ROOT") + c := config.Get() mergeVCAPServices() @@ -41,7 +39,7 @@ func Test_Service_EnrichBinding(t *testing.T) { elasticsearchServiceConfig.Binding = enrichBinding(elasticsearchServiceConfig.Binding) assert.Equal(t, 80, elasticsearchServiceConfig.Binding.Port) - // if no port is defined in uri, it is determined by schema/protocol + // if no port is defined in uri, it is determined by schema/protocol, but only known ones elasticsearchServiceConfig.Binding.Host = "nonehttp://0c061730-1b19-424b-8efd-349fd40957a0.yolo.elasticsearch.lyra-836.appcloud.swisscom.com" elasticsearchServiceConfig.Binding.URI = elasticsearchServiceConfig.Binding.Host elasticsearchServiceConfig.Binding.Port = 0 diff --git a/service/vcap_services_test.go b/service/vcap_services_test.go index 2cdb1cc..025a862 100644 --- a/service/vcap_services_test.go +++ b/service/vcap_services_test.go @@ -8,13 +8,11 @@ import ( "github.com/swisscom/backman/config" ) -func init() { - _ = os.Chdir("../") -} - func Test_Service_MergeVCAPServices(t *testing.T) { config.SetConfigFile("_fixtures/config_without_bindings.json") + os.Unsetenv("SERVICE_BINDING_ROOT") + c := config.Get() mergeVCAPServices()