Updated jobs and added more tests
This commit is contained in:
parent
b5fca5950a
commit
c404221154
|
|
@ -30,8 +30,6 @@ const (
|
||||||
RunningStatus = "running"
|
RunningStatus = "running"
|
||||||
// ExpiredStatus - this is custom build status for expired build, not present in jenkins build result
|
// ExpiredStatus - this is custom build status for expired build, not present in jenkins build result
|
||||||
ExpiredStatus = "expired"
|
ExpiredStatus = "expired"
|
||||||
// MaxBuildRetires - determines max amount of retires for failed build
|
|
||||||
MaxBuildRetires = 3
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -43,10 +41,12 @@ var (
|
||||||
ErrorBuildFailed = errors.New("build failed")
|
ErrorBuildFailed = errors.New("build failed")
|
||||||
// ErrorAbortBuildFailed - this is custom error returned when jenkins build couldn't be aborted
|
// ErrorAbortBuildFailed - this is custom error returned when jenkins build couldn't be aborted
|
||||||
ErrorAbortBuildFailed = errors.New("build abort failed")
|
ErrorAbortBuildFailed = errors.New("build abort failed")
|
||||||
// ErrorUncoverBuildFailed - this is custom error returned when jenkins build has failed and cannot be recovered
|
// ErrorUnrecoverableBuildFailed - this is custom error returned when jenkins build has failed and cannot be recovered
|
||||||
ErrorUncoverBuildFailed = errors.New("build failed and cannot be recovered")
|
ErrorUnrecoverableBuildFailed = errors.New("build failed and cannot be recovered")
|
||||||
// ErrorNotFound - this is error returned when jenkins build couldn't be found
|
// ErrorNotFound - this is error returned when jenkins build couldn't be found
|
||||||
ErrorNotFound = errors.New("404")
|
ErrorNotFound = errors.New("404")
|
||||||
|
// BuildRetires - determines max amount of retires for failed build
|
||||||
|
BuildRetires = 3
|
||||||
)
|
)
|
||||||
|
|
||||||
// Jobs defines Jobs API tailored for operator sdk
|
// Jobs defines Jobs API tailored for operator sdk
|
||||||
|
|
@ -168,17 +168,14 @@ func (jobs *Jobs) ensureRunningBuild(build virtuslabv1alpha1.Build, jenkins *vir
|
||||||
|
|
||||||
if build.Status == SuccessStatus {
|
if build.Status == SuccessStatus {
|
||||||
jobs.logger.Info(fmt.Sprintf("Build finished successfully, name:'%s' hash:'%s' status:'%s'", build.Name, build.Hash, build.Status))
|
jobs.logger.Info(fmt.Sprintf("Build finished successfully, name:'%s' hash:'%s' status:'%s'", build.Name, build.Hash, build.Status))
|
||||||
if !preserveStatus {
|
|
||||||
jobs.logger.Info(fmt.Sprintf("Removing build from status, name:'%s' hash:'%s'", build.Name, build.Hash))
|
|
||||||
err := jobs.removeBuildFromStatus(build, jenkins)
|
|
||||||
if err != nil {
|
|
||||||
jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't remove build from status, name:'%s' hash:'%s'", build.Name, build.Hash))
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if build.Status == FailureStatus || build.Status == UnstableStatus || build.Status == NotBuildStatus || build.Status == AbortedStatus {
|
||||||
|
jobs.logger.Info(fmt.Sprintf("Build failed, name:'%s' hash:'%s' status:'%s'", build.Name, build.Hash, build.Status))
|
||||||
|
return false, ErrorBuildFailed
|
||||||
|
}
|
||||||
|
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -190,7 +187,7 @@ func (jobs *Jobs) ensureFailedBuild(build virtuslabv1alpha1.Build, jenkins *virt
|
||||||
|
|
||||||
jobs.logger.Info(fmt.Sprintf("Ensuring failed build, name:'%s' hash:'%s' status: '%s'", build.Name, build.Hash, build.Status))
|
jobs.logger.Info(fmt.Sprintf("Ensuring failed build, name:'%s' hash:'%s' status: '%s'", build.Name, build.Hash, build.Status))
|
||||||
|
|
||||||
if build.Retires < MaxBuildRetires {
|
if build.Retires < BuildRetires {
|
||||||
jobs.logger.Info(fmt.Sprintf("Retrying build, name:'%s' hash:'%s' retries: '%d'", build.Name, build.Hash, build.Retires))
|
jobs.logger.Info(fmt.Sprintf("Retrying build, name:'%s' hash:'%s' retries: '%d'", build.Name, build.Hash, build.Retires))
|
||||||
build.Retires = build.Retires + 1
|
build.Retires = build.Retires + 1
|
||||||
_, err := jobs.buildJob(build, parameters, jenkins)
|
_, err := jobs.buildJob(build, parameters, jenkins)
|
||||||
|
|
@ -198,7 +195,7 @@ func (jobs *Jobs) ensureFailedBuild(build virtuslabv1alpha1.Build, jenkins *virt
|
||||||
jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't retry build, name:'%s' hash:'%s'", build.Name, build.Hash))
|
jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't retry build, name:'%s' hash:'%s'", build.Name, build.Hash))
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
return false, ErrorBuildFailed
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
jobs.logger.Info(fmt.Sprintf("The retries limit was reached , name:'%s' hash:'%s' retries: '%d'", build.Name, build.Hash, build.Retires))
|
jobs.logger.Info(fmt.Sprintf("The retries limit was reached , name:'%s' hash:'%s' retries: '%d'", build.Name, build.Hash, build.Retires))
|
||||||
|
|
@ -211,7 +208,7 @@ func (jobs *Jobs) ensureFailedBuild(build virtuslabv1alpha1.Build, jenkins *virt
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false, ErrorUncoverBuildFailed
|
return false, ErrorUnrecoverableBuildFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
func (jobs *Jobs) ensureExpiredBuild(build virtuslabv1alpha1.Build, jenkins *virtuslabv1alpha1.Jenkins, preserveStatus bool) (bool, error) {
|
func (jobs *Jobs) ensureExpiredBuild(build virtuslabv1alpha1.Build, jenkins *virtuslabv1alpha1.Jenkins, preserveStatus bool) (bool, error) {
|
||||||
|
|
@ -285,18 +282,28 @@ func (jobs *Jobs) buildJob(build virtuslabv1alpha1.Build, parameters map[string]
|
||||||
return false, ErrorEmptyJenkinsCR
|
return false, ErrorEmptyJenkinsCR
|
||||||
}
|
}
|
||||||
|
|
||||||
jobs.logger.Info(fmt.Sprintf("Running build, name:'%s' hash:'%s'", build.Name, build.Hash))
|
nextBuildNumber := int64(1)
|
||||||
|
job, err := jobs.jenkinsClient.GetJob(build.Name)
|
||||||
number, err := jobs.jenkinsClient.BuildJob(build.Name, parameters)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't run build, name:'%s' hash:'%s' number:'%d'", build.Name, build.Hash, number))
|
jobs.logger.Info(fmt.Sprintf("Couldn't find jenkins job, name:'%s' hash:'%s'", build.Name, build.Hash))
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if job != nil {
|
||||||
|
nextBuildNumber = job.GetDetails().NextBuildNumber
|
||||||
|
}
|
||||||
|
|
||||||
|
jobs.logger.Info(fmt.Sprintf("Running build, name:'%s' hash:'%s' number:'%d'", build.Name, build.Hash, nextBuildNumber))
|
||||||
|
_, err = jobs.jenkinsClient.BuildJob(build.Name, parameters)
|
||||||
|
if err != nil {
|
||||||
|
jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't run build, name:'%s' hash:'%s' number:'%d'", build.Name, build.Hash, nextBuildNumber))
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
build.Status = RunningStatus
|
build.Status = RunningStatus
|
||||||
build.Number = number
|
build.Number = nextBuildNumber
|
||||||
|
|
||||||
jobs.logger.Info(fmt.Sprintf("Updating build status, name:'%s' hash:'%s' status:'%s'", build.Name, build.Hash, build.Status))
|
jobs.logger.Info(fmt.Sprintf("Updating build status, name:'%s' hash:'%s' status:'%s' number:'%d'", build.Name, build.Hash, build.Status, build.Number))
|
||||||
err = jobs.updateBuildStatus(build, jenkins)
|
err = jobs.updateBuildStatus(build, jenkins)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't update build status, name:'%s' hash:'%s'", build.Name, build.Hash))
|
jobs.logger.V(log.VWarn).Info(fmt.Sprintf("Couldn't update build status, name:'%s' hash:'%s'", build.Name, build.Hash))
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
|
@ -29,53 +30,42 @@ func TestMain(m *testing.M) {
|
||||||
|
|
||||||
func TestSuccessEnsureJob(t *testing.T) {
|
func TestSuccessEnsureJob(t *testing.T) {
|
||||||
// given
|
// given
|
||||||
|
ctx := context.TODO()
|
||||||
logger := logf.ZapLogger(false)
|
logger := logf.ZapLogger(false)
|
||||||
ctrl := gomock.NewController(t)
|
ctrl := gomock.NewController(t)
|
||||||
ctx := context.TODO()
|
|
||||||
defer ctrl.Finish()
|
defer ctrl.Finish()
|
||||||
|
|
||||||
buildName := "Test Job"
|
buildName := "Test Job"
|
||||||
buildNumber := int64(1)
|
|
||||||
jenkinsClient := client.NewMockJenkins(ctrl)
|
|
||||||
fakeClient := fake.NewFakeClient()
|
|
||||||
|
|
||||||
hash := sha256.New()
|
hash := sha256.New()
|
||||||
hash.Write([]byte(buildName))
|
hash.Write([]byte(buildName))
|
||||||
encodedHash := base64.URLEncoding.EncodeToString(hash.Sum(nil))
|
encodedHash := base64.URLEncoding.EncodeToString(hash.Sum(nil))
|
||||||
|
|
||||||
// when
|
// when
|
||||||
jenkins := jenkinsCustomResource()
|
jenkins := jenkinsCustomResource()
|
||||||
|
fakeClient := fake.NewFakeClient()
|
||||||
err := fakeClient.Create(ctx, jenkins)
|
err := fakeClient.Create(ctx, jenkins)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
for reconcileAttempt := 1; reconcileAttempt <= 2; reconcileAttempt++ {
|
||||||
|
logger.Info(fmt.Sprintf("Reconcile attempt #%d", reconcileAttempt))
|
||||||
|
buildNumber := int64(1)
|
||||||
|
jenkinsClient := client.NewMockJenkins(ctrl)
|
||||||
jobs := New(jenkinsClient, fakeClient, logger)
|
jobs := New(jenkinsClient, fakeClient, logger)
|
||||||
|
|
||||||
// first run - build should be scheduled and status updated
|
jenkinsClient.
|
||||||
|
EXPECT().
|
||||||
|
GetJob(buildName).
|
||||||
|
Return(&gojenkins.Job{
|
||||||
|
Raw: &gojenkins.JobResponse{
|
||||||
|
NextBuildNumber: buildNumber,
|
||||||
|
},
|
||||||
|
}, nil).AnyTimes()
|
||||||
|
|
||||||
jenkinsClient.
|
jenkinsClient.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
BuildJob(buildName, gomock.Any()).
|
BuildJob(buildName, gomock.Any()).
|
||||||
Return(buildNumber, nil)
|
Return(int64(0), nil).AnyTimes()
|
||||||
|
|
||||||
done, err := jobs.EnsureBuildJob(buildName, encodedHash, nil, jenkins, true)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.False(t, done)
|
|
||||||
|
|
||||||
err = fakeClient.Get(ctx, types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, jenkins)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
assert.NotEmpty(t, jenkins.Status.Builds)
|
|
||||||
assert.Equal(t, len(jenkins.Status.Builds), 1)
|
|
||||||
|
|
||||||
build := jenkins.Status.Builds[0]
|
|
||||||
assert.Equal(t, build.Name, buildName)
|
|
||||||
assert.Equal(t, build.Hash, encodedHash)
|
|
||||||
assert.Equal(t, build.Number, buildNumber)
|
|
||||||
assert.Equal(t, build.Status, RunningStatus)
|
|
||||||
assert.Equal(t, build.Retires, 0)
|
|
||||||
assert.NotNil(t, build.CreateTime)
|
|
||||||
assert.NotNil(t, build.LastUpdateTime)
|
|
||||||
|
|
||||||
// second run - build should be success and status updated
|
|
||||||
jenkinsClient.
|
jenkinsClient.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
GetBuild(buildName, buildNumber).
|
GetBuild(buildName, buildNumber).
|
||||||
|
|
@ -83,60 +73,10 @@ func TestSuccessEnsureJob(t *testing.T) {
|
||||||
Raw: &gojenkins.BuildResponse{
|
Raw: &gojenkins.BuildResponse{
|
||||||
Result: SuccessStatus,
|
Result: SuccessStatus,
|
||||||
},
|
},
|
||||||
}, nil)
|
}, nil).AnyTimes()
|
||||||
|
|
||||||
done, err = jobs.EnsureBuildJob(buildName, encodedHash, nil, jenkins, true)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.True(t, done)
|
|
||||||
|
|
||||||
err = fakeClient.Get(ctx, types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, jenkins)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
assert.NotEmpty(t, jenkins.Status.Builds)
|
|
||||||
assert.Equal(t, len(jenkins.Status.Builds), 1)
|
|
||||||
|
|
||||||
build = jenkins.Status.Builds[0]
|
|
||||||
assert.Equal(t, build.Name, buildName)
|
|
||||||
assert.Equal(t, build.Hash, encodedHash)
|
|
||||||
assert.Equal(t, build.Number, buildNumber)
|
|
||||||
assert.Equal(t, build.Status, SuccessStatus)
|
|
||||||
assert.Equal(t, build.Retires, 0)
|
|
||||||
assert.NotNil(t, build.CreateTime)
|
|
||||||
assert.NotNil(t, build.LastUpdateTime)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEnsureJobWithFailedBuild(t *testing.T) {
|
|
||||||
// given
|
|
||||||
logger := logf.ZapLogger(false)
|
|
||||||
ctrl := gomock.NewController(t)
|
|
||||||
ctx := context.TODO()
|
|
||||||
defer ctrl.Finish()
|
|
||||||
|
|
||||||
buildName := "Test Job"
|
|
||||||
buildNumber := int64(1)
|
|
||||||
jenkinsClient := client.NewMockJenkins(ctrl)
|
|
||||||
fakeClient := fake.NewFakeClient()
|
|
||||||
|
|
||||||
hash := sha256.New()
|
|
||||||
hash.Write([]byte(buildName))
|
|
||||||
encodedHash := base64.URLEncoding.EncodeToString(hash.Sum(nil))
|
|
||||||
|
|
||||||
// when
|
|
||||||
jenkins := jenkinsCustomResource()
|
|
||||||
err := fakeClient.Create(ctx, jenkins)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
jobs := New(jenkinsClient, fakeClient, logger)
|
|
||||||
|
|
||||||
// first run - build should be scheduled and status updated
|
|
||||||
jenkinsClient.
|
|
||||||
EXPECT().
|
|
||||||
BuildJob(buildName, gomock.Any()).
|
|
||||||
Return(buildNumber, nil)
|
|
||||||
|
|
||||||
done, err := jobs.EnsureBuildJob(buildName, encodedHash, nil, jenkins, true)
|
done, err := jobs.EnsureBuildJob(buildName, encodedHash, nil, jenkins, true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.False(t, done)
|
|
||||||
|
|
||||||
err = fakeClient.Get(ctx, types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, jenkins)
|
err = fakeClient.Get(ctx, types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, jenkins)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
@ -148,78 +88,107 @@ func TestEnsureJobWithFailedBuild(t *testing.T) {
|
||||||
assert.Equal(t, build.Name, buildName)
|
assert.Equal(t, build.Name, buildName)
|
||||||
assert.Equal(t, build.Hash, encodedHash)
|
assert.Equal(t, build.Hash, encodedHash)
|
||||||
assert.Equal(t, build.Number, buildNumber)
|
assert.Equal(t, build.Number, buildNumber)
|
||||||
assert.Equal(t, build.Status, RunningStatus)
|
|
||||||
assert.Equal(t, build.Retires, 0)
|
assert.Equal(t, build.Retires, 0)
|
||||||
assert.NotNil(t, build.CreateTime)
|
assert.NotNil(t, build.CreateTime)
|
||||||
assert.NotNil(t, build.LastUpdateTime)
|
assert.NotNil(t, build.LastUpdateTime)
|
||||||
|
|
||||||
// second run - build should be failure and status updated
|
// first run - build should be scheduled and status updated
|
||||||
|
if reconcileAttempt == 1 {
|
||||||
|
assert.False(t, done)
|
||||||
|
assert.Equal(t, build.Status, RunningStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
// second run -job should be success and status updated
|
||||||
|
if reconcileAttempt == 2 {
|
||||||
|
assert.True(t, done)
|
||||||
|
assert.Equal(t, build.Status, SuccessStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnsureJobWithFailedBuild(t *testing.T) {
|
||||||
|
// given
|
||||||
|
ctx := context.TODO()
|
||||||
|
logger := logf.ZapLogger(false)
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
buildName := "Test Job"
|
||||||
|
hash := sha256.New()
|
||||||
|
hash.Write([]byte(buildName))
|
||||||
|
encodedHash := base64.URLEncoding.EncodeToString(hash.Sum(nil))
|
||||||
|
|
||||||
|
// when
|
||||||
|
jenkins := jenkinsCustomResource()
|
||||||
|
fakeClient := fake.NewFakeClient()
|
||||||
|
err := fakeClient.Create(ctx, jenkins)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
for reconcileAttempt := 1; reconcileAttempt <= 4; reconcileAttempt++ {
|
||||||
|
logger.Info(fmt.Sprintf("Reconcile attempt #%d", reconcileAttempt))
|
||||||
|
jenkinsClient := client.NewMockJenkins(ctrl)
|
||||||
|
jobs := New(jenkinsClient, fakeClient, logger)
|
||||||
|
|
||||||
|
// first run - build should be scheduled and status updated
|
||||||
|
if reconcileAttempt == 1 {
|
||||||
jenkinsClient.
|
jenkinsClient.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
GetBuild(buildName, buildNumber).
|
GetJob(buildName).
|
||||||
|
Return(&gojenkins.Job{
|
||||||
|
Raw: &gojenkins.JobResponse{
|
||||||
|
NextBuildNumber: int64(1),
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
jenkinsClient.
|
||||||
|
EXPECT().
|
||||||
|
BuildJob(buildName, gomock.Any()).
|
||||||
|
Return(int64(0), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// second run - build should be failure and status updated
|
||||||
|
if reconcileAttempt == 2 {
|
||||||
|
jenkinsClient.
|
||||||
|
EXPECT().
|
||||||
|
GetBuild(buildName, int64(1)).
|
||||||
Return(&gojenkins.Build{
|
Return(&gojenkins.Build{
|
||||||
Raw: &gojenkins.BuildResponse{
|
Raw: &gojenkins.BuildResponse{
|
||||||
Result: FailureStatus,
|
Result: FailureStatus,
|
||||||
},
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
|
}
|
||||||
done, err = jobs.EnsureBuildJob(buildName, encodedHash, nil, jenkins, true)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.False(t, done)
|
|
||||||
|
|
||||||
err = fakeClient.Get(ctx, types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, jenkins)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
assert.NotEmpty(t, jenkins.Status.Builds)
|
|
||||||
assert.Equal(t, len(jenkins.Status.Builds), 1)
|
|
||||||
|
|
||||||
build = jenkins.Status.Builds[0]
|
|
||||||
assert.Equal(t, build.Name, buildName)
|
|
||||||
assert.Equal(t, build.Hash, encodedHash)
|
|
||||||
assert.Equal(t, build.Number, buildNumber)
|
|
||||||
assert.Equal(t, build.Status, FailureStatus)
|
|
||||||
assert.Equal(t, build.Retires, 0)
|
|
||||||
assert.NotNil(t, build.CreateTime)
|
|
||||||
assert.NotNil(t, build.LastUpdateTime)
|
|
||||||
|
|
||||||
// third run - build should be rescheduled and status updated
|
// third run - build should be rescheduled and status updated
|
||||||
|
if reconcileAttempt == 3 {
|
||||||
|
jenkinsClient.
|
||||||
|
EXPECT().
|
||||||
|
GetJob(buildName).
|
||||||
|
Return(&gojenkins.Job{
|
||||||
|
Raw: &gojenkins.JobResponse{
|
||||||
|
NextBuildNumber: int64(2),
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
jenkinsClient.
|
jenkinsClient.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
BuildJob(buildName, gomock.Any()).
|
BuildJob(buildName, gomock.Any()).
|
||||||
Return(buildNumber+1, nil)
|
Return(int64(0), nil)
|
||||||
|
}
|
||||||
done, err = jobs.EnsureBuildJob(buildName, encodedHash, nil, jenkins, true)
|
|
||||||
assert.EqualError(t, err, ErrorBuildFailed.Error())
|
|
||||||
assert.False(t, done)
|
|
||||||
|
|
||||||
err = fakeClient.Get(ctx, types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, jenkins)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
assert.NotEmpty(t, jenkins.Status.Builds)
|
|
||||||
assert.Equal(t, len(jenkins.Status.Builds), 1)
|
|
||||||
|
|
||||||
build = jenkins.Status.Builds[0]
|
|
||||||
assert.Equal(t, build.Name, buildName)
|
|
||||||
assert.Equal(t, build.Hash, encodedHash)
|
|
||||||
assert.Equal(t, build.Number, buildNumber+1)
|
|
||||||
assert.Equal(t, build.Status, RunningStatus)
|
|
||||||
assert.Equal(t, build.Retires, 1)
|
|
||||||
assert.NotNil(t, build.CreateTime)
|
|
||||||
assert.NotNil(t, build.LastUpdateTime)
|
|
||||||
|
|
||||||
// fourth run - build should be success and status updated
|
// fourth run - build should be success and status updated
|
||||||
|
if reconcileAttempt == 4 {
|
||||||
jenkinsClient.
|
jenkinsClient.
|
||||||
EXPECT().
|
EXPECT().
|
||||||
GetBuild(buildName, buildNumber+1).
|
GetBuild(buildName, int64(2)).
|
||||||
Return(&gojenkins.Build{
|
Return(&gojenkins.Build{
|
||||||
Raw: &gojenkins.BuildResponse{
|
Raw: &gojenkins.BuildResponse{
|
||||||
Result: SuccessStatus,
|
Result: SuccessStatus,
|
||||||
},
|
},
|
||||||
}, nil)
|
}, nil)
|
||||||
|
}
|
||||||
|
|
||||||
done, err = jobs.EnsureBuildJob(buildName, encodedHash, nil, jenkins, true)
|
done, errEnsureBuildJob := jobs.EnsureBuildJob(buildName, encodedHash, nil, jenkins, true)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, done)
|
|
||||||
|
|
||||||
err = fakeClient.Get(ctx, types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, jenkins)
|
err = fakeClient.Get(ctx, types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, jenkins)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
@ -227,14 +196,191 @@ func TestEnsureJobWithFailedBuild(t *testing.T) {
|
||||||
assert.NotEmpty(t, jenkins.Status.Builds)
|
assert.NotEmpty(t, jenkins.Status.Builds)
|
||||||
assert.Equal(t, len(jenkins.Status.Builds), 1)
|
assert.Equal(t, len(jenkins.Status.Builds), 1)
|
||||||
|
|
||||||
build = jenkins.Status.Builds[0]
|
build := jenkins.Status.Builds[0]
|
||||||
assert.Equal(t, build.Name, buildName)
|
assert.Equal(t, build.Name, buildName)
|
||||||
assert.Equal(t, build.Hash, encodedHash)
|
assert.Equal(t, build.Hash, encodedHash)
|
||||||
assert.Equal(t, build.Number, buildNumber+1)
|
|
||||||
assert.Equal(t, build.Status, SuccessStatus)
|
|
||||||
assert.Equal(t, build.Retires, 1)
|
|
||||||
assert.NotNil(t, build.CreateTime)
|
assert.NotNil(t, build.CreateTime)
|
||||||
assert.NotNil(t, build.LastUpdateTime)
|
assert.NotNil(t, build.LastUpdateTime)
|
||||||
|
|
||||||
|
// first run - build should be scheduled and status updated
|
||||||
|
if reconcileAttempt == 1 {
|
||||||
|
assert.NoError(t, errEnsureBuildJob)
|
||||||
|
assert.False(t, done)
|
||||||
|
assert.Equal(t, build.Number, int64(1))
|
||||||
|
assert.Equal(t, build.Status, RunningStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
// second run - build should be failure and status updated
|
||||||
|
if reconcileAttempt == 2 {
|
||||||
|
assert.Error(t, errEnsureBuildJob)
|
||||||
|
assert.False(t, done)
|
||||||
|
assert.Equal(t, build.Number, int64(1))
|
||||||
|
assert.Equal(t, build.Status, FailureStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
// third run - build should be rescheduled and status updated
|
||||||
|
if reconcileAttempt == 3 {
|
||||||
|
assert.NoError(t, errEnsureBuildJob)
|
||||||
|
assert.False(t, done)
|
||||||
|
assert.Equal(t, build.Number, int64(2))
|
||||||
|
assert.Equal(t, build.Status, RunningStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fourth run - build should be success and status updated
|
||||||
|
if reconcileAttempt == 4 {
|
||||||
|
assert.NoError(t, errEnsureBuildJob)
|
||||||
|
assert.True(t, done)
|
||||||
|
assert.Equal(t, build.Number, int64(2))
|
||||||
|
assert.Equal(t, build.Status, SuccessStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestEnsureJobFailedWithMaxRetries(t *testing.T) {
|
||||||
|
// given
|
||||||
|
ctx := context.TODO()
|
||||||
|
logger := logf.ZapLogger(false)
|
||||||
|
ctrl := gomock.NewController(t)
|
||||||
|
defer ctrl.Finish()
|
||||||
|
|
||||||
|
buildName := "Test Job"
|
||||||
|
hash := sha256.New()
|
||||||
|
hash.Write([]byte(buildName))
|
||||||
|
encodedHash := base64.URLEncoding.EncodeToString(hash.Sum(nil))
|
||||||
|
|
||||||
|
// when
|
||||||
|
jenkins := jenkinsCustomResource()
|
||||||
|
fakeClient := fake.NewFakeClient()
|
||||||
|
err := fakeClient.Create(ctx, jenkins)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
BuildRetires = 1 // override max build retries
|
||||||
|
for reconcileAttempt := 1; reconcileAttempt <= 5; reconcileAttempt++ {
|
||||||
|
logger.Info(fmt.Sprintf("Reconcile attempt #%d", reconcileAttempt))
|
||||||
|
jenkinsClient := client.NewMockJenkins(ctrl)
|
||||||
|
jobs := New(jenkinsClient, fakeClient, logger)
|
||||||
|
|
||||||
|
// first run - build should be scheduled and status updated
|
||||||
|
if reconcileAttempt == 1 {
|
||||||
|
jenkinsClient.
|
||||||
|
EXPECT().
|
||||||
|
GetJob(buildName).
|
||||||
|
Return(&gojenkins.Job{
|
||||||
|
Raw: &gojenkins.JobResponse{
|
||||||
|
NextBuildNumber: int64(1),
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
jenkinsClient.
|
||||||
|
EXPECT().
|
||||||
|
BuildJob(buildName, gomock.Any()).
|
||||||
|
Return(int64(0), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// second run - build should be failure and status updated
|
||||||
|
if reconcileAttempt == 2 {
|
||||||
|
jenkinsClient.
|
||||||
|
EXPECT().
|
||||||
|
GetBuild(buildName, int64(1)).
|
||||||
|
Return(&gojenkins.Build{
|
||||||
|
Raw: &gojenkins.BuildResponse{
|
||||||
|
Result: FailureStatus,
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// third run - build should be rescheduled and status updated
|
||||||
|
if reconcileAttempt == 3 {
|
||||||
|
jenkinsClient.
|
||||||
|
EXPECT().
|
||||||
|
GetJob(buildName).
|
||||||
|
Return(&gojenkins.Job{
|
||||||
|
Raw: &gojenkins.JobResponse{
|
||||||
|
NextBuildNumber: int64(2),
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
|
||||||
|
jenkinsClient.
|
||||||
|
EXPECT().
|
||||||
|
BuildJob(buildName, gomock.Any()).
|
||||||
|
Return(int64(0), nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fourth run - build should be success and status updated
|
||||||
|
if reconcileAttempt == 4 {
|
||||||
|
jenkinsClient.
|
||||||
|
EXPECT().
|
||||||
|
GetBuild(buildName, int64(2)).
|
||||||
|
Return(&gojenkins.Build{
|
||||||
|
Raw: &gojenkins.BuildResponse{
|
||||||
|
Result: FailureStatus,
|
||||||
|
},
|
||||||
|
}, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
done, errEnsureBuildJob := jobs.EnsureBuildJob(buildName, encodedHash, nil, jenkins, true)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
err = fakeClient.Get(ctx, types.NamespacedName{Name: jenkins.Name, Namespace: jenkins.Namespace}, jenkins)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
assert.NotEmpty(t, jenkins.Status.Builds)
|
||||||
|
assert.Equal(t, len(jenkins.Status.Builds), 1)
|
||||||
|
|
||||||
|
build := jenkins.Status.Builds[0]
|
||||||
|
assert.Equal(t, build.Name, buildName)
|
||||||
|
assert.Equal(t, build.Hash, encodedHash)
|
||||||
|
|
||||||
|
assert.NotNil(t, build.CreateTime)
|
||||||
|
assert.NotNil(t, build.LastUpdateTime)
|
||||||
|
|
||||||
|
// first run - build should be scheduled and status updated
|
||||||
|
if reconcileAttempt == 1 {
|
||||||
|
assert.NoError(t, errEnsureBuildJob)
|
||||||
|
assert.False(t, done)
|
||||||
|
assert.Equal(t, build.Number, int64(1))
|
||||||
|
assert.Equal(t, build.Retires, 0)
|
||||||
|
assert.Equal(t, build.Status, RunningStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
// second run - build should be failure and status updated
|
||||||
|
if reconcileAttempt == 2 {
|
||||||
|
assert.EqualError(t, errEnsureBuildJob, ErrorBuildFailed.Error())
|
||||||
|
assert.False(t, done)
|
||||||
|
assert.Equal(t, build.Number, int64(1))
|
||||||
|
assert.Equal(t, build.Retires, 0)
|
||||||
|
assert.Equal(t, build.Status, FailureStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
// third run - build should be rescheduled and status updated
|
||||||
|
if reconcileAttempt == 3 {
|
||||||
|
assert.NoError(t, errEnsureBuildJob)
|
||||||
|
assert.False(t, done)
|
||||||
|
//assert.Equal(t, build.Retires, 1)
|
||||||
|
assert.Equal(t, build.Number, int64(2))
|
||||||
|
assert.Equal(t, build.Retires, 1)
|
||||||
|
assert.Equal(t, build.Status, RunningStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fourth run - build should be failure and status updated
|
||||||
|
if reconcileAttempt == 4 {
|
||||||
|
assert.EqualError(t, errEnsureBuildJob, ErrorBuildFailed.Error())
|
||||||
|
assert.False(t, done)
|
||||||
|
assert.Equal(t, build.Number, int64(2))
|
||||||
|
assert.Equal(t, build.Retires, 1)
|
||||||
|
assert.Equal(t, build.Status, FailureStatus)
|
||||||
|
}
|
||||||
|
|
||||||
|
// fifth run - build should be unrecoverable failed and status updated
|
||||||
|
if reconcileAttempt == 5 {
|
||||||
|
assert.EqualError(t, errEnsureBuildJob, ErrorUnrecoverableBuildFailed.Error())
|
||||||
|
assert.False(t, done)
|
||||||
|
assert.Equal(t, build.Number, int64(2))
|
||||||
|
assert.Equal(t, build.Retires, 1)
|
||||||
|
assert.Equal(t, build.Status, FailureStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func jenkinsCustomResource() *virtuslabv1alpha1.Jenkins {
|
func jenkinsCustomResource() *virtuslabv1alpha1.Jenkins {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue