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

Fix injecting volumes into rollover jobs #446

Merged
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion pkg/storage/elasticsearch.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ func ShouldDeployElasticsearch(s v1.JaegerStorageSpec) bool {

// ElasticsearchDeployment represents an ES deployment for Jaeger
type ElasticsearchDeployment struct {
Jaeger *v1.Jaeger
Jaeger *v1.Jaeger
CertScript string
Secrets []corev1.Secret
}

// InjectStorageConfiguration changes the given spec to include ES-related command line options
Expand Down
21 changes: 10 additions & 11 deletions pkg/storage/elasticsearch_secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (

const (
tmpWorkingDir = "/tmp/_certs"
certScript = "./scripts/cert_generation.sh"
)

type secret struct {
Expand Down Expand Up @@ -78,26 +77,26 @@ var curatorSecret = secret{
},
}

// ESSecrets assembles a set of secrets related to Elasticsearch
func ESSecrets(jaeger *v1.Jaeger) []corev1.Secret {
// ExtractSecrets assembles a set of secrets related to Elasticsearch
func (ed *ElasticsearchDeployment) ExtractSecrets() []corev1.Secret {
return []corev1.Secret{
createSecret(jaeger, masterSecret.instanceName(jaeger), getWorkingDirContents(getWorkingDir(jaeger), masterSecret.keyFileNameMap)),
createSecret(jaeger, esSecret.instanceName(jaeger), getWorkingDirContents(getWorkingDir(jaeger), esSecret.keyFileNameMap)),
createSecret(jaeger, jaegerSecret.instanceName(jaeger), getWorkingDirContents(getWorkingDir(jaeger), jaegerSecret.keyFileNameMap)),
createSecret(jaeger, curatorSecret.instanceName(jaeger), getWorkingDirContents(getWorkingDir(jaeger), curatorSecret.keyFileNameMap)),
createSecret(ed.Jaeger, masterSecret.instanceName(ed.Jaeger), getWorkingDirContents(getWorkingDir(ed.Jaeger), masterSecret.keyFileNameMap)),
createSecret(ed.Jaeger, esSecret.instanceName(ed.Jaeger), getWorkingDirContents(getWorkingDir(ed.Jaeger), esSecret.keyFileNameMap)),
createSecret(ed.Jaeger, jaegerSecret.instanceName(ed.Jaeger), getWorkingDirContents(getWorkingDir(ed.Jaeger), jaegerSecret.keyFileNameMap)),
createSecret(ed.Jaeger, curatorSecret.instanceName(ed.Jaeger), getWorkingDirContents(getWorkingDir(ed.Jaeger), curatorSecret.keyFileNameMap)),
}
}

// CreateESCerts creates certificates for elasticsearch, jaeger and curator
// CreateCerts creates certificates for elasticsearch, jaeger and curator
// The cert generation is done by shell script. If the certificates are not present
// on the filesystem the operator injects them from secrets - this allows operator restarts.
// The script also re-generates expired certificates.
func CreateESCerts(jaeger *v1.Jaeger, existingSecrets []corev1.Secret) error {
err := extractSecretsToFile(jaeger, existingSecrets, masterSecret, esSecret, jaegerSecret, curatorSecret)
func (ed *ElasticsearchDeployment) CreateCerts() error {
err := extractSecretsToFile(ed.Jaeger, ed.Secrets, masterSecret, esSecret, jaegerSecret, curatorSecret)
if err != nil {
return errors.Wrap(err, "failed to extract certificates from secrets to file")
}
return createESCerts(certScript, jaeger)
return createESCerts(ed.CertScript, ed.Jaeger)
}

func extractSecretsToFile(jaeger *v1.Jaeger, secrets []corev1.Secret, s ...secret) error {
Expand Down
14 changes: 8 additions & 6 deletions pkg/storage/elasticsearch_secrets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,20 @@ import (
"github.com/jaegertracing/jaeger-operator/pkg/apis/jaegertracing/v1"
)

func TestCreateESSecrets(t *testing.T) {
err := CreateESCerts(v1.NewJaeger("foo"), []corev1.Secret{})
assert.EqualError(t, err, "error running script ./scripts/cert_generation.sh: exit status 127")
func TestCreateESSecretsError(t *testing.T) {
es := &ElasticsearchDeployment{Jaeger: v1.NewJaeger("foo"), CertScript: "/foo"}
err := es.CreateCerts()
assert.EqualError(t, err, "error running script /foo: exit status 127")
}

func TestCreateESSecrets_internal(t *testing.T) {
func TestCreateESSecrets(t *testing.T) {
defer os.RemoveAll(tmpWorkingDir)
j := v1.NewJaeger("foo")
j.Namespace = "myproject"
err := createESCerts("../../scripts/cert_generation.sh", j)
es := &ElasticsearchDeployment{Jaeger: j, CertScript: "../../scripts/cert_generation.sh"}
err := es.CreateCerts()
assert.NoError(t, err)
sec := ESSecrets(j)
sec := es.ExtractSecrets()
assert.Equal(t, []string{
masterSecret.instanceName(j),
esSecret.instanceName(j),
Expand Down
7 changes: 6 additions & 1 deletion pkg/strategy/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import (
"github.com/jaegertracing/jaeger-operator/pkg/storage"
)

const (
esCertGenerationScript = "./scripts/cert_generation.sh"
)

// For returns the appropriate Strategy for the given Jaeger instance
func For(ctx context.Context, jaeger *v1.Jaeger, secrets []corev1.Secret) S {
if strings.EqualFold(jaeger.Spec.Strategy, "all-in-one") {
Expand All @@ -32,7 +36,8 @@ func For(ctx context.Context, jaeger *v1.Jaeger, secrets []corev1.Secret) S {
return newStreamingStrategy(jaeger)
}

return newProductionStrategy(jaeger, secrets)
es := &storage.ElasticsearchDeployment{Jaeger: jaeger, CertScript: esCertGenerationScript, Secrets: secrets}
return newProductionStrategy(jaeger, es)
}

// normalize changes the incoming Jaeger object so that the defaults are applied when
Expand Down
11 changes: 3 additions & 8 deletions pkg/strategy/production.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"github.com/spf13/viper"
appsv1 "k8s.io/api/apps/v1"
batchv1beta1 "k8s.io/api/batch/v1beta1"
corev1 "k8s.io/api/core/v1"

"github.com/jaegertracing/jaeger-operator/pkg/account"
"github.com/jaegertracing/jaeger-operator/pkg/apis/jaegertracing/v1"
Expand All @@ -20,7 +19,7 @@ import (
"github.com/jaegertracing/jaeger-operator/pkg/storage"
)

func newProductionStrategy(jaeger *v1.Jaeger, existingSecrets []corev1.Secret) S {
func newProductionStrategy(jaeger *v1.Jaeger, es *storage.ElasticsearchDeployment) S {
c := S{typ: Production}
collector := deployment.NewCollector(jaeger)
query := deployment.NewQuery(jaeger)
Expand Down Expand Up @@ -95,15 +94,11 @@ func newProductionStrategy(jaeger *v1.Jaeger, existingSecrets []corev1.Secret) S

// assembles the pieces for an elasticsearch self-provisioned deployment via the elasticsearch operator
if storage.ShouldDeployElasticsearch(jaeger.Spec.Storage) {
es := &storage.ElasticsearchDeployment{
Jaeger: jaeger,
}

err := storage.CreateESCerts(jaeger, existingSecrets)
err := es.CreateCerts()
if err != nil {
jaeger.Logger().WithError(err).Error("failed to create Elasticsearch certificates, Elasticsearch won't be deployed")
} else {
c.secrets = storage.ESSecrets(jaeger)
c.secrets = es.ExtractSecrets()
c.elasticsearches = append(c.elasticsearches, *es.Elasticsearch())

es.InjectStorageConfiguration(&queryDep.Spec.Template.Spec)
Expand Down
46 changes: 38 additions & 8 deletions pkg/strategy/production_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ func init() {

func TestCreateProductionDeployment(t *testing.T) {
name := "TestCreateProductionDeployment"
c := newProductionStrategy(v1.NewJaeger(name), []corev1.Secret{})
c := newProductionStrategy(v1.NewJaeger(name), &storage.ElasticsearchDeployment{})
assertDeploymentsAndServicesForProduction(t, name, c, false, false, false)
}

Expand All @@ -34,7 +34,7 @@ func TestCreateProductionDeploymentOnOpenShift(t *testing.T) {
jaeger := v1.NewJaeger(name)
normalize(jaeger)

c := newProductionStrategy(jaeger, []corev1.Secret{})
c := newProductionStrategy(jaeger, &storage.ElasticsearchDeployment{})
assertDeploymentsAndServicesForProduction(t, name, c, false, true, false)
}

Expand All @@ -44,7 +44,7 @@ func TestCreateProductionDeploymentWithDaemonSetAgent(t *testing.T) {
j := v1.NewJaeger(name)
j.Spec.Agent.Strategy = "DaemonSet"

c := newProductionStrategy(j, []corev1.Secret{})
c := newProductionStrategy(j, &storage.ElasticsearchDeployment{})
assertDeploymentsAndServicesForProduction(t, name, c, true, false, false)
}

Expand All @@ -58,7 +58,7 @@ func TestCreateProductionDeploymentWithUIConfigMap(t *testing.T) {
},
})

c := newProductionStrategy(j, []corev1.Secret{})
c := newProductionStrategy(j, &storage.ElasticsearchDeployment{})
assertDeploymentsAndServicesForProduction(t, name, c, false, false, true)
}

Expand Down Expand Up @@ -109,7 +109,7 @@ func TestDelegateProductionDependencies(t *testing.T) {
// for now, we just have storage dependencies
j := v1.NewJaeger("TestDelegateProductionDependencies")
j.Spec.Storage.Type = "cassandra"
c := newProductionStrategy(j, []corev1.Secret{})
c := newProductionStrategy(j, &storage.ElasticsearchDeployment{})
assert.Equal(t, c.Dependencies(), storage.Dependencies(j))
}

Expand Down Expand Up @@ -164,23 +164,53 @@ func assertDeploymentsAndServicesForProduction(t *testing.T, name string, s S, h

func TestSparkDependenciesProduction(t *testing.T) {
testSparkDependencies(t, func(jaeger *v1.Jaeger) S {
return newProductionStrategy(jaeger, []corev1.Secret{})
return newProductionStrategy(jaeger, &storage.ElasticsearchDeployment{Jaeger: jaeger})
})
}

func TestEsIndexCleanerProduction(t *testing.T) {
testEsIndexCleaner(t, func(jaeger *v1.Jaeger) S {
return newProductionStrategy(jaeger, []corev1.Secret{})
return newProductionStrategy(jaeger, &storage.ElasticsearchDeployment{Jaeger: jaeger})
})
}

func TestAgentSidecarIsInjectedIntoQueryForStreamingForProduction(t *testing.T) {
j := v1.NewJaeger("TestAgentSidecarIsInjectedIntoQueryForStreamingForProduction")
c := newProductionStrategy(j, []corev1.Secret{})
c := newProductionStrategy(j, &storage.ElasticsearchDeployment{})
for _, dep := range c.Deployments() {
if strings.HasSuffix(dep.Name, "-query") {
assert.Equal(t, 2, len(dep.Spec.Template.Spec.Containers))
assert.Equal(t, "jaeger-agent", dep.Spec.Template.Spec.Containers[1].Name)
}
}
}

func TestInjectElasticsearch(t *testing.T) {
j := v1.NewJaeger("TestAgentSidecarIsInjectedIntoQueryForStreamingForProduction")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Should use test name TestInjectElasticsearch

j.Spec.Storage.Type = "elasticsearch"
verdad := true
one := int(1)
j.Spec.Storage.EsIndexCleaner.Enabled = &verdad
j.Spec.Storage.EsIndexCleaner.NumberOfDays = &one
j.Spec.Storage.Options = v1.NewOptions(map[string]interface{}{"es.use-aliases": true})
c := newProductionStrategy(j, &storage.ElasticsearchDeployment{Jaeger: j, CertScript: "../../scripts/cert_generation.sh"})
// there should be index-cleaner, rollover, lookback
assert.Equal(t, 3, len(c.cronJobs))
assertInjectedEsSecrets(t, c.cronJobs[0].Spec.JobTemplate.Spec.Template.Spec)
assertInjectedEsSecrets(t, c.cronJobs[1].Spec.JobTemplate.Spec.Template.Spec)
assertInjectedEsSecrets(t, c.cronJobs[2].Spec.JobTemplate.Spec.Template.Spec)
}

func assertInjectedEsSecrets(t *testing.T, p corev1.PodSpec) {
assert.Equal(t, 1, len(p.Volumes))
assert.Equal(t, "certs", p.Volumes[0].Name)
assert.Equal(t, "certs", p.Containers[0].VolumeMounts[0].Name)
envs := map[string]corev1.EnvVar{}
for _, e := range p.Containers[0].Env {
envs[e.Name] = e
}
assert.Contains(t, envs, "ES_TLS")
assert.Contains(t, envs, "ES_TLS_CA")
assert.Contains(t, envs, "ES_TLS_KEY")
assert.Contains(t, envs, "ES_TLS_CERT")
}