#176 Refactor backup restore mechanism
This commit is contained in:
		
							parent
							
								
									554af5db80
								
							
						
					
					
						commit
						dbf6184898
					
				|  | @ -14,6 +14,7 @@ import ( | |||
| 	"github.com/go-logr/logr" | ||||
| 	"github.com/pkg/errors" | ||||
| 	corev1 "k8s.io/api/core/v1" | ||||
| 	apierrors "k8s.io/apimachinery/pkg/api/errors" | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| 	"k8s.io/client-go/kubernetes" | ||||
| 	"k8s.io/client-go/kubernetes/scheme" | ||||
|  | @ -27,7 +28,36 @@ type backupTrigger struct { | |||
| 	ticker   *time.Ticker | ||||
| } | ||||
| 
 | ||||
| var backupTriggers = map[string]backupTrigger{} | ||||
| type backupTriggers struct { | ||||
| 	triggers map[string]backupTrigger | ||||
| } | ||||
| 
 | ||||
| func (t *backupTriggers) stop(logger logr.Logger, namespace string, name string) { | ||||
| 	key := t.key(namespace, name) | ||||
| 	trigger, found := t.triggers[key] | ||||
| 	if found { | ||||
| 		logger.Info(fmt.Sprintf("Stopping backup trigger for '%s'", key)) | ||||
| 		trigger.ticker.Stop() | ||||
| 		delete(t.triggers, key) | ||||
| 	} else { | ||||
| 		logger.V(log.VWarn).Info(fmt.Sprintf("Can't stop backup trigger for '%s', not found, skipping", key)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func (t *backupTriggers) get(namespace, name string) (backupTrigger, bool) { | ||||
| 	trigger, found := t.triggers[t.key(namespace, name)] | ||||
| 	return trigger, found | ||||
| } | ||||
| 
 | ||||
| func (t *backupTriggers) key(namespace, name string) string { | ||||
| 	return namespace + "/" + name | ||||
| } | ||||
| 
 | ||||
| func (t *backupTriggers) add(namespace string, name string, trigger backupTrigger) { | ||||
| 	t.triggers[t.key(namespace, name)] = trigger | ||||
| } | ||||
| 
 | ||||
| var triggers = backupTriggers{triggers: make(map[string]backupTrigger)} | ||||
| 
 | ||||
| // BackupAndRestore represents Jenkins backup and restore client
 | ||||
| type BackupAndRestore struct { | ||||
|  | @ -169,7 +199,10 @@ func triggerBackup(ticker *time.Ticker, k8sClient k8s.Client, logger logr.Logger | |||
| 	for range ticker.C { | ||||
| 		jenkins := &v1alpha2.Jenkins{} | ||||
| 		err := k8sClient.Get(context.TODO(), types.NamespacedName{Namespace: namespace, Name: name}, jenkins) | ||||
| 		if err != nil { | ||||
| 		if err != nil && apierrors.IsNotFound(err) { | ||||
| 			triggers.stop(logger, namespace, name) | ||||
| 			return // abort
 | ||||
| 		} else if err != nil { | ||||
| 			logger.V(log.VWarn).Info(fmt.Sprintf("backup trigger, error when fetching CR: %s", err)) | ||||
| 		} | ||||
| 		if jenkins.Status.LastBackup == jenkins.Status.PendingBackup { | ||||
|  | @ -184,21 +217,22 @@ func triggerBackup(ticker *time.Ticker, k8sClient k8s.Client, logger logr.Logger | |||
| 
 | ||||
| // EnsureBackupTrigger creates or update trigger which update CR to make backup
 | ||||
| func (bar *BackupAndRestore) EnsureBackupTrigger() error { | ||||
| 	jenkins := bar.jenkins | ||||
| 	trigger, found := backupTriggers[jenkins.Name] | ||||
| 	if len(jenkins.Spec.Backup.ContainerName) == 0 || jenkins.Spec.Backup.Interval == 0 { | ||||
| 		bar.logger.V(log.VDebug).Info("Skipping create backup trigger") | ||||
| 		if found { | ||||
| 			bar.stopBackupTrigger(trigger) | ||||
| 		} | ||||
| 	trigger, found := triggers.get(bar.jenkins.Namespace, bar.jenkins.Name) | ||||
| 
 | ||||
| 	isBackupConfigured := len(bar.jenkins.Spec.Backup.ContainerName) == 0 || bar.jenkins.Spec.Backup.Interval == 0 | ||||
| 	if found && !isBackupConfigured { | ||||
| 		bar.StopBackupTrigger() | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	// configured backup has no trigger
 | ||||
| 	if !found { | ||||
| 		bar.startBackupTrigger() | ||||
| 	} | ||||
| 	if found && jenkins.Spec.Backup.Interval != trigger.interval { | ||||
| 		bar.stopBackupTrigger(trigger) | ||||
| 
 | ||||
| 	// configured interval has changes
 | ||||
| 	if found && bar.jenkins.Spec.Backup.Interval != trigger.interval { | ||||
| 		bar.StopBackupTrigger() | ||||
| 		bar.startBackupTrigger() | ||||
| 	} | ||||
| 
 | ||||
|  | @ -207,28 +241,19 @@ func (bar *BackupAndRestore) EnsureBackupTrigger() error { | |||
| 
 | ||||
| // StopBackupTrigger stops trigger which update CR to make backup
 | ||||
| func (bar *BackupAndRestore) StopBackupTrigger() { | ||||
| 	trigger, found := backupTriggers[bar.jenkins.Name] | ||||
| 	if found { | ||||
| 		bar.stopBackupTrigger(trigger) | ||||
| 	} | ||||
| 	triggers.stop(bar.logger, bar.jenkins.Namespace, bar.jenkins.Name) | ||||
| } | ||||
| 
 | ||||
| func (bar *BackupAndRestore) startBackupTrigger() { | ||||
| 	bar.logger.Info("Starting backup trigger") | ||||
| 	ticker := time.NewTicker(time.Duration(bar.jenkins.Spec.Backup.Interval) * time.Second) | ||||
| 	backupTriggers[bar.jenkins.Name] = backupTrigger{ | ||||
| 	triggers.add(bar.jenkins.Namespace, bar.jenkins.Name, backupTrigger{ | ||||
| 		interval: bar.jenkins.Spec.Backup.Interval, | ||||
| 		ticker:   ticker, | ||||
| 	} | ||||
| 	}) | ||||
| 	go triggerBackup(ticker, bar.k8sClient, bar.logger, bar.jenkins.Namespace, bar.jenkins.Name) | ||||
| } | ||||
| 
 | ||||
| func (bar *BackupAndRestore) stopBackupTrigger(trigger backupTrigger) { | ||||
| 	bar.logger.Info("Stopping backup trigger") | ||||
| 	trigger.ticker.Stop() | ||||
| 	delete(backupTriggers, bar.jenkins.Name) | ||||
| } | ||||
| 
 | ||||
| func (bar *BackupAndRestore) exec(podName, containerName string, command []string) (stdout, stderr bytes.Buffer, err error) { | ||||
| 	req := bar.clientSet.CoreV1().RESTClient().Post(). | ||||
| 		Resource("pods"). | ||||
|  |  | |||
|  | @ -28,7 +28,6 @@ import ( | |||
| 	"k8s.io/apimachinery/pkg/api/errors" | ||||
| 	apierrors "k8s.io/apimachinery/pkg/api/errors" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| 	"k8s.io/client-go/rest" | ||||
| 	"sigs.k8s.io/controller-runtime/pkg/client" | ||||
|  | @ -42,17 +41,15 @@ const ( | |||
| // ReconcileJenkinsBaseConfiguration defines values required for Jenkins base configuration
 | ||||
| type ReconcileJenkinsBaseConfiguration struct { | ||||
| 	configuration.Configuration | ||||
| 	scheme          *runtime.Scheme | ||||
| 	logger          logr.Logger | ||||
| 	local, minikube bool | ||||
| 	config          *rest.Config | ||||
| } | ||||
| 
 | ||||
| // New create structure which takes care of base configuration
 | ||||
| func New(config configuration.Configuration, scheme *runtime.Scheme, logger logr.Logger, local, minikube bool, restConfig *rest.Config) *ReconcileJenkinsBaseConfiguration { | ||||
| func New(config configuration.Configuration, logger logr.Logger, local, minikube bool, restConfig *rest.Config) *ReconcileJenkinsBaseConfiguration { | ||||
| 	return &ReconcileJenkinsBaseConfiguration{ | ||||
| 		Configuration: config, | ||||
| 		scheme:        scheme, | ||||
| 		logger:        logger, | ||||
| 		local:         local, | ||||
| 		minikube:      minikube, | ||||
|  | @ -255,7 +252,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createOperatorCredentialsSecret(meta | |||
| 	err := r.Configuration.Client.Get(context.TODO(), types.NamespacedName{Name: resources.GetOperatorCredentialsSecretName(r.Configuration.Jenkins), Namespace: r.Configuration.Jenkins.ObjectMeta.Namespace}, found) | ||||
| 
 | ||||
| 	if err != nil && apierrors.IsNotFound(err) { | ||||
| 		return stackerr.WithStack(r.createResource(resources.NewOperatorCredentialsSecret(meta, r.Configuration.Jenkins))) | ||||
| 		return stackerr.WithStack(r.CreateResource(resources.NewOperatorCredentialsSecret(meta, r.Configuration.Jenkins))) | ||||
| 	} else if err != nil && !apierrors.IsNotFound(err) { | ||||
| 		return stackerr.WithStack(err) | ||||
| 	} | ||||
|  | @ -265,7 +262,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createOperatorCredentialsSecret(meta | |||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	return stackerr.WithStack(r.updateResource(resources.NewOperatorCredentialsSecret(meta, r.Configuration.Jenkins))) | ||||
| 	return stackerr.WithStack(r.UpdateResource(resources.NewOperatorCredentialsSecret(meta, r.Configuration.Jenkins))) | ||||
| } | ||||
| 
 | ||||
| func (r *ReconcileJenkinsBaseConfiguration) createScriptsConfigMap(meta metav1.ObjectMeta) error { | ||||
|  | @ -273,7 +270,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createScriptsConfigMap(meta metav1.O | |||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return stackerr.WithStack(r.createOrUpdateResource(configMap)) | ||||
| 	return stackerr.WithStack(r.CreateOrUpdateResource(configMap)) | ||||
| } | ||||
| 
 | ||||
| func (r *ReconcileJenkinsBaseConfiguration) createInitConfigurationConfigMap(meta metav1.ObjectMeta) error { | ||||
|  | @ -281,12 +278,12 @@ func (r *ReconcileJenkinsBaseConfiguration) createInitConfigurationConfigMap(met | |||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	return stackerr.WithStack(r.createOrUpdateResource(configMap)) | ||||
| 	return stackerr.WithStack(r.CreateOrUpdateResource(configMap)) | ||||
| } | ||||
| 
 | ||||
| func (r *ReconcileJenkinsBaseConfiguration) createBaseConfigurationConfigMap(meta metav1.ObjectMeta) error { | ||||
| 	configMap := resources.NewBaseConfigurationConfigMap(meta, r.Configuration.Jenkins) | ||||
| 	return stackerr.WithStack(r.createOrUpdateResource(configMap)) | ||||
| 	return stackerr.WithStack(r.CreateOrUpdateResource(configMap)) | ||||
| } | ||||
| 
 | ||||
| func (r *ReconcileJenkinsBaseConfiguration) addLabelForWatchesResources(customization v1alpha2.Customization) error { | ||||
|  | @ -339,19 +336,19 @@ func (r *ReconcileJenkinsBaseConfiguration) addLabelForWatchesResources(customiz | |||
| 
 | ||||
| func (r *ReconcileJenkinsBaseConfiguration) createRBAC(meta metav1.ObjectMeta) error { | ||||
| 	serviceAccount := resources.NewServiceAccount(meta) | ||||
| 	err := r.createResource(serviceAccount) | ||||
| 	err := r.CreateResource(serviceAccount) | ||||
| 	if err != nil && !errors.IsAlreadyExists(err) { | ||||
| 		return stackerr.WithStack(err) | ||||
| 	} | ||||
| 
 | ||||
| 	role := resources.NewRole(meta) | ||||
| 	err = r.createOrUpdateResource(role) | ||||
| 	err = r.CreateOrUpdateResource(role) | ||||
| 	if err != nil { | ||||
| 		return stackerr.WithStack(err) | ||||
| 	} | ||||
| 
 | ||||
| 	roleBinding := resources.NewRoleBinding(meta) | ||||
| 	err = r.createOrUpdateResource(roleBinding) | ||||
| 	err = r.CreateOrUpdateResource(roleBinding) | ||||
| 	if err != nil { | ||||
| 		return stackerr.WithStack(err) | ||||
| 	} | ||||
|  | @ -373,7 +370,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createService(meta metav1.ObjectMeta | |||
| 				Selector: meta.Labels, | ||||
| 			}, | ||||
| 		}, config) | ||||
| 		if err = r.createResource(&service); err != nil { | ||||
| 		if err = r.CreateResource(&service); err != nil { | ||||
| 			return stackerr.WithStack(err) | ||||
| 		} | ||||
| 	} else if err != nil { | ||||
|  | @ -381,7 +378,7 @@ func (r *ReconcileJenkinsBaseConfiguration) createService(meta metav1.ObjectMeta | |||
| 	} | ||||
| 
 | ||||
| 	service = resources.UpdateService(service, config) | ||||
| 	return stackerr.WithStack(r.updateResource(&service)) | ||||
| 	return stackerr.WithStack(r.UpdateResource(&service)) | ||||
| } | ||||
| 
 | ||||
| func (r *ReconcileJenkinsBaseConfiguration) getJenkinsMasterPod() (*corev1.Pod, error) { | ||||
|  | @ -416,7 +413,7 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsMasterPod(meta metav1.O | |||
| 			Reason:  reason.NewPodCreation(reason.OperatorSource, []string{"Creating a new Jenkins Master Pod"}), | ||||
| 		} | ||||
| 		r.logger.Info(fmt.Sprintf("Creating a new Jenkins Master Pod %s/%s", jenkinsMasterPod.Namespace, jenkinsMasterPod.Name)) | ||||
| 		err = r.createResource(jenkinsMasterPod) | ||||
| 		err = r.CreateResource(jenkinsMasterPod) | ||||
| 		if err != nil { | ||||
| 			return reconcile.Result{}, stackerr.WithStack(err) | ||||
| 		} | ||||
|  | @ -827,7 +824,7 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureJenkinsClient(meta metav1.Obje | |||
| 		credentialsSecret.Data[resources.OperatorCredentialsSecretTokenKey] = []byte(token.GetToken()) | ||||
| 		now, _ := time.Now().UTC().MarshalText() | ||||
| 		credentialsSecret.Data[resources.OperatorCredentialsSecretTokenCreationKey] = now | ||||
| 		err = r.updateResource(credentialsSecret) | ||||
| 		err = r.UpdateResource(credentialsSecret) | ||||
| 		if err != nil { | ||||
| 			return nil, stackerr.WithStack(err) | ||||
| 		} | ||||
|  |  | |||
|  | @ -234,7 +234,7 @@ func TestCompareVolumes(t *testing.T) { | |||
| 				Volumes:            resources.GetJenkinsMasterPodBaseVolumes(jenkins), | ||||
| 			}, | ||||
| 		} | ||||
| 		reconciler := New(configuration.Configuration{Jenkins: jenkins}, nil, nil, false, false, nil) | ||||
| 		reconciler := New(configuration.Configuration{Jenkins: jenkins}, nil, false, false, nil) | ||||
| 
 | ||||
| 		got := reconciler.compareVolumes(pod) | ||||
| 
 | ||||
|  | @ -258,7 +258,7 @@ func TestCompareVolumes(t *testing.T) { | |||
| 				Volumes:            resources.GetJenkinsMasterPodBaseVolumes(jenkins), | ||||
| 			}, | ||||
| 		} | ||||
| 		reconciler := New(configuration.Configuration{Jenkins: jenkins}, nil, nil, false, false, nil) | ||||
| 		reconciler := New(configuration.Configuration{Jenkins: jenkins}, nil, false, false, nil) | ||||
| 
 | ||||
| 		got := reconciler.compareVolumes(pod) | ||||
| 
 | ||||
|  | @ -282,7 +282,7 @@ func TestCompareVolumes(t *testing.T) { | |||
| 				Volumes:            append(resources.GetJenkinsMasterPodBaseVolumes(jenkins), corev1.Volume{Name: "added"}), | ||||
| 			}, | ||||
| 		} | ||||
| 		reconciler := New(configuration.Configuration{Jenkins: jenkins}, nil, nil, false, false, nil) | ||||
| 		reconciler := New(configuration.Configuration{Jenkins: jenkins}, nil, false, false, nil) | ||||
| 
 | ||||
| 		got := reconciler.compareVolumes(pod) | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,56 +0,0 @@ | |||
| package base | ||||
| 
 | ||||
| import ( | ||||
| 	"context" | ||||
| 
 | ||||
| 	stackerr "github.com/pkg/errors" | ||||
| 	"k8s.io/apimachinery/pkg/api/errors" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" | ||||
| ) | ||||
| 
 | ||||
| func (r *ReconcileJenkinsBaseConfiguration) createResource(obj metav1.Object) error { | ||||
| 	runtimeObj, ok := obj.(runtime.Object) | ||||
| 	if !ok { | ||||
| 		return stackerr.Errorf("is not a %T a runtime.Object", obj) | ||||
| 	} | ||||
| 
 | ||||
| 	// Set Jenkins instance as the owner and controller
 | ||||
| 	if err := controllerutil.SetControllerReference(r.Configuration.Jenkins, obj, r.scheme); err != nil { | ||||
| 		return stackerr.WithStack(err) | ||||
| 	} | ||||
| 
 | ||||
| 	return r.Client.Create(context.TODO(), runtimeObj) // don't wrap error
 | ||||
| } | ||||
| 
 | ||||
| func (r *ReconcileJenkinsBaseConfiguration) updateResource(obj metav1.Object) error { | ||||
| 	runtimeObj, ok := obj.(runtime.Object) | ||||
| 	if !ok { | ||||
| 		return stackerr.Errorf("is not a %T a runtime.Object", obj) | ||||
| 	} | ||||
| 
 | ||||
| 	// set Jenkins instance as the owner and controller, don't check error(can be already set)
 | ||||
| 	_ = controllerutil.SetControllerReference(r.Configuration.Jenkins, obj, r.scheme) | ||||
| 
 | ||||
| 	return r.Client.Update(context.TODO(), runtimeObj) // don't wrap error
 | ||||
| } | ||||
| 
 | ||||
| func (r *ReconcileJenkinsBaseConfiguration) createOrUpdateResource(obj metav1.Object) error { | ||||
| 	runtimeObj, ok := obj.(runtime.Object) | ||||
| 	if !ok { | ||||
| 		return stackerr.Errorf("is not a %T a runtime.Object", obj) | ||||
| 	} | ||||
| 
 | ||||
| 	// set Jenkins instance as the owner and controller, don't check error(can be already set)
 | ||||
| 	_ = controllerutil.SetControllerReference(r.Configuration.Jenkins, obj, r.scheme) | ||||
| 
 | ||||
| 	err := r.Client.Create(context.TODO(), runtimeObj) | ||||
| 	if err != nil && errors.IsAlreadyExists(err) { | ||||
| 		return r.updateResource(obj) | ||||
| 	} else if err != nil && !errors.IsAlreadyExists(err) { | ||||
| 		return stackerr.WithStack(err) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
|  | @ -23,7 +23,7 @@ import ( | |||
| 
 | ||||
| func TestValidatePlugins(t *testing.T) { | ||||
| 	log.SetupLogger(true) | ||||
| 	baseReconcileLoop := New(configuration.Configuration{}, nil, log.Log, false, false, nil) | ||||
| 	baseReconcileLoop := New(configuration.Configuration{}, log.Log, false, false, nil) | ||||
| 	t.Run("empty", func(t *testing.T) { | ||||
| 		var requiredBasePlugins []plugins.Plugin | ||||
| 		var basePlugins []v1alpha2.Plugin | ||||
|  | @ -166,7 +166,7 @@ func TestReconcileJenkinsBaseConfiguration_validateImagePullSecrets(t *testing.T | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 
 | ||||
| 		got, err := baseReconcileLoop.validateImagePullSecrets() | ||||
| 		fmt.Println(got) | ||||
|  | @ -190,7 +190,7 @@ func TestReconcileJenkinsBaseConfiguration_validateImagePullSecrets(t *testing.T | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, nil, false, false, nil) | ||||
| 		}, nil, false, false, nil) | ||||
| 
 | ||||
| 		got, _ := baseReconcileLoop.validateImagePullSecrets() | ||||
| 
 | ||||
|  | @ -226,7 +226,7 @@ func TestReconcileJenkinsBaseConfiguration_validateImagePullSecrets(t *testing.T | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, nil, false, false, nil) | ||||
| 		}, nil, false, false, nil) | ||||
| 
 | ||||
| 		got, _ := baseReconcileLoop.validateImagePullSecrets() | ||||
| 
 | ||||
|  | @ -262,7 +262,7 @@ func TestReconcileJenkinsBaseConfiguration_validateImagePullSecrets(t *testing.T | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 
 | ||||
| 		got, _ := baseReconcileLoop.validateImagePullSecrets() | ||||
| 
 | ||||
|  | @ -298,7 +298,7 @@ func TestReconcileJenkinsBaseConfiguration_validateImagePullSecrets(t *testing.T | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 
 | ||||
| 		got, _ := baseReconcileLoop.validateImagePullSecrets() | ||||
| 
 | ||||
|  | @ -334,7 +334,7 @@ func TestReconcileJenkinsBaseConfiguration_validateImagePullSecrets(t *testing.T | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 
 | ||||
| 		got, _ := baseReconcileLoop.validateImagePullSecrets() | ||||
| 
 | ||||
|  | @ -367,7 +367,7 @@ func TestValidateJenkinsMasterPodEnvs(t *testing.T) { | |||
| 		} | ||||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		got := baseReconcileLoop.validateJenkinsMasterPodEnvs() | ||||
| 		assert.Nil(t, got) | ||||
| 	}) | ||||
|  | @ -394,7 +394,7 @@ func TestValidateJenkinsMasterPodEnvs(t *testing.T) { | |||
| 		} | ||||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		got := baseReconcileLoop.validateJenkinsMasterPodEnvs() | ||||
| 
 | ||||
| 		assert.Equal(t, got, []string{"Jenkins Master container env 'JENKINS_HOME' cannot be overridden"}) | ||||
|  | @ -418,7 +418,7 @@ func TestValidateJenkinsMasterPodEnvs(t *testing.T) { | |||
| 		} | ||||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		got := baseReconcileLoop.validateJenkinsMasterPodEnvs() | ||||
| 
 | ||||
| 		assert.Equal(t, got, []string{"Jenkins Master container env 'JAVA_OPTS' doesn't have required flag '-Djava.awt.headless=true'"}) | ||||
|  | @ -442,7 +442,7 @@ func TestValidateJenkinsMasterPodEnvs(t *testing.T) { | |||
| 		} | ||||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		got := baseReconcileLoop.validateJenkinsMasterPodEnvs() | ||||
| 
 | ||||
| 		assert.Equal(t, got, []string{"Jenkins Master container env 'JAVA_OPTS' doesn't have required flag '-Djenkins.install.runSetupWizard=false'"}) | ||||
|  | @ -464,7 +464,7 @@ func TestValidateReservedVolumes(t *testing.T) { | |||
| 		} | ||||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		got := baseReconcileLoop.validateReservedVolumes() | ||||
| 		assert.Nil(t, got) | ||||
| 	}) | ||||
|  | @ -482,7 +482,7 @@ func TestValidateReservedVolumes(t *testing.T) { | |||
| 		} | ||||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		got := baseReconcileLoop.validateReservedVolumes() | ||||
| 
 | ||||
| 		assert.Equal(t, got, []string{"Jenkins Master pod volume 'jenkins-home' is reserved please choose different one"}) | ||||
|  | @ -498,7 +498,7 @@ func TestValidateContainerVolumeMounts(t *testing.T) { | |||
| 		} | ||||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		got := baseReconcileLoop.validateContainerVolumeMounts(v1alpha2.Container{}) | ||||
| 		assert.Nil(t, got) | ||||
| 	}) | ||||
|  | @ -526,7 +526,7 @@ func TestValidateContainerVolumeMounts(t *testing.T) { | |||
| 		} | ||||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		got := baseReconcileLoop.validateContainerVolumeMounts(jenkins.Spec.Master.Containers[0]) | ||||
| 		assert.Nil(t, got) | ||||
| 	}) | ||||
|  | @ -554,7 +554,7 @@ func TestValidateContainerVolumeMounts(t *testing.T) { | |||
| 		} | ||||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		got := baseReconcileLoop.validateContainerVolumeMounts(jenkins.Spec.Master.Containers[0]) | ||||
| 		assert.Equal(t, got, []string{"mountPath not set for 'example' volume mount in container ''"}) | ||||
| 	}) | ||||
|  | @ -577,7 +577,7 @@ func TestValidateContainerVolumeMounts(t *testing.T) { | |||
| 		} | ||||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: &jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		got := baseReconcileLoop.validateContainerVolumeMounts(jenkins.Spec.Master.Containers[0]) | ||||
| 
 | ||||
| 		assert.Equal(t, got, []string{"Not found volume for 'missing-volume' volume mount in container ''"}) | ||||
|  | @ -599,7 +599,7 @@ func TestValidateConfigMapVolume(t *testing.T) { | |||
| 		fakeClient := fake.NewFakeClient() | ||||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Client: fakeClient, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 
 | ||||
| 		got, err := baseReconcileLoop.validateConfigMapVolume(volume) | ||||
| 
 | ||||
|  | @ -627,7 +627,7 @@ func TestValidateConfigMapVolume(t *testing.T) { | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 
 | ||||
| 		got, err := baseReconcileLoop.validateConfigMapVolume(volume) | ||||
| 
 | ||||
|  | @ -653,7 +653,7 @@ func TestValidateConfigMapVolume(t *testing.T) { | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 
 | ||||
| 		got, err := baseReconcileLoop.validateConfigMapVolume(volume) | ||||
| 
 | ||||
|  | @ -678,7 +678,7 @@ func TestValidateSecretVolume(t *testing.T) { | |||
| 		fakeClient := fake.NewFakeClient() | ||||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Client: fakeClient, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 
 | ||||
| 		got, err := baseReconcileLoop.validateSecretVolume(volume) | ||||
| 
 | ||||
|  | @ -704,7 +704,7 @@ func TestValidateSecretVolume(t *testing.T) { | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 
 | ||||
| 		got, err := baseReconcileLoop.validateSecretVolume(volume) | ||||
| 
 | ||||
|  | @ -728,7 +728,7 @@ func TestValidateSecretVolume(t *testing.T) { | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Client:  fakeClient, | ||||
| 			Jenkins: jenkins, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		got, err := baseReconcileLoop.validateSecretVolume(volume) | ||||
| 
 | ||||
| 		assert.NoError(t, err) | ||||
|  | @ -752,7 +752,7 @@ func TestValidateCustomization(t *testing.T) { | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: jenkins, | ||||
| 			Client:  fakeClient, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 
 | ||||
| 		got, err := baseReconcileLoop.validateCustomization(customization, "spec.groovyScripts") | ||||
| 
 | ||||
|  | @ -774,7 +774,7 @@ func TestValidateCustomization(t *testing.T) { | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: jenkins, | ||||
| 			Client:  fakeClient, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		err := fakeClient.Create(context.TODO(), secret) | ||||
| 		require.NoError(t, err) | ||||
| 
 | ||||
|  | @ -805,7 +805,7 @@ func TestValidateCustomization(t *testing.T) { | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: jenkins, | ||||
| 			Client:  fakeClient, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		err := fakeClient.Create(context.TODO(), secret) | ||||
| 		require.NoError(t, err) | ||||
| 		err = fakeClient.Create(context.TODO(), configMap) | ||||
|  | @ -832,7 +832,7 @@ func TestValidateCustomization(t *testing.T) { | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: jenkins, | ||||
| 			Client:  fakeClient, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		err := fakeClient.Create(context.TODO(), configMap) | ||||
| 		require.NoError(t, err) | ||||
| 
 | ||||
|  | @ -857,7 +857,7 @@ func TestValidateCustomization(t *testing.T) { | |||
| 		baseReconcileLoop := New(configuration.Configuration{ | ||||
| 			Jenkins: jenkins, | ||||
| 			Client:  fakeClient, | ||||
| 		}, nil, logf.ZapLogger(false), false, false, nil) | ||||
| 		}, logf.ZapLogger(false), false, false, nil) | ||||
| 		err := fakeClient.Create(context.TODO(), secret) | ||||
| 		require.NoError(t, err) | ||||
| 
 | ||||
|  |  | |||
|  | @ -10,9 +10,13 @@ import ( | |||
| 
 | ||||
| 	stackerr "github.com/pkg/errors" | ||||
| 	corev1 "k8s.io/api/core/v1" | ||||
| 	"k8s.io/apimachinery/pkg/api/errors" | ||||
| 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||||
| 	"k8s.io/apimachinery/pkg/runtime" | ||||
| 	"k8s.io/apimachinery/pkg/types" | ||||
| 	"k8s.io/client-go/kubernetes" | ||||
| 	"sigs.k8s.io/controller-runtime/pkg/client" | ||||
| 	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" | ||||
| ) | ||||
| 
 | ||||
| // Configuration holds required for Jenkins configuration
 | ||||
|  | @ -21,6 +25,7 @@ type Configuration struct { | |||
| 	ClientSet     kubernetes.Clientset | ||||
| 	Notifications *chan event.Event | ||||
| 	Jenkins       *v1alpha2.Jenkins | ||||
| 	Scheme        *runtime.Scheme | ||||
| } | ||||
| 
 | ||||
| // RestartJenkinsMasterPod terminate Jenkins master pod and notifies about it
 | ||||
|  | @ -49,3 +54,51 @@ func (c *Configuration) getJenkinsMasterPod() (*corev1.Pod, error) { | |||
| 	} | ||||
| 	return currentJenkinsMasterPod, nil | ||||
| } | ||||
| 
 | ||||
| // CreateResource is creating kubernetes resource and references it to Jenkins CR
 | ||||
| func (c *Configuration) CreateResource(obj metav1.Object) error { | ||||
| 	runtimeObj, ok := obj.(runtime.Object) | ||||
| 	if !ok { | ||||
| 		return stackerr.Errorf("is not a %T a runtime.Object", obj) | ||||
| 	} | ||||
| 
 | ||||
| 	// Set Jenkins instance as the owner and controller
 | ||||
| 	if err := controllerutil.SetControllerReference(c.Jenkins, obj, c.Scheme); err != nil { | ||||
| 		return stackerr.WithStack(err) | ||||
| 	} | ||||
| 
 | ||||
| 	return c.Client.Create(context.TODO(), runtimeObj) // don't wrap error
 | ||||
| } | ||||
| 
 | ||||
| // UpdateResource is updating kubernetes resource and references it to Jenkins CR
 | ||||
| func (c *Configuration) UpdateResource(obj metav1.Object) error { | ||||
| 	runtimeObj, ok := obj.(runtime.Object) | ||||
| 	if !ok { | ||||
| 		return stackerr.Errorf("is not a %T a runtime.Object", obj) | ||||
| 	} | ||||
| 
 | ||||
| 	// set Jenkins instance as the owner and controller, don't check error(can be already set)
 | ||||
| 	_ = controllerutil.SetControllerReference(c.Jenkins, obj, c.Scheme) | ||||
| 
 | ||||
| 	return c.Client.Update(context.TODO(), runtimeObj) // don't wrap error
 | ||||
| } | ||||
| 
 | ||||
| // CreateOrUpdateResource is creating or updating kubernetes resource and references it to Jenkins CR
 | ||||
| func (c *Configuration) CreateOrUpdateResource(obj metav1.Object) error { | ||||
| 	runtimeObj, ok := obj.(runtime.Object) | ||||
| 	if !ok { | ||||
| 		return stackerr.Errorf("is not a %T a runtime.Object", obj) | ||||
| 	} | ||||
| 
 | ||||
| 	// set Jenkins instance as the owner and controller, don't check error(can be already set)
 | ||||
| 	_ = controllerutil.SetControllerReference(c.Jenkins, obj, c.Scheme) | ||||
| 
 | ||||
| 	err := c.Client.Create(context.TODO(), runtimeObj) | ||||
| 	if err != nil && errors.IsAlreadyExists(err) { | ||||
| 		return c.UpdateResource(obj) | ||||
| 	} else if err != nil && !errors.IsAlreadyExists(err) { | ||||
| 		return stackerr.WithStack(err) | ||||
| 	} | ||||
| 
 | ||||
| 	return nil | ||||
| } | ||||
|  |  | |||
|  | @ -340,16 +340,6 @@ func agentDeployment(jenkins *v1alpha2.Jenkins, namespace string, agentName stri | |||
| 		ObjectMeta: metav1.ObjectMeta{ | ||||
| 			Name:      agentDeploymentName(*jenkins, agentName), | ||||
| 			Namespace: namespace, | ||||
| 			OwnerReferences: []metav1.OwnerReference{ | ||||
| 				{ | ||||
| 					BlockOwnerDeletion: &[]bool{true}[0], | ||||
| 					Controller: &[]bool{true}[0], | ||||
| 					Kind: jenkins.Kind, | ||||
| 					Name: jenkins.Name, | ||||
| 					APIVersion: jenkins.APIVersion, | ||||
| 					UID: jenkins.UID, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 		Spec: apps.DeploymentSpec{ | ||||
| 			Template: corev1.PodTemplateSpec{ | ||||
|  |  | |||
|  | @ -214,10 +214,11 @@ func (r *ReconcileJenkins) reconcile(request reconcile.Request, logger logr.Logg | |||
| 		ClientSet:     r.clientSet, | ||||
| 		Notifications: r.notificationEvents, | ||||
| 		Jenkins:       jenkins, | ||||
| 		Scheme:        r.scheme, | ||||
| 	} | ||||
| 
 | ||||
| 	// Reconcile base configuration
 | ||||
| 	baseConfiguration := base.New(config, r.scheme, logger, r.local, r.minikube, &r.config) | ||||
| 	baseConfiguration := base.New(config, logger, r.local, r.minikube, &r.config) | ||||
| 
 | ||||
| 	baseMessages, err := baseConfiguration.Validate(jenkins) | ||||
| 	if err != nil { | ||||
|  |  | |||
|  | @ -39,12 +39,12 @@ func TestUndefined_HasMessages(t *testing.T) { | |||
| 		podRestart := NewUndefined(KubernetesSource, []string{"test", "another-test"}) | ||||
| 		assert.True(t, podRestart.HasMessages()) | ||||
| 	}) | ||||
| 	 | ||||
| 
 | ||||
| 	t.Run("verbose full", func(t *testing.T) { | ||||
| 		podRestart := NewUndefined(KubernetesSource, []string{}, []string{"test", "another-test"}...) | ||||
| 		assert.True(t, podRestart.HasMessages()) | ||||
| 	}) | ||||
| 	 | ||||
| 
 | ||||
| 	t.Run("short empty", func(t *testing.T) { | ||||
| 		podRestart := NewUndefined(KubernetesSource, []string{}) | ||||
| 		assert.False(t, podRestart.HasMessages()) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue