diff --git a/pkg/controller/logstash/env.go b/pkg/controller/logstash/env.go index bece7fa127..2c273c90be 100644 --- a/pkg/controller/logstash/env.go +++ b/pkg/controller/logstash/env.go @@ -6,6 +6,7 @@ package logstash import ( "errors" + "net/url" "path/filepath" "strings" @@ -37,7 +38,12 @@ func buildEnv(params Params, esAssociations []commonv1.Association) ([]corev1.En normalizedClusterName := normalize(clusterName) - envs = append(envs, createEnvVar(normalizedClusterName+"_ES_HOSTS", assocConf.GetURL())) + modifiedUrl, err := addPortToHttpsUrl(assocConf.GetURL()) + if err != nil { + return nil, err + } + + envs = append(envs, createEnvVar(normalizedClusterName+"_ES_HOSTS", modifiedUrl)) envs = append(envs, createEnvVar(normalizedClusterName+"_ES_USER", credentials.Username)) envs = append(envs, corev1.EnvVar{ Name: normalizedClusterName + "_ES_PASSWORD", @@ -78,3 +84,20 @@ func createEnvVar(key string, value string) corev1.EnvVar { Value: value, } } + +// addPortToHttpsUrl add port 443 to HTTPS URL if the URL does not specify the port. +// HTTPS is normally expected to be port 443. Logstash by default add port 9200 to +// elasticsearch URL regardless of HTTP/HTTPS, which could fail the connection to +// Elastic Cloud. +func addPortToHttpsUrl(esUrl string) (string, error) { + parsedUrl, err := url.Parse(esUrl) + if err != nil { + return "", err + } + + if parsedUrl.Scheme == "https" && parsedUrl.Port() == "" { + parsedUrl.Host = parsedUrl.Host + ":443" + } + + return parsedUrl.String(), nil +} diff --git a/pkg/controller/logstash/env_test.go b/pkg/controller/logstash/env_test.go index b58e8c6217..f974f20d33 100644 --- a/pkg/controller/logstash/env_test.go +++ b/pkg/controller/logstash/env_test.go @@ -8,6 +8,7 @@ import ( "context" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -138,7 +139,7 @@ func Test_getEnvVars(t *testing.T) { assocs[0].SetNamespace("default") }, wantEnvs: []corev1.EnvVar{ - {Name: "PRODUCTION_ES_HOSTS", Value: "https://some.gcp.cloud.es.io"}, + {Name: "PRODUCTION_ES_HOSTS", Value: "https://some.gcp.cloud.es.io:443"}, {Name: "PRODUCTION_ES_USER", Value: "fake_user"}, {Name: "PRODUCTION_ES_PASSWORD", ValueFrom: &corev1.EnvVarSource{ @@ -162,3 +163,60 @@ func Test_getEnvVars(t *testing.T) { }) } } + +func Test_addPortToHttpsUrl(t *testing.T) { + tests := []struct { + name string + url string + expected string + wantErr bool + }{ + { + name: "HTTPS URL without port", + url: "https://some.gcp.cloud.es.io", + expected: "https://some.gcp.cloud.es.io:443", + wantErr: false, + }, + { + name: "HTTPS URL with port", + url: "https://some.gcp.cloud.es.io:9200", + expected: "https://some.gcp.cloud.es.io:9200", + wantErr: false, + }, + { + name: "Non-HTTPS URL", + url: "http://some.gcp.cloud.es.io", + expected: "http://some.gcp.cloud.es.io", + wantErr: false, + }, + { + name: "Non-HTTPS without port", + url: "http://some.gcp.cloud.es.io:9200", + expected: "http://some.gcp.cloud.es.io:9200", + wantErr: false, + }, + { + name: "HTTPS IPv6 URL without port", + url: "https://[fe80::1]/", + expected: "https://[fe80::1]:443/", + wantErr: false, + }, + { + name: "invalid URL", + url: "ht tp://foo.com/", + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := addPortToHttpsUrl(tt.url) + if (err != nil) != tt.wantErr { + t.Errorf("addPortToHttpsUrl() error = %v, wantErr %v", err, tt.wantErr) + return + } + + assert.Equal(t, tt.expected, got) + }) + } +}