From e96993f658e9852ac8a7305f38b77099aa6ffd24 Mon Sep 17 00:00:00 2001 From: Vibhav Bobade Date: Tue, 12 May 2020 11:13:07 +0530 Subject: [PATCH] Intermediate change for usage of Deployment Allows for using the annotation jenkins.io/use-deployment and setting the value to true makes the operator use a Deployment instead of Pod for serving Jenkins. This is part of an experimental feature. --- go.mod | 1 + pkg/apis/apis.go | 2 + .../jenkins/configuration/base/deployment.go | 56 +++++ .../jenkins/configuration/base/reconcile.go | 111 +++++---- .../base/resources/deployment.go | 215 ++++++++++++++++++ .../configuration/base/resources/pod.go | 167 +------------- .../jenkins/configuration/configuration.go | 23 +- 7 files changed, 363 insertions(+), 212 deletions(-) create mode 100644 pkg/controller/jenkins/configuration/base/deployment.go create mode 100644 pkg/controller/jenkins/configuration/base/resources/deployment.go diff --git a/go.mod b/go.mod index 5e95b57cd..cb297196f 100644 --- a/go.mod +++ b/go.mod @@ -34,6 +34,7 @@ require ( k8s.io/code-generator v0.17.4 k8s.io/gengo v0.0.0-20191010091904-7fa3014cb28f k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a + k8s.io/utils v0.0.0-20190801114015-581e00157fb1 sigs.k8s.io/controller-runtime v0.5.2 sigs.k8s.io/controller-tools v0.2.8 ) diff --git a/pkg/apis/apis.go b/pkg/apis/apis.go index 515f2f6ff..bb5ee814e 100644 --- a/pkg/apis/apis.go +++ b/pkg/apis/apis.go @@ -3,6 +3,7 @@ package apis import ( "github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" routev1 "github.com/openshift/api/route/v1" + appsv1 "k8s.io/api/apps/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -19,4 +20,5 @@ func init() { // Register the types with the Scheme so the components can map objects to GroupVersionKinds and back AddToSchemes = append(AddToSchemes, v1alpha2.SchemeBuilder.AddToScheme) AddToSchemes = append(AddToSchemes, routev1.AddToScheme) + AddToSchemes = append(AddToSchemes, appsv1.AddToScheme) } diff --git a/pkg/controller/jenkins/configuration/base/deployment.go b/pkg/controller/jenkins/configuration/base/deployment.go new file mode 100644 index 000000000..07a9dacf4 --- /dev/null +++ b/pkg/controller/jenkins/configuration/base/deployment.go @@ -0,0 +1,56 @@ +package base + +import ( + "context" + "fmt" + + "github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" + "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources" + "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/notifications/event" + "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/notifications/reason" + "github.com/jenkinsci/kubernetes-operator/version" + stackerr "github.com/pkg/errors" + apierrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/reconcile" +) + +func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsDeployment(meta metav1.ObjectMeta) (reconcile.Result, error) { + userAndPasswordHash, err := r.calculateUserAndPasswordHash() + if err != nil { + return reconcile.Result{}, err + } + + jenkinsDeployment, err := r.GetJenkinsDeployment() + if apierrors.IsNotFound(err) { + jenkinsDeployment = resources.NewJenkinsDeployment(meta, r.Configuration.Jenkins) + *r.Notifications <- event.Event{ + Jenkins: *r.Configuration.Jenkins, + Phase: event.PhaseBase, + Level: v1alpha2.NotificationLevelInfo, + Reason: reason.NewPodCreation(reason.OperatorSource, []string{"Creating a Jenkins Deployment"}), + } + + r.logger.Info(fmt.Sprintf("Creating a new Jenkins Deployment %s/%s", jenkinsDeployment.Namespace, jenkinsDeployment.Name)) + err := r.CreateResource(jenkinsDeployment) + if err != nil { + return reconcile.Result{}, stackerr.WithStack(err) + } + + now := metav1.Now() + r.Configuration.Jenkins.Status = v1alpha2.JenkinsStatus{ + OperatorVersion: version.Version, + ProvisionStartTime: &now, + LastBackup: r.Configuration.Jenkins.Status.LastBackup, + PendingBackup: r.Configuration.Jenkins.Status.LastBackup, + UserAndPasswordHash: userAndPasswordHash, + } + return reconcile.Result{Requeue: true}, r.Client.Update(context.TODO(), r.Configuration.Jenkins) + } else if err != nil && !apierrors.IsNotFound(err) { + return reconcile.Result{}, stackerr.WithStack(err) + } + + // TODO (waveywaves): replace with a cleaner solution + _ = jenkinsDeployment // This is to escape the variable is never used golint err + return reconcile.Result{}, nil +} diff --git a/pkg/controller/jenkins/configuration/base/reconcile.go b/pkg/controller/jenkins/configuration/base/reconcile.go index 13f8335b9..faa2b70da 100644 --- a/pkg/controller/jenkins/configuration/base/reconcile.go +++ b/pkg/controller/jenkins/configuration/base/reconcile.go @@ -49,65 +49,88 @@ func New(config configuration.Configuration, logger logr.Logger, jenkinsAPIConne // Reconcile takes care of base configuration func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (reconcile.Result, jenkinsclient.Jenkins, error) { + result := reconcile.Result{} metaObject := resources.NewResourceObjectMeta(r.Configuration.Jenkins) + // Create Necessary err := r.ensureResourcesRequiredForJenkinsPod(metaObject) if err != nil { return reconcile.Result{}, nil, err } r.logger.V(log.VDebug).Info("Kubernetes resources are present") - result, err := r.ensureJenkinsMasterPod(metaObject) - if err != nil { - return reconcile.Result{}, nil, err - } - if result.Requeue { - return result, nil, nil - } - r.logger.V(log.VDebug).Info("Jenkins master pod is present") + if useDeploymentForJenkinsMaster(r.Configuration.Jenkins) { + result, err = r.ensureJenkinsDeployment(metaObject) + if err != nil { + return reconcile.Result{}, nil, err + } + if result.Requeue { + return result, nil, nil + } + r.logger.V(log.VDebug).Info("Jenkins Deployment is present") + } else { + result, err = r.ensureJenkinsMasterPod(metaObject) + if err != nil { + return reconcile.Result{}, nil, err + } + if result.Requeue { + return result, nil, nil + } + r.logger.V(log.VDebug).Info("Jenkins master pod is present") - stopReconcileLoop, err := r.detectJenkinsMasterPodStartingIssues() - if err != nil { - return reconcile.Result{}, nil, err - } - if stopReconcileLoop { - return reconcile.Result{Requeue: false}, nil, nil - } + stopReconcileLoop, err := r.detectJenkinsMasterPodStartingIssues() + if err != nil { + return reconcile.Result{}, nil, err + } + if stopReconcileLoop { + return reconcile.Result{Requeue: false}, nil, nil + } - result, err = r.waitForJenkins() - if err != nil { - return reconcile.Result{}, nil, err - } - if result.Requeue { - return result, nil, nil - } - r.logger.V(log.VDebug).Info("Jenkins master pod is ready") + result, err = r.waitForJenkins() + if err != nil { + return reconcile.Result{}, nil, err + } + if result.Requeue { + return result, nil, nil + } + r.logger.V(log.VDebug).Info("Jenkins Pod is ready") - jenkinsClient, err := r.Configuration.GetJenkinsClient() - if err != nil { - return reconcile.Result{}, nil, err - } - r.logger.V(log.VDebug).Info("Jenkins API client set") + jenkinsClient, err := r.Configuration.GetJenkinsClient() + if err != nil { + return reconcile.Result{}, nil, err + } + r.logger.V(log.VDebug).Info("Jenkins API client set") - ok, err := r.verifyPlugins(jenkinsClient) - if err != nil { - return reconcile.Result{}, nil, err - } - if !ok { - //TODO add what plugins have been changed - message := "Some plugins have changed, restarting Jenkins" - r.logger.Info(message) + ok, err := r.verifyPlugins(jenkinsClient) + if err != nil { + return reconcile.Result{}, nil, err + } + if !ok { + //TODO add what plugins have been changed + message := "Some plugins have changed, restarting Jenkins" + r.logger.Info(message) - restartReason := reason.NewPodRestart( - reason.OperatorSource, - []string{message}, - ) - return reconcile.Result{Requeue: true}, nil, r.Configuration.RestartJenkinsMasterPod(restartReason) + restartReason := reason.NewPodRestart( + reason.OperatorSource, + []string{message}, + ) + return reconcile.Result{Requeue: true}, nil, r.Configuration.RestartJenkinsMasterPod(restartReason) + } + result, err = r.ensureBaseConfiguration(jenkinsClient) + if err != nil { + return result, nil, err // But return all other errors + } } + return result, nil, err +} - result, err = r.ensureBaseConfiguration(jenkinsClient) - - return result, jenkinsClient, err +func useDeploymentForJenkinsMaster(jenkins *v1alpha2.Jenkins) bool { + if val, ok := jenkins.Annotations["jenkins.io/use-deployment"]; ok { + if val == "true" { + return true + } + } + return false } func (r *ReconcileJenkinsBaseConfiguration) ensureResourcesRequiredForJenkinsPod(metaObject metav1.ObjectMeta) error { diff --git a/pkg/controller/jenkins/configuration/base/resources/deployment.go b/pkg/controller/jenkins/configuration/base/resources/deployment.go new file mode 100644 index 000000000..c8b54016c --- /dev/null +++ b/pkg/controller/jenkins/configuration/base/resources/deployment.go @@ -0,0 +1,215 @@ +package resources + +import ( + "fmt" + + "github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" + "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/constants" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/pointer" +) + +// NewJenkinsMasterContainer returns Jenkins master Kubernetes container +func NewJenkinsMasterContainer(jenkins *v1alpha2.Jenkins) corev1.Container { + jenkinsContainer := jenkins.Spec.Master.Containers[0] + + envs := GetJenkinsMasterContainerBaseEnvs(jenkins) + envs = append(envs, jenkinsContainer.Env...) + + jenkinsHomeEnvVar := corev1.EnvVar{ + Name: "JENKINS_HOME", + Value: getJenkinsHomePath(jenkins), + } + + jenkinsHomeEnvVarExists := false + for _, env := range jenkinsContainer.Env { + if env.Name == jenkinsHomeEnvVar.Name { + jenkinsHomeEnvVarExists = true + break + } + } + + if !jenkinsHomeEnvVarExists { + envs = append(envs, jenkinsHomeEnvVar) + } + + return corev1.Container{ + Name: JenkinsMasterContainerName, + Image: jenkinsContainer.Image, + ImagePullPolicy: jenkinsContainer.ImagePullPolicy, + Command: jenkinsContainer.Command, + LivenessProbe: jenkinsContainer.LivenessProbe, + ReadinessProbe: jenkinsContainer.ReadinessProbe, + Ports: []corev1.ContainerPort{ + { + Name: httpPortName, + ContainerPort: constants.DefaultHTTPPortInt32, + Protocol: corev1.ProtocolTCP, + }, + { + Name: slavePortName, + ContainerPort: constants.DefaultSlavePortInt32, + Protocol: corev1.ProtocolTCP, + }, + }, + SecurityContext: jenkinsContainer.SecurityContext, + Env: envs, + Resources: jenkinsContainer.Resources, + VolumeMounts: append(GetJenkinsMasterContainerBaseVolumeMounts(jenkins), jenkinsContainer.VolumeMounts...), + } +} + +func newContainers(jenkins *v1alpha2.Jenkins) (containers []corev1.Container) { + containers = append(containers, NewJenkinsMasterContainer(jenkins)) + for _, container := range jenkins.Spec.Master.Containers[1:] { + containers = append(containers, ConvertJenkinsContainerToKubernetesContainer(container)) + } + return containers +} + +// NewJenkinsMasterPod builds Jenkins Master Kubernetes Pod resource +func NewJenkinsDeployment(objectMeta metav1.ObjectMeta, jenkins *v1alpha2.Jenkins) *appsv1.Deployment { + serviceAccountName := objectMeta.Name + objectMeta.Annotations = jenkins.Spec.Master.Annotations + objectMeta.Name = GetJenkinsMasterPodName(*jenkins) + selector := &metav1.LabelSelector{MatchLabels: objectMeta.Labels} + return &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: objectMeta.Name, + Namespace: objectMeta.Namespace, + Labels: objectMeta.Labels, + OwnerReferences: []metav1.OwnerReference{ + { + BlockOwnerDeletion: pointer.BoolPtr(true), + Controller: pointer.BoolPtr(true), + Kind: jenkins.Kind, + Name: jenkins.Name, + APIVersion: jenkins.APIVersion, + UID: jenkins.UID, + }, + }, + }, + Spec: appsv1.DeploymentSpec{ + Replicas: pointer.Int32Ptr(1), + Strategy: appsv1.DeploymentStrategy{Type: appsv1.RollingUpdateDeploymentStrategyType}, + Template: corev1.PodTemplateSpec{ + ObjectMeta: objectMeta, + Spec: corev1.PodSpec{ + ServiceAccountName: serviceAccountName, + NodeSelector: jenkins.Spec.Master.NodeSelector, + Containers: newContainers(jenkins), + Volumes: append(GetJenkinsMasterPodBaseVolumes(jenkins), jenkins.Spec.Master.Volumes...), + SecurityContext: jenkins.Spec.Master.SecurityContext, + ImagePullSecrets: jenkins.Spec.Master.ImagePullSecrets, + Tolerations: jenkins.Spec.Master.Tolerations, + PriorityClassName: jenkins.Spec.Master.PriorityClassName, + }, + }, + Selector: selector, + }, + } +} + +// GetJenkinsMasterContainerBaseEnvs returns Jenkins master pod envs required by operator +func GetJenkinsMasterContainerBaseEnvs(jenkins *v1alpha2.Jenkins) []corev1.EnvVar { + envVars := []corev1.EnvVar{ + { + Name: "COPY_REFERENCE_FILE_LOG", + Value: fmt.Sprintf("%s/%s", getJenkinsHomePath(jenkins), "copy_reference_file.log"), + }, + } + + if len(jenkins.Spec.ConfigurationAsCode.Secret.Name) > 0 { + envVars = append(envVars, corev1.EnvVar{ + Name: "SECRETS", // https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/demos/kubernetes-secrets/README.md + Value: ConfigurationAsCodeSecretVolumePath, + }) + } + + return envVars +} + +// getJenkinsHomePath fetches the Home Path for Jenkins +func getJenkinsHomePath(jenkins *v1alpha2.Jenkins) string { + defaultJenkinsHomePath := "/var/lib/jenkins" + for _, envVar := range jenkins.Spec.Master.Containers[0].Env { + if envVar.Name == "JENKINS_HOME" { + return envVar.Value + } + } + return defaultJenkinsHomePath +} + +// GetJenkinsMasterContainerBaseVolumeMounts returns Jenkins master pod volume mounts required by operator +func GetJenkinsMasterContainerBaseVolumeMounts(jenkins *v1alpha2.Jenkins) []corev1.VolumeMount { + volumeMounts := []corev1.VolumeMount{ + { + Name: JenkinsHomeVolumeName, + MountPath: getJenkinsHomePath(jenkins), + ReadOnly: false, + }, + { + Name: jenkinsScriptsVolumeName, + MountPath: JenkinsScriptsVolumePath, + ReadOnly: true, + }, + { + Name: jenkinsInitConfigurationVolumeName, + MountPath: jenkinsInitConfigurationVolumePath, + ReadOnly: true, + }, + { + Name: jenkinsOperatorCredentialsVolumeName, + MountPath: jenkinsOperatorCredentialsVolumePath, + ReadOnly: true, + }, + } + + if len(jenkins.Spec.GroovyScripts.Secret.Name) > 0 { + volumeMounts = append(volumeMounts, corev1.VolumeMount{ + Name: getGroovyScriptsSecretVolumeName(jenkins), + MountPath: GroovyScriptsSecretVolumePath, + ReadOnly: true, + }) + } + if len(jenkins.Spec.ConfigurationAsCode.Secret.Name) > 0 { + volumeMounts = append(volumeMounts, corev1.VolumeMount{ + Name: getConfigurationAsCodeSecretVolumeName(jenkins), + MountPath: ConfigurationAsCodeSecretVolumePath, + ReadOnly: true, + }) + } + + return volumeMounts +} + +func getGroovyScriptsSecretVolumeName(jenkins *v1alpha2.Jenkins) string { + return "gs-" + jenkins.Spec.GroovyScripts.Secret.Name +} + +func getConfigurationAsCodeSecretVolumeName(jenkins *v1alpha2.Jenkins) string { + return "casc-" + jenkins.Spec.ConfigurationAsCode.Secret.Name +} + +// ConvertJenkinsContainerToKubernetesContainer converts Jenkins container to Kubernetes container +func ConvertJenkinsContainerToKubernetesContainer(container v1alpha2.Container) corev1.Container { + return corev1.Container{ + Name: container.Name, + Image: container.Image, + Command: container.Command, + Args: container.Args, + WorkingDir: container.WorkingDir, + Ports: container.Ports, + EnvFrom: container.EnvFrom, + Env: container.Env, + Resources: container.Resources, + VolumeMounts: container.VolumeMounts, + LivenessProbe: container.LivenessProbe, + ReadinessProbe: container.ReadinessProbe, + Lifecycle: container.Lifecycle, + ImagePullPolicy: container.ImagePullPolicy, + SecurityContext: container.SecurityContext, + } +} diff --git a/pkg/controller/jenkins/configuration/base/resources/pod.go b/pkg/controller/jenkins/configuration/base/resources/pod.go index dde4609bb..9bbfaa6e1 100644 --- a/pkg/controller/jenkins/configuration/base/resources/pod.go +++ b/pkg/controller/jenkins/configuration/base/resources/pod.go @@ -4,8 +4,6 @@ import ( "fmt" "github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" - "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/constants" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -57,36 +55,6 @@ func GetJenkinsMasterContainerBaseCommand() []string { } } -// GetJenkinsMasterContainerBaseEnvs returns Jenkins master pod envs required by operator -func GetJenkinsMasterContainerBaseEnvs(jenkins *v1alpha2.Jenkins) []corev1.EnvVar { - envVars := []corev1.EnvVar{ - { - Name: "COPY_REFERENCE_FILE_LOG", - Value: fmt.Sprintf("%s/%s", getJenkinsHomePath(jenkins), "copy_reference_file.log"), - }, - } - - if len(jenkins.Spec.ConfigurationAsCode.Secret.Name) > 0 { - envVars = append(envVars, corev1.EnvVar{ - Name: "SECRETS", // https://github.com/jenkinsci/configuration-as-code-plugin/blob/master/demos/kubernetes-secrets/README.md - Value: ConfigurationAsCodeSecretVolumePath, - }) - } - - return envVars -} - -// getJenkinsHomePath fetches the Home Path for Jenkins -func getJenkinsHomePath(jenkins *v1alpha2.Jenkins) string { - defaultJenkinsHomePath := "/var/lib/jenkins" - for _, envVar := range jenkins.Spec.Master.Containers[0].Env { - if envVar.Name == "JENKINS_HOME" { - return envVar.Value - } - } - return defaultJenkinsHomePath -} - // GetJenkinsMasterPodBaseVolumes returns Jenkins master pod volumes required by operator func GetJenkinsMasterPodBaseVolumes(jenkins *v1alpha2.Jenkins) []corev1.Volume { configMapVolumeSourceDefaultMode := corev1.ConfigMapVolumeSourceDefaultMode @@ -158,140 +126,13 @@ func GetJenkinsMasterPodBaseVolumes(jenkins *v1alpha2.Jenkins) []corev1.Volume { return volumes } -func getGroovyScriptsSecretVolumeName(jenkins *v1alpha2.Jenkins) string { - return "gs-" + jenkins.Spec.GroovyScripts.Secret.Name -} - -func getConfigurationAsCodeSecretVolumeName(jenkins *v1alpha2.Jenkins) string { - return "casc-" + jenkins.Spec.ConfigurationAsCode.Secret.Name -} - -// GetJenkinsMasterContainerBaseVolumeMounts returns Jenkins master pod volume mounts required by operator -func GetJenkinsMasterContainerBaseVolumeMounts(jenkins *v1alpha2.Jenkins) []corev1.VolumeMount { - volumeMounts := []corev1.VolumeMount{ - { - Name: JenkinsHomeVolumeName, - MountPath: getJenkinsHomePath(jenkins), - ReadOnly: false, - }, - { - Name: jenkinsScriptsVolumeName, - MountPath: JenkinsScriptsVolumePath, - ReadOnly: true, - }, - { - Name: jenkinsInitConfigurationVolumeName, - MountPath: jenkinsInitConfigurationVolumePath, - ReadOnly: true, - }, - { - Name: jenkinsOperatorCredentialsVolumeName, - MountPath: jenkinsOperatorCredentialsVolumePath, - ReadOnly: true, - }, - } - - if len(jenkins.Spec.GroovyScripts.Secret.Name) > 0 { - volumeMounts = append(volumeMounts, corev1.VolumeMount{ - Name: getGroovyScriptsSecretVolumeName(jenkins), - MountPath: GroovyScriptsSecretVolumePath, - ReadOnly: true, - }) - } - if len(jenkins.Spec.ConfigurationAsCode.Secret.Name) > 0 { - volumeMounts = append(volumeMounts, corev1.VolumeMount{ - Name: getConfigurationAsCodeSecretVolumeName(jenkins), - MountPath: ConfigurationAsCodeSecretVolumePath, - ReadOnly: true, - }) - } - - return volumeMounts -} - -// NewJenkinsMasterContainer returns Jenkins master Kubernetes container -func NewJenkinsMasterContainer(jenkins *v1alpha2.Jenkins) corev1.Container { - jenkinsContainer := jenkins.Spec.Master.Containers[0] - - envs := GetJenkinsMasterContainerBaseEnvs(jenkins) - envs = append(envs, jenkinsContainer.Env...) - - jenkinsHomeEnvVar := corev1.EnvVar{ - Name: "JENKINS_HOME", - Value: getJenkinsHomePath(jenkins), - } - - jenkinsHomeEnvVarExists := false - for _, env := range jenkinsContainer.Env { - if env.Name == jenkinsHomeEnvVar.Name { - jenkinsHomeEnvVarExists = true - break - } - } - - if !jenkinsHomeEnvVarExists { - envs = append(envs, jenkinsHomeEnvVar) - } - - return corev1.Container{ - Name: JenkinsMasterContainerName, - Image: jenkinsContainer.Image, - ImagePullPolicy: jenkinsContainer.ImagePullPolicy, - Command: jenkinsContainer.Command, - LivenessProbe: jenkinsContainer.LivenessProbe, - ReadinessProbe: jenkinsContainer.ReadinessProbe, - Ports: []corev1.ContainerPort{ - { - Name: httpPortName, - ContainerPort: constants.DefaultHTTPPortInt32, - Protocol: corev1.ProtocolTCP, - }, - { - Name: slavePortName, - ContainerPort: constants.DefaultSlavePortInt32, - Protocol: corev1.ProtocolTCP, - }, - }, - SecurityContext: jenkinsContainer.SecurityContext, - Env: envs, - Resources: jenkinsContainer.Resources, - VolumeMounts: append(GetJenkinsMasterContainerBaseVolumeMounts(jenkins), jenkinsContainer.VolumeMounts...), - } -} - -// ConvertJenkinsContainerToKubernetesContainer converts Jenkins container to Kubernetes container -func ConvertJenkinsContainerToKubernetesContainer(container v1alpha2.Container) corev1.Container { - return corev1.Container{ - Name: container.Name, - Image: container.Image, - Command: container.Command, - Args: container.Args, - WorkingDir: container.WorkingDir, - Ports: container.Ports, - EnvFrom: container.EnvFrom, - Env: container.Env, - Resources: container.Resources, - VolumeMounts: container.VolumeMounts, - LivenessProbe: container.LivenessProbe, - ReadinessProbe: container.ReadinessProbe, - Lifecycle: container.Lifecycle, - ImagePullPolicy: container.ImagePullPolicy, - SecurityContext: container.SecurityContext, - } -} - -func newContainers(jenkins *v1alpha2.Jenkins) (containers []corev1.Container) { - containers = append(containers, NewJenkinsMasterContainer(jenkins)) - - for _, container := range jenkins.Spec.Master.Containers[1:] { - containers = append(containers, ConvertJenkinsContainerToKubernetesContainer(container)) - } - - return +// GetJenkinsMasterPodName returns Jenkins pod name for given CR +func GetJenkinsMasterPodName(jenkins v1alpha2.Jenkins) string { + return fmt.Sprintf("jenkins-%s", jenkins.Name) } // GetJenkinsMasterPodName returns Jenkins pod name for given CR -func GetJenkinsMasterPodName(jenkins v1alpha2.Jenkins) string { +func GetJenkinsDeploymentName(jenkins v1alpha2.Jenkins) string { return fmt.Sprintf("jenkins-%s", jenkins.Name) } diff --git a/pkg/controller/jenkins/configuration/configuration.go b/pkg/controller/jenkins/configuration/configuration.go index 26b9c70a8..62ac0d09f 100644 --- a/pkg/controller/jenkins/configuration/configuration.go +++ b/pkg/controller/jenkins/configuration/configuration.go @@ -6,12 +6,8 @@ import ( "strings" "time" - "github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" - jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/client" - "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources" - "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/notifications/event" - "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/notifications/reason" stackerr "github.com/pkg/errors" + appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -23,6 +19,12 @@ import ( "k8s.io/client-go/tools/remotecommand" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + + "github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2" + jenkinsclient "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/client" + "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/configuration/base/resources" + "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/notifications/event" + "github.com/jenkinsci/kubernetes-operator/pkg/controller/jenkins/notifications/reason" ) // Configuration holds required for Jenkins configuration @@ -68,6 +70,17 @@ func (c *Configuration) GetJenkinsMasterPod() (*corev1.Pod, error) { return currentJenkinsMasterPod, nil } +// GetJenkinsMasterPod gets the jenkins master pod +func (c *Configuration) GetJenkinsDeployment() (*appsv1.Deployment, error) { + jenkinsDeploymentName := resources.GetJenkinsDeploymentName(*c.Jenkins) + currentJenkinsDeployment := &appsv1.Deployment{} + err := c.Client.Get(context.TODO(), types.NamespacedName{Name: jenkinsDeploymentName, Namespace: c.Jenkins.Namespace}, currentJenkinsDeployment) + if err != nil { + return nil, err // don't wrap error + } + return currentJenkinsDeployment, nil +} + // IsJenkinsTerminating returns true if the Jenkins pod is terminating func (c *Configuration) IsJenkinsTerminating(pod corev1.Pod) bool { return pod.ObjectMeta.DeletionTimestamp != nil