#9 Allow mount pvc in Jenkins pod

This commit is contained in:
Tomasz Sęk 2019-06-09 14:56:31 +02:00
parent a271078227
commit f9ad157c8b
No known key found for this signature in database
GPG Key ID: DC356D23F6A644D0
3 changed files with 136 additions and 81 deletions

View File

@ -4,77 +4,83 @@ apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: jenkins-operator
rules:
- apiGroups:
- ""
resources:
- services
- configmaps
- secrets
verbs:
- get
- create
- update
- list
- watch
- apiGroups:
- "extensions"
resources:
- ingresses
verbs:
- create
- update
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- create
- apiGroups:
- rbac.authorization.k8s.io
resources:
- roles
- rolebindings
verbs:
- create
- update
- apiGroups:
- ""
resources:
- pods/portforward
verbs:
- create
- apiGroups:
- ""
resources:
- pods/log
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
- pods/exec
verbs:
- "*"
- apiGroups:
- ""
resources:
- events
verbs:
- create
- apiGroups:
- apps
resourceNames:
- jenkins-operator
resources:
- deployments/finalizers
verbs:
- update
- apiGroups:
- jenkins.io
resources:
- '*'
verbs:
- '*'
- apiGroups:
- ""
resources:
- services
- configmaps
- secrets
verbs:
- get
- create
- update
- list
- watch
- apiGroups:
- "extensions"
resources:
- ingresses
verbs:
- create
- update
- apiGroups:
- ""
resources:
- serviceaccounts
verbs:
- create
- apiGroups:
- rbac.authorization.k8s.io
resources:
- roles
- rolebindings
verbs:
- create
- update
- apiGroups:
- ""
resources:
- pods/portforward
verbs:
- create
- apiGroups:
- ""
resources:
- pods/log
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- pods
- pods/exec
verbs:
- "*"
- apiGroups:
- ""
resources:
- events
verbs:
- create
- apiGroups:
- apps
resourceNames:
- jenkins-operator
resources:
- deployments/finalizers
verbs:
- update
- apiGroups:
- jenkins.io
resources:
- '*'
verbs:
- '*'
- apiGroups:
- ""
resources:
- persistentvolumeclaims
verbs:
- get

View File

