mirror of
https://github.com/jenkinsci/kubernetes-operator.git
synced 2026-10-07 08:31:11 +02:00
Allow configure sidecars in Jenkins pod
This commit is contained in:
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user