Skip to content

Commit

Permalink
Added e2e tests
Browse files Browse the repository at this point in the history
Signed-off-by: Juraci Paixão Kröhling <[email protected]>
  • Loading branch information
jpkrohling committed Oct 18, 2018
1 parent 9eedaf2 commit 12f5a4c
Show file tree
Hide file tree
Showing 8 changed files with 149 additions and 5 deletions.
3 changes: 2 additions & 1 deletion CONTRIBUTING.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,10 @@ Accessing the provided "address" in your web browser should display the Jaeger U

==== Storage configuration

There's a template under the `test` directory that can be used to setup an Elasticsearch cluster. Alternatively, the following command can be executed to install it:
There are a set of templates under the `test` directory that can be used to setup an Elasticsearch and/or Cassandra cluster. Alternatively, the following commands can be executed to install it:

[source,bash]
----
make es
make cassandra
----
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ unit-tests:
@go test $(PACKAGES) -cover -coverprofile=cover.out

.PHONY: e2e-tests
e2e-tests: es crd build docker push
e2e-tests: cassandra es crd build docker push
@echo Running end-to-end tests...
@cp deploy/rbac.yaml deploy/test/namespace-manifests.yaml
@echo "---" >> deploy/test/namespace-manifests.yaml
Expand Down
47 changes: 47 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,53 @@ spec:
fieldPath: status.hostIP
----

== Schema migration

=== Cassandra

When the storage type is set to Cassandra, the operator will automatically create a batch job that creates the required schema for Jaeger to run. This batch job will block the Jaeger installation, so that it starts only after the schema is successfuly created. The creation of this batch job can be disabled by setting the `enabled` property to `false`:

[source,yaml]
----
apiVersion: io.jaegertracing/v1alpha1
kind: Jaeger
metadata:
name: cassandra-without-create-schema
spec:
strategy: all-in-one
storage:
type: cassandra
cassandra-create-schema:
enabled: false # <1>
----
<1> Defaults to `true`

Further aspects of the batch job can be configured as well. An example with all the possible options is shown below:

[source,yaml]
----
apiVersion: io.jaegertracing/v1alpha1
kind: Jaeger
metadata:
name: cassandra-with-create-schema
spec:
strategy: all-in-one # <1>
storage:
type: cassandra
options: # <2>
cassandra:
servers: cassandra
keyspace: jaeger_v1_datacenter3
cassandra-create-schema: # <3>
datacenter: "datacenter3"
mode: "test"
----
<1> The same works for `production`
<2> These options are for the regular Jaeger components, like `collector` and `query`
<3> The options for the `create-schema` job

NOTE: the default create-schema job uses `MODE=prod`, which implies a replication factor of `2`, using `NetworkTopologyStrategy` as the class, effectively meaning that at least 3 nodes are required in the Cassandra cluster. If a `SimpleStrategy` is desired, set the mode to `test`, which then sets the replication factor of `1`. Refer to the link:https://github.com/jaegertracing/jaeger/blob/v1.7.0/plugin/storage/cassandra/schema/create.sh[create-schema script] for more details.

== Removing an instance

To remove an instance, just use the `delete` command with the file used for the instance creation:
Expand Down
7 changes: 6 additions & 1 deletion deploy/rbac.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ rules:
- ingresses
verbs:
- "*"

- apiGroups:
- batch
resources:
- jobs
verbs:
- "*"
---

kind: RoleBinding
Expand Down
5 changes: 3 additions & 2 deletions pkg/storage/cassandra_dependencies.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ func cassandraDeps(jaeger *v1alpha1.Jaeger) []batchv1.Job {
}

if jaeger.Spec.Storage.CassandraCreateSchema.Datacenter == "" {
logrus.WithField("instance", jaeger.Name).Info("Datacenter not specified. Using 'dc1' for the cassandra-create-schema job.")
jaeger.Spec.Storage.CassandraCreateSchema.Datacenter = "dc1"
// the default in the create-schema is "dc1", but the default in Jaeger is "test"! We align with Jaeger here
logrus.WithField("instance", jaeger.Name).Info("Datacenter not specified. Using 'test' for the cassandra-create-schema job.")
jaeger.Spec.Storage.CassandraCreateSchema.Datacenter = "test"
}

