mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-26 04:05:40 +01:00
Add UT cases for new added code
Signed-off-by: Steven Zou <szou@vmware.com>
This commit is contained in:
parent
ccd486a0ad
commit
84d864607c
@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/goharbor/harbor/src/jobservice/errs"
|
||||
"github.com/goharbor/harbor/src/jobservice/models"
|
||||
"github.com/goharbor/harbor/src/jobservice/utils"
|
||||
"github.com/gomodule/redigo/redis"
|
||||
@ -16,29 +17,53 @@ import (
|
||||
// Once a job is declared to be unique, the job can be enqueued only if
|
||||
// no same job (same job name and parameters) in the queue or running in progress.
|
||||
// Adopt the same unique mechanism with the upstream framework.
|
||||
type DeDuplicator struct {
|
||||
type DeDuplicator interface {
|
||||
// Check the uniqueness of the unique job and set the unique flag if it is not set yet.
|
||||
//
|
||||
// Parameters:
|
||||
// jobName string : name of the job
|
||||
// params models.Parameters : parameters of the job
|
||||
//
|
||||
// Returns:
|
||||
// If no unique flag and successfully set it, a nil error is returned;
|
||||
// otherwise, a non nil error is returned.
|
||||
Unique(jobName string, params models.Parameters) error
|
||||
|
||||
// Remove the unique flag after job exiting
|
||||
// Parameters:
|
||||
// jobName string : name of the job
|
||||
// params models.Parameters : parameters of the job
|
||||
//
|
||||
// Returns:
|
||||
// If unique flag is successfully removed, a nil error is returned;
|
||||
// otherwise, a non nil error is returned.
|
||||
DelUniqueSign(jobName string, params models.Parameters) error
|
||||
}
|
||||
|
||||
// RedisDeDuplicator implement the DeDuplicator interface based on redis.
|
||||
type RedisDeDuplicator struct {
|
||||
// Redis namespace
|
||||
namespace string
|
||||
// Redis conn pool
|
||||
pool *redis.Pool
|
||||
}
|
||||
|
||||
// NewDeDuplicator is constructor of DeDuplicator
|
||||
func NewDeDuplicator(ns string, pool *redis.Pool) *DeDuplicator {
|
||||
return &DeDuplicator{
|
||||
// NewRedisDeDuplicator is constructor of RedisDeDuplicator
|
||||
func NewRedisDeDuplicator(ns string, pool *redis.Pool) *RedisDeDuplicator {
|
||||
return &RedisDeDuplicator{
|
||||
namespace: ns,
|
||||
pool: pool,
|
||||
}
|
||||
}
|
||||
|
||||
// Unique checks if the job is unique and set unique flag if it is not set yet.
|
||||
func (dd *DeDuplicator) Unique(jobName string, params models.Parameters) error {
|
||||
uniqueKey, err := redisKeyUniqueJob(dd.namespace, jobName, params)
|
||||
func (rdd *RedisDeDuplicator) Unique(jobName string, params models.Parameters) error {
|
||||
uniqueKey, err := redisKeyUniqueJob(rdd.namespace, jobName, params)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unique job error: %s", err)
|
||||
}
|
||||
|
||||
conn := dd.pool.Get()
|
||||
conn := rdd.pool.Get()
|
||||
defer conn.Close()
|
||||
|
||||
args := []interface{}{
|
||||
@ -50,21 +75,29 @@ func (dd *DeDuplicator) Unique(jobName string, params models.Parameters) error {
|
||||
}
|
||||
|
||||
res, err := redis.String(conn.Do("SET", args...))
|
||||
if err == nil && strings.ToUpper(res) == "OK" {
|
||||
return nil
|
||||
if err == redis.ErrNil {
|
||||
return errs.ConflictError(uniqueKey)
|
||||
}
|
||||
|
||||
return errors.New("unique job error: duplicated")
|
||||
if err == nil {
|
||||
if strings.ToUpper(res) == "OK" {
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("unique job error: missing 'OK' reply")
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// DelUniqueSign delete the job unique sign
|
||||
func (dd *DeDuplicator) DelUniqueSign(jobName string, params models.Parameters) error {
|
||||
uniqueKey, err := redisKeyUniqueJob(dd.namespace, jobName, params)
|
||||
func (rdd *RedisDeDuplicator) DelUniqueSign(jobName string, params models.Parameters) error {
|
||||
uniqueKey, err := redisKeyUniqueJob(rdd.namespace, jobName, params)
|
||||
if err != nil {
|
||||
return fmt.Errorf("delete unique job error: %s", err)
|
||||
}
|
||||
|
||||
conn := dd.pool.Get()
|
||||
conn := rdd.pool.Get()
|
||||
defer conn.Close()
|
||||
|
||||
if _, err := conn.Do("DEL", uniqueKey); err != nil {
|
||||
|
28
src/jobservice/pool/de_duplicator_test.go
Normal file
28
src/jobservice/pool/de_duplicator_test.go
Normal file
@ -0,0 +1,28 @@
|
||||
package pool
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/goharbor/harbor/src/jobservice/tests"
|
||||
)
|
||||
|
||||
func TestDeDuplicator(t *testing.T) {
|
||||
jobName := "fake_job"
|
||||
jobParams := map[string]interface{}{
|
||||
"image": "ubuntu:latest",
|
||||
}
|
||||
|
||||
rdd := NewRedisDeDuplicator(tests.GiveMeTestNamespace(), rPool)
|
||||
|
||||
if err := rdd.Unique(jobName, jobParams); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
if err := rdd.Unique(jobName, jobParams); err == nil {
|
||||
t.Errorf("expect duplicated error but got nil error")
|
||||
}
|
||||
|
||||
if err := rdd.DelUniqueSign(jobName, jobParams); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
@ -37,11 +37,11 @@ type RedisJob struct {
|
||||
job interface{} // the real job implementation
|
||||
context *env.Context // context
|
||||
statsManager opm.JobStatsManager // job stats manager
|
||||
deDuplicator *DeDuplicator // handle unique job
|
||||
deDuplicator DeDuplicator // handle unique job
|
||||
}
|
||||
|
||||
// NewRedisJob is constructor of RedisJob
|
||||
func NewRedisJob(j interface{}, ctx *env.Context, statsManager opm.JobStatsManager, deDuplicator *DeDuplicator) *RedisJob {
|
||||
func NewRedisJob(j interface{}, ctx *env.Context, statsManager opm.JobStatsManager, deDuplicator DeDuplicator) *RedisJob {
|
||||
return &RedisJob{
|
||||
job: j,
|
||||
context: ctx,
|
||||
|
@ -50,7 +50,8 @@ func TestJobWrapper(t *testing.T) {
|
||||
WG: &sync.WaitGroup{},
|
||||
ErrorChan: make(chan error, 1), // with 1 buffer
|
||||
}
|
||||
wrapper := NewRedisJob((*fakeParentJob)(nil), envContext, mgr)
|
||||
deDuplicator := NewRedisDeDuplicator(tests.GiveMeTestNamespace(), rPool)
|
||||
wrapper := NewRedisJob((*fakeParentJob)(nil), envContext, mgr, deDuplicator)
|
||||
j := &work.Job{
|
||||
ID: "FAKE",
|
||||
Name: "DEMO",
|
||||
|
@ -59,7 +59,7 @@ type GoCraftWorkPool struct {
|
||||
scheduler period.Interface
|
||||
statsManager opm.JobStatsManager
|
||||
messageServer *MessageServer
|
||||
deDuplicator *DeDuplicator
|
||||
deDuplicator DeDuplicator
|
||||
|
||||
// no need to sync as write once and then only read
|
||||
// key is name of known job
|
||||
@ -80,7 +80,7 @@ func NewGoCraftWorkPool(ctx *env.Context, namespace string, workerCount uint, re
|
||||
scheduler := period.NewRedisPeriodicScheduler(ctx, namespace, redisPool, statsMgr)
|
||||
sweeper := period.NewSweeper(namespace, redisPool, client)
|
||||
msgServer := NewMessageServer(ctx.SystemContext, namespace, redisPool)
|
||||
deDepulicator := NewDeDuplicator(namespace, redisPool)
|
||||
deDepulicator := NewRedisDeDuplicator(namespace, redisPool)
|
||||
return &GoCraftWorkPool{
|
||||
namespace: namespace,
|
||||
redisPool: redisPool,
|
||||
|
Loading…
Reference in New Issue
Block a user