Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Grand Christmas Patch #479

Merged
merged 1 commit into from
Dec 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ PACKAGES_FOR_UNIT_TESTS = $(shell go list -f '{{.ImportPath}}/' ./... | grep -v
E2E_TEST_SELECTOR ?= .*

JENKINS_API_HOSTNAME := $(shell $(JENKINS_API_HOSTNAME_COMMAND) 2> /dev/null || echo "" )
OPERATOR_ARGS ?= --jenkins-api-hostname=$(JENKINS_API_HOSTNAME) --jenkins-api-port=$(JENKINS_API_PORT) --jenkins-api-use-nodeport=$(JENKINS_API_USE_NODEPORT) $(OPERATOR_EXTRA_ARGS)
OPERATOR_ARGS ?= --jenkins-api-hostname=$(JENKINS_API_HOSTNAME) --jenkins-api-port=$(JENKINS_API_PORT) --jenkins-api-use-nodeport=$(JENKINS_API_USE_NODEPORT) --cluster-domain=$(CLUSTER_DOMAIN) $(OPERATOR_EXTRA_ARGS)

.DEFAULT_GOAL := help

Expand Down Expand Up @@ -422,7 +422,7 @@ endif
minikube-start: check-minikube ## Start minikube
@echo "+ $@"
@minikube status && exit 0 || \
minikube start --kubernetes-version $(MINIKUBE_KUBERNETES_VERSION) --vm-driver=$(MINIKUBE_DRIVER) --memory 4096 --cpus 3
minikube start --kubernetes-version $(MINIKUBE_KUBERNETES_VERSION) --dns-domain=$(CLUSTER_DOMAIN) --extra-config=kubelet.cluster-domain=$(CLUSTER_DOMAIN) --vm-driver=$(MINIKUBE_DRIVER) --memory 4096 --cpus 3

.PHONY: crc-start
crc-start: check-crc ## Start CodeReady Containers Kubernetes cluster
Expand Down
27 changes: 27 additions & 0 deletions chart/jenkins-operator/templates/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -98,3 +98,30 @@ rules:
- get
- list
- watch
- apiGroups:
- "route.openshift.io"
resources:
- routes
verbs:
- get
- list
- watch
- create
- update
- apiGroups:
- "image.openshift.io"
resources:
- imagestreams
verbs:
- get
- list
- watch
- apiGroups:
- "build.openshift.io"
resources:
- builds
- buildconfigs
verbs:
- get
- list
- watch
31 changes: 17 additions & 14 deletions chart/jenkins-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ jenkins:
# image is the name (and tag) of the Jenkins instance
# Default: jenkins/jenkins:lts
# It's recommended to use LTS (tag: "lts") version
image: jenkins/jenkins:lts
image: jenkins/jenkins:2.249.3-lts-alpine

# env contains jenkins container environment variables
env: []
Expand Down Expand Up @@ -63,34 +63,34 @@ jenkins:
#
# basePlugins:
# - name: kubernetes
# version: 1.18.3
# version: 1.27.6
# - name: workflow-job
# version: "2.34"
# version: "2.40"
# - name: workflow-aggregator
# version: "2.6"
# - name: git
# version: 3.12.0
# version: 4.4.5
# - name: job-dsl
# version: "1.76"
# version: "1.77"
# - name: configuration-as-code
# version: "1.29"
# version: "1.46"
# - name: kubernetes-credentials-provider
# version: 0.12.1
# version: 0.15
basePlugins:
- name: kubernetes
version: "1.25.2"
version: "1.27.6"
- name: workflow-job
version: "2.39"
version: "2.40"
- name: workflow-aggregator
version: "2.6"
- name: git
version: "4.2.2"
version: "4.4.5"
- name: job-dsl
version: "1.77"
- name: configuration-as-code
version: "1.38"
version: "1.46"
- name: kubernetes-credentials-provider
version: "0.13"
version: "0.15"

# plugins are plugins required by the user
# You can define plugins here
Expand All @@ -100,7 +100,7 @@ jenkins:
#
# plugins:
# - name: simple-theme-plugin
# version: 0.5.1
# version: "0.6"
plugins: []

# seedJobs is placeholder for jenkins seed jobs
Expand Down Expand Up @@ -159,7 +159,7 @@ jenkins:

# image used by backup feature
# By default using prebuilt backup PVC image by VirtusLab
image: virtuslab/jenkins-operator-backup-pvc:v0.0.8
image: virtuslab/jenkins-operator-backup-pvc:v0.1.0

# containerName is backup container name
containerName: backup
Expand All @@ -178,6 +178,9 @@ jenkins:
restoreCommand:
- /home/user/bin/restore.sh

getLatestAction:
- /home/user/bin/get-latest.sh

# pvc is Persistent Volume Claim Kubernetes resource
pvc:
# enabled is enable/disable switch for PVC
Expand Down
8 changes: 7 additions & 1 deletion cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ func main() {
port := pflag.Int("jenkins-api-port", 0, "The port on which Jenkins API is running. Note: If you want to use nodePort don't set this setting and --jenkins-api-use-nodeport must be true.")
useNodePort := pflag.Bool("jenkins-api-use-nodeport", false, "Connect to Jenkins API using the service nodePort instead of service port. If you want to set this as true - don't set --jenkins-api-port.")
debug := pflag.Bool("debug", false, "Set log level to debug")
kubernetesClusterDomain := pflag.String("cluster-domain", "cluster.local", "Use custom domain name instead of 'cluster.local'.")
pflag.Parse()

log.SetupLogger(*debug)
Expand Down Expand Up @@ -136,8 +137,13 @@ func main() {
fatal(errors.Wrap(err, "invalid command line parameters"), *debug)
}

// validate kubernetes cluster domain
if *kubernetesClusterDomain == "" {
fatal(errors.Wrap(err, "Kubernetes cluster domain can't be empty"), *debug)
}

// setup Jenkins controller
if err := jenkins.Add(mgr, jenkinsAPIConnectionSettings, *clientSet, *cfg, &c); err != nil {
if err := jenkins.Add(mgr, jenkinsAPIConnectionSettings, *kubernetesClusterDomain, *clientSet, *cfg, &c); err != nil {
fatal(errors.Wrap(err, "failed to setup controllers"), *debug)
}
// setup JenkinsImage controller
Expand Down
1 change: 1 addition & 0 deletions config.base.env
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@ ALL_IN_ONE_DEPLOY_FILE_PREFIX=all-in-one
GEN_CRD_API=gen-crd-api-reference-docs
IMAGE_PULL_MODE=local
HELM_VERSION=3.1.2
CLUSTER_DOMAIN=cluster.local
2 changes: 1 addition & 1 deletion deploy/crds/jenkins_v1alpha2_jenkins_cr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ spec:
master:
containers:
- name: jenkins-master
image: jenkins/jenkins:lts
image: jenkins/jenkins:2.249.3-lts-alpine
imagePullPolicy: Always
livenessProbe:
failureThreshold: 12
Expand Down
16 changes: 8 additions & 8 deletions deploy/crds/jenkins_v1alpha2_jenkinsimage_cr.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ metadata:
spec:
image:
name: jenkins/jenkins
tag: lts
tag: 2.249.3-lts-alpine
plugins:
- name: kubernetes
version: "1.15.7"
- name: workflow-job
version: "2.39"
version: "1.27.6"
- name: workflow-job
version: "2.40"
- name: workflow-aggregator
version: "2.6"
- name: git
version: "3.10.0"
version: "4.4.5"
- name: job-dsl
version: "1.74"
version: "1.77"
- name: configuration-as-code
version: "1.19"
version: "1.46"
- name: kubernetes-credentials-provider
version: "0.12.1"
version: "0.15"

5 changes: 5 additions & 0 deletions pkg/apis/jenkins/v1alpha2/jenkins_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,11 @@ type Restore struct {
// Action defines action which performs restore backup in restore container sidecar
Action Handler `json:"action"`

// GetLatestAction defines action which returns the latest backup number. If there is no backup "-1" should be
// returned.
// +optional
GetLatestAction Handler `json:"getLatestAction"`

// RecoveryOnce if want to restore specific backup set this field and then Jenkins will be restarted and desired backup will be restored
// +optional
RecoveryOnce uint64 `json:"recoveryOnce,omitempty"`
Expand Down
1 change: 1 addition & 0 deletions pkg/apis/jenkins/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 37 additions & 5 deletions pkg/configuration/backuprestore/backuprestore.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package backuprestore
import (
"context"
"fmt"
"strconv"
"strings"
"time"

"github.com/jenkinsci/kubernetes-operator/pkg/apis/jenkins/v1alpha2"
Expand All @@ -12,6 +14,7 @@ import (
"github.com/jenkinsci/kubernetes-operator/pkg/log"

"github.com/go-logr/logr"
"github.com/pkg/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
k8s "sigs.k8s.io/controller-runtime/pkg/client"
Expand Down Expand Up @@ -109,6 +112,8 @@ func (bar *BackupAndRestore) Validate() []string {

return messages
}
// helper value indicating no saved backup
const noBackup = "-1"
tomaszsek marked this conversation as resolved.
Show resolved Hide resolved

// Restore performs Jenkins restore backup operation
func (bar *BackupAndRestore) Restore(jenkinsClient jenkinsclient.Jenkins) error {
Expand All @@ -121,7 +126,8 @@ func (bar *BackupAndRestore) Restore(jenkinsClient jenkinsclient.Jenkins) error
bar.logger.V(log.VDebug).Info("Skipping restore backup, backup already restored")
return nil
}
if jenkins.Status.LastBackup == 0 {

if jenkins.Status.LastBackup == 0 && jenkins.Spec.Restore.GetLatestAction.Exec == nil {
bar.logger.V(log.VDebug).Info("Skipping restore backup")
if jenkins.Status.PendingBackup == 0 {
jenkins.Status.PendingBackup = 1
Expand All @@ -130,14 +136,40 @@ func (bar *BackupAndRestore) Restore(jenkinsClient jenkinsclient.Jenkins) error
return nil
}

var backupNumber uint64
podName := resources.GetJenkinsMasterPodName(jenkins)
var backupNumber = jenkins.Status.LastBackup

if jenkins.Spec.Restore.GetLatestAction.Exec != nil {
command := jenkins.Spec.Restore.GetLatestAction.Exec.Command
backupNumberRaw, _, err := bar.Exec(podName, jenkins.Spec.Restore.ContainerName, command)
if err != nil {
return err
}

backupNumberString := strings.TrimSuffix(backupNumberRaw.String(), "\n")
if backupNumberString == noBackup {
bar.logger.V(log.VDebug).Info("Skipping restore backup, get latest action returned -1")
jenkins.Status.LastBackup = 0
jenkins.Status.PendingBackup = 1
return bar.Client.Update(context.TODO(), jenkins)
}

backupNumber, err = strconv.ParseUint(backupNumberString, 10, 64)
if err != nil {
return errors.Wrapf(err, "invalid backup number '%s' returned by get last backup number action", backupNumberString)
}

if backupNumber < 1 {
return errors.Errorf("invalid backup number '%d' returned by get last backup number action", backupNumber)
}
} else {
bar.logger.V(log.VWarn).Info("spec.restore.getLatestAction not set, you may loose backup history when Jenkins CR status will be clear")
}

tomaszsek marked this conversation as resolved.
Show resolved Hide resolved
if jenkins.Spec.Restore.RecoveryOnce != 0 {
backupNumber = jenkins.Spec.Restore.RecoveryOnce
} else {
backupNumber = jenkins.Status.LastBackup
}
bar.logger.Info(fmt.Sprintf("Restoring backup '%d'", backupNumber))
podName := resources.GetJenkinsMasterPodName(jenkins)
command := jenkins.Spec.Restore.Action.Exec.Command
command = append(command, fmt.Sprintf("%d", backupNumber))
_, _, err := bar.Exec(podName, jenkins.Spec.Restore.ContainerName, command)
Expand Down
2 changes: 1 addition & 1 deletion pkg/configuration/base/configmap.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createInitConfigurationConfigMap(met
}

func (r *ReconcileJenkinsBaseConfiguration) createBaseConfigurationConfigMap(meta metav1.ObjectMeta) error {
configMap, err := resources.NewBaseConfigurationConfigMap(meta, r.Configuration.Jenkins)
configMap, err := resources.NewBaseConfigurationConfigMap(meta, r.Configuration.Jenkins, r.KubernetesClusterDomain)
if err != nil {
return err
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ if (kubernetes == null) {
add = true
kubernetes = new KubernetesCloud("kubernetes")
}
kubernetes.setServerUrl("https://kubernetes.default.svc.cluster.local:443")
kubernetes.setServerUrl("https://kubernetes.default.svc.%s:443")
kubernetes.setNamespace("%s")
kubernetes.setJenkinsUrl("%s")
kubernetes.setJenkinsTunnel("%s")
Expand Down Expand Up @@ -178,30 +178,40 @@ func GetBaseConfigurationConfigMapName(jenkins *v1alpha2.Jenkins) string {
}

// NewBaseConfigurationConfigMap builds Kubernetes config map used to base configuration.
func NewBaseConfigurationConfigMap(meta metav1.ObjectMeta, jenkins *v1alpha2.Jenkins) (*corev1.ConfigMap, error) {
func NewBaseConfigurationConfigMap(meta metav1.ObjectMeta, jenkins *v1alpha2.Jenkins, kubernetesClusterDomain string) (*corev1.ConfigMap, error) {
meta.Name = GetBaseConfigurationConfigMapName(jenkins)
jenkinsServiceFQDN, err := GetJenkinsHTTPServiceFQDN(jenkins)
clusterDomain, err := getClusterDomain(kubernetesClusterDomain)
if err != nil {
return nil, err
}
jenkinsSlavesServiceFQDN, err := GetJenkinsSlavesServiceFQDN(jenkins)
jenkinsServiceFQDN, err := GetJenkinsHTTPServiceFQDN(jenkins, kubernetesClusterDomain)
if err != nil {
return nil, err
}
jenkinsSlavesServiceFQDN, err := GetJenkinsSlavesServiceFQDN(jenkins, kubernetesClusterDomain)
if err != nil {
return nil, err
}
suffix := ""
if prefix, ok := GetJenkinsOpts(*jenkins)["prefix"]; ok {
suffix = prefix
}
groovyScriptsMap := map[string]string{
basicSettingsGroovyScriptName: fmt.Sprintf(basicSettingsFmt, constants.DefaultAmountOfExecutors),
enableCSRFGroovyScriptName: enableCSRF,
disableUsageStatsGroovyScriptName: disableUsageStats,
enableMasterAccessControlGroovyScriptName: enableMasterAccessControl,
disableInsecureFeaturesGroovyScriptName: disableInsecureFeatures,
configureKubernetesPluginGroovyScriptName: fmt.Sprintf(configureKubernetesPluginFmt,
clusterDomain,
jenkins.ObjectMeta.Namespace,
fmt.Sprintf("http://%s:%d", jenkinsServiceFQDN, jenkins.Spec.Service.Port),
fmt.Sprintf("http://%s:%d%s", jenkinsServiceFQDN, jenkins.Spec.Service.Port, suffix),
fmt.Sprintf("%s:%d", jenkinsSlavesServiceFQDN, jenkins.Spec.SlaveService.Port),
),
configureViewsGroovyScriptName: configureViews,
disableJobDslScriptApprovalGroovyScriptName: disableJobDSLScriptApproval,
}

if jenkins.Spec.Master.DisableCSRFProtection {
delete(groovyScriptsMap, enableCSRFGroovyScriptName)
}
Expand Down
Loading