Skip to content

Commit

Permalink
operator: Expose Loki Ruler API via the lokistack-gateway (#7254)
Browse files Browse the repository at this point in the history
  • Loading branch information
periklis authored Sep 29, 2022
1 parent 10e9695 commit ec0bf70
Show file tree
Hide file tree
Showing 3 changed files with 241 additions and 0 deletions.
1 change: 1 addition & 0 deletions operator/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## Main

- [7254](https://github.com/grafana/loki/pull/7254) **periklis**: Expose Loki Ruler API via the lokistack-gateway
- [7214](https://github.com/grafana/loki/pull/7214) **periklis**: Fix ruler GRPC tls client configuration
- [7201](https://github.com/grafana/loki/pull/7201) **xperimental**: Write configuration for per-tenant retention
- [7037](https://github.com/grafana/loki/pull/7037) **xperimental**: Skip enforcing matcher for certain tenants on OpenShift
Expand Down
29 changes: 29 additions & 0 deletions operator/internal/manifests/gateway.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,12 @@ func BuildGateway(opts Options) ([]client.Object, error) {
}
}

if opts.Stack.Rules != nil && opts.Stack.Rules.Enabled {
if err := configureGatewayRulesAPI(&dpl.Spec.Template.Spec, opts.Name, opts.Namespace); err != nil {
return nil, err
}
}

if opts.Stack.Tenants != nil {
mode := opts.Stack.Tenants.Mode

Expand Down Expand Up @@ -420,6 +426,29 @@ func configureGatewayMetricsPKI(podSpec *corev1.PodSpec, serviceName, minTLSVers
return nil
}

func configureGatewayRulesAPI(podSpec *corev1.PodSpec, stackName, stackNs string) error {
var gwIndex int
for i, c := range podSpec.Containers {
if c.Name == gatewayContainerName {
gwIndex = i
break
}
}

container := corev1.Container{
Args: []string{
fmt.Sprintf("--logs.rules.endpoint=http://%s:%d", fqdn(serviceNameRulerHTTP(stackName), stackNs), httpPort),
"--logs.rules.read-only=true",
},
}

if err := mergo.Merge(&podSpec.Containers[gwIndex], container, mergo.WithAppendSlice); err != nil {
return kverrors.Wrap(err, "failed to merge container")
}

return nil
}

func configureDeploymentForRestrictedPolicy(d *appsv1.Deployment, fg configv1.FeatureGates) {
podSpec := d.Spec.Template.Spec

Expand Down
211 changes: 211 additions & 0 deletions operator/internal/manifests/gateway_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,5 +414,216 @@ func TestBuildGateway_WithTLSProfile(t *testing.T) {
}
})
}
}

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)
}
})
}
}

0 comments on commit ec0bf70

Please sign in to comment.