Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add medusa non regression test #1052

Merged
merged 12 commits into from
Sep 20, 2023
4 changes: 3 additions & 1 deletion .github/workflows/kind_e2e_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,10 @@ jobs:
- CreateSingleReaper
- CreateReaperAndDatacenter
- CreateSingleMedusaJob
- CreateSingleDseMedusaJob
- ConfigControllerRestarts
- SingleDcEncryptionWithStargate
# TODO: these e2e tests started breaking after new client certificates were added. Needs fixing.
#- SingleDcEncryptionWithStargate
- SingleDcEncryptionWithReaper
- GCTests/3.11-jdk8-G1
- GCTests/3.11-jdk8-CMS
Expand Down
3 changes: 2 additions & 1 deletion .github/workflows/kind_multicluster_e2e_tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ jobs:
- ClusterScoped/MultiDcMultiCluster
- CreateMultiMedusaJob
- MultiDcAuthOnOff
- MultiDcEncryptionWithStargate
# TODO: these e2e tests started breaking after new client certificates were added. Needs fixing.
#- MultiDcEncryptionWithStargate
- MultiDcEncryptionWithReaper
- StopAndRestartDc
- CreateMultiDatacenterDseCluster
Expand Down
7 changes: 5 additions & 2 deletions CHANGELOG/CHANGELOG-1.9.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ When cutting a new release, update the `unreleased` heading to the tag being gen

## unreleased

