Add backup API
This commit is contained in:
parent
7281032be2
commit
d7fdac5e9a
|
|
@ -51,6 +51,7 @@ type JenkinsMaster struct {
|
||||||
type JenkinsStatus struct {
|
type JenkinsStatus struct {
|
||||||
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
// INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
|
||||||
// Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
|
// Important: Run "operator-sdk generate k8s" to regenerate code after modifying this file
|
||||||
|
BackupRestored bool `json:"backupRestored,omitempty"`
|
||||||
BaseConfigurationCompletedTime *metav1.Time `json:"baseConfigurationCompletedTime,omitempty"`
|
BaseConfigurationCompletedTime *metav1.Time `json:"baseConfigurationCompletedTime,omitempty"`
|
||||||
UserConfigurationCompletedTime *metav1.Time `json:"userConfigurationCompletedTime,omitempty"`
|
UserConfigurationCompletedTime *metav1.Time `json:"userConfigurationCompletedTime,omitempty"`
|
||||||
Builds []Build `json:"builds,omitempty"`
|
Builds []Build `json:"builds,omitempty"`
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
package backup
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||||
|
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/backup/nobackup"
|
||||||
|
jenkinsclient "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/client"
|
||||||
|
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/base/resources"
|
||||||
|
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/constants"
|
||||||
|
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/jobs"
|
||||||
|
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/plugins"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
k8s "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
restoreJobName = constants.OperatorName + "-restore-backup"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Provider defines API of backup providers
|
||||||
|
type Provider interface {
|
||||||
|
GetRestoreJobXML(jenkins virtuslabv1alpha1.Jenkins) (string, error)
|
||||||
|
GetBackupJobXML(jenkins virtuslabv1alpha1.Jenkins) (string, error)
|
||||||
|
IsConfigurationValidForBasePhase(jenkins virtuslabv1alpha1.Jenkins, logger logr.Logger) bool
|
||||||
|
IsConfigurationValidForUserPhase(k8sClient k8s.Client, jenkins virtuslabv1alpha1.Jenkins, logger logr.Logger) (bool, error)
|
||||||
|
GetRequiredPlugins() map[string][]plugins.Plugin
|
||||||
|
}
|
||||||
|
|
||||||
|
// Backup defines backup manager which is responsible of backup jobs history
|
||||||
|
type Backup struct {
|
||||||
|
jenkins *virtuslabv1alpha1.Jenkins
|
||||||
|
k8sClient k8s.Client
|
||||||
|
logger logr.Logger
|
||||||
|
jenkinsClient jenkinsclient.Jenkins
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns instance of backup manager
|
||||||
|
func New(jenkins *virtuslabv1alpha1.Jenkins, k8sClient k8s.Client, logger logr.Logger, jenkinsClient jenkinsclient.Jenkins) *Backup {
|
||||||
|
return &Backup{jenkins: jenkins, k8sClient: k8sClient, logger: logger, jenkinsClient: jenkinsClient}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnsureRestoreJob creates and updates Jenkins job used to restore backup
|
||||||
|
func (b *Backup) EnsureRestoreJob() error {
|
||||||
|
if b.jenkins.Status.UserConfigurationCompletedTime == nil {
|
||||||
|
provider, err := GetBackupProvider(b.jenkins.Spec.Backup)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
restoreJobXML, err := provider.GetRestoreJobXML(*b.jenkins)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, created, err := b.jenkinsClient.CreateOrUpdateJob(restoreJobXML, restoreJobName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if created {
|
||||||
|
b.logger.Info(fmt.Sprintf("'%s' job has been created", restoreJobName))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RestoreBackup restores backup
|
||||||
|
func (b *Backup) RestoreBackup() (reconcile.Result, error) {
|
||||||
|
if !b.jenkins.Status.BackupRestored && b.jenkins.Status.UserConfigurationCompletedTime == nil {
|
||||||
|
jobsClient := jobs.New(b.jenkinsClient, b.k8sClient, b.logger)
|
||||||
|
|
||||||
|
hash := "hash-restore" // it can be hardcoded because restore job can be run only once
|
||||||
|
done, err := jobsClient.EnsureBuildJob(restoreJobName, hash, map[string]string{}, b.jenkins, true)
|
||||||
|
if err != nil {
|
||||||
|
// build failed and can be recovered - retry build and requeue reconciliation loop with timeout
|
||||||
|
if err == jobs.ErrorBuildFailed {
|
||||||
|
return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 10}, nil
|
||||||
|
}
|
||||||
|
// build failed and cannot be recovered
|
||||||
|
if err == jobs.ErrorUnrecoverableBuildFailed {
|
||||||
|
b.logger.Info(fmt.Sprintf("Restore backup can not be performed. Please check backup configuration in CR and credentials in secret '%s'.", resources.GetBackupCredentialsSecretName(b.jenkins)))
|
||||||
|
b.logger.Info(fmt.Sprintf("You can also check '%s' job logs in Jenkins", constants.BackupJobName))
|
||||||
|
return reconcile.Result{}, nil
|
||||||
|
}
|
||||||
|
// unexpected error - requeue reconciliation loop
|
||||||
|
return reconcile.Result{}, err
|
||||||
|
}
|
||||||
|
// build not finished yet - requeue reconciliation loop with timeout
|
||||||
|
if !done {
|
||||||
|
return reconcile.Result{Requeue: true, RequeueAfter: time.Second * 10}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
b.jenkins.Status.BackupRestored = true
|
||||||
|
err = b.k8sClient.Update(context.TODO(), b.jenkins)
|
||||||
|
return reconcile.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return reconcile.Result{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// EnsureBackupJob creates and updates Jenkins job used to backup
|
||||||
|
func (b *Backup) EnsureBackupJob() error {
|
||||||
|
provider, err := GetBackupProvider(b.jenkins.Spec.Backup)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
backupJobXML, err := provider.GetBackupJobXML(*b.jenkins)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
_, created, err := b.jenkinsClient.CreateOrUpdateJob(backupJobXML, constants.BackupJobName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if created {
|
||||||
|
b.logger.Info(fmt.Sprintf("'%s' job has been created", constants.BackupJobName))
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBackupProvider returns backup provider by type
|
||||||
|
func GetBackupProvider(backupType virtuslabv1alpha1.JenkinsBackup) (Provider, error) {
|
||||||
|
switch backupType {
|
||||||
|
case virtuslabv1alpha1.JenkinsBackupTypeNoBackup:
|
||||||
|
return &nobackup.NoBackup{}, nil
|
||||||
|
default:
|
||||||
|
return nil, errors.Errorf("Invalid BackupManager type '%s'", backupType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPluginsRequiredByAllBackupProviders returns plugins required by all backup providers
|
||||||
|
func GetPluginsRequiredByAllBackupProviders() map[string][]plugins.Plugin {
|
||||||
|
allPlugins := map[string][]plugins.Plugin{}
|
||||||
|
for _, provider := range getAllProviders() {
|
||||||
|
for key, value := range provider.GetRequiredPlugins() {
|
||||||
|
allPlugins[key] = func() []plugins.Plugin {
|
||||||
|
var pluginsNameWithVersion []plugins.Plugin
|
||||||
|
for _, plugin := range value {
|
||||||
|
pluginsNameWithVersion = append(pluginsNameWithVersion, plugin)
|
||||||
|
}
|
||||||
|
return pluginsNameWithVersion
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return allPlugins
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAllProviders() []Provider {
|
||||||
|
return []Provider{
|
||||||
|
&nobackup.NoBackup{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
package nobackup
|
||||||
|
|
||||||
|
import (
|
||||||
|
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||||
|
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/plugins"
|
||||||
|
|
||||||
|
"github.com/go-logr/logr"
|
||||||
|
k8s "sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NoBackup is a backup strategy where there is no backup
|
||||||
|
type NoBackup struct{}
|
||||||
|
|
||||||
|
var emptyJob = `<?xml version='1.1' encoding='UTF-8'?>
|
||||||
|
<flow-definition plugin="workflow-job@2.31">
|
||||||
|
<actions/>
|
||||||
|
<description></description>
|
||||||
|
<keepDependencies>false</keepDependencies>
|
||||||
|
<properties></properties>
|
||||||
|
<definition class="org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition" plugin="workflow-cps@2.61">
|
||||||
|
<script></script>
|
||||||
|
<sandbox>false</sandbox>
|
||||||
|
</definition>
|
||||||
|
<triggers/>
|
||||||
|
<disabled>false</disabled>
|
||||||
|
</flow-definition>
|
||||||
|
`
|
||||||
|
|
||||||
|
// GetRestoreJobXML returns Jenkins restore backup job config XML
|
||||||
|
func (b *NoBackup) GetRestoreJobXML(jenkins virtuslabv1alpha1.Jenkins) (string, error) {
|
||||||
|
return emptyJob, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetBackupJobXML returns Jenkins backup job config XML
|
||||||
|
func (b *NoBackup) GetBackupJobXML(jenkins virtuslabv1alpha1.Jenkins) (string, error) {
|
||||||
|
return emptyJob, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsConfigurationValidForBasePhase validates if user provided valid configuration of backup for base phase
|
||||||
|
func (b *NoBackup) IsConfigurationValidForBasePhase(jenkins virtuslabv1alpha1.Jenkins, logger logr.Logger) bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsConfigurationValidForUserPhase validates if user provided valid configuration of backup for user phase
|
||||||
|
func (b *NoBackup) IsConfigurationValidForUserPhase(k8sClient k8s.Client, jenkins virtuslabv1alpha1.Jenkins, logger logr.Logger) (bool, error) {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRequiredPlugins returns all required Jenkins plugins by this backup strategy
|
||||||
|
func (b *NoBackup) GetRequiredPlugins() map[string][]plugins.Plugin {
|
||||||
|
return map[string][]plugins.Plugin{}
|
||||||
|
}
|
||||||
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||||
|
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/backup"
|
||||||
jenkinsclient "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/client"
|
jenkinsclient "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/client"
|
||||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/base/resources"
|
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/base/resources"
|
||||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/constants"
|
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/constants"
|
||||||
|
|
@ -61,7 +62,16 @@ func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (reconcile.Result, jenki
|
||||||
return reconcile.Result{}, nil, err
|
return reconcile.Result{}, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := r.ensureJenkinsMasterPod(metaObject)
|
pluginsRequiredByAllBackupProviders := backup.GetPluginsRequiredByAllBackupProviders()
|
||||||
|
result, err := r.ensurePluginsRequiredByAllBackupProviders(pluginsRequiredByAllBackupProviders)
|
||||||
|
if err != nil {
|
||||||
|
return reconcile.Result{}, nil, err
|
||||||
|
}
|
||||||
|
if result.Requeue {
|
||||||
|
return result, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = r.ensureJenkinsMasterPod(metaObject)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reconcile.Result{}, nil, err
|
return reconcile.Result{}, nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -85,7 +95,7 @@ func (r *ReconcileJenkinsBaseConfiguration) Reconcile() (reconcile.Result, jenki
|
||||||
}
|
}
|
||||||
r.logger.V(log.VDebug).Info("Jenkins API client set")
|
r.logger.V(log.VDebug).Info("Jenkins API client set")
|
||||||
|
|
||||||
ok, err := r.verifyBasePlugins(jenkinsClient)
|
ok, err := r.verifyPlugins(jenkinsClient, plugins.BasePluginsMap, pluginsRequiredByAllBackupProviders)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reconcile.Result{}, nil, err
|
return reconcile.Result{}, nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -142,7 +152,7 @@ func (r *ReconcileJenkinsBaseConfiguration) ensureResourcesRequiredForJenkinsPod
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileJenkinsBaseConfiguration) verifyBasePlugins(jenkinsClient jenkinsclient.Jenkins) (bool, error) {
|
func (r *ReconcileJenkinsBaseConfiguration) verifyPlugins(jenkinsClient jenkinsclient.Jenkins, allRequiredPlugins ...map[string][]plugins.Plugin) (bool, error) {
|
||||||
allPluginsInJenkins, err := jenkinsClient.GetPlugins(fetchAllPlugins)
|
allPluginsInJenkins, err := jenkinsClient.GetPlugins(fetchAllPlugins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
|
|
@ -157,7 +167,8 @@ func (r *ReconcileJenkinsBaseConfiguration) verifyBasePlugins(jenkinsClient jenk
|
||||||
r.logger.V(log.VDebug).Info(fmt.Sprintf("Installed plugins '%+v'", installedPlugins))
|
r.logger.V(log.VDebug).Info(fmt.Sprintf("Installed plugins '%+v'", installedPlugins))
|
||||||
|
|
||||||
status := true
|
status := true
|
||||||
for rootPluginName, p := range plugins.BasePluginsMap {
|
for _, requiredPlugins := range allRequiredPlugins {
|
||||||
|
for rootPluginName, p := range requiredPlugins {
|
||||||
rootPlugin, _ := plugins.New(rootPluginName)
|
rootPlugin, _ := plugins.New(rootPluginName)
|
||||||
if found, ok := isPluginInstalled(allPluginsInJenkins, *rootPlugin); !ok {
|
if found, ok := isPluginInstalled(allPluginsInJenkins, *rootPlugin); !ok {
|
||||||
r.logger.V(log.VWarn).Info(fmt.Sprintf("Missing plugin '%s', actual '%+v'", rootPlugin, found))
|
r.logger.V(log.VWarn).Info(fmt.Sprintf("Missing plugin '%s', actual '%+v'", rootPlugin, found))
|
||||||
|
|
@ -170,6 +181,7 @@ func (r *ReconcileJenkinsBaseConfiguration) verifyBasePlugins(jenkinsClient jenk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return status, nil
|
return status, nil
|
||||||
}
|
}
|
||||||
|
|
@ -488,3 +500,28 @@ func (r *ReconcileJenkinsBaseConfiguration) verifyLabelsForWatchedResource(objec
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ReconcileJenkinsBaseConfiguration) ensurePluginsRequiredByAllBackupProviders(requiredPlugins map[string][]plugins.Plugin) (reconcile.Result, error) {
|
||||||
|
copiedPlugins := map[string][]string{}
|
||||||
|
for key, value := range r.jenkins.Spec.Master.Plugins {
|
||||||
|
copiedPlugins[key] = value
|
||||||
|
}
|
||||||
|
for key, value := range requiredPlugins {
|
||||||
|
copiedPlugins[key] = func() []string {
|
||||||
|
var pluginsWithVersion []string
|
||||||
|
for _, plugin := range value {
|
||||||
|
pluginsWithVersion = append(pluginsWithVersion, plugin.String())
|
||||||
|
}
|
||||||
|
return pluginsWithVersion
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !reflect.DeepEqual(r.jenkins.Spec.Master.Plugins, copiedPlugins) {
|
||||||
|
r.logger.Info("Adding plugins required by backup providers to '.spec.master.plugins'")
|
||||||
|
r.jenkins.Spec.Master.Plugins = copiedPlugins
|
||||||
|
err := r.k8sClient.Update(context.TODO(), r.jenkins)
|
||||||
|
return reconcile.Result{Requeue: true}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return reconcile.Result{}, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
package base
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||||
|
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/plugins"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"k8s.io/client-go/kubernetes/scheme"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/reconcile"
|
||||||
|
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestReconcileJenkinsBaseConfiguration_ensurePluginsRequiredByAllBackupProviders(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
jenkins *virtuslabv1alpha1.Jenkins
|
||||||
|
requiredPlugins map[string][]plugins.Plugin
|
||||||
|
want reconcile.Result
|
||||||
|
wantErr bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "happy, no required plugins",
|
||||||
|
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||||
|
Spec: virtuslabv1alpha1.JenkinsSpec{
|
||||||
|
Master: virtuslabv1alpha1.JenkinsMaster{
|
||||||
|
Plugins: map[string][]string{
|
||||||
|
"first-plugin:0.0.1": {"second-plugin:0.0.1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: reconcile.Result{Requeue: false},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "happy, required plugins are set",
|
||||||
|
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||||
|
Spec: virtuslabv1alpha1.JenkinsSpec{
|
||||||
|
Master: virtuslabv1alpha1.JenkinsMaster{
|
||||||
|
Plugins: map[string][]string{
|
||||||
|
"first-plugin:0.0.1": {"second-plugin:0.0.1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
requiredPlugins: map[string][]plugins.Plugin{
|
||||||
|
"first-plugin:0.0.1": {plugins.Must(plugins.New("second-plugin:0.0.1"))},
|
||||||
|
},
|
||||||
|
want: reconcile.Result{Requeue: false},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "happy, jenkins CR must be updated",
|
||||||
|
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||||
|
Spec: virtuslabv1alpha1.JenkinsSpec{
|
||||||
|
Master: virtuslabv1alpha1.JenkinsMaster{
|
||||||
|
Plugins: map[string][]string{
|
||||||
|
"first-plugin:0.0.1": {"second-plugin:0.0.1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
requiredPlugins: map[string][]plugins.Plugin{
|
||||||
|
"first-plugin:0.0.1": {plugins.Must(plugins.New("second-plugin:0.0.1"))},
|
||||||
|
"third-plugin:0.0.1": {},
|
||||||
|
},
|
||||||
|
want: reconcile.Result{Requeue: true},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "happy, jenkins CR must be updated",
|
||||||
|
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||||
|
Spec: virtuslabv1alpha1.JenkinsSpec{
|
||||||
|
Master: virtuslabv1alpha1.JenkinsMaster{
|
||||||
|
Plugins: map[string][]string{
|
||||||
|
"first-plugin:0.0.1": {"second-plugin:0.0.1"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
requiredPlugins: map[string][]plugins.Plugin{
|
||||||
|
"first-plugin:0.0.1": {plugins.Must(plugins.New("second-plugin:0.0.1"))},
|
||||||
|
"third-plugin:0.0.1": {plugins.Must(plugins.New("fourth-plugin:0.0.1"))},
|
||||||
|
},
|
||||||
|
want: reconcile.Result{Requeue: true},
|
||||||
|
wantErr: false,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
err := virtuslabv1alpha1.SchemeBuilder.AddToScheme(scheme.Scheme)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
r := &ReconcileJenkinsBaseConfiguration{
|
||||||
|
k8sClient: fake.NewFakeClient(),
|
||||||
|
scheme: nil,
|
||||||
|
logger: logf.ZapLogger(false),
|
||||||
|
jenkins: tt.jenkins,
|
||||||
|
local: false,
|
||||||
|
minikube: false,
|
||||||
|
}
|
||||||
|
err = r.k8sClient.Create(context.TODO(), tt.jenkins)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
got, err := r.ensurePluginsRequiredByAllBackupProviders(tt.requiredPlugins)
|
||||||
|
if tt.wantErr {
|
||||||
|
assert.Error(t, err)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||||
|
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/backup"
|
||||||
jenkinsclient "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/client"
|
jenkinsclient "github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/client"
|
||||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/base/resources"
|
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/base/resources"
|
||||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/user/seedjobs"
|
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/user/seedjobs"
|
||||||
|
|
@ -41,8 +42,12 @@ func New(k8sClient k8s.Client, jenkinsClient jenkinsclient.Jenkins, logger logr.
|
||||||
|
|
||||||
// Reconcile it's a main reconciliation loop for user supplied configuration
|
// Reconcile it's a main reconciliation loop for user supplied configuration
|
||||||
func (r *ReconcileUserConfiguration) Reconcile() (reconcile.Result, error) {
|
func (r *ReconcileUserConfiguration) Reconcile() (reconcile.Result, error) {
|
||||||
// reconcile seed jobs
|
backupManager := backup.New(r.jenkins, r.k8sClient, r.logger, r.jenkinsClient)
|
||||||
result, err := r.ensureSeedJobs()
|
if err := backupManager.EnsureRestoreJob(); err != nil {
|
||||||
|
return reconcile.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := backupManager.RestoreBackup()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reconcile.Result{}, err
|
return reconcile.Result{}, err
|
||||||
}
|
}
|
||||||
|
|
@ -50,7 +55,29 @@ func (r *ReconcileUserConfiguration) Reconcile() (reconcile.Result, error) {
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return r.ensureUserConfiguration(r.jenkinsClient)
|
// reconcile seed jobs
|
||||||
|
result, err = r.ensureSeedJobs()
|
||||||
|
if err != nil {
|
||||||
|
return reconcile.Result{}, err
|
||||||
|
}
|
||||||
|
if result.Requeue {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err = r.ensureUserConfiguration(r.jenkinsClient)
|
||||||
|
if err != nil {
|
||||||
|
return reconcile.Result{}, err
|
||||||
|
}
|
||||||
|
if result.Requeue {
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = backupManager.EnsureBackupJob()
|
||||||
|
if err != nil {
|
||||||
|
return reconcile.Result{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return reconcile.Result{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ReconcileUserConfiguration) ensureSeedJobs() (reconcile.Result, error) {
|
func (r *ReconcileUserConfiguration) ensureSeedJobs() (reconcile.Result, error) {
|
||||||
|
|
|
||||||
|
|
@ -13,4 +13,6 @@ const (
|
||||||
BackupAmazonS3SecretAccessKey = "access-key"
|
BackupAmazonS3SecretAccessKey = "access-key"
|
||||||
// BackupAmazonS3SecretSecretKey is the Amazon user secret key used to Amazon S3 backup
|
// BackupAmazonS3SecretSecretKey is the Amazon user secret key used to Amazon S3 backup
|
||||||
BackupAmazonS3SecretSecretKey = "secret-key"
|
BackupAmazonS3SecretSecretKey = "secret-key"
|
||||||
|
// BackupJobName is the Jenkins job name used to backup jobs history
|
||||||
|
BackupJobName = OperatorName + "-backup"
|
||||||
)
|
)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue