operator: Store gateway tenant information in secret instead of configmap (#8577)

pull/8578/head^2
Gerard Vanloo 2 years ago committed by GitHub
parent 2836c79537
commit 233997ef20
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      operator/CHANGELOG.md
  2. 26
      operator/internal/handlers/internal/gateway/tenant_configsecret.go
  3. 12
      operator/internal/handlers/internal/gateway/tenant_configsecret_test.go
  4. 4
      operator/internal/handlers/lokistack_create_or_update.go
  5. 59
      operator/internal/manifests/gateway.go
  6. 26
      operator/internal/manifests/gateway_test.go
  7. 40
      operator/internal/manifests/internal/config/build_test.go

@ -1,5 +1,6 @@
## Main ## Main
- [8577](https://github.com/grafana/loki/pull/8577) **Red-GV**: Store gateway tenant information in secret instead of configmap
- [8397](https://github.com/grafana/loki/pull/8397) **periklis**: Update Loki operand to v2.7.3 - [8397](https://github.com/grafana/loki/pull/8397) **periklis**: Update Loki operand to v2.7.3
- [8308](https://github.com/grafana/loki/pull/8308) **aminesnow**: operator: Cleanup ruler resources when disabled - [8308](https://github.com/grafana/loki/pull/8308) **aminesnow**: operator: Cleanup ruler resources when disabled
- [8336](https://github.com/grafana/loki/pull/8336) **periklis**: Update Loki operand to v2.7.2 - [8336](https://github.com/grafana/loki/pull/8336) **periklis**: Update Loki operand to v2.7.2

@ -35,22 +35,22 @@ type openShiftSpec struct {
CookieSecret string `json:"cookieSecret"` CookieSecret string `json:"cookieSecret"`
} }
// GetTenantConfigMapData returns the tenantName, tenantId, cookieSecret // GetTenantConfigSecretData returns the tenantName, tenantId, cookieSecret
// clusters to auto-create redirect URLs for OpenShift Auth or an error. // clusters to auto-create redirect URLs for OpenShift Auth or an error.
func GetTenantConfigMapData(ctx context.Context, k k8s.Client, req ctrl.Request) (map[string]manifests.TenantConfig, error) { func GetTenantConfigSecretData(ctx context.Context, k k8s.Client, req ctrl.Request) (map[string]manifests.TenantConfig, error) {
var tenantConfigMap corev1.ConfigMap var tenantSecret corev1.Secret
key := client.ObjectKey{Name: manifests.GatewayName(req.Name), Namespace: req.Namespace} key := client.ObjectKey{Name: manifests.GatewayName(req.Name), Namespace: req.Namespace}
if err := k.Get(ctx, key, &tenantConfigMap); err != nil { if err := k.Get(ctx, key, &tenantSecret); err != nil {
return nil, kverrors.Wrap(err, "couldn't find tenant configMap.") return nil, kverrors.Wrap(err, "couldn't find tenant secret.")
} }
tcm, err := extractTenantConfigMap(&tenantConfigMap) ts, err := extractTenantConfigMap(&tenantSecret)
if err != nil { if err != nil {
return nil, kverrors.Wrap(err, "error occurred in extracting tenants.yaml configMap.") return nil, kverrors.Wrap(err, "error occurred in extracting tenants.yaml secret.")
} }
tcmMap := make(map[string]manifests.TenantConfig) tsMap := make(map[string]manifests.TenantConfig)
for _, tenant := range tcm.Tenants { for _, tenant := range ts.Tenants {
tc := manifests.TenantConfig{} tc := manifests.TenantConfig{}
if tenant.OpenShift != nil { if tenant.OpenShift != nil {
tc.OpenShift = &manifests.TenantOpenShiftSpec{ tc.OpenShift = &manifests.TenantOpenShiftSpec{
@ -58,17 +58,17 @@ func GetTenantConfigMapData(ctx context.Context, k k8s.Client, req ctrl.Request)
} }
} }
tcmMap[tenant.Name] = tc tsMap[tenant.Name] = tc
} }
return tcmMap, nil return tsMap, nil
} }
// extractTenantConfigMap extracts tenants.yaml data if valid. // extractTenantConfigMap extracts tenants.yaml data if valid.
// This is to be used to configure tenant's authentication spec when exists. // This is to be used to configure tenant's authentication spec when exists.
func extractTenantConfigMap(cm *corev1.ConfigMap) (*tenantsConfigJSON, error) { func extractTenantConfigMap(s *corev1.Secret) (*tenantsConfigJSON, error) {
// Extract required fields from tenants.yaml // Extract required fields from tenants.yaml
tenantConfigYAML, ok := cm.BinaryData[LokiGatewayTenantFileName] tenantConfigYAML, ok := s.Data[LokiGatewayTenantFileName]
if !ok { if !ok {
return nil, kverrors.New("missing tenants.yaml file in configMap.") return nil, kverrors.New("missing tenants.yaml file in configMap.")
} }

@ -36,7 +36,7 @@ tenants:
cookieSecret: test789 cookieSecret: test789
`) `)
func TestGetTenantConfigMapData_ConfigMapExist(t *testing.T) { func TestGetTenantConfigSecretData_SecretExist(t *testing.T) {
k := &k8sfakes.FakeClient{} k := &k8sfakes.FakeClient{}
r := ctrl.Request{ r := ctrl.Request{
NamespacedName: types.NamespacedName{ NamespacedName: types.NamespacedName{
@ -47,12 +47,12 @@ func TestGetTenantConfigMapData_ConfigMapExist(t *testing.T) {
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object, _ ...client.GetOption) error { k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object, _ ...client.GetOption) error {
if name.Name == "lokistack-dev-gateway" && name.Namespace == "some-ns" { if name.Name == "lokistack-dev-gateway" && name.Namespace == "some-ns" {
k.SetClientObject(object, &corev1.ConfigMap{ k.SetClientObject(object, &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: "lokistack-dev-gateway", Name: "lokistack-dev-gateway",
Namespace: "some-ns", Namespace: "some-ns",
}, },
BinaryData: map[string][]byte{ Data: map[string][]byte{
"tenants.yaml": tenantConfigData, "tenants.yaml": tenantConfigData,
}, },
}) })
@ -60,7 +60,7 @@ func TestGetTenantConfigMapData_ConfigMapExist(t *testing.T) {
return nil return nil
} }
ts, err := GetTenantConfigMapData(context.TODO(), k, r) ts, err := GetTenantConfigSecretData(context.TODO(), k, r)
require.NotNil(t, ts) require.NotNil(t, ts)
require.NoError(t, err) require.NoError(t, err)
@ -84,7 +84,7 @@ func TestGetTenantConfigMapData_ConfigMapExist(t *testing.T) {
require.Equal(t, expected, ts) require.Equal(t, expected, ts)
} }
func TestGetTenantConfigMapData_ConfigMapNotExist(t *testing.T) { func TestGetTenantConfigSecretData_SecretNotExist(t *testing.T) {
k := &k8sfakes.FakeClient{} k := &k8sfakes.FakeClient{}
r := ctrl.Request{ r := ctrl.Request{
NamespacedName: types.NamespacedName{ NamespacedName: types.NamespacedName{
@ -97,7 +97,7 @@ func TestGetTenantConfigMapData_ConfigMapNotExist(t *testing.T) {
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found")
} }
ts, err := GetTenantConfigMapData(context.TODO(), k, r) ts, err := GetTenantConfigSecretData(context.TODO(), k, r)
require.Nil(t, ts) require.Nil(t, ts)
require.Error(t, err) require.Error(t, err)
} }

@ -190,9 +190,9 @@ func CreateOrUpdateLokiStack(
} }
// extract the existing tenant's id, cookieSecret if exists, otherwise create new. // extract the existing tenant's id, cookieSecret if exists, otherwise create new.
tenantConfigs, err = gateway.GetTenantConfigMapData(ctx, k, req) tenantConfigs, err = gateway.GetTenantConfigSecretData(ctx, k, req)
if err != nil { if err != nil {
ll.Error(err, "error in getting tenant config map data") ll.Error(err, "error in getting tenant secret data")
} }
} }

@ -30,7 +30,7 @@ var logsEndpointRe = regexp.MustCompile(`^--logs\.(?:read|tail|write|rules)\.end
// BuildGateway returns a list of k8s objects for Loki Stack Gateway // BuildGateway returns a list of k8s objects for Loki Stack Gateway
func BuildGateway(opts Options) ([]client.Object, error) { func BuildGateway(opts Options) ([]client.Object, error) {
cm, sha1C, err := gatewayConfigMap(opts) cm, tenantSecret, sha1C, err := gatewayConfigObjs(opts)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -45,7 +45,7 @@ func BuildGateway(opts Options) ([]client.Object, error) {
return nil, err return nil, err
} }
objs := []client.Object{cm, dpl, sa, saToken, svc, ing} objs := []client.Object{cm, tenantSecret, dpl, sa, saToken, svc, ing}
minTLSVersion := opts.TLSProfile.MinTLSVersion minTLSVersion := opts.TLSProfile.MinTLSVersion
ciphersList := opts.TLSProfile.Ciphers ciphersList := opts.TLSProfile.Ciphers
@ -104,10 +104,8 @@ func NewGatewayDeployment(opts Options, sha1C string) *appsv1.Deployment {
{ {
Name: "tenants", Name: "tenants",
VolumeSource: corev1.VolumeSource{ VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{ Secret: &corev1.SecretVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{ SecretName: GatewayName(opts.Name),
Name: GatewayName(opts.Name),
},
}, },
}, },
}, },
@ -349,36 +347,49 @@ func NewServiceAccountTokenSecret(opts Options) client.Object {
} }
} }
// gatewayConfigMap creates a configMap for rbac.yaml and tenants.yaml // gatewayConfigObjs creates a configMap for rbac.yaml and a secret for tenants.yaml
func gatewayConfigMap(opt Options) (*corev1.ConfigMap, string, error) { func gatewayConfigObjs(opt Options) (*corev1.ConfigMap, *corev1.Secret, string, error) {
cfg := gatewayConfigOptions(opt) cfg := gatewayConfigOptions(opt)
rbacConfig, tenantsConfig, regoConfig, err := gateway.Build(cfg) rbacConfig, tenantsConfig, regoConfig, err := gateway.Build(cfg)
if err != nil { if err != nil {
return nil, "", err return nil, nil, "", err
} }
s := sha1.New() s := sha1.New()
_, err = s.Write(tenantsConfig) _, err = s.Write(tenantsConfig)
if err != nil { if err != nil {
return nil, "", err return nil, nil, "", err
} }
sha1C := fmt.Sprintf("%x", s.Sum(nil)) sha1C := fmt.Sprintf("%x", s.Sum(nil))
return &corev1.ConfigMap{ return &corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{ TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap", Kind: "ConfigMap",
APIVersion: corev1.SchemeGroupVersion.String(), APIVersion: corev1.SchemeGroupVersion.String(),
}, },
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: GatewayName(opt.Name), Name: GatewayName(opt.Name),
Labels: commonLabels(opt.Name), Labels: commonLabels(opt.Name),
}, },
BinaryData: map[string][]byte{ BinaryData: map[string][]byte{
gateway.LokiGatewayRbacFileName: rbacConfig, gateway.LokiGatewayRbacFileName: rbacConfig,
gateway.LokiGatewayTenantFileName: tenantsConfig, gateway.LokiGatewayRegoFileName: regoConfig,
gateway.LokiGatewayRegoFileName: regoConfig, },
}, }, &corev1.Secret{
}, sha1C, nil TypeMeta: metav1.TypeMeta{
Kind: "Secret",
APIVersion: corev1.SchemeGroupVersion.String(),
},
ObjectMeta: metav1.ObjectMeta{
Name: GatewayName(opt.Name),
Labels: ComponentLabels(LabelGatewayComponent, opt.Name),
Namespace: opt.Namespace,
},
Data: map[string][]byte{
gateway.LokiGatewayTenantFileName: tenantsConfig,
},
Type: corev1.SecretTypeOpaque,
}, sha1C, nil
} }
// gatewayConfigOptions converts Options to gateway.Options // gatewayConfigOptions converts Options to gateway.Options

@ -152,7 +152,7 @@ func TestGatewayConfigMap_ReturnsSHA1OfBinaryContents(t *testing.T) {
}, },
} }
_, sha1C, err := gatewayConfigMap(opts) _, _, sha1C, err := gatewayConfigObjs(opts)
require.NoError(t, err) require.NoError(t, err)
require.NotEmpty(t, sha1C) require.NotEmpty(t, sha1C)
} }
@ -178,7 +178,7 @@ func TestBuildGateway_HasConfigForTenantMode(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
d, ok := objs[1].(*appsv1.Deployment) d, ok := objs[2].(*appsv1.Deployment)
require.True(t, ok) require.True(t, ok)
require.Len(t, d.Spec.Template.Spec.Containers, 2) require.Len(t, d.Spec.Template.Spec.Containers, 2)
} }
@ -210,7 +210,7 @@ func TestBuildGateway_HasExtraObjectsForTenantMode(t *testing.T) {
}) })
require.NoError(t, err) require.NoError(t, err)
require.Len(t, objs, 11) require.Len(t, objs, 12)
} }
func TestBuildGateway_WithExtraObjectsForTenantMode_RouteSvcMatches(t *testing.T) { func TestBuildGateway_WithExtraObjectsForTenantMode_RouteSvcMatches(t *testing.T) {
@ -243,8 +243,8 @@ func TestBuildGateway_WithExtraObjectsForTenantMode_RouteSvcMatches(t *testing.T
require.NoError(t, err) require.NoError(t, err)
svc := objs[4].(*corev1.Service) svc := objs[5].(*corev1.Service)
rt := objs[5].(*routev1.Route) rt := objs[6].(*routev1.Route)
require.Equal(t, svc.Kind, rt.Spec.To.Kind) require.Equal(t, svc.Kind, rt.Spec.To.Kind)
require.Equal(t, svc.Name, rt.Spec.To.Name) require.Equal(t, svc.Name, rt.Spec.To.Name)
require.Equal(t, svc.Spec.Ports[0].Name, rt.Spec.Port.TargetPort.StrVal) require.Equal(t, svc.Spec.Ports[0].Name, rt.Spec.Port.TargetPort.StrVal)
@ -280,8 +280,8 @@ func TestBuildGateway_WithExtraObjectsForTenantMode_ServiceAccountNameMatches(t
require.NoError(t, err) require.NoError(t, err)
dpl := objs[1].(*appsv1.Deployment) dpl := objs[2].(*appsv1.Deployment)
sa := objs[2].(*corev1.ServiceAccount) sa := objs[3].(*corev1.ServiceAccount)
require.Equal(t, dpl.Spec.Template.Spec.ServiceAccountName, sa.Name) require.Equal(t, dpl.Spec.Template.Spec.ServiceAccountName, sa.Name)
} }
@ -450,7 +450,7 @@ func TestBuildGateway_WithTLSProfile(t *testing.T) {
objs, err := BuildGateway(tc.options) objs, err := BuildGateway(tc.options)
require.NoError(t, err) require.NoError(t, err)
d, ok := objs[1].(*appsv1.Deployment) d, ok := objs[2].(*appsv1.Deployment)
require.True(t, ok) require.True(t, ok)
for _, arg := range tc.expectedArgs { for _, arg := range tc.expectedArgs {
@ -659,7 +659,7 @@ func TestBuildGateway_WithRulesEnabled(t *testing.T) {
objs, err := BuildGateway(tc.opts) objs, err := BuildGateway(tc.opts)
require.NoError(t, err) require.NoError(t, err)
d, ok := objs[1].(*appsv1.Deployment) d, ok := objs[2].(*appsv1.Deployment)
require.True(t, ok) require.True(t, ok)
for _, arg := range tc.wantArgs { for _, arg := range tc.wantArgs {
@ -702,7 +702,7 @@ func TestBuildGateway_WithHTTPEncryption(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
dpl := objs[1].(*appsv1.Deployment) dpl := objs[2].(*appsv1.Deployment)
require.NotNil(t, dpl) require.NotNil(t, dpl)
require.Len(t, dpl.Spec.Template.Spec.Containers, 1) require.Len(t, dpl.Spec.Template.Spec.Containers, 1)
@ -793,10 +793,8 @@ func TestBuildGateway_WithHTTPEncryption(t *testing.T) {
{ {
Name: "tenants", Name: "tenants",
VolumeSource: corev1.VolumeSource{ VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{ Secret: &corev1.SecretVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{ SecretName: "abcd-gateway",
Name: "abcd-gateway",
},
}, },
}, },
}, },

@ -193,8 +193,8 @@ overrides:
Namespace: "test-ns", Namespace: "test-ns",
Name: "test", Name: "test",
Compactor: Address{ Compactor: Address{
FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local",
Port: 9095, Port: 9095,
}, },
FrontendWorker: Address{ FrontendWorker: Address{
FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local",
@ -459,8 +459,8 @@ overrides:
Namespace: "test-ns", Namespace: "test-ns",
Name: "test", Name: "test",
Compactor: Address{ Compactor: Address{
FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local",
Port: 9095, Port: 9095,
}, },
FrontendWorker: Address{ FrontendWorker: Address{
FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local",
@ -533,8 +533,8 @@ func TestBuild_ConfigAndRuntimeConfig_CreateLokiConfigFailed(t *testing.T) {
Namespace: "test-ns", Namespace: "test-ns",
Name: "test", Name: "test",
Compactor: Address{ Compactor: Address{
FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local",
Port: 9095, Port: 9095,
}, },
FrontendWorker: Address{ FrontendWorker: Address{
FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local",
@ -821,8 +821,8 @@ overrides:
Namespace: "test-ns", Namespace: "test-ns",
Name: "test", Name: "test",
Compactor: Address{ Compactor: Address{
FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local",
Port: 9095, Port: 9095,
}, },
FrontendWorker: Address{ FrontendWorker: Address{
FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local",
@ -1157,8 +1157,8 @@ overrides:
Namespace: "test-ns", Namespace: "test-ns",
Name: "test", Name: "test",
Compactor: Address{ Compactor: Address{
FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local",
Port: 9095, Port: 9095,
}, },
FrontendWorker: Address{ FrontendWorker: Address{
FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local",
@ -1507,8 +1507,8 @@ overrides:
Namespace: "test-ns", Namespace: "test-ns",
Name: "test", Name: "test",
Compactor: Address{ Compactor: Address{
FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local",
Port: 9095, Port: 9095,
}, },
FrontendWorker: Address{ FrontendWorker: Address{
FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local",
@ -1898,8 +1898,8 @@ overrides:
Port: 9095, Port: 9095,
}, },
Compactor: Address{ Compactor: Address{
FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local",
Port: 9095, Port: 9095,
}, },
StorageDirectory: "/tmp/loki", StorageDirectory: "/tmp/loki",
MaxConcurrent: MaxConcurrent{ MaxConcurrent: MaxConcurrent{
@ -2199,8 +2199,8 @@ overrides:
Namespace: "test-ns", Namespace: "test-ns",
Name: "test", Name: "test",
Compactor: Address{ Compactor: Address{
FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local",
Port: 9095, Port: 9095,
}, },
FrontendWorker: Address{ FrontendWorker: Address{
FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local",
@ -2605,8 +2605,8 @@ overrides:
Namespace: "test-ns", Namespace: "test-ns",
Name: "test", Name: "test",
Compactor: Address{ Compactor: Address{
FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local",
Port: 9095, Port: 9095,
}, },
FrontendWorker: Address{ FrontendWorker: Address{
FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local",
@ -2948,8 +2948,8 @@ overrides:
Namespace: "test-ns", Namespace: "test-ns",
Name: "test", Name: "test",
Compactor: Address{ Compactor: Address{
FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-compactor-grpc-lokistack-dev.default.svc.cluster.local",
Port: 9095, Port: 9095,
}, },
FrontendWorker: Address{ FrontendWorker: Address{
FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local", FQDN: "loki-query-frontend-grpc-lokistack-dev.default.svc.cluster.local",

Loading…
Cancel
Save