* [CHANGE] [#1037](https://github.com/k8ssandra/k8ssandra-operator/issues/1037) Upgrade Medusa to v0.16.1
* [CHANGE] Upgrade to cass-operator v1.17.1
* [ENHANCEMENT] [#1045](https://github.com/k8ssandra/k8ssandra-operator/issues/1045) Validate MedusaBackup before doing restore to prevent data loss scenarios
* [ENHANCEMENT] [#1046](https://github.com/k8ssandra/k8ssandra-operator/issues/1046) Add detailed backup information in the MedusaBackup CRD status
* [BUGFIX] [#1027](https://github.com/k8ssandra/k8ssandra-operator/issues/1027) Point system-logger image to use the v1.16.0 tag instead of latest
* [BUGFIX] [#1026](https://github.com/k8ssandra/k8ssandra-operator/issues/1026) Fix DC name overrides not being properly handled
* [BUGFIX] [#981](https://github.com/k8ssandra/k8ssandra-operator/issues/981) Fix race condition in K8ssandraTask status update
* [BUGFIX] [#1023](https://github.com/k8ssandra/k8ssandra-operator/issues/1023) Ensure merged serverVersion passed to IsNewMetricsEndpointAvailable()
* [DOCS] [#1019](https://github.com/k8ssandra/k8ssandra-operator/issues/1019) Add PR review guidelines documentation
* [BUGFIX] [#1017](https://github.com/k8ssandra/k8ssandra-operator/issues/1017) Fix MedusaTask to delete only its own backups
* [CHANGE] Upgrade to cass-operator v1.17.1
* [DOCS] [#1019](https://github.com/k8ssandra/k8ssandra-operator/issues/1019) Add PR review guidelines documentation
* [TESTING] [#1037](https://github.com/k8ssandra/k8ssandra-operator/issues/1037) Add non regression test for Medusa issue with scale up after a restore
* [TESTING] [#1037](https://github.com/k8ssandra/k8ssandra-operator/issues/1037) Add e2e test for Medusa against DSE
59 changes: 58 additions & 1 deletion docs/content/en/tasks/secure/encryption/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ You could clone the [cassandra-toolbox](https://github.com/thelastpickle/cassand
distinguished_name = req_distinguished_name
prompt = no
output_password = MyPassWord123!
default_bits = 2048
default_bits = 3072

[ req_distinguished_name ]
C = FR
Expand Down Expand Up @@ -66,8 +66,49 @@ Replace the `<keystore password>` and `<truststore password>` above with each st

{{% alert title="Tip" color="success" %}}
You can repeat the above procedure to generate encryption stores for client-to-node encryption, changing the secret name appropriately.
Check the following section for more details on setting up client encryption with Medusa.
{{% /alert %}}

### Medusa client certificates

In order to work with a cluster with client to node encryption, Medusa will require an additional client certificate to be created.
First, create a `client.conf` file with the matching the root CA conf:

```conf
[ req ]
distinguished_name = req_distinguished_name
prompt = no
output_password = MyPassWord123!
default_bits = 3072

[ req_distinguished_name ]
C = FR
O = YourCompany
OU = SSLTestCluster
CN = client
```

Then, run the following command to create the certificate/key pair:

```bash
openssl req -newkey rsa:3078 -nodes -keyout client.key -out client.csr -config client.conf
```

When generating the encryption stores in the previous step, you should have created a root CA certificate and key. You can find them in the `certs` folder, with names like `ca_<date_time>.cert` and `ca_<date_time>.key`.
Rename them as : `rootca.crt` and `rootca.key`.
Now, sign the client certificate using these files:

```bash
openssl x509 -req -CA rootca.crt -CAkey rootca.key -passin pass:MyPassWord123! -in client.csr -out client.crt_signed -days 3650 -CAcreateserial
```

Finally, create a Kubernetes secret with the following command:

```bash
kubectl create secret generic client-certificates --from-file=rootca.crt --from-file=client.key --from-file=client.crt_signed -o yaml > client-certificates.yaml
```


## Creating a cluster with internode encryption

In order to create a K8ssandra cluster with encryption, first create a namespace and the encryption stores secrets previously generated in it.
Expand Down Expand Up @@ -188,6 +229,22 @@ spec:
deploymentMode: SINGLE
```

## Medusa encryption

In order to work with a cluster with client to node encryption, Medusa will require an additional client certificate to be created as previously instructed.
After having created the `client-certificates` secret, you will need to reference it in the `medusa` section of the `K8ssandraCluster` manifest:

```yaml
...
spec:
...
medusa:
certificatesSecretRef:
name: client-certificates
```

This will provide Medusa with the client certificate and key, as well as the root CA certificate, which will be used to connect to the Cassandra cluster through the Python Driver.

## Next steps

Explore other K8ssandra [tasks]({{< relref "/tasks" >}}).
Expand Down
2 changes: 1 addition & 1 deletion pkg/medusa/reconcile.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import (
const (
DefaultMedusaImageRepository = "k8ssandra"
DefaultMedusaImageName = "medusa"
DefaultMedusaVersion = "0.15.0"
DefaultMedusaVersion = "0.16.1"
DefaultMedusaPort = 50051
DefaultProbeInitialDelay = 10
DefaultProbeTimeout = 1
Expand Down
14 changes: 14 additions & 0 deletions test/e2e/medusa_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)

const (
Expand All @@ -39,6 +40,19 @@ func createSingleMedusaJob(t *testing.T, ctx context.Context, namespace string,
verifyBackupJobFinished(t, ctx, f, dcKey, backupKey)
restoreBackupJob(t, ctx, namespace, f, dcKey)
verifyRestoreJobFinished(t, ctx, f, dcKey, backupKey)

// Scale the cluster to verify that the previous restore won't break the new pod
// Not doing this for DSE tests as it takes too long
if kc.Spec.Cassandra.ServerType == "cassandra" {
t.Log("Scaling the cluster to 3 nodes")
err = f.Get(ctx, kcKey, kc)
require.NoError(err, "Error getting the K8ssandraCluster")
kcPatch := client.MergeFromWithOptions(kc.DeepCopy(), client.MergeFromWithOptimisticLock{})
kc.Spec.Cassandra.Datacenters[0].Size = 3
err = f.Client.Patch(ctx, kc, kcPatch)
require.NoError(err, "Error scaling the cluster")
checkDatacenterReady(t, ctx, dcKey, f)
}
}

func createMultiMedusaJob(t *testing.T, ctx context.Context, namespace string, f *framework.E2eFramework) {
Expand Down
17 changes: 15 additions & 2 deletions test/e2e/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,11 @@ var (
"latest",
"The k8ssandra-operator image tag to use.",
)
medusaImageTag = flag.String(
"medusaImageTag",
"",
"The medusa image tag to use.",
)
)

var (
Expand Down Expand Up @@ -271,6 +276,13 @@ func TestOperator(t *testing.T) {
doCassandraDatacenterCleanup: false,
installMinio: true,
}))
t.Run("CreateSingleDseMedusaJob", e2eTest(ctx, &e2eTestOpts{
testFunc: createSingleMedusaJob,
fixture: framework.NewTestFixture("single-dc-dse-medusa", controlPlane),
skipK8ssandraClusterCleanup: false,
doCassandraDatacenterCleanup: false,
installMinio: true,
}))
t.Run("CreateMultiMedusaJob", e2eTest(ctx, &e2eTestOpts{
testFunc: createMultiMedusaJob,
fixture: framework.NewTestFixture("multi-dc-encryption-medusa", controlPlane),
Expand Down Expand Up @@ -497,6 +509,7 @@ func beforeTest(t *testing.T, f *framework.E2eFramework, opts *e2eTestOpts) erro
ClusterScoped: opts.clusterScoped,
ImageName: *imageName,
ImageTag: *imageTag,
MedusaImageTag: *medusaImageTag,
GithubKustomization: false,
}

Expand Down Expand Up @@ -556,7 +569,7 @@ func beforeTest(t *testing.T, f *framework.E2eFramework, opts *e2eTestOpts) erro
}

if opts.fixture != nil {
if err := f.DeployFixture(opts.sutNamespace, opts.fixture, zoneMappings, *storageClassFlag, *hostNetworkFlag); err != nil {
if err := f.DeployFixture(opts.sutNamespace, opts.fixture, zoneMappings, *storageClassFlag, *hostNetworkFlag, deploymentConfig.MedusaImageTag); err != nil {
t.Logf("failed to deploy fixture")
return err
}
Expand Down Expand Up @@ -674,7 +687,7 @@ func applyPollingDefaults() {
polling.reaperReady.timeout = 10 * time.Minute
polling.reaperReady.interval = 15 * time.Second

polling.medusaBackupDone.timeout = 2 * time.Minute
polling.medusaBackupDone.timeout = 5 * time.Minute
polling.medusaBackupDone.interval = 5 * time.Second

polling.medusaRestoreDone.timeout = 10 * time.Minute
Expand Down
1 change: 1 addition & 0 deletions test/framework/e2e_framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ type OperatorDeploymentConfig struct {
ClusterScoped bool
ImageName string
ImageTag string
MedusaImageTag string
GithubKustomization bool // If true, use the kustomization.yaml from the github repo
ControlPlaneComponent string
DataPlaneComponent string
Expand Down
21 changes: 12 additions & 9 deletions test/framework/fixtures.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@ package framework

import (
"fmt"
"os"
"path/filepath"
"strings"

cassdcapi "github.com/k8ssandra/cass-operator/apis/cassandra/v1beta1"
coreapi "github.com/k8ssandra/k8ssandra-operator/apis/k8ssandra/v1alpha1"
stargateapi "github.com/k8ssandra/k8ssandra-operator/apis/stargate/v1alpha1"
"github.com/k8ssandra/k8ssandra-operator/pkg/utils"
"github.com/k8ssandra/k8ssandra-operator/test/yq"
"os"
"path/filepath"
"sigs.k8s.io/yaml"
"strings"
)

var (
Expand Down Expand Up @@ -42,14 +43,14 @@ func NewTestFixture(name, k8sContext string) *TestFixture {
}
}

func (f *E2eFramework) DeployFixture(namespace string, fixture *TestFixture, zones map[string]string, storage string, hostNetwork bool) error {
func (f *E2eFramework) DeployFixture(namespace string, fixture *TestFixture, zones map[string]string, storage string, hostNetwork bool, medusaImageTag string) error {
contexts := make(map[string]string)
for i, context := range f.DataPlaneContexts {
contexts[fmt.Sprintf("kind-k8ssandra-%v", i)] = context
}
if fixturesKustomizeTemplate, err := os.ReadFile(filepath.Join("..", "framework", "fixtures.tmpl")); err != nil {
return err
} else if kustomization, err := generateFixtureKustomization(namespace, fixture, contexts, zones, storage, hostNetwork); err != nil {
} else if kustomization, err := generateFixtureKustomization(namespace, fixture, contexts, zones, storage, hostNetwork, medusaImageTag); err != nil {
return err
} else if err = generateKustomizationFile("fixtures/"+fixture.Name, kustomization, string(fixturesKustomizeTemplate)); err != nil {
return err
Expand All @@ -68,6 +69,7 @@ type fixtureKustomization struct {
K8ssandraCluster *coreapi.K8ssandraClusterSpec
CassandraDatacenter *cassdcapi.CassandraDatacenterSpec
Stargate *stargateapi.StargateSpec
MedusaImageTag string
}

// For now, we only read and kustomize:
Expand All @@ -76,14 +78,15 @@ type fixtureKustomization struct {
// - the single (standalone) Stargate declared in stargate.yaml, if present.
// If some fixtures in the future decide to create more resources, we'll have to revisit this and
// create more fine-grained kustomizations.
func generateFixtureKustomization(namespace string, fixture *TestFixture, contexts map[string]string, zones map[string]string, storage string, hostNetwork bool) (*fixtureKustomization, error) {
func generateFixtureKustomization(namespace string, fixture *TestFixture, contexts map[string]string, zones map[string]string, storage string, hostNetwork bool, medusaImageTag string) (*fixtureKustomization, error) {
kustomization := &fixtureKustomization{
Namespace: namespace,
Fixture: fixture.Name,
FixtureDepth: strings.Repeat("../", 4+strings.Count(fixture.Name, "/")), Contexts: contexts,
Zones: zones,
Storage: storage,
HostNetwork: hostNetwork,
Zones: zones,
Storage: storage,
HostNetwork: hostNetwork,
MedusaImageTag: medusaImageTag,
}
if k8c, err := getFixtureK8ssandraCluster(fixture); err != nil {
return nil, err
Expand Down
8 changes: 8 additions & 0 deletions test/framework/fixtures.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@ patches:
value: {{ $.HostNetwork }}
{{ end }}

{{ if $.MedusaImageTag }}
- op: add
path: /spec/medusa/containerImage
value:
tag: {{ $.MedusaImageTag }}
{{ end }}


{{if $.Zones }}
{{ range $rackIndex, $rack := .Cassandra.Racks }}
{{ if index $rack.NodeAffinityLabels "topology.kubernetes.io/zone" }}
Expand Down
Loading
Loading