Skip to content

Commit

Permalink
Merged extractTenant() with TenantUUID()
Browse files Browse the repository at this point in the history
  • Loading branch information
toszr committed Feb 24, 2022
1 parent fda5c44 commit 0a39ab5
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 50 deletions.
19 changes: 12 additions & 7 deletions src/api/v1beta1/properties.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"strings"

"github.com/Dynatrace/dynatrace-operator/src/dtclient"
"github.com/Dynatrace/dynatrace-operator/src/util"
"github.com/pkg/errors"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -261,15 +262,19 @@ func tenantUUID(apiUrl string) (string, error) {
return "", errors.WithMessagef(err, "problem parsing tenant id from url %s", apiUrl)
}

fqdn := parsedUrl.Hostname()
hostnameWithDomains := strings.FieldsFunc(fqdn,
func(r rune) bool { return r == '.' },
)
if len(hostnameWithDomains) < 1 {
return "", fmt.Errorf("problem getting tenant id from fqdn '%s'", fqdn)
// Path = "/e/<token>/api" -> ["e", "<tenant>", "api"]
subPaths := util.Tokenize(parsedUrl.Path, '/')
if len(subPaths) >= 3 && subPaths[0] == "e" && subPaths[2] == "api" {
return subPaths[1], nil
}

return hostnameWithDomains[0], nil
hostnameWithDomains := util.Tokenize(parsedUrl.Hostname(), '.')
if len(hostnameWithDomains) >= 1 {
return hostnameWithDomains[0], nil

}

return "", fmt.Errorf("problem getting tenant id from API URL '%s'", apiUrl)
}

