Skip to content

Commit

Permalink
Add RBAC rules for operator so it can manage users (redpanda-data/hel…
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewstucki authored Sep 16, 2024
1 parent 1446196 commit 6d0c1f2
Show file tree
Hide file tree
Showing 4 changed files with 880 additions and 113 deletions.
112 changes: 0 additions & 112 deletions charts/operator/chart_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,13 @@ import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"regexp"
"slices"
"strconv"
"testing"

appsv1 "k8s.io/api/apps/v1"

fuzz "github.com/google/gofuzz"
"github.com/redpanda-data/helm-charts/pkg/helm"
"github.com/redpanda-data/helm-charts/pkg/kube"
"github.com/redpanda-data/helm-charts/pkg/testutil"
"github.com/santhosh-tekuri/jsonschema/v5"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -226,111 +222,3 @@ func makeSureTagIsNotEmptyString(values PartialValues, fuzzer *fuzz.Fuzzer) {
}
}
}

// preTranspilerChartVersion is the latest release of the Operator helm chart prior to the introduction of
// ConfigMap go base implementation. It's used to verify that translated code is functionally equivalent.
const preTranspilerChartVersion = "0.4.28"

// TestChartDifferences can be removed if in the next operator chart version values definition changes or any resource.
// That test only validates clean transition to gotohelm definition of the operator helm chart.
func TestChartDifferences(t *testing.T) {
ctx := testutil.Context(t)
client, err := helm.New(helm.Options{ConfigHome: testutil.TempDir(t)})
require.NoError(t, err)

// Downloading Operator helm chart release is required as client.Template
// function does not pass HELM_CONFIG_HOME, that prevents from downloading specific
// Operator helm chart version from public helm repository.
require.NoError(t, client.DownloadFile(ctx,
fmt.Sprintf("https://github.com/redpanda-data/helm-charts/releases/download/operator-%s/operator-%s.tgz", preTranspilerChartVersion, preTranspilerChartVersion),
fmt.Sprintf("operator-%s.tgz", preTranspilerChartVersion)))

values, err := os.ReadDir("./ci")
require.NoError(t, err)

for _, v := range values {
t.Run(v.Name(), func(t *testing.T) {
t.Parallel()

// First generate latest released Redpanda charts manifests. From ConfigMap bootstrap,
// redpanda node configuration and RPK profile.
manifests, err := client.Template(ctx,
filepath.Join(client.GetConfigHome(), fmt.Sprintf("operator-%s.tgz", preTranspilerChartVersion)),
helm.TemplateOptions{
Name: "operator",
ValuesFile: "./ci/" + v.Name(),
Set: []string{},
})
require.NoError(t, err)

oldOperator, err := convertToMap(manifests)
require.NoError(t, err)

// Now helm template will generate Redpanda configuration from local definition
manifests, err = client.Template(ctx, ".", helm.TemplateOptions{
Name: "operator",
ValuesFile: "./ci/" + v.Name(),
Set: []string{},
})
require.NoError(t, err)

operator, err := convertToMap(manifests)
require.NoError(t, err)

for key, val := range oldOperator {
require.Equal(t, val, operator[key])
delete(oldOperator, key)
delete(operator, key)
}

require.Len(t, oldOperator, 0)
require.Len(t, operator, 0)
})
}
}

func convertToMap(manifests []byte) (map[string]string, error) {
objs, err := kube.DecodeYAML(manifests, Scheme)
if err != nil {
return nil, err
}

result := map[string]string{}
for _, obj := range objs {
key := fmt.Sprintf("%s, %s", obj.GetObjectKind().GroupVersionKind().String(), obj.GetName())
if _, exist := result[key]; exist {
panic("duplicate key " + key)
}

labels := obj.GetLabels()
delete(labels, "app.kubernetes.io/version")
delete(labels, "helm.sh/chart")
obj.SetLabels(labels)

// Previous operator configuration was malformed as `{{.values.config}}` was dictionary
// which should be translated by `toYaml` function
if cfg, ok := obj.(*corev1.ConfigMap); ok && obj.GetName() == "operator-config" {
cfg.Data = map[string]string{}
obj = kube.Object(cfg)
}

// Due to operator helm chart bump the Deployment needs to remove few properites
if dep, ok := obj.(*appsv1.Deployment); ok && obj.GetName() == "operator" {
dep.Spec.Template.Spec.Containers[0].Image = "REDACTED_DUE_TO_CONTAINER_TAG_MISS_MATCH"
dep.Spec.Template.Spec.Containers[0].Args[3] = "REDACTED_DUE_TO_CONTAINER_TAG_MISS_MATCH"
obj = kube.Object(dep)
}

// In previous operator templates namespace was omitted in multiple places
obj.SetNamespace("")

b, err := yaml.Marshal(obj)
if err != nil {
return nil, err
}

result[key] = string(b)
}

return result, nil
}
15 changes: 15 additions & 0 deletions charts/operator/rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,21 @@ func Roles(dot *helmette.Dot) []rbacv1.Role {
APIGroups: []string{"cluster.redpanda.com"},
Resources: []string{"topics/status"},
},
{
Verbs: []string{"get", "list", "patch", "update", "watch"},
APIGroups: []string{"cluster.redpanda.com"},
Resources: []string{"users"},
},
{
Verbs: []string{"update"},
APIGroups: []string{"cluster.redpanda.com"},
Resources: []string{"users/finalizers"},
},
{
Verbs: []string{"get", "patch", "update"},
APIGroups: []string{"cluster.redpanda.com"},
Resources: []string{"users/status"},
},
},
})
}
Expand Down
Loading

0 comments on commit 6d0c1f2

Please sign in to comment.