Allow configure sidecars in Jenkins pod

This commit is contained in:
Tomasz Sęk
2019-05-17 16:35:18 +02:00
parent 127992eb96
commit af10a97299
12 changed files with 519 additions and 221 deletions
+43 -29
View File
@@ -3,11 +3,11 @@ package e2e
import (
"context"
"fmt"
"reflect"
"testing"
"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkinsio/v1alpha1"
jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/client"
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base"
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources"
"github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/plugins"
@@ -133,43 +133,57 @@ func verifyJenkinsMasterPodAttributes(t *testing.T, jenkins *v1alpha1.Jenkins) {
jenkinsPod := getJenkinsMasterPod(t, jenkins)
jenkins = getJenkins(t, jenkins.Namespace, jenkins.Name)
for key, value := range jenkins.Spec.Master.Annotations {
if jenkinsPod.ObjectMeta.Annotations[key] != value {
t.Fatalf("Invalid Jenkins pod annotation expected '%+v', actual '%+v'", jenkins.Spec.Master.Annotations, jenkinsPod.ObjectMeta.Annotations)
assert.Equal(t, jenkins.Spec.Master.Annotations, jenkinsPod.ObjectMeta.Annotations)
assert.Equal(t, jenkins.Spec.Master.NodeSelector, jenkinsPod.Spec.NodeSelector)
assert.Equal(t, resources.JenkinsMasterContainerName, jenkinsPod.Spec.Containers[0].Name)
assert.Equal(t, len(jenkins.Spec.Master.Containers)+1, len(jenkinsPod.Spec.Containers))
for _, actualContainer := range jenkinsPod.Spec.Containers {
if actualContainer.Name == resources.JenkinsMasterContainerName {
verifyContainer(t, resources.NewJenkinsMasterContainer(jenkins), actualContainer)
continue
}
}
jenkinsContainer := jenkinsPod.Spec.Containers[0]
var expectedContainer *corev1.Container
for _, jenkinsContainer := range jenkins.Spec.Master.Containers {
if jenkinsContainer.Name == actualContainer.Name {
tmp := resources.ConvertJenkinsContainerToKubernetesContainer(jenkinsContainer)
expectedContainer = &tmp
}
}
if jenkinsContainer.Image != jenkins.Spec.Master.Image {
t.Fatalf("Invalid jenkins pod image expected '%s', actual '%s'", jenkins.Spec.Master.Image, jenkinsContainer.Image)
}
if expectedContainer == nil {
t.Errorf("Container '%+v' not found in pod", actualContainer)
continue
}
if !reflect.DeepEqual(jenkinsContainer.Resources, jenkins.Spec.Master.Resources) {
t.Fatalf("Invalid jenkins pod continer resources expected '%+v', actual '%+v'", jenkins.Spec.Master.Resources, jenkinsContainer.Resources)
}
if !reflect.DeepEqual(jenkinsPod.Spec.NodeSelector, jenkins.Spec.Master.NodeSelector) {
t.Fatalf("Invalid jenkins pod node selector expected '%+v', actual '%+v'", jenkins.Spec.Master.NodeSelector, jenkinsPod.Spec.NodeSelector)
}
if !reflect.DeepEqual(jenkinsContainer.ReadinessProbe, jenkins.Spec.Master.ReadinessProbe) {
t.Fatalf("Invalid jenkins pod readinessProbe. Expected '%+v', actual '%+v'", jenkins.Spec.Master.ReadinessProbe, jenkinsContainer.ReadinessProbe)
}
if !reflect.DeepEqual(jenkinsContainer.LivenessProbe, jenkins.Spec.Master.LivenessProbe) {
t.Fatalf("Invalid jenkins pod livenessProbe. Expected '%+v', actual '%+v'", jenkins.Spec.Master.LivenessProbe, jenkinsContainer.LivenessProbe)
}
requiredEnvs := resources.GetJenkinsMasterPodBaseEnvs()
requiredEnvs = append(requiredEnvs, jenkins.Spec.Master.Env...)
if !reflect.DeepEqual(jenkinsContainer.Env, requiredEnvs) {
t.Fatalf("Invalid jenkins pod continer resources expected '%+v', actual '%+v'", requiredEnvs, jenkinsContainer.Env)
verifyContainer(t, *expectedContainer, actualContainer)
}
t.Log("Jenkins pod attributes are valid")
}
func verifyContainer(t *testing.T, expected corev1.Container, actual corev1.Container) {
assert.Equal(t, expected.Args, actual.Args, expected.Name, expected.Name)
assert.Equal(t, expected.Command, actual.Command, expected.Name)
assert.Equal(t, expected.Env, actual.Env, expected.Name)
assert.Equal(t, expected.EnvFrom, actual.EnvFrom, expected.Name)
assert.Equal(t, expected.Image, actual.Image, expected.Name)
assert.Equal(t, expected.ImagePullPolicy, actual.ImagePullPolicy, expected.Name)
assert.Equal(t, expected.Lifecycle, actual.Lifecycle, expected.Name)
assert.Equal(t, expected.LivenessProbe, actual.LivenessProbe, expected.Name)
assert.Equal(t, expected.Ports, actual.Ports, expected.Name)
assert.Equal(t, expected.ReadinessProbe, actual.ReadinessProbe, expected.Name)
assert.Equal(t, expected.Resources, actual.Resources, expected.Name)
assert.Equal(t, expected.SecurityContext, actual.SecurityContext, expected.Name)
assert.Equal(t, expected.WorkingDir, actual.WorkingDir, expected.Name)
if !base.CompareContainerVolumeMounts(expected, actual) {
t.Errorf("Volume mounts are different in container '%s': expected '%+v', actual '%+v'",
expected.Name, expected.VolumeMounts, actual.VolumeMounts)
}
}
func verifyPlugins(t *testing.T, jenkinsClient jenkinsclient.Jenkins, jenkins *v1alpha1.Jenkins) {
installedPlugins, err := jenkinsClient.GetPlugins(1)
if err != nil {
+39 -31
View File
@@ -73,43 +73,51 @@ func createJenkinsCR(t *testing.T, name, namespace string, seedJob *[]v1alpha1.S
},
Spec: v1alpha1.JenkinsSpec{
Master: v1alpha1.JenkinsMaster{
Image: "jenkins/jenkins",
Annotations: map[string]string{"test": "label"},
Container: v1alpha1.Container{
Image: "jenkins/jenkins",
Env: []v1.EnvVar{
{
Name: "TEST_ENV",
Value: "test_env_value",
},
},
ReadinessProbe: &corev1.Probe{
Handler: corev1.Handler{
HTTPGet: &corev1.HTTPGetAction{
Path: "/login",
Port: intstr.FromString("http"),
Scheme: corev1.URISchemeHTTP,
},
},
InitialDelaySeconds: int32(80),
TimeoutSeconds: int32(4),
FailureThreshold: int32(10),
},
LivenessProbe: &corev1.Probe{
Handler: corev1.Handler{
HTTPGet: &corev1.HTTPGetAction{
Path: "/login",
Port: intstr.FromString("http"),
Scheme: corev1.URISchemeHTTP,
},
},
InitialDelaySeconds: int32(80),
TimeoutSeconds: int32(4),
FailureThreshold: int32(10),
},
},
Containers: []v1alpha1.Container{
{
Name: "envoyproxy",
Image: "envoyproxy/envoy-alpine",
},
},
Plugins: map[string][]string{
"audit-trail:2.4": {},
"simple-theme-plugin:0.5.1": {},
},
NodeSelector: map[string]string{"kubernetes.io/hostname": "minikube"},
Env: []v1.EnvVar{
{
Name: "TEST_ENV",
Value: "test_env_value",
},
},
ReadinessProbe: &corev1.Probe{
Handler: corev1.Handler{
HTTPGet: &corev1.HTTPGetAction{
Path: "/login",
Port: intstr.FromString("http"),
Scheme: corev1.URISchemeHTTP,
},
},
InitialDelaySeconds: int32(35),
TimeoutSeconds: int32(4),
FailureThreshold: int32(10),
},
LivenessProbe: &corev1.Probe{
Handler: corev1.Handler{
HTTPGet: &corev1.HTTPGetAction{
Path: "/login",
Port: intstr.FromString("http"),
Scheme: corev1.URISchemeHTTP,
},
},
InitialDelaySeconds: int32(40),
TimeoutSeconds: int32(4),
FailureThreshold: int32(10),
},
},
SeedJobs: seedJobs,
},
+11 -15
View File
@@ -2,7 +2,6 @@ package e2e
import (
goctx "context"
"fmt"
"net/http"
"testing"
"time"
@@ -27,14 +26,14 @@ var (
timeout = time.Second * 60
)
// checkConditionFunc is used to check if a condition for the jenkins CR is true
type checkConditionFunc func(*v1alpha1.Jenkins) bool
// checkConditionFunc is used to check if a condition for the jenkins CR is set
type checkConditionFunc func(*v1alpha1.Jenkins, error) bool
func waitForJenkinsBaseConfigurationToComplete(t *testing.T, jenkins *v1alpha1.Jenkins) {
t.Log("Waiting for Jenkins base configuration to complete")
_, err := WaitUntilJenkinsConditionTrue(retryInterval, 150, jenkins, func(jenkins *v1alpha1.Jenkins) bool {
t.Logf("Current Jenkins status '%+v'", jenkins.Status)
return jenkins.Status.BaseConfigurationCompletedTime != nil
_, err := WaitUntilJenkinsConditionSet(retryInterval, 150, jenkins, func(jenkins *v1alpha1.Jenkins, err error) bool {
t.Logf("Current Jenkins status: '%+v', error '%s'", jenkins.Status, err)
return err == nil && jenkins.Status.BaseConfigurationCompletedTime != nil
})
assert.NoError(t, err)
t.Log("Jenkins pod is running")
@@ -68,9 +67,9 @@ func waitForRecreateJenkinsMasterPod(t *testing.T, jenkins *v1alpha1.Jenkins) {
func waitForJenkinsUserConfigurationToComplete(t *testing.T, jenkins *v1alpha1.Jenkins) {
t.Log("Waiting for Jenkins user configuration to complete")
_, err := WaitUntilJenkinsConditionTrue(retryInterval, 30, jenkins, func(jenkins *v1alpha1.Jenkins) bool {
t.Logf("Current Jenkins status '%+v'", jenkins.Status)
return jenkins.Status.UserConfigurationCompletedTime != nil
_, err := WaitUntilJenkinsConditionSet(retryInterval, 70, jenkins, func(jenkins *v1alpha1.Jenkins, err error) bool {
t.Logf("Current Jenkins status: '%+v', error '%s'", jenkins.Status, err)
return err == nil && jenkins.Status.UserConfigurationCompletedTime != nil
})
if err != nil {
t.Fatal(err)
@@ -92,16 +91,13 @@ func waitForJenkinsSafeRestart(t *testing.T, jenkinsClient jenkinsclient.Jenkins
require.NoError(t, err)
}
// WaitUntilJenkinsConditionTrue retries until the specified condition check becomes true for the jenkins CR
func WaitUntilJenkinsConditionTrue(retryInterval time.Duration, retries int, jenkins *v1alpha1.Jenkins, checkCondition checkConditionFunc) (*v1alpha1.Jenkins, error) {
// WaitUntilJenkinsConditionSet retries until the specified condition check becomes true for the jenkins CR
func WaitUntilJenkinsConditionSet(retryInterval time.Duration, retries int, jenkins *v1alpha1.Jenkins, checkCondition checkConditionFunc) (*v1alpha1.Jenkins, error) {
jenkinsStatus := &v1alpha1.Jenkins{}
err := wait.Poll(retryInterval, time.Duration(retries)*retryInterval, func() (bool, error) {
namespacedName := types.NamespacedName{Namespace: jenkins.Namespace, Name: jenkins.Name}
err := framework.Global.Client.Get(goctx.TODO(), namespacedName, jenkinsStatus)
if err != nil {
return false, fmt.Errorf("failed to get CR: %v", err)
}
return checkCondition(jenkinsStatus), nil
return checkCondition(jenkinsStatus, err), nil
})
if err != nil {
return nil, err