func (dk *DynaKube) HostGroup() string {
Expand Down
28 changes: 20 additions & 8 deletions src/api/v1beta1/properties_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,20 @@ func TestTokens(t *testing.T) {

func TestTenantUUID(t *testing.T) {
t.Run("happy path", func(t *testing.T) {
apiUrl := "https://demo.dev.dynatracelabs.com/api"
expectedTenantId := "demo"
const apiUrl = "https://demo.dev.dynatracelabs.com/api"
const expectedTenantId = "demo"

actualTenantId, err := tenantUUID(apiUrl)

assert.NoErrorf(t, err, "Expected that getting tenant id from '%s' will be successful", apiUrl)
assert.Equalf(t, expectedTenantId, actualTenantId, "Expected that tenant id of %s is %s, but found %s",
apiUrl, expectedTenantId, actualTenantId,
)
})

t.Run("happy path (alternative)", func(t *testing.T) {
const apiUrl = "https://dynakube-activegate.dynatrace/e/tenant/api/v2/metrics/ingest"
const expectedTenantId = "tenant"

actualTenantId, err := tenantUUID(apiUrl)

Expand All @@ -129,9 +141,9 @@ func TestTenantUUID(t *testing.T) {
})

t.Run("missing API URL protocol", func(t *testing.T) {
apiUrl := "demo.dev.dynatracelabs.com/api"
expectedTenantId := ""
expectedError := "problem getting tenant id from fqdn ''"
const apiUrl = "demo.dev.dynatracelabs.com/api"
const expectedTenantId = ""
const expectedError = "problem getting tenant id from API URL 'demo.dev.dynatracelabs.com/api'"

actualTenantId, err := tenantUUID(apiUrl)

Expand All @@ -144,9 +156,9 @@ func TestTenantUUID(t *testing.T) {
})

t.Run("suffix-only, relative API URL", func(t *testing.T) {
apiUrl := "/api"
expectedTenantId := ""
expectedError := "problem getting tenant id from fqdn ''"
const apiUrl = "/api"
const expectedTenantId = ""
const expectedError = "problem getting tenant id from API URL '/api'"

actualTenantId, err := tenantUUID(apiUrl)

Expand Down
5 changes: 0 additions & 5 deletions src/controllers/activegate/reconciler/capability/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,6 @@ func createService(instance *dynatracev1beta1.DynaKube, feature string) *corev1.
)
}

// TODO Return nil instead of empty Service if it's not needed
//if len(ports) == 0 {
// return nil
//}

return &corev1.Service{
ObjectMeta: metav1.ObjectMeta{
Name: BuildServiceName(instance.Name, feature),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
dynatracev1beta1 "github.com/Dynatrace/dynatrace-operator/src/api/v1beta1"
"github.com/Dynatrace/dynatrace-operator/src/controllers/activegate/capability"
"github.com/Dynatrace/dynatrace-operator/src/kubeobjects"
"github.com/Dynatrace/dynatrace-operator/src/kubeobjects/address_of"
"github.com/Dynatrace/dynatrace-operator/src/util/address_of"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/intstr"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
dynatracev1beta1 "github.com/Dynatrace/dynatrace-operator/src/api/v1beta1"
"github.com/Dynatrace/dynatrace-operator/src/controllers/activegate/capability"
"github.com/Dynatrace/dynatrace-operator/src/kubeobjects"
"github.com/Dynatrace/dynatrace-operator/src/kubeobjects/address_of"
"github.com/Dynatrace/dynatrace-operator/src/util/address_of"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/util/intstr"
Expand Down
29 changes: 1 addition & 28 deletions src/ingestendpoint/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import (
"bytes"
"context"
"fmt"
"net/url"
"strings"

dynatracev1beta1 "github.com/Dynatrace/dynatrace-operator/src/api/v1beta1"
agcapability "github.com/Dynatrace/dynatrace-operator/src/controllers/activegate/capability"
Expand Down Expand Up @@ -112,14 +110,12 @@ func (g *EndpointSecretGenerator) prepare(ctx context.Context, dk *dynatracev1be

var endpointBuf bytes.Buffer

//if dk.NeedsMetricsIngest() {
if _, err := endpointBuf.WriteString(fmt.Sprintf("%s=%s\n", UrlSecretField, fields[UrlSecretField])); err != nil {
return nil, errors.WithStack(err)
}
if _, err := endpointBuf.WriteString(fmt.Sprintf("%s=%s\n", TokenSecretField, fields[TokenSecretField])); err != nil {
return nil, errors.WithStack(err)
}
//}

if dk.NeedsStatsd() {
if _, err := endpointBuf.WriteString(fmt.Sprintf("%s=%s\n", StatsdIngestUrl, fields[StatsdIngestUrl])); err != nil {
Expand All @@ -137,7 +133,6 @@ func (g *EndpointSecretGenerator) prepare(ctx context.Context, dk *dynatracev1be
func (g *EndpointSecretGenerator) PrepareFields(ctx context.Context, dk *dynatracev1beta1.DynaKube) (map[string]string, error) {
fields := make(map[string]string)

//if dk.NeedsMetricsIngest() {
var tokens corev1.Secret
if err := g.client.Get(ctx, client.ObjectKey{Name: dk.Tokens(), Namespace: g.namespace}, &tokens); err != nil {
return nil, errors.WithMessage(err, "failed to query tokens")
Expand All @@ -152,7 +147,6 @@ func (g *EndpointSecretGenerator) PrepareFields(ctx context.Context, dk *dynatra
} else {
fields[UrlSecretField] = diUrl
}
//}

if dk.NeedsStatsd() {
if statsdUrl, err := statsdIngestUrl(dk); err != nil {
Expand Down Expand Up @@ -180,12 +174,7 @@ func metricsIngestUrlForDynatraceActiveGate(dk *dynatracev1beta1.DynaKube) (stri
}

func metricsIngestUrlForClusterActiveGate(dk *dynatracev1beta1.DynaKube) (string, error) {
apiUrl, err := url.Parse(dk.Spec.APIURL)
if err != nil {
return "", errors.WithMessage(err, "failed to parse DynaKube.spec.apiUrl")
}

tenant, err := extractTenant(apiUrl)
tenant, err := dk.TenantUUID()
if err != nil {
return "", err
}
Expand All @@ -194,22 +183,6 @@ func metricsIngestUrlForClusterActiveGate(dk *dynatracev1beta1.DynaKube) (string
return fmt.Sprintf("https://%s.%s/e/%s/api/v2/metrics/ingest", serviceName, dk.Namespace, tenant), nil
}

// TODO: Merge with DynaKube.TenantUUID()?
func extractTenant(url *url.URL) (string, error) {
tenant := ""
subdomains := strings.Split(url.Hostname(), ".")
subpaths := strings.Split(url.Path, "/")
//Path = '/e/<token>/api' -> ['', 'e', '<tenant>', 'api']
if len(subpaths) >= 4 && subpaths[1] == "e" && subpaths[3] == "api" {
tenant = subpaths[2]
} else if len(subdomains) >= 2 {
tenant = subdomains[0]
} else {
return "", fmt.Errorf("failed to parse DynaKube.spec.apiUrl, unknown tenant")
}
return tenant, nil
}

func statsdIngestUrl(dk *dynatracev1beta1.DynaKube) (string, error) {
serviceName := capability.BuildServiceName(dk.Name, agcapability.MultiActiveGateName)
return fmt.Sprintf("%s.%s:%d", serviceName, dk.Namespace, agcapability.StatsdIngestPort), nil
Expand Down
File renamed without changes.
File renamed without changes.
13 changes: 13 additions & 0 deletions src/util/strings.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package util

import "strings"

func RuneIs(wanted rune) func(rune) bool {
return func(actual rune) bool {
return actual == wanted
}
}

func Tokenize(s string, separator rune) []string {
return strings.FieldsFunc(s, RuneIs(separator))
}
46 changes: 46 additions & 0 deletions src/util/strings_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package util

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestRuneIs(t *testing.T) {
t.Run("positive matches", func(t *testing.T) {
assert.True(t, RuneIs('ą')('ą'))
assert.True(t, RuneIs('\t')(' '))
assert.True(t, RuneIs(' ')(' '))
assert.True(t, RuneIs(0)(0))
})

t.Run("negative matches", func(t *testing.T) {
assert.False(t, RuneIs('ą')('ä'))
assert.False(t, RuneIs('\t')(' '))
assert.False(t, RuneIs(' ')(' '))
assert.False(t, RuneIs(0)(1))
})
}

func TestTokenize(t *testing.T) {
t.Run("separators only", func(t *testing.T) {
assert.Equal(t, []string{}, Tokenize("", ' '))
assert.Equal(t, []string{}, Tokenize(" ", ' '))
assert.Equal(t, []string{}, Tokenize(" ", ' '))
})

t.Run("start or end with separators", func(t *testing.T) {
assert.Equal(t, []string{"aaa"}, Tokenize("#aaa", '#'))
assert.Equal(t, []string{"aaa"}, Tokenize("aaa#", '#'))
assert.Equal(t, []string{"aaa"}, Tokenize("#aaa#", '#'))
assert.Equal(t, []string{"aaa"}, Tokenize("####aaa####", '#'))
})

t.Run("merged separators", func(t *testing.T) {
assert.Equal(t, []string{"a", "b", "c"}, Tokenize("/a/b/c", '/'))
assert.Equal(t, []string{"a", "b", "c"}, Tokenize("/a/b/c/", '/'))
assert.Equal(t, []string{"a", "b", "c"}, Tokenize("a/b/c", '/'))
assert.Equal(t, []string{"a", "b", "c"}, Tokenize("//a//b//c", '/'))
assert.Equal(t, []string{"a", "b", "c"}, Tokenize("//a//b//c//", '/'))
})
}

0 comments on commit 0a39ab5

Please sign in to comment.