Skip to content

Commit

Permalink
feat(job): update failfast schema (#68)
Browse files Browse the repository at this point in the history
In addition, this commit adds few unit test cases

Signed-off-by: AmitKumarDas <[email protected]>
  • Loading branch information
Amit Kumar Das authored Jun 3, 2020
1 parent 2621087 commit 2fd8a3f
Show file tree
Hide file tree
Showing 8 changed files with 590 additions and 11 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ $(IMG_NAME): $(ALL_SRC)

$(ALL_SRC): ;

#$(GIT_TAGS): ;
$(GIT_TAGS): ;

# go mod download modules to local cache
# make vendored copy of dependencies
Expand Down
31 changes: 30 additions & 1 deletion pkg/job/fixture.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package job

import (
"github.com/pkg/errors"
apiextnv1beta1 "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
Expand All @@ -35,9 +36,20 @@ type FixtureConfig struct {
IsTearDown bool
}

// BaseFixture holds the common fields of Fixture structure
type BaseFixture struct {

// functions useful to mock during unit tests
getClientForAPIVersionAndKindFn func(string, string) (*clientset.ResourceClient, error)
getClientForAPIVersionAndResourceFn func(string, string) (*clientset.ResourceClient, error)
getAPIForAPIVersionAndResourceFn func(string, string) *dynamicdiscovery.APIResource
}

// Fixture is the base structure that ties a job specification
// with one or more kubernetes api operations.
type Fixture struct {
*BaseFixture

apiDiscovery *dynamicdiscovery.APIResourceDiscovery

// dynamic client to invoke kubernetes operations
Expand Down Expand Up @@ -68,6 +80,12 @@ func (f *Fixture) setAPIDiscovery(config FixtureConfig) {
}

func (f *Fixture) setCRDClient(config FixtureConfig) {
if config.KubeConfig == nil {
f.err = errors.Errorf(
"Failed to set crd client: Nil kube config provided",
)
return
}
f.crdClient, f.err = apiextnv1beta1.NewForConfig(
config.KubeConfig,
)
Expand All @@ -88,7 +106,9 @@ func (f *Fixture) setKubeClientset(config FixtureConfig) {

// NewFixture returns a new instance of Fixture
func NewFixture(config FixtureConfig) (*Fixture, error) {
f := &Fixture{}
f := &Fixture{
BaseFixture: &BaseFixture{},
}
var setters = []func(FixtureConfig){
f.setTearDown,
f.setAPIDiscovery,
Expand Down Expand Up @@ -154,6 +174,9 @@ func (f *Fixture) GetClientForAPIVersionAndKind(
apiversion string,
kind string,
) (*clientset.ResourceClient, error) {
if f.getClientForAPIVersionAndKindFn != nil {
return f.getClientForAPIVersionAndKindFn(apiversion, kind)
}
return f.dynamicClientset.GetClientForAPIVersionAndKind(
apiversion,
kind,
Expand All @@ -166,6 +189,9 @@ func (f *Fixture) GetClientForAPIVersionAndResource(
apiversion string,
resource string,
) (*clientset.ResourceClient, error) {
if f.getClientForAPIVersionAndResourceFn != nil {
return f.getClientForAPIVersionAndResourceFn(apiversion, resource)
}
return f.dynamicClientset.GetClientForAPIVersionAndResource(
apiversion,
resource,
Expand All @@ -178,6 +204,9 @@ func (f *Fixture) GetAPIForAPIVersionAndResource(
apiversion string,
resource string,
) *dynamicdiscovery.APIResource {
if f.getAPIForAPIVersionAndResourceFn != nil {
return f.getAPIForAPIVersionAndResourceFn(apiversion, resource)
}
return f.apiDiscovery.
GetAPIForAPIVersionAndResource(
apiversion,
Expand Down
52 changes: 52 additions & 0 deletions pkg/job/fixture_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
Copyright 2020 The MayaData Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
https://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package job

import (
"testing"

"k8s.io/client-go/rest"
)

func TestNewFixture(t *testing.T) {
var tests = map[string]struct {
kubeConfig *rest.Config
isErr bool
}{
"nil kubeconfig": {
isErr: true,
},
"empty kubeconfig": {
kubeConfig: &rest.Config{},
},
}
for name, mock := range tests {
name := name
mock := mock
t.Run(name, func(t *testing.T) {
_, err := NewFixture(FixtureConfig{
KubeConfig: mock.kubeConfig,
})
if mock.isErr && err == nil {
t.Fatal("Expected error got none")
}
if !mock.isErr && err != nil {
t.Fatalf("Expected no error got %s", err.Error())
}
})
}
}
29 changes: 22 additions & 7 deletions pkg/job/job.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ import (

// RunnerConfig helps constructing new Runner instances
type RunnerConfig struct {
Job types.Job
Job types.Job
Retry *Retryable
}

// Runner helps executing a Job
type Runner struct {
Job types.Job
JobStatus *types.JobStatus
Retry *Retryable

fixture *Fixture
isTearDown bool
Expand All @@ -48,16 +50,23 @@ type Runner struct {

// NewRunner returns a new instance of Runner
func NewRunner(config RunnerConfig) *Runner {
// check teardown
var isTearDown bool
if config.Job.Spec.Teardown != nil {
isTearDown = *config.Job.Spec.Teardown
}
// check retry
var retry = NewRetry(RetryConfig{})
if config.Retry != nil {
retry = config.Retry
}
return &Runner{
isTearDown: isTearDown,
Job: config.Job,
JobStatus: &types.JobStatus{
TaskListStatus: map[string]types.TaskStatus{},
},
Retry: retry,
}
}

Expand Down Expand Up @@ -114,7 +123,7 @@ func (r *Runner) isRunEnabled() (bool, error) {
JobName: fmt.Sprintf("%s %s", r.Job.GetNamespace(), r.Job.GetName()),
Fixture: r.fixture,
Eligible: r.Job.Spec.Eligible,
Retry: NewRetry(RetryConfig{}),
Retry: r.Retry,
})
if err != nil {
return false, err
Expand Down Expand Up @@ -170,7 +179,9 @@ func (r *Runner) buildLockRunner() *LockRunner {
isLockForever = true
}
lock := types.Task{
FailFastRule: types.FailFastOnDiscoveryError,
FailFast: &types.FailFast{
When: types.FailFastOnDiscoveryError,
},
Apply: &types.Apply{
State: &unstructured.Unstructured{
Object: map[string]interface{}{
Expand All @@ -190,8 +201,8 @@ func (r *Runner) buildLockRunner() *LockRunner {
return &LockRunner{
BaseRunner: BaseRunner{
Fixture: r.fixture,
Retry: NewRetry(RetryConfig{}),
FailFastRule: lock.FailFastRule,
Retry: r.Retry,
FailFastRule: lock.FailFast.When,
},
Task: lock,
LockForever: isLockForever,
Expand Down Expand Up @@ -253,13 +264,17 @@ func (r *Runner) runAll() (status *types.JobStatus, err error) {
var failedTasks int
var start = time.Now()
for idx, task := range r.Job.Spec.Tasks {
var failFastRule types.FailFastRule
if task.FailFast != nil {
failFastRule = task.FailFast.When
}
tr := &TaskRunner{
BaseRunner: BaseRunner{
Fixture: r.fixture,
TaskIndex: idx + 1,
TaskName: task.Name,
Retry: NewRetry(RetryConfig{}),
FailFastRule: task.FailFastRule,
Retry: r.Retry,
FailFastRule: failFastRule,
},
Task: task,
}
Expand Down
Loading

0 comments on commit 2fd8a3f

Please sign in to comment.