Skip to content

Commit bfa38fb

Browse files
authored
refactor(e2e-tests): names and logger (#6999)
* scenario.go is now called suite.go * assertions are now in steps * k8s client clean up * tidy up names * moved dependency init at start of InitializeTestSuite * changed logger to use interface logrus.FieldLogger * made struct fields private except for label in world struct * del reset func
1 parent f528d19 commit bfa38fb

File tree

10 files changed

+111
-113
lines changed

10 files changed

+111
-113
lines changed

tests/integration/godog/k8sclient/client.go

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,16 @@ import (
1414
"fmt"
1515

1616
mlopsv1alpha1 "github.com/seldonio/seldon-core/operator/v2/apis/mlops/v1alpha1"
17+
log "github.com/sirupsen/logrus"
1718
apierrors "k8s.io/apimachinery/pkg/api/errors"
1819
"k8s.io/apimachinery/pkg/runtime"
1920
"k8s.io/client-go/kubernetes/scheme"
2021
"sigs.k8s.io/controller-runtime/pkg/client"
2122
"sigs.k8s.io/controller-runtime/pkg/client/config"
2223
)
2324

24-
type Client interface {
25-
ApplyModel(model *mlopsv1alpha1.Model) error
26-
GetModel(model string) (*mlopsv1alpha1.Model, error)
27-
ApplyPipeline(pipeline *mlopsv1alpha1.Pipeline) error
28-
GetPipeline(pipeline string) (*mlopsv1alpha1.Pipeline, error)
29-
}
30-
3125
type K8sClient struct {
26+
logger log.FieldLogger
3227
namespace string
3328
KubeClient client.WithWatch
3429
}
@@ -42,7 +37,11 @@ const (
4237
)
4338

4439
// New todo: separate k8s client init and pass to new
45-
func New(namespace string) (*K8sClient, error) {
40+
func New(namespace string, logger *log.Logger) (*K8sClient, error) {
41+
if logger == nil {
42+
logger = log.New()
43+
}
44+
4645
k8sScheme := runtime.NewScheme()
4746

4847
if err := scheme.AddToScheme(k8sScheme); err != nil {
@@ -64,6 +63,7 @@ func New(namespace string) (*K8sClient, error) {
6463
}
6564

6665
return &K8sClient{
66+
logger: logger.WithField("client", "k8sClient"),
6767
namespace: namespace,
6868
KubeClient: cl,
6969
}, nil
@@ -109,23 +109,15 @@ func (k8s *K8sClient) ApplyModel(model *mlopsv1alpha1.Model) error {
109109
}
110110

111111
func (k8s *K8sClient) DeleteScenarioResources(ctx context.Context, labels client.MatchingLabels) error {
112-
113-
list := &mlopsv1alpha1.ModelList{}
114-
err := k8s.KubeClient.List(ctx, list,
112+
// 1) Delete Models
113+
if err := k8s.KubeClient.DeleteAllOf(
114+
ctx,
115+
&mlopsv1alpha1.Model{},
115116
client.InNamespace(k8s.namespace),
116117
labels,
117-
)
118-
if err != nil {
118+
); err != nil {
119119
return err
120120
}
121121

122-
for _, m := range list.Items {
123-
// Copy because Delete expects a pointer
124-
model := m
125-
if err := k8s.KubeClient.Delete(ctx, &model); err != nil {
126-
return err
127-
}
128-
}
129-
130122
return nil
131123
}

tests/integration/godog/k8sclient/watcher.go renamed to tests/integration/godog/k8sclient/watcher_store.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"sync"
1616

1717
"github.com/seldonio/seldon-core/operator/v2/pkg/generated/clientset/versioned/typed/mlops/v1alpha1"
18+
log "github.com/sirupsen/logrus"
1819
"k8s.io/apimachinery/pkg/api/meta"
1920
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2021
"k8s.io/apimachinery/pkg/runtime"
@@ -35,6 +36,7 @@ type WatcherStore struct {
3536
label string
3637
mlopsClient v1alpha1.MlopsV1alpha1Interface
3738
modelWatcher watch.Interface
39+
logger log.FieldLogger
3840

3941
mu sync.RWMutex
4042
store map[string]runtime.Object // key: "namespace/name"
@@ -52,7 +54,11 @@ type waiter struct {
5254
type ConditionFunc func(obj runtime.Object) (done bool, err error)
5355

5456
// NewWatcherStore receives events that match on a particular object list and creates a database store to query crd state
55-
func NewWatcherStore(namespace string, label string, mlopsClient v1alpha1.MlopsV1alpha1Interface) (*WatcherStore, error) {
57+
func NewWatcherStore(namespace string, label string, mlopsClient v1alpha1.MlopsV1alpha1Interface, logger *log.Logger) (*WatcherStore, error) {
58+
if logger == nil {
59+
logger = log.New()
60+
}
61+
5662
modelWatcher, err := mlopsClient.Models(namespace).Watch(context.Background(), v1.ListOptions{LabelSelector: "test-suite=godog"})
5763
if err != nil {
5864
return nil, fmt.Errorf("failed to create model watcher: %w", err)
@@ -63,6 +69,7 @@ func NewWatcherStore(namespace string, label string, mlopsClient v1alpha1.MlopsV
6369
label: label,
6470
mlopsClient: mlopsClient,
6571
modelWatcher: modelWatcher,
72+
logger: logger.WithField("client", "watcher_store"),
6673
store: make(map[string]runtime.Object),
6774
doneChan: make(chan struct{}),
6875
}, nil
@@ -79,7 +86,12 @@ func (s *WatcherStore) Start() {
7986
return
8087
}
8188

82-
fmt.Printf("model watch event: %v\n", event)
89+
accessor, err := meta.Accessor(event.Object)
90+
if err != nil {
91+
s.logger.WithError(err).Error("failed to access model watcher")
92+
} else {
93+
s.logger.Debugf("new model watch event with name: %s on namespace: %s", accessor.GetName(), accessor.GetNamespace())
94+
}
8395

8496
if event.Object == nil {
8597
continue

tests/integration/godog/main_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515

1616
"github.com/cucumber/godog"
1717
"github.com/cucumber/godog/colors"
18-
"github.com/seldonio/seldon-core/tests/integration/godog/scenario"
18+
"github.com/seldonio/seldon-core/tests/integration/godog/suite"
1919
"github.com/spf13/pflag" // godog v0.11.0 and later
2020
)
2121

@@ -34,8 +34,8 @@ func TestMain(m *testing.M) {
3434

3535
status := godog.TestSuite{
3636
Name: "godogs",
37-
TestSuiteInitializer: scenario.InitializeTestSuite,
38-
ScenarioInitializer: scenario.InitializeScenario,
37+
TestSuiteInitializer: suite.InitializeTestSuite,
38+
ScenarioInitializer: suite.InitializeScenario,
3939
Options: &opts,
4040
}.Run()
4141

File renamed without changes.

tests/integration/godog/steps/explicit_model_steps.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import "context"
1414
func (m *Model) waitForModelReady(ctx context.Context, model string) error {
1515
// TODO: uncomment when auto-gen k8s client merged
1616

17-
//foundModel, err := w.k8sClient.MlopsV1alpha1().Models(w.namespace).Get(ctx, model, metav1.GetOptions{})
17+
//foundModel, err := w.corek8sClient.MlopsV1alpha1().Models(w.namespace).Get(ctx, model, metav1.GetOptions{})
1818
//if err != nil {
1919
// return fmt.Errorf("failed getting model: %w", err)
2020
//}
@@ -23,7 +23,7 @@ func (m *Model) waitForModelReady(ctx context.Context, model string) error {
2323
// return nil
2424
//}
2525
//
26-
//watcher, err := w.k8sClient.MlopsV1alpha1().Models(w.namespace).Watch(ctx, metav1.ListOptions{
26+
//watcher, err := w.corek8sClient.MlopsV1alpha1().Models(w.namespace).Watch(ctx, metav1.ListOptions{
2727
// FieldSelector: fmt.Sprintf("metadata.name=%s", model),
2828
// ResourceVersion: foundModel.ResourceVersion,
2929
// Watch: true,

tests/integration/godog/steps/model_steps.go

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import (
1717
"github.com/cucumber/godog"
1818
mlopsv1alpha1 "github.com/seldonio/seldon-core/operator/v2/apis/mlops/v1alpha1"
1919
"github.com/seldonio/seldon-core/tests/integration/godog/k8sclient"
20-
"github.com/seldonio/seldon-core/tests/integration/godog/scenario/assertions"
20+
"github.com/seldonio/seldon-core/tests/integration/godog/steps/assertions"
2121
"gopkg.in/yaml.v3"
2222
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2323
)
@@ -50,29 +50,29 @@ var testModels = map[string]TestModelConfig{
5050
func LoadModelSteps(scenario *godog.ScenarioContext, w *World) {
5151
// Model Operations
5252
scenario.Step(`^I have an? "([^"]+)" model$`, func(modelName string) error {
53-
return w.CurrentModel.IHaveAModel(modelName, w.Label)
53+
return w.currentModel.IHaveAModel(modelName, w.Label)
5454
})
55-
scenario.Step(`^the model has "(\d+)" min replicas$`, w.CurrentModel.SetMinReplicas)
56-
scenario.Step(`^the model has "(\d+)" max replicas$`, w.CurrentModel.SetMaxReplicas)
57-
scenario.Step(`^the model has "(\d+)" replicas$`, w.CurrentModel.SetReplicas)
55+
scenario.Step(`^the model has "(\d+)" min replicas$`, w.currentModel.SetMinReplicas)
56+
scenario.Step(`^the model has "(\d+)" max replicas$`, w.currentModel.SetMaxReplicas)
57+
scenario.Step(`^the model has "(\d+)" replicas$`, w.currentModel.SetReplicas)
5858
// Model Deployments
5959
scenario.Step(`^the model is applied$`, func() error {
60-
return w.CurrentModel.ApplyModel(w.KubeClient)
60+
return w.currentModel.ApplyModel(w.kubeClient)
6161
})
6262
// Model Assertions
6363
scenario.Step(`^the model (?:should )?eventually become(?:s)? Ready$`, func() error {
64-
return w.CurrentModel.ModelReady(w.WatcherStorage)
64+
return w.currentModel.ModelReady(w.watcherStorage)
6565
})
66-
scenario.Step(`^the model status message should be "([^"]+)"$`, w.CurrentModel.AssertModelStatus)
66+
scenario.Step(`^the model status message should be "([^"]+)"$`, w.currentModel.AssertModelStatus)
6767
}
6868

6969
func LoadExplicitModelSteps(scenario *godog.ScenarioContext, w *World) {
7070
scenario.Step(`^I deploy model spec:$`, func(spec *godog.DocString) error {
71-
return w.CurrentModel.deployModelSpec(spec, w.namespace, w.KubeClient)
71+
return w.currentModel.deployModelSpec(spec, w.namespace, w.kubeClient)
7272
})
7373
scenario.Step(`^the model "([^"]+)" should eventually become Ready with timeout "([^"]+)"$`, func(model, timeout string) error {
7474
return withTimeoutCtx(timeout, func(ctx context.Context) error {
75-
return w.CurrentModel.waitForModelReady(ctx, model)
75+
return w.currentModel.waitForModelReady(ctx, model)
7676
})
7777
})
7878
}
@@ -100,7 +100,7 @@ func (m *Model) deployModelSpec(spec *godog.DocString, namespace string, _ *k8sc
100100
}
101101
modelSpec.Namespace = namespace
102102
// TODO: uncomment when auto-gen k8s client merged
103-
//if _, err := w.k8sClient.MlopsV1alpha1().Models(w.namespace).Create(context.TODO(), modelSpec, metav1.CreateOptions{}); err != nil {
103+
//if _, err := w.corek8sClient.MlopsV1alpha1().Models(w.namespace).Create(context.TODO(), modelSpec, metav1.CreateOptions{}); err != nil {
104104
// return fmt.Errorf("failed creating model: %w", err)
105105
//}
106106
return nil
@@ -112,7 +112,7 @@ func (m *Model) IHaveAModel(model string, label map[string]string) error {
112112
return fmt.Errorf("model %s not found", model)
113113
}
114114

115-
modelName := fmt.Sprintf("%s-%s", testModel.Name, randomSuffix(3))
115+
modelName := fmt.Sprintf("%s-%s", testModel.Name, randomString(3))
116116

117117
m.model = &mlopsv1alpha1.Model{
118118
TypeMeta: metav1.TypeMeta{
@@ -165,10 +165,6 @@ func NewModel() *Model {
165165
return &Model{model: &mlopsv1alpha1.Model{}}
166166
}
167167

168-
func (m *Model) Reset(world *World) {
169-
world.CurrentModel.model = &mlopsv1alpha1.Model{}
170-
}
171-
172168
func (m *Model) SetMinReplicas(replicas int) {
173169

174170
}
@@ -179,11 +175,8 @@ func (m *Model) SetReplicas(replicas int) {}
179175

180176
// ApplyModel model is aware of namespace and testsuite config and it might add extra information to the cr that the step hasn't added like namespace
181177
func (m *Model) ApplyModel(k *k8sclient.K8sClient) error {
182-
183178
// retrieve current model and apply in k8s
184-
err := k.ApplyModel(m.model)
185-
186-
if err != nil {
179+
if err := k.ApplyModel(m.model); err != nil {
187180
return err
188181
}
189182

@@ -194,7 +187,7 @@ func (m *Model) ModelReady(w k8sclient.WatcherStorage) error {
194187
ctx, cancel := context.WithTimeout(context.Background(), 20*time.Second)
195188
defer cancel()
196189

197-
// m.world.CurrentModel.model is assumed to be *mlopsv1alpha1.Model
190+
// m.world.currentModel.model is assumed to be *mlopsv1alpha1.Model
198191
// which implements runtime.Object, so no cast needed.
199192
return w.WaitFor(
200193
ctx,

tests/integration/godog/steps/util.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ import (
1515
"strings"
1616
)
1717

18-
// RandomSuffix returns a lowercase, short, k8s-safe random string.
19-
func randomSuffix(n int) string {
18+
// randomString returns a lowercase, short, k8s-safe random string.
19+
func randomString(n int) string {
2020
b := make([]byte, n)
2121
_, err := rand.Read(b)
2222
if err != nil {

tests/integration/godog/steps/world.go

Lines changed: 13 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -10,38 +10,34 @@ the Change License after the Change Date as each is defined in accordance with t
1010
package steps
1111

1212
import (
13-
"crypto/tls"
14-
"fmt"
1513
"net/http"
1614

1715
"github.com/seldonio/seldon-core/apis/go/v2/mlops/v2_dataplane"
1816
v "github.com/seldonio/seldon-core/operator/v2/pkg/generated/clientset/versioned"
1917
"github.com/seldonio/seldon-core/tests/integration/godog/k8sclient"
20-
"github.com/sirupsen/logrus"
21-
"google.golang.org/grpc"
22-
"google.golang.org/grpc/credentials"
23-
"google.golang.org/grpc/credentials/insecure"
18+
log "github.com/sirupsen/logrus"
2419
)
2520

2621
type World struct {
2722
namespace string
28-
KubeClient *k8sclient.K8sClient
29-
k8sClient v.Interface
30-
WatcherStorage k8sclient.WatcherStorage
23+
kubeClient *k8sclient.K8sClient
24+
corek8sClient v.Interface
25+
watcherStorage k8sclient.WatcherStorage
3126
StartingClusterState string //todo: this will be a combination of starting state awareness of core 2 such as the
3227
//todo: server config,seldon config and seldon runtime to be able to reconcile to starting state should we change
3328
//todo: the state such as reducing replicas to 0 of scheduler to test unavailability
34-
CurrentModel *Model
29+
currentModel *Model
3530
infer inference
36-
logger *logrus.Entry
31+
logger log.FieldLogger
3732
Label map[string]string
3833
}
3934

4035
type Config struct {
4136
Namespace string
42-
Logger *logrus.Entry
37+
Logger log.FieldLogger
4338
KubeClient *k8sclient.K8sClient
4439
WatcherStorage k8sclient.WatcherStorage
40+
GRPC v2_dataplane.GRPCInferenceServiceClient
4541
IngressHost string
4642
HTTPPort uint
4743
GRPCPort uint
@@ -59,36 +55,20 @@ type inference struct {
5955
}
6056

6157
func NewWorld(c Config) (*World, error) {
62-
creds := insecure.NewCredentials()
63-
if c.SSL {
64-
creds = credentials.NewTLS(&tls.Config{
65-
InsecureSkipVerify: true,
66-
})
67-
}
68-
69-
opts := []grpc.DialOption{
70-
grpc.WithTransportCredentials(creds),
71-
}
72-
73-
conn, err := grpc.NewClient(fmt.Sprintf("%s:%d", c.IngressHost, c.GRPCPort), opts...)
74-
if err != nil {
75-
return nil, fmt.Errorf("could not create grpc client: %w", err)
76-
}
77-
grpcClient := v2_dataplane.NewGRPCInferenceServiceClient(conn)
78-
7958
label := map[string]string{
80-
"scenario": randomSuffix(6),
59+
"scenario": randomString(6),
8160
}
8261

8362
w := &World{
8463
namespace: c.Namespace,
85-
KubeClient: c.KubeClient,
86-
WatcherStorage: c.WatcherStorage,
64+
kubeClient: c.KubeClient,
65+
watcherStorage: c.WatcherStorage,
66+
currentModel: NewModel(),
8767
infer: inference{
8868
host: c.IngressHost,
8969
http: &http.Client{},
70+
grpc: c.GRPC,
9071
httpPort: c.HTTPPort,
91-
grpc: grpcClient,
9272
ssl: c.SSL},
9373
Label: label,
9474
}

tests/integration/godog/scenario/config.go renamed to tests/integration/godog/suite/config.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Use of this software is governed BY
77
the Change License after the Change Date as each is defined in accordance with the LICENSE file.
88
*/
99

10-
package scenario
10+
package suite
1111

1212
import (
1313
"encoding/json"

0 commit comments

Comments
 (0)