diff --git a/pkg/apis/jenkins/v1alpha2/jenkins_types.go b/pkg/apis/jenkins/v1alpha2/jenkins_types.go index 9fd2f7a1..bea6bffd 100644 --- a/pkg/apis/jenkins/v1alpha2/jenkins_types.go +++ b/pkg/apis/jenkins/v1alpha2/jenkins_types.go @@ -232,6 +232,13 @@ type JenkinsMaster struct { // +optional AnnotationsDeprecated map[string]string `json:"masterAnnotations,omitempty"` + // Map of string keys and values that can be used to organize and categorize + // (scope and select) objects. May match selectors of replication controllers + // and services. + // More info: http://kubernetes.io/docs/user-guide/labels + // +optional + Labels map[string]string `json:"labels,omitempty"` + // NodeSelector is a selector which must be true for the pod to fit on a node. // Selector which must match a node's labels for the pod to be scheduled on that node. // More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/ diff --git a/pkg/apis/jenkins/v1alpha2/zz_generated.deepcopy.go b/pkg/apis/jenkins/v1alpha2/zz_generated.deepcopy.go index 7175530d..3954ae5e 100644 --- a/pkg/apis/jenkins/v1alpha2/zz_generated.deepcopy.go +++ b/pkg/apis/jenkins/v1alpha2/zz_generated.deepcopy.go @@ -286,6 +286,13 @@ func (in *JenkinsMaster) DeepCopyInto(out *JenkinsMaster) { (*out)[key] = val } } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } if in.NodeSelector != nil { in, out := &in.NodeSelector, &out.NodeSelector *out = make(map[string]string, len(*in)) diff --git a/pkg/controller/jenkins/configuration/base/reconcile.go b/pkg/controller/jenkins/configuration/base/reconcile.go index baf8e658..dc994cfc 100644 --- a/pkg/controller/jenkins/configuration/base/reconcile.go +++ b/pkg/controller/jenkins/configuration/base/reconcile.go @@ -540,6 +540,12 @@ func (r *ReconcileJenkinsBaseConfiguration) checkForPodRecreation(currentJenkins currentJenkinsMasterPod.Spec.NodeSelector, r.Configuration.Jenkins.Spec.Master.NodeSelector)) } + if !compareMap(r.Configuration.Jenkins.Spec.Master.Labels, currentJenkinsMasterPod.Labels) { + messages = append(messages, "Jenkins pod labels have changed") + verbose = append(verbose, fmt.Sprintf("Jenkins pod labels have changed, actual '%+v' required '%+v'", + currentJenkinsMasterPod.Labels, r.Configuration.Jenkins.Spec.Master.Labels)) + } + if !compareMap(r.Configuration.Jenkins.Spec.Master.Annotations, currentJenkinsMasterPod.ObjectMeta.Annotations) { messages = append(messages, "Jenkins pod annotations have changed") verbose = append(verbose, fmt.Sprintf("Jenkins pod annotations have changed, actual '%+v' required '%+v'", diff --git a/pkg/controller/jenkins/configuration/base/resources/pod.go b/pkg/controller/jenkins/configuration/base/resources/pod.go index 7a5e842f..8e625af3 100644 --- a/pkg/controller/jenkins/configuration/base/resources/pod.go +++ b/pkg/controller/jenkins/configuration/base/resources/pod.go @@ -290,11 +290,26 @@ func GetJenkinsMasterPodName(jenkins v1alpha2.Jenkins) string { return fmt.Sprintf("jenkins-%s", jenkins.Name) } +// GetJenkinsMasterPodLabels returns Jenkins pod labels for given CR +func GetJenkinsMasterPodLabels(jenkins v1alpha2.Jenkins) map[string]string { + var labels map[string]string + if jenkins.Spec.Master.Labels == nil { + labels = map[string]string{} + } else { + labels = jenkins.Spec.Master.Labels + } + for key, value := range BuildResourceLabels(&jenkins) { + labels[key] = value + } + return labels +} + // NewJenkinsMasterPod builds Jenkins Master Kubernetes Pod resource func NewJenkinsMasterPod(objectMeta metav1.ObjectMeta, jenkins *v1alpha2.Jenkins) *corev1.Pod { serviceAccountName := objectMeta.Name objectMeta.Annotations = jenkins.Spec.Master.Annotations objectMeta.Name = GetJenkinsMasterPodName(*jenkins) + objectMeta.Labels = GetJenkinsMasterPodLabels(*jenkins) return &corev1.Pod{ TypeMeta: buildPodTypeMeta(), diff --git a/test/e2e/configuration_test.go b/test/e2e/configuration_test.go index a8f1b319..e6896cb1 100644 --- a/test/e2e/configuration_test.go +++ b/test/e2e/configuration_test.go @@ -225,6 +225,8 @@ func verifyJenkinsMasterPodAttributes(t *testing.T, jenkins *v1alpha2.Jenkins) { assert.Equal(t, jenkins.Spec.Master.ImagePullSecrets, jenkinsPod.Spec.ImagePullSecrets) + assert.Equal(t, resources.GetJenkinsMasterPodLabels(*jenkins), jenkinsPod.Labels) + for _, actualContainer := range jenkinsPod.Spec.Containers { if actualContainer.Name == resources.JenkinsMasterContainerName { verifyContainer(t, resources.NewJenkinsMasterContainer(jenkins), actualContainer) diff --git a/test/e2e/jenkins.go b/test/e2e/jenkins.go index 66c3df56..23b33f9d 100644 --- a/test/e2e/jenkins.go +++ b/test/e2e/jenkins.go @@ -33,7 +33,7 @@ func getJenkins(t *testing.T, namespace, name string) *v1alpha2.Jenkins { func getJenkinsMasterPod(t *testing.T, jenkins *v1alpha2.Jenkins) *corev1.Pod { lo := metav1.ListOptions{ - LabelSelector: labels.SelectorFromSet(resources.BuildResourceLabels(jenkins)).String(), + LabelSelector: labels.SelectorFromSet(resources.GetJenkinsMasterPodLabels(*jenkins)).String(), } podList, err := framework.Global.KubeClient.CoreV1().Pods(jenkins.ObjectMeta.Namespace).List(lo) if err != nil { diff --git a/test/e2e/wait.go b/test/e2e/wait.go index 9a4cdf3f..167caa7a 100644 --- a/test/e2e/wait.go +++ b/test/e2e/wait.go @@ -75,7 +75,7 @@ func waitForJenkinsBaseConfigurationToComplete(t *testing.T, jenkins *v1alpha2.J func waitForRecreateJenkinsMasterPod(t *testing.T, jenkins *v1alpha2.Jenkins) { err := wait.Poll(retryInterval, 30*retryInterval, func() (bool, error) { lo := metav1.ListOptions{ - LabelSelector: labels.SelectorFromSet(resources.BuildResourceLabels(jenkins)).String(), + LabelSelector: labels.SelectorFromSet(resources.GetJenkinsMasterPodLabels(*jenkins)).String(), } podList, err := framework.Global.KubeClient.CoreV1().Pods(jenkins.ObjectMeta.Namespace).List(lo) if err != nil {