if jaeger.Spec.Storage.CassandraCreateSchema.Mode == "" {
Expand Down
63 changes: 63 additions & 0 deletions test/e2e/cassandra.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package e2e

import (
goctx "context"
"fmt"
"testing"

"github.com/jaegertracing/jaeger-operator/pkg/apis/io/v1alpha1"
framework "github.com/operator-framework/operator-sdk/pkg/test"
"github.com/operator-framework/operator-sdk/pkg/test/e2eutil"
"github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Cassandra runs a test with Cassandra as the backing storage
func Cassandra(t *testing.T) {
ctx := prepare(t)
defer ctx.Cleanup()

if err := cassandraTest(t, framework.Global, ctx); err != nil {
t.Fatal(err)
}
}

func cassandraTest(t *testing.T, f *framework.Framework, ctx *framework.TestCtx) error {
cleanupOptions := &framework.CleanupOptions{TestContext: ctx, Timeout: timeout, RetryInterval: retryInterval}
namespace, err := ctx.GetNamespace()
if err != nil {
return fmt.Errorf("could not get namespace: %v", err)
}

j := &v1alpha1.Jaeger{
TypeMeta: metav1.TypeMeta{
Kind: "Jaeger",
APIVersion: "io.jaegertracing/v1alpha1",
},
ObjectMeta: metav1.ObjectMeta{
Name: "with-cassandra",
Namespace: namespace,
},
Spec: v1alpha1.JaegerSpec{
Strategy: "all-in-one",
AllInOne: v1alpha1.JaegerAllInOneSpec{},
Storage: v1alpha1.JaegerStorageSpec{
Type: "cassandra",
Options: v1alpha1.NewOptions(map[string]interface{}{"cassandra.servers": "cassandra.default.svc"}),
},
},
}

logrus.Infof("passing %v", j)
err = f.Client.Create(goctx.TODO(), j, cleanupOptions)
if err != nil {
return err
}

err = WaitForJob(t, f.KubeClient, namespace, "with-cassandra-cassandra-schema-job", retryInterval, timeout)
if err != nil {
return err
}

return e2eutil.WaitForDeployment(t, f.KubeClient, namespace, "with-cassandra", 1, retryInterval, timeout)
}
1 change: 1 addition & 0 deletions test/e2e/jaeger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func TestJaeger(t *testing.T) {

t.Run("daemonset", DaemonSet)
t.Run("sidecar", Sidecar)
t.Run("cassandra", Cassandra)
})
}

Expand Down
26 changes: 26 additions & 0 deletions test/e2e/wait_util.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,3 +87,29 @@ func WaitForIngress(t *testing.T, kubeclient kubernetes.Interface, namespace, na
t.Logf("Ingress available\n")
return nil
}

// WaitForJob checks to see if a given job has the completed successfuly
// See #WaitForDeployment for the full semantics
func WaitForJob(t *testing.T, kubeclient kubernetes.Interface, namespace, name string, retryInterval, timeout time.Duration) error {
err := wait.Poll(retryInterval, timeout, func() (done bool, err error) {
job, err := kubeclient.BatchV1().Jobs(namespace).Get(name, metav1.GetOptions{IncludeUninitialized: true})
if err != nil {
if apierrors.IsNotFound(err) {
t.Logf("Waiting for availability of %s job\n", name)
return false, nil
}
return false, err
}

if job.Status.Succeeded > 0 && job.Status.Failed == 0 && job.Status.Active == 0 {
return true, nil
}
t.Logf("Waiting for job %s to succeed. Succeeded: %d, failed: %d, active: %d\n", name, job.Status.Succeeded, job.Status.Failed, job.Status.Active)
return false, nil
})
if err != nil {
return err
}
t.Logf("Jobs succeeded\n")
return nil
}

0 comments on commit 12f5a4c

Please sign in to comment.