[WIP] AWS S3 backup
- add backup validation in base configuration phase - add backup validation in user configuration phase - add tests
This commit is contained in:
parent
e507d23b0e
commit
79112b50dc
|
|
@ -0,0 +1,25 @@
|
|||
package resources
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/constants"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// GetBackupCredentialsSecretName returns name of Kubernetes secret used to store backup credentials
|
||||
func GetBackupCredentialsSecretName(jenkins *virtuslabv1alpha1.Jenkins) string {
|
||||
return fmt.Sprintf("%s-backup-credentials-%s", constants.OperatorName, jenkins.Name)
|
||||
}
|
||||
|
||||
// NewBackupCredentialsSecret builds the Kubernetes secret used to store backup credentials
|
||||
func NewBackupCredentialsSecret(meta metav1.ObjectMeta, jenkins *virtuslabv1alpha1.Jenkins) *corev1.Secret {
|
||||
meta.Name = GetBackupCredentialsSecretName(jenkins)
|
||||
return &corev1.Secret{
|
||||
TypeMeta: buildSecretTypeMeta(),
|
||||
ObjectMeta: meta,
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,9 @@ package resources
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/constants"
|
||||
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/constants"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,19 @@
|
|||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/base/resources"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/plugin"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/log"
|
||||
|
||||
docker "github.com/docker/distribution/reference"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -16,23 +21,32 @@ var (
|
|||
)
|
||||
|
||||
// Validate validates Jenkins CR Spec.master section
|
||||
func (r *ReconcileJenkinsBaseConfiguration) Validate(jenkins *virtuslabv1alpha1.Jenkins) bool {
|
||||
func (r *ReconcileJenkinsBaseConfiguration) Validate(jenkins *virtuslabv1alpha1.Jenkins) (bool, error) {
|
||||
if jenkins.Spec.Master.Image == "" {
|
||||
r.logger.V(log.VWarn).Info("Image not set")
|
||||
return false
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if !dockerImageRegexp.MatchString(jenkins.Spec.Master.Image) && !docker.ReferenceRegexp.MatchString(jenkins.Spec.Master.Image) {
|
||||
r.logger.V(log.VWarn).Info("Invalid image")
|
||||
return false
|
||||
return false, nil
|
||||
|
||||
}
|
||||
|
||||
if !r.validatePlugins(jenkins.Spec.Master.Plugins) {
|
||||
return false
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true
|
||||
valid, err := r.verifyBackup()
|
||||
if !valid || err != nil {
|
||||
return valid, err
|
||||
}
|
||||
|
||||
if r.jenkins.Spec.Backup == virtuslabv1alpha1.JenkinsBackupTypeAmazonS3 && !r.verifyBackupAmazonS3() {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (r *ReconcileJenkinsBaseConfiguration) validatePlugins(plugins map[string][]string) bool {
|
||||
|
|
@ -64,3 +78,58 @@ func (r *ReconcileJenkinsBaseConfiguration) validatePlugins(plugins map[string][
|
|||
|
||||
return valid
|
||||
}
|
||||
|
||||
func (r *ReconcileJenkinsBaseConfiguration) verifyBackup() (bool, error) {
|
||||
if r.jenkins.Spec.Backup == "" {
|
||||
r.logger.V(log.VWarn).Info("Backup strategy not set in 'spec.backup'")
|
||||
return false, nil
|
||||
}
|
||||
|
||||
valid := false
|
||||
for _, backup := range virtuslabv1alpha1.AllowedJenkinsBackups {
|
||||
if r.jenkins.Spec.Backup == backup {
|
||||
valid = true
|
||||
}
|
||||
}
|
||||
|
||||
if !valid {
|
||||
r.logger.V(log.VWarn).Info(fmt.Sprintf("Invalid backup strategy '%s'", r.jenkins.Spec.Backup))
|
||||
r.logger.V(log.VWarn).Info(fmt.Sprintf("Allowed backups '%+v'", virtuslabv1alpha1.AllowedJenkinsBackups))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if r.jenkins.Spec.Backup == virtuslabv1alpha1.JenkinsBackupTypeNoBackup {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
backupSecretName := resources.GetBackupCredentialsSecretName(r.jenkins)
|
||||
backupSecret := &corev1.Secret{}
|
||||
err := r.k8sClient.Get(context.TODO(), types.NamespacedName{Namespace: r.jenkins.Namespace, Name: backupSecretName}, backupSecret)
|
||||
if err != nil && errors.IsNotFound(err) {
|
||||
r.logger.V(log.VWarn).Info(fmt.Sprintf("Please create secret '%s' in namespace '%s'", backupSecretName, r.jenkins.Namespace))
|
||||
return false, nil
|
||||
} else if err != nil && !errors.IsNotFound(err) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (r *ReconcileJenkinsBaseConfiguration) verifyBackupAmazonS3() bool {
|
||||
if len(r.jenkins.Spec.BackupAmazonS3.BucketName) == 0 {
|
||||
r.logger.V(log.VWarn).Info("Bucket name not set in 'spec.backupAmazonS3.bucketName'")
|
||||
return false
|
||||
}
|
||||
|
||||
if len(r.jenkins.Spec.BackupAmazonS3.BucketPath) == 0 {
|
||||
r.logger.V(log.VWarn).Info("Bucket path not set in 'spec.backupAmazonS3.bucketPath'")
|
||||
return false
|
||||
}
|
||||
|
||||
if len(r.jenkins.Spec.BackupAmazonS3.Region) == 0 {
|
||||
r.logger.V(log.VWarn).Info("Region not set in 'spec.backupAmazonS3.region'")
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,10 +1,16 @@
|
|||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/fake"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
|
||||
)
|
||||
|
||||
|
|
@ -56,3 +62,163 @@ func TestValidatePlugins(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReconcileJenkinsBaseConfiguration_verifyBackup(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
jenkins *virtuslabv1alpha1.Jenkins
|
||||
secret *corev1.Secret
|
||||
want bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "happy, no backup",
|
||||
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace-name", Name: "jenkins-cr-name"},
|
||||
Spec: virtuslabv1alpha1.JenkinsSpec{
|
||||
Backup: virtuslabv1alpha1.JenkinsBackupTypeNoBackup,
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "happy",
|
||||
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace-name", Name: "jenkins-cr-name"},
|
||||
Spec: virtuslabv1alpha1.JenkinsSpec{
|
||||
Backup: virtuslabv1alpha1.JenkinsBackupTypeAmazonS3,
|
||||
},
|
||||
},
|
||||
secret: &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace-name", Name: "jenkins-operator-backup-credentials-jenkins-cr-name"},
|
||||
},
|
||||
want: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "fail, no secret",
|
||||
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace-name", Name: "jenkins-cr-name"},
|
||||
Spec: virtuslabv1alpha1.JenkinsSpec{
|
||||
Backup: virtuslabv1alpha1.JenkinsBackupTypeAmazonS3,
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "fail, empty backup type",
|
||||
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace-name", Name: "jenkins-cr-name"},
|
||||
Spec: virtuslabv1alpha1.JenkinsSpec{
|
||||
Backup: "",
|
||||
},
|
||||
},
|
||||
secret: &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace-name", Name: "jenkins-operator-backup-credentials-jenkins-cr-name"},
|
||||
},
|
||||
want: false,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &ReconcileJenkinsBaseConfiguration{
|
||||
k8sClient: fake.NewFakeClient(),
|
||||
scheme: nil,
|
||||
logger: logf.ZapLogger(false),
|
||||
jenkins: tt.jenkins,
|
||||
local: false,
|
||||
minikube: false,
|
||||
}
|
||||
if tt.secret != nil {
|
||||
e := r.k8sClient.Create(context.TODO(), tt.secret)
|
||||
assert.NoError(t, e)
|
||||
}
|
||||
got, err := r.verifyBackup()
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestReconcileJenkinsBaseConfiguration_verifyBackupAmazonS3(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
jenkins *virtuslabv1alpha1.Jenkins
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "happy",
|
||||
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||
Spec: virtuslabv1alpha1.JenkinsSpec{
|
||||
BackupAmazonS3: virtuslabv1alpha1.JenkinsBackupAmazonS3{
|
||||
BucketName: "some-value",
|
||||
BucketPath: "some-value",
|
||||
Region: "some-value",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
name: "fail, no bucket name",
|
||||
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||
Spec: virtuslabv1alpha1.JenkinsSpec{
|
||||
BackupAmazonS3: virtuslabv1alpha1.JenkinsBackupAmazonS3{
|
||||
BucketName: "",
|
||||
BucketPath: "some-value",
|
||||
Region: "some-value",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "fail, no bucket path",
|
||||
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||
Spec: virtuslabv1alpha1.JenkinsSpec{
|
||||
BackupAmazonS3: virtuslabv1alpha1.JenkinsBackupAmazonS3{
|
||||
BucketName: "some-value",
|
||||
BucketPath: "",
|
||||
Region: "some-value",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
{
|
||||
name: "fail, no region",
|
||||
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||
Spec: virtuslabv1alpha1.JenkinsSpec{
|
||||
BackupAmazonS3: virtuslabv1alpha1.JenkinsBackupAmazonS3{
|
||||
BucketName: "some-value",
|
||||
BucketPath: "some-value",
|
||||
Region: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &ReconcileJenkinsBaseConfiguration{
|
||||
k8sClient: fake.NewFakeClient(),
|
||||
scheme: nil,
|
||||
logger: logf.ZapLogger(false),
|
||||
jenkins: tt.jenkins,
|
||||
local: false,
|
||||
minikube: false,
|
||||
}
|
||||
got := r.verifyBackupAmazonS3()
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,16 +9,24 @@ import (
|
|||
"strings"
|
||||
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
"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/log"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
)
|
||||
|
||||
// Validate validates Jenkins CR Spec section
|
||||
func (r *ReconcileUserConfiguration) Validate(jenkins *virtuslabv1alpha1.Jenkins) (bool, error) {
|
||||
return r.validateSeedJobs(jenkins)
|
||||
valid, err := r.validateSeedJobs(jenkins)
|
||||
if !valid || err != nil {
|
||||
return valid, err
|
||||
}
|
||||
|
||||
return r.verifyBackup()
|
||||
}
|
||||
|
||||
func (r *ReconcileUserConfiguration) validateSeedJobs(jenkins *virtuslabv1alpha1.Jenkins) (bool, error) {
|
||||
|
|
@ -87,3 +95,32 @@ func validatePrivateKey(privateKey string) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ReconcileUserConfiguration) verifyBackup() (bool, error) {
|
||||
if r.jenkins.Spec.Backup == virtuslabv1alpha1.JenkinsBackupTypeAmazonS3 {
|
||||
return r.verifyBackupAmazonS3()
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (r *ReconcileUserConfiguration) verifyBackupAmazonS3() (bool, error) {
|
||||
backupSecretName := resources.GetBackupCredentialsSecretName(r.jenkins)
|
||||
backupSecret := &corev1.Secret{}
|
||||
err := r.k8sClient.Get(context.TODO(), types.NamespacedName{Namespace: r.jenkins.Namespace, Name: backupSecretName}, backupSecret)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if len(backupSecret.Data[constants.BackupAmazonS3SecretSecretKey]) == 0 {
|
||||
r.logger.V(log.VWarn).Info(fmt.Sprintf("Secret '%s' doesn't contains key: %s", backupSecretName, constants.BackupAmazonS3SecretSecretKey))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if len(backupSecret.Data[constants.BackupAmazonS3SecretAccessKey]) == 0 {
|
||||
r.logger.V(log.VWarn).Info(fmt.Sprintf("Secret '%s' doesn't contains key: %s", backupSecretName, constants.BackupAmazonS3SecretAccessKey))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/constants"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
|
@ -14,7 +15,42 @@ import (
|
|||
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
|
||||
)
|
||||
|
||||
func TestValidateUserConfiguration(t *testing.T) {
|
||||
var fakePrivateKey = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEArK4ld6i2iqW6L3jaTZaKD/v7PjDn+Ik9MXp+kvLcUw/+wEGm
|
||||
285UwqLnDDlBhSi9nDgJ+m1XU87VCpz/DXW23R/CQcMX2xunib4wWLQqoR3CWbk3
|
||||
SwiLd8TWAvXkxdXm8fDOGAZbYK2alMV+M+9E2OpZsBUCxmb/3FAofF6JccKoJOH8
|
||||
UveRNSOx7IXPKtHFiypBhWM4l6ZjgJKm+DRIEhyvoC+pHzcum2ZEPOv+ZJDy5jXK
|
||||
ZHcNQXVnAZtCcojcjVUBw2rZms+fQ6Volv2JT71Gpykzx/rChhwNwxdAEwjLjKjL
|
||||
nBWEh/WxsS3NbM7zb4B2XGMCeWVeb/niUwpy+wIDAQABAoIBAQCjGkJNidARmYQI
|
||||
/u/DxWNWwb2H+o3BFW/1YixYBIjS9BK96cT/bR5mUZRG2XXnnpmqCsxx/AE2KfDU
|
||||
e4H1ZrB4oFzN3MaVsMNIuZnUzyhM0l0WfnmZp9KEKCm01ilmLCpdcARacPaylIej
|
||||
6f7QcznmYUShqtbaK8OUhyoWfvz3s0VLkpBlqm63uPtjAx6sAl399THxHVwbYgYy
|
||||
TxPY8wdjOvNzQJ7ColUh05Zq6TsCGGFUFg7v4to/AXtDhcTMVONlapP+XxekRx8P
|
||||
98BepIgzgvQhWak8gm+cKQYANk14Q8BDzUCDplYuIZVvKl+/ZHltjHGjrqxDrcDA
|
||||
0U7REgtxAoGBAN+LAEf2o14ffs/ebVSxiv7LnuAxFh2L6i7RqtehpSf7BnYC65vB
|
||||
6TMsc/0/KFkD5Az7nrJmA7HmM8J/NI2ks0Mbft+0XCRFx/zfU6pOvPinRKp/8Vtm
|
||||
aUmNzhz8UMaQ1JXOvBOqvXKWYrN1WPha1+/BnUQrpTdhGxAoAh1FW4eHAoGBAMXA
|
||||
mXTN5X8+mp9KW2bIpFsjrZ+EyhxO6a6oBMZY54rceeOzf5RcXY7EOiTrnmr+lQvp
|
||||
fAKBeX5V8G96nSEIDmPhKGZ1C1vEP6hRWahJo1XkN5E1j6hRHCu3DQLtL2lxlyfG
|
||||
Fx11fysgmLoPVVytLAEQwt4WxMp7OsM1NWqB+u3tAoGBAILUg3Gas7pejIV0FGDB
|
||||
GCxPV8i2cc8RGBoWs/pHrLVdgUaIJwSd1LISjj/lOuP+FvZSPWsDsZ3osNpgQI21
|
||||
mwTnjrW2hUblYEprGjhOpOKSYum2v7dSlMRrrfng4hWUphaXTBPmlcH+qf2F7HBO
|
||||
GptDoZtIQAXNW111TOd8tDj5AoGAC1PO9nvcy38giENQHQEdOQNALMUEdr6mcBS7
|
||||
wUjSaofai4p6olrwGP9wfTDp8CMJEpebPOGBvhTaIuiZG41ElcAN+mB1+Bmzs8aF
|
||||
JjihnIfoDu9MfU24GWDw49wGPTn+eI7GQC+8yxGg7fd24kohHSaCowoW16pbYVco
|
||||
6iLr5rkCgYBt0bcYJ3AOTH0UXS8kvJvnyce/RBIAMoUABwvdkZt9r5B4UzsoLq5e
|
||||
WrrU6fSRsE6lSsBd83pOAQ46tv+vntQ+0EihD9/0INhkQM99lBw1TFdFTgGSAs1e
|
||||
ns4JGP6f5uIuwqu/nbqPqMyDovjkGbX2znuGBcvki90Pi97XL7MMWw==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
`
|
||||
|
||||
var fakeInvalidPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEArK4ld6i2iqW6L3jaTZaKD/v7PjDn+Ik9MXp+kvLcUw/+wEGm
|
||||
285UwqLnDDlBhSi9nDgJ+m1XU87VCpz/DXW23R/CQcMX2xunib4wWLQqoR3CWbk3
|
||||
SwiLd8TWAvXkxdXm8fDOGAZbYK2alMV+M+9E2OpZsBUCxmb/3FAofF6JccKoJOH8
|
||||
`
|
||||
|
||||
func TestValidateSeedJobs(t *testing.T) {
|
||||
data := []struct {
|
||||
description string
|
||||
jenkins *virtuslabv1alpha1.Jenkins
|
||||
|
|
@ -195,44 +231,94 @@ func TestValidateUserConfiguration(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
}
|
||||
userReconcileLoop := New(fakeClient, nil, logf.ZapLogger(false), nil)
|
||||
result, err := userReconcileLoop.Validate(testingData.jenkins)
|
||||
result, err := userReconcileLoop.validateSeedJobs(testingData.jenkins)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, testingData.expectedResult, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var fakePrivateKey = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEArK4ld6i2iqW6L3jaTZaKD/v7PjDn+Ik9MXp+kvLcUw/+wEGm
|
||||
285UwqLnDDlBhSi9nDgJ+m1XU87VCpz/DXW23R/CQcMX2xunib4wWLQqoR3CWbk3
|
||||
SwiLd8TWAvXkxdXm8fDOGAZbYK2alMV+M+9E2OpZsBUCxmb/3FAofF6JccKoJOH8
|
||||
UveRNSOx7IXPKtHFiypBhWM4l6ZjgJKm+DRIEhyvoC+pHzcum2ZEPOv+ZJDy5jXK
|
||||
ZHcNQXVnAZtCcojcjVUBw2rZms+fQ6Volv2JT71Gpykzx/rChhwNwxdAEwjLjKjL
|
||||
nBWEh/WxsS3NbM7zb4B2XGMCeWVeb/niUwpy+wIDAQABAoIBAQCjGkJNidARmYQI
|
||||
/u/DxWNWwb2H+o3BFW/1YixYBIjS9BK96cT/bR5mUZRG2XXnnpmqCsxx/AE2KfDU
|
||||
e4H1ZrB4oFzN3MaVsMNIuZnUzyhM0l0WfnmZp9KEKCm01ilmLCpdcARacPaylIej
|
||||
6f7QcznmYUShqtbaK8OUhyoWfvz3s0VLkpBlqm63uPtjAx6sAl399THxHVwbYgYy
|
||||
TxPY8wdjOvNzQJ7ColUh05Zq6TsCGGFUFg7v4to/AXtDhcTMVONlapP+XxekRx8P
|
||||
98BepIgzgvQhWak8gm+cKQYANk14Q8BDzUCDplYuIZVvKl+/ZHltjHGjrqxDrcDA
|
||||
0U7REgtxAoGBAN+LAEf2o14ffs/ebVSxiv7LnuAxFh2L6i7RqtehpSf7BnYC65vB
|
||||
6TMsc/0/KFkD5Az7nrJmA7HmM8J/NI2ks0Mbft+0XCRFx/zfU6pOvPinRKp/8Vtm
|
||||
aUmNzhz8UMaQ1JXOvBOqvXKWYrN1WPha1+/BnUQrpTdhGxAoAh1FW4eHAoGBAMXA
|
||||
mXTN5X8+mp9KW2bIpFsjrZ+EyhxO6a6oBMZY54rceeOzf5RcXY7EOiTrnmr+lQvp
|
||||
fAKBeX5V8G96nSEIDmPhKGZ1C1vEP6hRWahJo1XkN5E1j6hRHCu3DQLtL2lxlyfG
|
||||
Fx11fysgmLoPVVytLAEQwt4WxMp7OsM1NWqB+u3tAoGBAILUg3Gas7pejIV0FGDB
|
||||
GCxPV8i2cc8RGBoWs/pHrLVdgUaIJwSd1LISjj/lOuP+FvZSPWsDsZ3osNpgQI21
|
||||
mwTnjrW2hUblYEprGjhOpOKSYum2v7dSlMRrrfng4hWUphaXTBPmlcH+qf2F7HBO
|
||||
GptDoZtIQAXNW111TOd8tDj5AoGAC1PO9nvcy38giENQHQEdOQNALMUEdr6mcBS7
|
||||
wUjSaofai4p6olrwGP9wfTDp8CMJEpebPOGBvhTaIuiZG41ElcAN+mB1+Bmzs8aF
|
||||
JjihnIfoDu9MfU24GWDw49wGPTn+eI7GQC+8yxGg7fd24kohHSaCowoW16pbYVco
|
||||
6iLr5rkCgYBt0bcYJ3AOTH0UXS8kvJvnyce/RBIAMoUABwvdkZt9r5B4UzsoLq5e
|
||||
WrrU6fSRsE6lSsBd83pOAQ46tv+vntQ+0EihD9/0INhkQM99lBw1TFdFTgGSAs1e
|
||||
ns4JGP6f5uIuwqu/nbqPqMyDovjkGbX2znuGBcvki90Pi97XL7MMWw==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
`
|
||||
|
||||
var fakeInvalidPrivateKey = `-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpAIBAAKCAQEArK4ld6i2iqW6L3jaTZaKD/v7PjDn+Ik9MXp+kvLcUw/+wEGm
|
||||
285UwqLnDDlBhSi9nDgJ+m1XU87VCpz/DXW23R/CQcMX2xunib4wWLQqoR3CWbk3
|
||||
SwiLd8TWAvXkxdXm8fDOGAZbYK2alMV+M+9E2OpZsBUCxmb/3FAofF6JccKoJOH8
|
||||
`
|
||||
func TestReconcileUserConfiguration_verifyBackupAmazonS3(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
jenkins *virtuslabv1alpha1.Jenkins
|
||||
secret *corev1.Secret
|
||||
want bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "happy",
|
||||
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace-name", Name: "jenkins-cr-name"},
|
||||
},
|
||||
secret: &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace-name", Name: "jenkins-operator-backup-credentials-jenkins-cr-name"},
|
||||
Data: map[string][]byte{
|
||||
constants.BackupAmazonS3SecretSecretKey: []byte("some-value"),
|
||||
constants.BackupAmazonS3SecretAccessKey: []byte("some-value"),
|
||||
},
|
||||
},
|
||||
want: true,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "fail, no secret",
|
||||
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace-name", Name: "jenkins-cr-name"},
|
||||
},
|
||||
want: false,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "fail, no secret key in secret",
|
||||
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace-name", Name: "jenkins-cr-name"},
|
||||
},
|
||||
secret: &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace-name", Name: "jenkins-operator-backup-credentials-jenkins-cr-name"},
|
||||
Data: map[string][]byte{
|
||||
constants.BackupAmazonS3SecretSecretKey: []byte(""),
|
||||
constants.BackupAmazonS3SecretAccessKey: []byte("some-value"),
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "fail, no access key in secret",
|
||||
jenkins: &virtuslabv1alpha1.Jenkins{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace-name", Name: "jenkins-cr-name"},
|
||||
},
|
||||
secret: &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace-name", Name: "jenkins-operator-backup-credentials-jenkins-cr-name"},
|
||||
Data: map[string][]byte{
|
||||
constants.BackupAmazonS3SecretSecretKey: []byte("some-value"),
|
||||
constants.BackupAmazonS3SecretAccessKey: []byte(""),
|
||||
},
|
||||
},
|
||||
want: false,
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := &ReconcileUserConfiguration{
|
||||
k8sClient: fake.NewFakeClient(),
|
||||
jenkinsClient: nil,
|
||||
logger: logf.ZapLogger(false),
|
||||
jenkins: tt.jenkins,
|
||||
}
|
||||
if tt.secret != nil {
|
||||
e := r.k8sClient.Create(context.TODO(), tt.secret)
|
||||
assert.NoError(t, e)
|
||||
}
|
||||
got, err := r.verifyBackupAmazonS3()
|
||||
if tt.wantErr {
|
||||
assert.Error(t, err)
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
assert.Equal(t, tt.want, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,4 +7,10 @@ const (
|
|||
DefaultAmountOfExecutors = 3
|
||||
// SeedJobSuffix is a suffix added for all seed jobs
|
||||
SeedJobSuffix = "job-dsl-seed"
|
||||
// DefaultJenkinsMasterImage is the default Jenkins master docker image
|
||||
DefaultJenkinsMasterImage = "jenkins/jenkins:lts"
|
||||
// BackupAmazonS3SecretAccessKey is the Amazon user access key used to Amazon S3 backup
|
||||
BackupAmazonS3SecretAccessKey = "access-key"
|
||||
// BackupAmazonS3SecretSecretKey is the Amazon user secret key used to Amazon S3 backup
|
||||
BackupAmazonS3SecretSecretKey = "secret-key"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
virtuslabv1alpha1 "github.com/VirtusLab/jenkins-operator/pkg/apis/virtuslab/v1alpha1"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/base"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/configuration/user"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/constants"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/controller/jenkins/plugin"
|
||||
"github.com/VirtusLab/jenkins-operator/pkg/log"
|
||||
|
||||
|
|
@ -99,7 +100,7 @@ func (r *ReconcileJenkins) Reconcile(request reconcile.Request) (reconcile.Resul
|
|||
logger.V(log.VWarn).Info(fmt.Sprintf("Reconcile loop failed: %+v", err))
|
||||
return reconcile.Result{Requeue: true}, nil
|
||||
}
|
||||
return result, err
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *ReconcileJenkins) reconcile(request reconcile.Request, logger logr.Logger) (reconcile.Result, error) {
|
||||
|
|
@ -124,10 +125,16 @@ func (r *ReconcileJenkins) reconcile(request reconcile.Request, logger logr.Logg
|
|||
|
||||
// Reconcile base configuration
|
||||
baseConfiguration := base.New(r.client, r.scheme, logger, jenkins, r.local, r.minikube)
|
||||
if !baseConfiguration.Validate(jenkins) {
|
||||
logger.V(log.VWarn).Info("Validation of base configuration failed, please correct Jenkins CR")
|
||||
|
||||
valid, err := baseConfiguration.Validate(jenkins)
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
if !valid {
|
||||
logger.V(log.VWarn).Info("Validation of user configuration failed, please correct Jenkins CR")
|
||||
return reconcile.Result{}, nil // don't requeue
|
||||
}
|
||||
|
||||
result, jenkinsClient, err := baseConfiguration.Reconcile()
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
|
|
@ -148,7 +155,8 @@ func (r *ReconcileJenkins) reconcile(request reconcile.Request, logger logr.Logg
|
|||
|
||||
// Reconcile user configuration
|
||||
userConfiguration := user.New(r.client, jenkinsClient, logger, jenkins)
|
||||
valid, err := userConfiguration.Validate(jenkins)
|
||||
|
||||
valid, err = userConfiguration.Validate(jenkins)
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
}
|
||||
|
|
@ -156,6 +164,7 @@ func (r *ReconcileJenkins) reconcile(request reconcile.Request, logger logr.Logg
|
|||
logger.V(log.VWarn).Info("Validation of user configuration failed, please correct Jenkins CR")
|
||||
return reconcile.Result{}, nil // don't requeue
|
||||
}
|
||||
|
||||
result, err = userConfiguration.Reconcile()
|
||||
if err != nil {
|
||||
return reconcile.Result{}, err
|
||||
|
|
@ -183,8 +192,18 @@ func (r *ReconcileJenkins) buildLogger(jenkinsName string) logr.Logger {
|
|||
|
||||
func (r *ReconcileJenkins) setDefaults(jenkins *virtuslabv1alpha1.Jenkins, logger logr.Logger) error {
|
||||
changed := false
|
||||
if len(jenkins.Spec.Master.Image) == 0 {
|
||||
logger.Info("Setting default Jenkins master image: " + constants.DefaultJenkinsMasterImage)
|
||||
changed = true
|
||||
jenkins.Spec.Master.Image = constants.DefaultJenkinsMasterImage
|
||||
}
|
||||
if len(jenkins.Spec.Backup) == 0 {
|
||||
logger.Info("Setting default backup strategy: " + virtuslabv1alpha1.JenkinsBackupTypeNoBackup)
|
||||
changed = true
|
||||
jenkins.Spec.Backup = virtuslabv1alpha1.JenkinsBackupTypeNoBackup
|
||||
}
|
||||
if len(jenkins.Spec.Master.Plugins) == 0 {
|
||||
logger.Info("Setting default base plugins in CR")
|
||||
logger.Info("Setting default base plugins")
|
||||
changed = true
|
||||
jenkins.Spec.Master.Plugins = plugin.BasePlugins()
|
||||
}
|
||||
|
|
@ -193,7 +212,7 @@ func (r *ReconcileJenkins) setDefaults(jenkins *virtuslabv1alpha1.Jenkins, logge
|
|||
_, limitCPUSet := jenkins.Spec.Master.Resources.Limits[corev1.ResourceCPU]
|
||||
_, limitMemporySet := jenkins.Spec.Master.Resources.Limits[corev1.ResourceMemory]
|
||||
if !limitCPUSet || !limitMemporySet || !requestCPUSet || !requestMemporySet {
|
||||
logger.Info("Setting default Jenkins master pod resource requirements in CR")
|
||||
logger.Info("Setting default Jenkins master pod resource requirements")
|
||||
changed = true
|
||||
jenkins.Spec.Master.Resources = corev1.ResourceRequirements{
|
||||
Requests: corev1.ResourceList{
|
||||
|
|
|
|||
Loading…
Reference in New Issue