#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

@ -20,6 +20,7 @@ type JenkinsSpec struct {
// every single change requires Jenkins master pod restart // every single change requires Jenkins master pod restart
type JenkinsMaster struct { type JenkinsMaster struct {
Image string `json:"image,omitempty"` Image string `json:"image,omitempty"`
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
Annotations map[string]string `json:"masterAnnotations,omitempty"` Annotations map[string]string `json:"masterAnnotations,omitempty"`
Resources corev1.ResourceRequirements `json:"resources,omitempty"` Resources corev1.ResourceRequirements `json:"resources,omitempty"`
// OperatorPlugins contains plugins required by operator // OperatorPlugins contains plugins required by operator

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. // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JenkinsMaster) DeepCopyInto(out *JenkinsMaster) { func (in *JenkinsMaster) DeepCopyInto(out *JenkinsMaster) {
*out = *in *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 { if in.Annotations != nil {
in, out := &in.Annotations, &out.Annotations in, out := &in.Annotations, &out.Annotations
*out = make(map[string]string, len(*in)) *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) 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 recreatePod := false
if currentJenkinsMasterPod != nil &&
(currentJenkinsMasterPod.Status.Phase == corev1.PodFailed || if currentJenkinsMasterPod.Status.Phase == corev1.PodFailed ||
currentJenkinsMasterPod.Status.Phase == corev1.PodSucceeded || currentJenkinsMasterPod.Status.Phase == corev1.PodSucceeded ||
currentJenkinsMasterPod.Status.Phase == corev1.PodUnknown) { currentJenkinsMasterPod.Status.Phase == corev1.PodUnknown {
r.logger.Info(fmt.Sprintf("Invalid Jenkins pod phase '%+v', recreating pod", currentJenkinsMasterPod.Status.Phase)) r.logger.Info(fmt.Sprintf("Invalid Jenkins pod phase '%+v', recreating pod", currentJenkinsMasterPod.Status))
recreatePod = true recreatePod = true
} }
if currentJenkinsMasterPod != nil && if r.jenkins.Spec.Master.Image != currentJenkinsMasterPod.Spec.Containers[0].Image {
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)) r.logger.Info(fmt.Sprintf("Jenkins image has changed to '%+v', recreating pod", r.jenkins.Spec.Master.Image))
recreatePod = true 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) { !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)) r.logger.Info(fmt.Sprintf("Jenkins pod annotations have changed to '%+v', recreating pod", r.jenkins.Spec.Master.Annotations))
recreatePod = true recreatePod = true
} }
if currentJenkinsMasterPod != nil && if !reflect.DeepEqual(r.jenkins.Spec.Master.Resources, currentJenkinsMasterPod.Spec.Containers[0].Resources) {
!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", 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)) currentJenkinsMasterPod.Spec.Containers[0].Resources, r.jenkins.Spec.Master.Resources))
recreatePod = true recreatePod = true
} }
if currentJenkinsMasterPod != nil && recreatePod && currentJenkinsMasterPod.ObjectMeta.DeletionTimestamp == nil { if !reflect.DeepEqual(r.jenkins.Spec.Master.NodeSelector, currentJenkinsMasterPod.Spec.NodeSelector) {
return reconcile.Result{Requeue: true}, r.restartJenkinsMasterPod(meta) 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 { func (r *ReconcileJenkinsBaseConfiguration) restartJenkinsMasterPod(meta metav1.ObjectMeta) error {

View File

@ -76,6 +76,7 @@ func NewJenkinsMasterPod(objectMeta metav1.ObjectMeta, jenkins *v1alpha1.Jenkins
RunAsUser: &runAsUser, RunAsUser: &runAsUser,
RunAsGroup: &runAsUser, RunAsGroup: &runAsUser,
}, },
NodeSelector: jenkins.Spec.Master.NodeSelector,
Containers: []corev1.Container{ Containers: []corev1.Container{
{ {
Name: "jenkins-master", 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) 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") 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": {}, "audit-trail:2.4": {},
"simple-theme-plugin:0.5.1": {}, "simple-theme-plugin:0.5.1": {},
}, },
NodeSelector: map[string]string{"kubernetes.io/hostname": "minikube"},
}, },
//TODO(bantoniak) add seed job with private key //TODO(bantoniak) add seed job with private key
SeedJobs: []v1alpha1.SeedJob{ SeedJobs: []v1alpha1.SeedJob{