mirror of https://github.com/grafana/loki
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
629 lines
15 KiB
629 lines
15 KiB
package manifests
|
|
|
|
import (
|
|
"math/rand"
|
|
"reflect"
|
|
"testing"
|
|
|
|
configv1 "github.com/grafana/loki/operator/apis/config/v1"
|
|
lokiv1 "github.com/grafana/loki/operator/apis/loki/v1"
|
|
"github.com/grafana/loki/operator/internal/manifests/openshift"
|
|
|
|
"github.com/google/uuid"
|
|
"github.com/stretchr/testify/require"
|
|
|
|
routev1 "github.com/openshift/api/route/v1"
|
|
appsv1 "k8s.io/api/apps/v1"
|
|
corev1 "k8s.io/api/core/v1"
|
|
)
|
|
|
|
func TestNewGatewayDeployment_HasTemplateConfigHashAnnotation(t *testing.T) {
|
|
sha1C := "deadbeef"
|
|
ss := NewGatewayDeployment(Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Compactor: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
Distributor: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
Ingester: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
Querier: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
QueryFrontend: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
},
|
|
}, sha1C)
|
|
|
|
expected := "loki.grafana.com/config-hash"
|
|
annotations := ss.Spec.Template.Annotations
|
|
require.Contains(t, annotations, expected)
|
|
require.Equal(t, annotations[expected], sha1C)
|
|
}
|
|
|
|
func TestGatewayConfigMap_ReturnsSHA1OfBinaryContents(t *testing.T) {
|
|
opts := Options{
|
|
Name: uuid.New().String(),
|
|
Namespace: uuid.New().String(),
|
|
Image: uuid.New().String(),
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Compactor: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
Distributor: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
Ingester: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
Querier: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
QueryFrontend: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.Dynamic,
|
|
Authentication: []lokiv1.AuthenticationSpec{
|
|
{
|
|
TenantName: "test",
|
|
TenantID: "1234",
|
|
OIDC: &lokiv1.OIDCSpec{
|
|
Secret: &lokiv1.TenantSecretSpec{
|
|
Name: "test",
|
|
},
|
|
IssuerURL: "https://127.0.0.1:5556/dex",
|
|
RedirectURL: "https://localhost:8443/oidc/test/callback",
|
|
GroupClaim: "test",
|
|
UsernameClaim: "test",
|
|
},
|
|
},
|
|
},
|
|
Authorization: &lokiv1.AuthorizationSpec{
|
|
OPA: &lokiv1.OPASpec{
|
|
URL: "http://127.0.0.1:8181/v1/data/observatorium/allow",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
Tenants: Tenants{
|
|
Secrets: []*TenantSecrets{
|
|
{
|
|
TenantName: "test",
|
|
ClientID: "test",
|
|
ClientSecret: "test",
|
|
IssuerCAPath: "/tmp/test",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
_, sha1C, err := gatewayConfigMap(opts)
|
|
require.NoError(t, err)
|
|
require.NotEmpty(t, sha1C)
|
|
}
|
|
|
|
func TestBuildGateway_HasConfigForTenantMode(t *testing.T) {
|
|
objs, err := BuildGateway(Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Gates: configv1.FeatureGates{
|
|
LokiStackGateway: true,
|
|
},
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Gateway: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.OpenshiftLogging,
|
|
},
|
|
},
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
d, ok := objs[1].(*appsv1.Deployment)
|
|
require.True(t, ok)
|
|
require.Len(t, d.Spec.Template.Spec.Containers, 2)
|
|
}
|
|
|
|
func TestBuildGateway_HasExtraObjectsForTenantMode(t *testing.T) {
|
|
objs, err := BuildGateway(Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Gates: configv1.FeatureGates{
|
|
LokiStackGateway: true,
|
|
},
|
|
OpenShiftOptions: openshift.Options{
|
|
BuildOpts: openshift.BuildOptions{
|
|
GatewayName: "abc",
|
|
LokiStackName: "abc",
|
|
LokiStackNamespace: "efgh",
|
|
},
|
|
},
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Gateway: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.OpenshiftLogging,
|
|
},
|
|
},
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
require.Len(t, objs, 9)
|
|
}
|
|
|
|
func TestBuildGateway_WithExtraObjectsForTenantMode_RouteSvcMatches(t *testing.T) {
|
|
objs, err := BuildGateway(Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Gates: configv1.FeatureGates{
|
|
LokiStackGateway: true,
|
|
},
|
|
OpenShiftOptions: openshift.Options{
|
|
BuildOpts: openshift.BuildOptions{
|
|
GatewayName: "abc",
|
|
GatewaySvcName: serviceNameGatewayHTTP("abcd"),
|
|
GatewaySvcTargetPort: gatewayHTTPPortName,
|
|
LokiStackName: "abc",
|
|
LokiStackNamespace: "efgh",
|
|
},
|
|
},
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Gateway: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.OpenshiftLogging,
|
|
},
|
|
},
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
svc := objs[2].(*corev1.Service)
|
|
rt := objs[3].(*routev1.Route)
|
|
require.Equal(t, svc.Kind, rt.Spec.To.Kind)
|
|
require.Equal(t, svc.Name, rt.Spec.To.Name)
|
|
require.Equal(t, svc.Spec.Ports[0].Name, rt.Spec.Port.TargetPort.StrVal)
|
|
}
|
|
|
|
func TestBuildGateway_WithExtraObjectsForTenantMode_ServiceAccountNameMatches(t *testing.T) {
|
|
objs, err := BuildGateway(Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Gates: configv1.FeatureGates{
|
|
LokiStackGateway: true,
|
|
},
|
|
OpenShiftOptions: openshift.Options{
|
|
BuildOpts: openshift.BuildOptions{
|
|
GatewayName: GatewayName("abcd"),
|
|
GatewaySvcName: serviceNameGatewayHTTP("abcd"),
|
|
GatewaySvcTargetPort: gatewayHTTPPortName,
|
|
LokiStackName: "abc",
|
|
LokiStackNamespace: "efgh",
|
|
},
|
|
},
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Gateway: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.OpenshiftLogging,
|
|
},
|
|
},
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
dpl := objs[1].(*appsv1.Deployment)
|
|
sa := objs[4].(*corev1.ServiceAccount)
|
|
require.Equal(t, dpl.Spec.Template.Spec.ServiceAccountName, sa.Name)
|
|
}
|
|
|
|
func TestBuildGateway_WithExtraObjectsForTenantMode_ReplacesIngressWithRoute(t *testing.T) {
|
|
objs, err := BuildGateway(Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Gates: configv1.FeatureGates{
|
|
LokiStackGateway: true,
|
|
},
|
|
OpenShiftOptions: openshift.Options{
|
|
BuildOpts: openshift.BuildOptions{
|
|
GatewayName: GatewayName("abcd"),
|
|
GatewaySvcName: serviceNameGatewayHTTP("abcd"),
|
|
GatewaySvcTargetPort: gatewayHTTPPortName,
|
|
LokiStackName: "abc",
|
|
LokiStackNamespace: "efgh",
|
|
},
|
|
},
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Gateway: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.OpenshiftLogging,
|
|
},
|
|
},
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
var kinds []string
|
|
for _, o := range objs {
|
|
kinds = append(kinds, reflect.TypeOf(o).String())
|
|
}
|
|
|
|
require.NotContains(t, kinds, "*v1.Ingress")
|
|
require.Contains(t, kinds, "*v1.Route")
|
|
}
|
|
|
|
func TestBuildGateway_WithTLSProfile(t *testing.T) {
|
|
tt := []struct {
|
|
desc string
|
|
options Options
|
|
expectedArgs []string
|
|
}{
|
|
{
|
|
desc: "static mode",
|
|
options: Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Gates: configv1.FeatureGates{
|
|
LokiStackGateway: true,
|
|
HTTPEncryption: true,
|
|
TLSProfile: string(configv1.TLSProfileOldType),
|
|
},
|
|
TLSProfileSpec: configv1.TLSProfileSpec{
|
|
MinTLSVersion: "min-version",
|
|
Ciphers: []string{"cipher1", "cipher2"},
|
|
},
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Gateway: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.Static,
|
|
Authorization: &lokiv1.AuthorizationSpec{
|
|
Roles: []lokiv1.RoleSpec{
|
|
{
|
|
Name: "some-name",
|
|
Resources: []string{"metrics"},
|
|
Tenants: []string{"test-a"},
|
|
Permissions: []lokiv1.PermissionType{"read"},
|
|
},
|
|
},
|
|
RoleBindings: []lokiv1.RoleBindingsSpec{
|
|
{
|
|
Name: "test-a",
|
|
Subjects: []lokiv1.Subject{
|
|
{
|
|
Name: "test@example.com",
|
|
Kind: "user",
|
|
},
|
|
},
|
|
Roles: []string{"read-write"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
expectedArgs: []string{
|
|
"--tls.min-version=min-version",
|
|
"--tls.cipher-suites=cipher1,cipher2",
|
|
},
|
|
},
|
|
{
|
|
desc: "dynamic mode",
|
|
options: Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Gates: configv1.FeatureGates{
|
|
LokiStackGateway: true,
|
|
HTTPEncryption: true,
|
|
TLSProfile: string(configv1.TLSProfileOldType),
|
|
},
|
|
TLSProfileSpec: configv1.TLSProfileSpec{
|
|
MinTLSVersion: "min-version",
|
|
Ciphers: []string{"cipher1", "cipher2"},
|
|
},
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Gateway: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.Dynamic,
|
|
},
|
|
},
|
|
},
|
|
expectedArgs: []string{
|
|
"--tls.min-version=min-version",
|
|
"--tls.cipher-suites=cipher1,cipher2",
|
|
},
|
|
},
|
|
{
|
|
desc: "openshift-logging mode",
|
|
options: Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Gates: configv1.FeatureGates{
|
|
LokiStackGateway: true,
|
|
HTTPEncryption: true,
|
|
TLSProfile: string(configv1.TLSProfileOldType),
|
|
},
|
|
TLSProfileSpec: configv1.TLSProfileSpec{
|
|
MinTLSVersion: "min-version",
|
|
Ciphers: []string{"cipher1", "cipher2"},
|
|
},
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Gateway: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.OpenshiftLogging,
|
|
},
|
|
},
|
|
},
|
|
expectedArgs: []string{
|
|
"--tls.min-version=min-version",
|
|
"--tls.cipher-suites=cipher1,cipher2",
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range tt {
|
|
tc := tc
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
t.Parallel()
|
|
objs, err := BuildGateway(tc.options)
|
|
require.NoError(t, err)
|
|
|
|
d, ok := objs[1].(*appsv1.Deployment)
|
|
require.True(t, ok)
|
|
|
|
for _, arg := range tc.expectedArgs {
|
|
require.Contains(t, d.Spec.Template.Spec.Containers[0].Args, arg)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBuildGateway_WithRulesEnabled(t *testing.T) {
|
|
tt := []struct {
|
|
desc string
|
|
opts Options
|
|
wantArgs []string
|
|
missingArgs []string
|
|
}{
|
|
{
|
|
desc: "rules disabled",
|
|
opts: Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Gates: configv1.FeatureGates{
|
|
LokiStackGateway: true,
|
|
},
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Gateway: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.Static,
|
|
Authorization: &lokiv1.AuthorizationSpec{
|
|
Roles: []lokiv1.RoleSpec{
|
|
{
|
|
Name: "some-name",
|
|
Resources: []string{"metrics"},
|
|
Tenants: []string{"test-a"},
|
|
Permissions: []lokiv1.PermissionType{"read"},
|
|
},
|
|
},
|
|
RoleBindings: []lokiv1.RoleBindingsSpec{
|
|
{
|
|
Name: "test-a",
|
|
Subjects: []lokiv1.Subject{
|
|
{
|
|
Name: "test@example.com",
|
|
Kind: "user",
|
|
},
|
|
},
|
|
Roles: []string{"read-write"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
missingArgs: []string{
|
|
"--logs.rules.endpoint=http://abcd-ruler-http.efgh.svc.cluster.local:3100",
|
|
"--logs.rules.read-only=true",
|
|
},
|
|
},
|
|
{
|
|
desc: "static mode",
|
|
opts: Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Gates: configv1.FeatureGates{
|
|
LokiStackGateway: true,
|
|
},
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Gateway: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Rules: &lokiv1.RulesSpec{
|
|
Enabled: true,
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.Static,
|
|
Authorization: &lokiv1.AuthorizationSpec{
|
|
Roles: []lokiv1.RoleSpec{
|
|
{
|
|
Name: "some-name",
|
|
Resources: []string{"metrics"},
|
|
Tenants: []string{"test-a"},
|
|
Permissions: []lokiv1.PermissionType{"read"},
|
|
},
|
|
},
|
|
RoleBindings: []lokiv1.RoleBindingsSpec{
|
|
{
|
|
Name: "test-a",
|
|
Subjects: []lokiv1.Subject{
|
|
{
|
|
Name: "test@example.com",
|
|
Kind: "user",
|
|
},
|
|
},
|
|
Roles: []string{"read-write"},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
wantArgs: []string{
|
|
"--logs.rules.endpoint=http://abcd-ruler-http.efgh.svc.cluster.local:3100",
|
|
"--logs.rules.read-only=true",
|
|
},
|
|
},
|
|
{
|
|
desc: "dynamic mode",
|
|
opts: Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Gates: configv1.FeatureGates{
|
|
LokiStackGateway: true,
|
|
},
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Gateway: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Rules: &lokiv1.RulesSpec{
|
|
Enabled: true,
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.Dynamic,
|
|
},
|
|
},
|
|
},
|
|
wantArgs: []string{
|
|
"--logs.rules.endpoint=http://abcd-ruler-http.efgh.svc.cluster.local:3100",
|
|
"--logs.rules.read-only=true",
|
|
},
|
|
},
|
|
{
|
|
desc: "openshift-logging mode",
|
|
opts: Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Gates: configv1.FeatureGates{
|
|
LokiStackGateway: true,
|
|
HTTPEncryption: true,
|
|
OpenShift: configv1.OpenShiftFeatureGates{
|
|
ServingCertsService: true,
|
|
},
|
|
},
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Gateway: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Rules: &lokiv1.RulesSpec{
|
|
Enabled: true,
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.OpenshiftLogging,
|
|
},
|
|
},
|
|
},
|
|
wantArgs: []string{
|
|
"--logs.rules.endpoint=https://abcd-ruler-http.efgh.svc.cluster.local:3100",
|
|
"--logs.rules.read-only=true",
|
|
},
|
|
},
|
|
{
|
|
desc: "openshift-network mode",
|
|
opts: Options{
|
|
Name: "abcd",
|
|
Namespace: "efgh",
|
|
Gates: configv1.FeatureGates{
|
|
LokiStackGateway: true,
|
|
HTTPEncryption: true,
|
|
OpenShift: configv1.OpenShiftFeatureGates{
|
|
ServingCertsService: true,
|
|
},
|
|
},
|
|
Stack: lokiv1.LokiStackSpec{
|
|
Template: &lokiv1.LokiTemplateSpec{
|
|
Gateway: &lokiv1.LokiComponentSpec{
|
|
Replicas: rand.Int31(),
|
|
},
|
|
},
|
|
Rules: &lokiv1.RulesSpec{
|
|
Enabled: true,
|
|
},
|
|
Tenants: &lokiv1.TenantsSpec{
|
|
Mode: lokiv1.OpenshiftLogging,
|
|
},
|
|
},
|
|
},
|
|
wantArgs: []string{
|
|
"--logs.rules.endpoint=https://abcd-ruler-http.efgh.svc.cluster.local:3100",
|
|
"--logs.rules.read-only=true",
|
|
},
|
|
},
|
|
}
|
|
for _, tc := range tt {
|
|
tc := tc
|
|
t.Run(tc.desc, func(t *testing.T) {
|
|
t.Parallel()
|
|
objs, err := BuildGateway(tc.opts)
|
|
require.NoError(t, err)
|
|
|
|
d, ok := objs[1].(*appsv1.Deployment)
|
|
require.True(t, ok)
|
|
|
|
for _, arg := range tc.wantArgs {
|
|
require.Contains(t, d.Spec.Template.Spec.Containers[0].Args, arg)
|
|
}
|
|
for _, arg := range tc.missingArgs {
|
|
require.NotContains(t, d.Spec.Template.Spec.Containers[0].Args, arg)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|