#13 Add node selector for Jenkins master pod

This commit is contained in:
Tomasz Sęk 2019-03-08 07:30:04 +01:00
parent f842be89d9
commit 75c403b941
No known key found for this signature in database
GPG Key ID: DC356D23F6A644D0
6 changed files with 45 additions and 17 deletions

View File

@ -19,9 +19,10 @@ type JenkinsSpec struct {
// JenkinsMaster defines the Jenkins master pod attributes and plugins,
// every single change requires Jenkins master pod restart
type JenkinsMaster struct {
Image string `json:"image,omitempty"`
Annotations map[string]string `json:"masterAnnotations,omitempty"`
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
Image string `json:"image,omitempty"`
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
Annotations map[string]string `json:"masterAnnotations,omitempty"`
Resources corev1.ResourceRequirements `json:"resources,omitempty"`
// OperatorPlugins contains plugins required by operator
OperatorPlugins map[string][]string `json:"basePlugins,omitempty"`
// Plugins contains plugins required by user

View File

@ -113,6 +113,13 @@ func (in *JenkinsList) DeepCopyObject() runtime.Object {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JenkinsMaster) DeepCopyInto(out *JenkinsMaster) {
*out = *in
if in.NodeSelector != nil {
in, out := &in.NodeSelector, &out.NodeSelector
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.Annotations != nil {
in, out := &in.Annotations, &out.Annotations
*out = make(map[string]string, len(*in))

View File

@ -338,40 +338,54 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsMasterPod(meta metav1.O
return reconcile.Result{}, stackerr.WithStack(err)
}
// Recreate pod
if currentJenkinsMasterPod != nil && isPodTerminating(*currentJenkinsMasterPod) {
return reconcile.Result{Requeue: true}, nil
}
if currentJenkinsMasterPod != nil && r.isRecreatePodNeeded(*currentJenkinsMasterPod) {
return reconcile.Result{Requeue: true}, r.restartJenkinsMasterPod(meta)
}
return reconcile.Result{}, nil
}
func isPodTerminating(pod corev1.Pod) bool {
return pod.ObjectMeta.DeletionTimestamp != nil
}
func (r *ReconcileJenkinsBaseConfiguration) isRecreatePodNeeded(currentJenkinsMasterPod corev1.Pod) bool {
recreatePod := false
if currentJenkinsMasterPod != nil &&
(currentJenkinsMasterPod.Status.Phase == corev1.PodFailed ||
currentJenkinsMasterPod.Status.Phase == corev1.PodSucceeded ||
currentJenkinsMasterPod.Status.Phase == corev1.PodUnknown) {
r.logger.Info(fmt.Sprintf("Invalid Jenkins pod phase '%+v', recreating pod", currentJenkinsMasterPod.Status.Phase))
if currentJenkinsMasterPod.Status.Phase == corev1.PodFailed ||
currentJenkinsMasterPod.Status.Phase == corev1.PodSucceeded ||
currentJenkinsMasterPod.Status.Phase == corev1.PodUnknown {
r.logger.Info(fmt.Sprintf("Invalid Jenkins pod phase '%+v', recreating pod", currentJenkinsMasterPod.Status))
recreatePod = true
}
if currentJenkinsMasterPod != nil &&
r.jenkins.Spec.Master.Image != currentJenkinsMasterPod.Spec.Containers[0].Image {
if r.jenkins.Spec.Master.Image != currentJenkinsMasterPod.Spec.Containers[0].Image {
r.logger.Info(fmt.Sprintf("Jenkins image has changed to '%+v', recreating pod", r.jenkins.Spec.Master.Image))
recreatePod = true
}
if currentJenkinsMasterPod != nil && len(r.jenkins.Spec.Master.Annotations) > 0 &&
if len(r.jenkins.Spec.Master.Annotations) > 0 &&
!reflect.DeepEqual(r.jenkins.Spec.Master.Annotations, currentJenkinsMasterPod.ObjectMeta.Annotations) {
r.logger.Info(fmt.Sprintf("Jenkins pod annotations have changed to '%+v', recreating pod", r.jenkins.Spec.Master.Annotations))
recreatePod = true
}
if currentJenkinsMasterPod != nil &&
!reflect.DeepEqual(r.jenkins.Spec.Master.Resources, currentJenkinsMasterPod.Spec.Containers[0].Resources) {
if !reflect.DeepEqual(r.jenkins.Spec.Master.Resources, currentJenkinsMasterPod.Spec.Containers[0].Resources) {
r.logger.Info(fmt.Sprintf("Jenkins pod resources have changed, actual '%+v' required '%+v' - recreating pod",
currentJenkinsMasterPod.Spec.Containers[0].Resources, r.jenkins.Spec.Master.Resources))
recreatePod = true
}
if currentJenkinsMasterPod != nil && recreatePod && currentJenkinsMasterPod.ObjectMeta.DeletionTimestamp == nil {
return reconcile.Result{Requeue: true}, r.restartJenkinsMasterPod(meta)
if !reflect.DeepEqual(r.jenkins.Spec.Master.NodeSelector, currentJenkinsMasterPod.Spec.NodeSelector) {
r.logger.Info(fmt.Sprintf("Jenkins pod node selector has changed, actual '%+v' required '%+v' - recreating pod",
r.jenkins.Spec.Master.NodeSelector, currentJenkinsMasterPod.Spec.NodeSelector))
recreatePod = true
}
return reconcile.Result{}, nil
return recreatePod
}
func (r *ReconcileJenkinsBaseConfiguration) restartJenkinsMasterPod(meta metav1.ObjectMeta) error {

View File

@ -76,6 +76,7 @@ func NewJenkinsMasterPod(objectMeta metav1.ObjectMeta, jenkins *v1alpha1.Jenkins
RunAsUser: &runAsUser,
RunAsGroup: &runAsUser,
},
NodeSelector: jenkins.Spec.Master.NodeSelector,
Containers: []corev1.Container{
{
Name: "jenkins-master",

View File

@ -139,6 +139,10 @@ func verifyJenkinsMasterPodAttributes(t *testing.T, jenkins *v1alpha1.Jenkins) {
t.Fatalf("Invalid jenkins pod continer resources expected '%+v', actual '%+v'", jenkins.Spec.Master.Resources, jenkinsPod.Spec.Containers[0].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)
}
t.Log("Jenkins pod attributes are valid")
}

View File

@ -72,6 +72,7 @@ func createJenkinsCR(t *testing.T, name, namespace string) *v1alpha1.Jenkins {
"audit-trail:2.4": {},
"simple-theme-plugin:0.5.1": {},
},
NodeSelector: map[string]string{"kubernetes.io/hostname": "minikube"},
},
//TODO(bantoniak) add seed job with private key
SeedJobs: []v1alpha1.SeedJob{