diff --git a/api/v1alpha2/jenkinsimage_types.go b/api/v1alpha2/jenkinsimage_types.go deleted file mode 100644 index 0be257a9..00000000 --- a/api/v1alpha2/jenkinsimage_types.go +++ /dev/null @@ -1,49 +0,0 @@ -package v1alpha2 - -import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - -// JenkinsImageSpec defines the desired state of JenkinsImage -type JenkinsImageSpec struct { - BaseImage Image `json:"image"` - Plugins []JenkinsPlugin `json:"plugins"` // Plugins list -} - -// Defines Jenkins Plugin structure -type JenkinsPlugin struct { - Name string `json:"name"` - Version string `json:"version,omitempty"` -} - -// Defines Jenkins Plugin structure -type Image struct { - Name string `json:"name"` - Tag string `json:"version,omitempty"` -} - -// JenkinsImageStatus defines the observed state of JenkinsImage -type JenkinsImageStatus struct { - Image string `json:"image,omitempty"` - MD5Sum string `json:"md5sum,omitempty"` - InstalledPlugins []JenkinsPlugin `json:"installedPlugins,omitempty"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// JenkinsImage is the Schema for the jenkinsimages API -// +kubebuilder:subresource:status -// +kubebuilder:resource:path=jenkinsimages,scope=Namespaced -type JenkinsImage struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - Spec JenkinsImageSpec `json:"spec,omitempty"` - Status JenkinsImageStatus `json:"status,omitempty"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// JenkinsImageList contains a list of JenkinsImage -type JenkinsImageList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []JenkinsImage `json:"items"` -} diff --git a/api/v1alpha2/register.go b/api/v1alpha2/register.go index d3e4c040..cecb9df5 100644 --- a/api/v1alpha2/register.go +++ b/api/v1alpha2/register.go @@ -53,5 +53,4 @@ func JenkinsTypeMeta() metav1.TypeMeta { func init() { SchemeBuilder.Register(&Jenkins{}, &JenkinsList{}) - SchemeBuilder.Register(&JenkinsImage{}, &JenkinsImageList{}) } diff --git a/api/v1alpha2/zz_generated.deepcopy.go b/api/v1alpha2/zz_generated.deepcopy.go index af28e1fd..566f8d1d 100644 --- a/api/v1alpha2/zz_generated.deepcopy.go +++ b/api/v1alpha2/zz_generated.deepcopy.go @@ -217,21 +217,6 @@ func (in *Handler) DeepCopy() *Handler { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Image) DeepCopyInto(out *Image) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Image. -func (in *Image) DeepCopy() *Image { - if in == nil { - return nil - } - out := new(Image) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Jenkins) DeepCopyInto(out *Jenkins) { *out = *in @@ -274,106 +259,6 @@ func (in *JenkinsAPISettings) DeepCopy() *JenkinsAPISettings { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *JenkinsImage) DeepCopyInto(out *JenkinsImage) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsImage. -func (in *JenkinsImage) DeepCopy() *JenkinsImage { - if in == nil { - return nil - } - out := new(JenkinsImage) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *JenkinsImage) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *JenkinsImageList) DeepCopyInto(out *JenkinsImageList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]JenkinsImage, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsImageList. -func (in *JenkinsImageList) DeepCopy() *JenkinsImageList { - if in == nil { - return nil - } - out := new(JenkinsImageList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *JenkinsImageList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *JenkinsImageSpec) DeepCopyInto(out *JenkinsImageSpec) { - *out = *in - out.BaseImage = in.BaseImage - if in.Plugins != nil { - in, out := &in.Plugins, &out.Plugins - *out = make([]JenkinsPlugin, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsImageSpec. -func (in *JenkinsImageSpec) DeepCopy() *JenkinsImageSpec { - if in == nil { - return nil - } - out := new(JenkinsImageSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *JenkinsImageStatus) DeepCopyInto(out *JenkinsImageStatus) { - *out = *in - if in.InstalledPlugins != nil { - in, out := &in.InstalledPlugins, &out.InstalledPlugins - *out = make([]JenkinsPlugin, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsImageStatus. -func (in *JenkinsImageStatus) DeepCopy() *JenkinsImageStatus { - if in == nil { - return nil - } - out := new(JenkinsImageStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *JenkinsList) DeepCopyInto(out *JenkinsList) { *out = *in @@ -483,21 +368,6 @@ func (in *JenkinsMaster) DeepCopy() *JenkinsMaster { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *JenkinsPlugin) DeepCopyInto(out *JenkinsPlugin) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JenkinsPlugin. -func (in *JenkinsPlugin) DeepCopy() *JenkinsPlugin { - if in == nil { - return nil - } - out := new(JenkinsPlugin) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *JenkinsSpec) DeepCopyInto(out *JenkinsSpec) { *out = *in diff --git a/config/crd/bases/jenkins.io_jenkinsimages.yaml b/config/crd/bases/jenkins.io_jenkinsimages.yaml deleted file mode 100644 index 7c79607a..00000000 --- a/config/crd/bases/jenkins.io_jenkinsimages.yaml +++ /dev/null @@ -1,95 +0,0 @@ - ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.4.1 - creationTimestamp: null - name: jenkinsimages.jenkins.io -spec: - group: jenkins.io - names: - kind: JenkinsImage - listKind: JenkinsImageList - plural: jenkinsimages - singular: jenkinsimage - scope: Namespaced - versions: - - name: v1alpha2 - schema: - openAPIV3Schema: - description: JenkinsImage is the Schema for the jenkinsimages API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - description: JenkinsImageSpec defines the desired state of JenkinsImage - properties: - image: - description: Defines Jenkins Plugin structure - properties: - name: - type: string - version: - type: string - required: - - name - type: object - plugins: - items: - description: Defines Jenkins Plugin structure - properties: - name: - type: string - version: - type: string - required: - - name - type: object - type: array - required: - - image - - plugins - type: object - status: - description: JenkinsImageStatus defines the observed state of JenkinsImage - properties: - image: - type: string - installedPlugins: - items: - description: Defines Jenkins Plugin structure - properties: - name: - type: string - version: - type: string - required: - - name - type: object - type: array - md5sum: - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -status: - acceptedNames: - kind: "" - plural: "" - conditions: [] - storedVersions: [] diff --git a/config/samples/jenkins.io_v1alpha2_jenkins.yaml b/config/samples/jenkins.io_v1alpha2_jenkins.yaml index 68c07cfb..265b967c 100644 --- a/config/samples/jenkins.io_v1alpha2_jenkins.yaml +++ b/config/samples/jenkins.io_v1alpha2_jenkins.yaml @@ -18,7 +18,7 @@ spec: disableCSRFProtection: false containers: - name: jenkins-master - image: jenkins/jenkins:2.249.3-lts-alpine + image: jenkins/jenkins:2.263.3-lts-alpine imagePullPolicy: Always livenessProbe: failureThreshold: 12 @@ -31,12 +31,12 @@ spec: successThreshold: 1 timeoutSeconds: 5 readinessProbe: - failureThreshold: 5 + failureThreshold: 10 httpGet: path: /login port: http scheme: HTTP - initialDelaySeconds: 60 + initialDelaySeconds: 80 periodSeconds: 10 successThreshold: 1 timeoutSeconds: 1 diff --git a/controllers/jenkinsImage_controller.go b/controllers/jenkinsImage_controller.go deleted file mode 100644 index 5fb4d020..00000000 --- a/controllers/jenkinsImage_controller.go +++ /dev/null @@ -1,111 +0,0 @@ -package controllers - -import ( - "context" - - "github.com/jenkinsci/kubernetes-operator/api/v1alpha2" - "github.com/jenkinsci/kubernetes-operator/pkg/configuration/base/resources" - "github.com/jenkinsci/kubernetes-operator/pkg/log" - - corev1 "k8s.io/api/core/v1" - apierrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/types" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "sigs.k8s.io/controller-runtime/pkg/reconcile" -) - -var logxx = log.Log - -// JenkinsImageReconciler reconciles a JenkinsImage object -type JenkinsImageReconciler struct { - // This Client, initialized using mgr.Client() above, is a split Client - // that reads objects from the cache and writes to the apiserver - Client client.Client - Scheme *runtime.Scheme -} - -// SetupWithManager sets up the controller with the Manager. -func (r *JenkinsImageReconciler) SetupWithManager(mgr ctrl.Manager) error { - return ctrl.NewControllerManagedBy(mgr). - For(&v1alpha2.JenkinsImage{}). - Owns(&corev1.Pod{}). - Owns(&corev1.ConfigMap{}). - Complete(r) -} - -// Reconcile reads that state of the cluster for a JenkinsImage object and makes changes based on the state read -// and what is in the JenkinsImage.Spec -// The Controller will requeue the Request to be processed again if the returned error is non-nil or -// Result.Requeue is true, otherwise upon completion it will remove the work from the queue. -func (r *JenkinsImageReconciler) Reconcile(_ context.Context, request ctrl.Request) (ctrl.Result, error) { - reqLogger := logxx.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name) - reqLogger.Info("Reconciling JenkinsImage") - - // Fetch the JenkinsImage instance - instance := &v1alpha2.JenkinsImage{} - err := r.Client.Get(context.TODO(), request.NamespacedName, instance) - if err != nil { - if apierrors.IsNotFound(err) { - // Request object not found, could have been deleted after reconcile request. - // Owned objects are automatically garbage collected. For additional cleanup logic use finalizers. - // Return and don't requeue - return reconcile.Result{}, nil - } - // Error reading the object - requeue the request. - return reconcile.Result{}, err - } - - // Define a new ConfigMap containing the Dockerfile used to build the image - dockerfile := resources.NewDockerfileConfigMap(instance) - // Set JenkinsImage instance as the owner and controller - if err := controllerutil.SetControllerReference(instance, dockerfile, r.Scheme); err != nil { - return reconcile.Result{}, err - } - - // Check if this ConfigMap already exists - foundConfigMap := &corev1.ConfigMap{} - err = r.Client.Get(context.TODO(), types.NamespacedName{Name: dockerfile.Name, Namespace: dockerfile.Namespace}, foundConfigMap) - if err != nil && apierrors.IsNotFound(err) { - reqLogger.Info("Creating a new ConfigMap", "ConfigMap.Namespace", dockerfile.Namespace, "ConfigMap.Name", dockerfile.Name) - err = r.Client.Create(context.TODO(), dockerfile) - if err != nil { - return reconcile.Result{}, err - } - // ConfigMap created successfully - don't requeue - return reconcile.Result{}, nil - } else if err != nil { - return reconcile.Result{}, err - } - // ConfigMap already exists - don't requeue - reqLogger.Info("Skip reconcile: ConfigMap already exists", "ConfigMap.Namespace", foundConfigMap.Namespace, "ConfigMap.Name", foundConfigMap.Name) - - // Define a new Pod object - pod := resources.NewBuilderPod(instance) - // Set JenkinsImage instance as the owner and controller - if err := controllerutil.SetControllerReference(instance, pod, r.Scheme); err != nil { - return reconcile.Result{}, err - } - - // Check if this Pod already exists - foundPod := &corev1.Pod{} - err = r.Client.Get(context.TODO(), types.NamespacedName{Name: pod.Name, Namespace: pod.Namespace}, foundPod) - if err != nil && apierrors.IsNotFound(err) { - reqLogger.Info("Creating a new Pod", "Pod.Namespace", pod.Namespace, "Pod.Name", pod.Name) - err = r.Client.Create(context.TODO(), pod) - if err != nil { - return reconcile.Result{}, err - } - - // Pod created successfully - don't requeue - return reconcile.Result{}, nil - } else if err != nil { - return reconcile.Result{}, err - } - // Pod already exists - don't requeue - reqLogger.Info("Skip reconcile: Pod already exists", "Pod.Namespace", foundPod.Namespace, "Pod.Name", foundPod.Name) - - return reconcile.Result{}, nil -} diff --git a/controllers/jenkins_controller.go b/controllers/jenkins_controller.go index 23b3d9df..875250f2 100644 --- a/controllers/jenkins_controller.go +++ b/controllers/jenkins_controller.go @@ -359,7 +359,7 @@ func (r *JenkinsReconciler) setDefaults(jenkins *v1alpha2.Jenkins) (requeue bool if jenkinsContainer.ReadinessProbe == nil { logger.Info("Setting default Jenkins readinessProbe") changed = true - jenkinsContainer.ReadinessProbe = resources.NewProbe(containerProbeURI, containerProbePortName, corev1.URISchemeHTTP, 30, 1, 3) + jenkinsContainer.ReadinessProbe = resources.NewProbe(containerProbeURI, containerProbePortName, corev1.URISchemeHTTP, 60, 1, 10) } if jenkinsContainer.LivenessProbe == nil { logger.Info("Setting default Jenkins livenessProbe") diff --git a/main.go b/main.go index 949adda9..0ef69846 100644 --- a/main.go +++ b/main.go @@ -168,13 +168,6 @@ func main() { fatal(errors.Wrap(err, "unable to create Jenkins controller"), *debug) } - if err = (&controllers.JenkinsImageReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - }).SetupWithManager(mgr); err != nil { - fatal(errors.Wrap(err, "unable to create Jenkins controller"), *debug) - } - // +kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("health", healthz.Ping); err != nil { diff --git a/pkg/configuration/base/resources/builder.go b/pkg/configuration/base/resources/builder.go deleted file mode 100644 index 181a6292..00000000 --- a/pkg/configuration/base/resources/builder.go +++ /dev/null @@ -1,129 +0,0 @@ -package resources - -import ( - "fmt" - - "github.com/jenkinsci/kubernetes-operator/api/v1alpha2" - - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - logf "sigs.k8s.io/controller-runtime/pkg/log" -) - -const ( - NameWithSuffixFormat = "%s-%s" - PluginDefinitionFormat = "%s:%s" - BuilderDockerfileArg = "--dockerfile=/workspace/dockerfile/Dockerfile" - BuilderContextDirArg = "--context=dir://workspace/" - BuilderPushArg = "--no-push" - BuilderDigestFileArg = "--digest-file=/dev/termination-log" - BuilderSuffix = "builder" - DockerfileStorageSuffix = "dockerfile-storage" - DockerfileNameSuffix = "dockerfile" - JenkinsImageBuilderImage = "gcr.io/kaniko-project/executor:latest" - JenkinsImageBuilderName = "jenkins-image-builder" - JenkinsImageDefaultBaseImage = "jenkins/jenkins:lts" - DockerfileName = "Dockerfile" - DockerfileTemplate = `FROM %s -RUN curl -o /tmp/install-plugins.sh https://raw.githubusercontent.com/jenkinsci/docker/master/install-plugins.sh -RUN chmod +x /tmp/install-plugins.sh -RUN install-plugins.sh %s ` -) - -var log = logf.Log.WithName("controller_jenkinsimage") - -// NewBuilderPod returns a busybox pod with the same name/namespace as the cr. -func NewBuilderPod(cr *v1alpha2.JenkinsImage) *corev1.Pod { - name := fmt.Sprintf(NameWithSuffixFormat, cr.Name, BuilderSuffix) - args := []string{BuilderDockerfileArg, BuilderContextDirArg, BuilderPushArg, BuilderDigestFileArg} - volumes := getVolumes(cr) - volumeMounts := getVolumesMounts(cr) - p := &corev1.Pod{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: cr.Namespace, - }, - Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, - Containers: []corev1.Container{ - { - Name: JenkinsImageBuilderName, - Image: JenkinsImageBuilderImage, - Args: args, - VolumeMounts: volumeMounts, - }, - }, - Volumes: volumes, - }, - } - return p -} - -// NewDockerfileConfigMap returns a busybox pod with the same name/namespace as the cr. -func NewDockerfileConfigMap(cr *v1alpha2.JenkinsImage) *corev1.ConfigMap { - dockerfileContent := fmt.Sprintf(DockerfileTemplate, getDefaultedBaseImage(cr), getPluginsList(cr)) - name := fmt.Sprintf(NameWithSuffixFormat, cr.Name, DockerfileNameSuffix) - data := map[string]string{DockerfileName: dockerfileContent} - dockerfile := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: cr.Namespace, - }, - Data: data, - } - return dockerfile -} - -func getPluginsList(cr *v1alpha2.JenkinsImage) string { - logger := log.WithName("jenkinsimage_getPluginsList") - plugins := "" - for _, v := range cr.Spec.Plugins { - plugins += fmt.Sprintf(PluginDefinitionFormat, v.Name, v.Version) + " " - logger.Info(fmt.Sprintf("Adding plugin %s:%s ", v.Name, v.Version)) - } - return plugins -} - -func getDefaultedBaseImage(cr *v1alpha2.JenkinsImage) string { - if len(cr.Spec.BaseImage.Name) != 0 { - return cr.Spec.BaseImage.Name - } - return JenkinsImageDefaultBaseImage -} - -func getVolumes(cr *v1alpha2.JenkinsImage) []corev1.Volume { - name := fmt.Sprintf(NameWithSuffixFormat, cr.Name, DockerfileStorageSuffix) - storage := corev1.Volume{ - Name: name, - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - } - - name = fmt.Sprintf(NameWithSuffixFormat, cr.Name, DockerfileNameSuffix) - config := corev1.Volume{ - Name: name, - VolumeSource: corev1.VolumeSource{ - ConfigMap: &corev1.ConfigMapVolumeSource{ - LocalObjectReference: corev1.LocalObjectReference{Name: name}, - }, - }, - } - volumes := []corev1.Volume{storage, config} - return volumes -} - -func getVolumesMounts(cr *v1alpha2.JenkinsImage) []corev1.VolumeMount { - name := fmt.Sprintf(NameWithSuffixFormat, cr.Name, DockerfileStorageSuffix) - storage := corev1.VolumeMount{ - Name: name, - MountPath: "/workspace", - } - name = fmt.Sprintf(NameWithSuffixFormat, cr.Name, DockerfileNameSuffix) - config := corev1.VolumeMount{ - Name: name, - MountPath: "/workspace/dockerfile", - } - volumeMounts := []corev1.VolumeMount{storage, config} - return volumeMounts -} diff --git a/pkg/plugins/base_plugins.go b/pkg/plugins/base_plugins.go index 21b83ba6..7f8a761b 100644 --- a/pkg/plugins/base_plugins.go +++ b/pkg/plugins/base_plugins.go @@ -1,11 +1,11 @@ package plugins const ( - configurationAsCodePlugin = "configuration-as-code:1.46" + configurationAsCodePlugin = "configuration-as-code:1.47" gitPlugin = "git:4.5.0" jobDslPlugin = "job-dsl:1.77" kubernetesCredentialsProviderPlugin = "kubernetes-credentials-provider:0.15" - kubernetesPlugin = "kubernetes:1.28.6" + kubernetesPlugin = "kubernetes:1.29.0" workflowAggregatorPlugin = "workflow-aggregator:2.6" workflowJobPlugin = "workflow-job:2.40" )