@ -63,8 +63,18 @@ func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (reconcile.Result, jenki
if err != nil {
return reconcile.Result{}, nil, err
}
r.logger.V(log.VDebug).Info("Kubernetes resources are present")
result, err := r.ensureJenkinsMasterPod(metaObject)
result, err := r.waitForVolumes()
if err != nil {
return reconcile.Result{}, nil, err
}
if result.Requeue {
return result, nil, nil
}
r.logger.V(log.VDebug).Info("Jenkins master pod volumes are ready")
result, err = r.ensureJenkinsMasterPod(metaObject)
if err != nil {
return reconcile.Result{}, nil, err
}
@ -149,6 +159,26 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureResourcesRequiredForJenkinsPod
return nil
}
func (r *ReconcileJenkinsBaseConfiguration) waitForVolumes() (reconcile.Result, error) {
for _, volume := range r.jenkins.Spec.Master.Volumes {
if volume.PersistentVolumeClaim != nil {
pvc := &corev1.PersistentVolumeClaim{}
err := r.k8sClient.Get(context.TODO(), types.NamespacedName{Name: volume.PersistentVolumeClaim.ClaimName, Namespace: r.jenkins.ObjectMeta.Namespace}, pvc)
if err != nil {
return reconcile.Result{}, err
}
if pvc.Status.Phase != corev1.ClaimBound {
r.logger.V(log.VWarn).Info(fmt.Sprintf("PersistentVolumeClaim '%s' have invalid state '%s' - required '%s', volume '%v'",
volume.PersistentVolumeClaim.ClaimName, pvc.Status.Phase, corev1.ClaimBound, volume))
return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 5}, nil
}
}
}
return reconcile.Result{}, nil
}
func (r *ReconcileJenkinsBaseConfiguration) verifyPlugins(jenkinsClient jenkinsclient.Jenkins, basePlugins map[string][]plugins.Plugin) (bool, error) {
allPluginsInJenkins, err := jenkinsClient.GetPlugins(fetchAllPlugins)
if err != nil {
@ -427,7 +457,7 @@ func (r *ReconcileJenkinsBaseConfiguration) isRecreatePodNeeded(currentJenkinsMa
}
if !r.compareVolumes(currentJenkinsMasterPod) {
r.logger.Info(fmt.Sprintf("Jenkins pod volumes have changed, actual '%+v' required '%+v', recreating pod",
r.logger.Info(fmt.Sprintf("Jenkins pod volumes have changed, actual '%v' required '%v', recreating pod",
currentJenkinsMasterPod.Spec.Volumes, r.jenkins.Spec.Master.Volumes))
return true
}

View File

@ -69,15 +69,34 @@ func (r *ReconcileJenkinsBaseConfiguration) validateVolumes() (bool, error) {
} else if !ok {
valid = false
}
case volume.PersistentVolumeClaim != nil:
if ok, err := r.validatePersistentVolumeClaim(volume); err != nil {
return false, err
} else if !ok {
valid = false
}
default: //TODO add support for rest of volumes
valid = false
r.logger.V(log.VWarn).Info(fmt.Sprintf("Unsupported volume '%+v'", volume))
r.logger.V(log.VWarn).Info(fmt.Sprintf("Unsupported volume '%v'", volume))
}
}
return valid, nil
}
func (r *ReconcileJenkinsBaseConfiguration) validatePersistentVolumeClaim(volume corev1.Volume) (bool, error) {
pvc := &corev1.PersistentVolumeClaim{}
err := r.k8sClient.Get(context.TODO(), types.NamespacedName{Name: volume.PersistentVolumeClaim.ClaimName, Namespace: r.jenkins.ObjectMeta.Namespace}, pvc)
if err != nil && apierrors.IsNotFound(err) {
r.logger.V(log.VWarn).Info(fmt.Sprintf("PersistentVolumeClaim '%s' not found for volume '%v'", volume.PersistentVolumeClaim.ClaimName, volume))
return false, nil
} else if err != nil && !apierrors.IsNotFound(err) {
return false, stackerr.WithStack(err)
}
return true, nil
}
func (r *ReconcileJenkinsBaseConfiguration) validateConfigMapVolume(volume corev1.Volume) (bool, error) {
if volume.ConfigMap.Optional != nil && *volume.ConfigMap.Optional {
return true, nil
@ -86,7 +105,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateConfigMapVolume(volume corev
configMap := &corev1.ConfigMap{}
err := r.k8sClient.Get(context.TODO(), types.NamespacedName{Name: volume.ConfigMap.Name, Namespace: r.jenkins.ObjectMeta.Namespace}, configMap)
if err != nil && apierrors.IsNotFound(err) {
r.logger.V(log.VWarn).Info(fmt.Sprintf("ConfigMap '%s' not found for volume '%+v'", volume.ConfigMap.Name, volume))
r.logger.V(log.VWarn).Info(fmt.Sprintf("ConfigMap '%s' not found for volume '%v'", volume.ConfigMap.Name, volume))
return false, nil
} else if err != nil && !apierrors.IsNotFound(err) {
return false, stackerr.WithStack(err)
@ -103,7 +122,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateSecretVolume(volume corev1.V
secret := &corev1.Secret{}
err := r.k8sClient.Get(context.TODO(), types.NamespacedName{Name: volume.Secret.SecretName, Namespace: r.jenkins.ObjectMeta.Namespace}, secret)
if err != nil && apierrors.IsNotFound(err) {
r.logger.V(log.VWarn).Info(fmt.Sprintf("Secret '%s' not found for volume '%+v'", volume.Secret.SecretName, volume))
r.logger.V(log.VWarn).Info(fmt.Sprintf("Secret '%s' not found for volume '%v'", volume.Secret.SecretName, volume))
return false, nil
} else if err != nil && !apierrors.IsNotFound(err) {
return false, stackerr.WithStack(err)
@ -158,7 +177,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateContainerVolumeMounts(contai
for _, volumeMount := range container.VolumeMounts {
if len(volumeMount.MountPath) == 0 {
logger.V(log.VWarn).Info(fmt.Sprintf("mountPath not set for '%s' volume mount", volumeMount.Name))
logger.V(log.VWarn).Info(fmt.Sprintf("mountPath not set for '%s' volume mount in container '%s'", volumeMount.Name, container.Name))
valid = false
}
@ -170,7 +189,7 @@ func (r *ReconcileJenkinsBaseConfiguration) validateContainerVolumeMounts(contai
}
if !foundVolume {
logger.V(log.VWarn).Info(fmt.Sprintf("Not found volume for '%s' volume mount", volumeMount.Name))
logger.V(log.VWarn).Info(fmt.Sprintf("Not found volume for '%s' volume mount in container '%s'", volumeMount.Name, container.Name))
valid = false
}
}