Skip to content

Commit d265621

Browse files
committed
Playground should be triggered to create Services and then Pods once the model is created
1 parent 9c77c38 commit d265621

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

pkg/controller/inference/playground_controller.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,34 @@ func (r *PlaygroundReconciler) Reconcile(ctx context.Context, req ctrl.Request)
119119

120120
// SetupWithManager sets up the controller with the Manager.
121121
func (r *PlaygroundReconciler) SetupWithManager(mgr ctrl.Manager) error {
122+
mapFn := func(ctx context.Context, obj client.Object) []ctrl.Request {
123+
logger := log.FromContext(ctx)
124+
125+
namespace := obj.GetNamespace()
126+
name := obj.GetName()
127+
128+
playgrounds := &inferenceapi.PlaygroundList{}
129+
err := r.List(ctx, playgrounds, client.InNamespace(namespace))
130+
if err != nil {
131+
logger.Error(err, "failed to list playgrounds")
132+
return nil
133+
}
134+
135+
var reqs []ctrl.Request
136+
for _, playground := range playgrounds.Items {
137+
if playground.Spec.ModelClaim != nil && playground.Spec.ModelClaim.ModelName == coreapi.ModelName(name) {
138+
reqs = append(reqs, ctrl.Request{
139+
NamespacedName: types.NamespacedName{
140+
Namespace: namespace,
141+
Name: playground.Name,
142+
},
143+
})
144+
}
145+
// TODO: handle MultiModelsClaims in the future.
146+
}
147+
return reqs
148+
}
149+
122150
return ctrl.NewControllerManagedBy(mgr).
123151
For(&inferenceapi.Playground{}).
124152
Watches(&inferenceapi.Service{}, &handler.EnqueueRequestForObject{},
@@ -129,6 +157,12 @@ func (r *PlaygroundReconciler) SetupWithManager(mgr ctrl.Manager) error {
129157
return !reflect.DeepEqual(oldBar.Status, newBar.Status)
130158
},
131159
})).
160+
Watches(&coreapi.OpenModel{}, handler.EnqueueRequestsFromMapFunc(mapFn),
161+
builder.WithPredicates(predicate.Funcs{
162+
UpdateFunc: func(e event.UpdateEvent) bool { return false },
163+
DeleteFunc: func(e event.DeleteEvent) bool { return false },
164+
GenericFunc: func(e event.GenericEvent) bool { return false },
165+
})).
132166
Complete(r)
133167
}
134168

test/integration/controller/inference/playground_test.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ package inference
1818

1919
import (
2020
"context"
21+
"fmt"
2122

2223
"github.com/onsi/ginkgo/v2"
2324
"github.com/onsi/gomega"
2425
corev1 "k8s.io/api/core/v1"
26+
apierrors "k8s.io/apimachinery/pkg/api/errors"
2527
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2628
"k8s.io/apimachinery/pkg/types"
2729
"k8s.io/utils/ptr"
@@ -155,5 +157,56 @@ var _ = ginkgo.Describe("playground controller test", func() {
155157
},
156158
},
157159
}),
160+
ginkgo.Entry("create the model after playground is created", &testValidatingCase{
161+
makePlayground: func() *inferenceapi.Playground {
162+
return util.MockASamplePlayground(ns.Name)
163+
},
164+
updates: []*update{
165+
{
166+
// Delete the pre-provision model before creating playground.
167+
playgroundUpdateFn: func(_ *inferenceapi.Playground) {
168+
gomega.Expect(k8sClient.Delete(ctx, model)).To(gomega.Succeed())
169+
// To make sure model not exists.
170+
gomega.Eventually(func() error {
171+
oldModel := &coreapi.OpenModel{}
172+
if err := k8sClient.Get(ctx, types.NamespacedName{Name: model.Name, Namespace: model.Namespace}, oldModel); err != nil {
173+
if apierrors.IsNotFound(err) {
174+
return nil
175+
}
176+
return err
177+
}
178+
return fmt.Errorf("model %s/%s still exists", model.Namespace, model.Name)
179+
}, util.IntegrationTimeout, util.Interval).Should(gomega.Succeed())
180+
},
181+
},
182+
{ // Create the playground when the model not exists.
183+
playgroundUpdateFn: func(playground *inferenceapi.Playground) {
184+
gomega.Expect(k8sClient.Create(ctx, playground)).To(gomega.Succeed())
185+
},
186+
checkPlayground: func(ctx context.Context, k8sClient client.Client, playground *inferenceapi.Playground) {
187+
validation.ValidatePlayground(ctx, k8sClient, playground)
188+
gomega.Consistently(func() error {
189+
updatePlayground := inferenceapi.Playground{}
190+
if err := k8sClient.Get(ctx, types.NamespacedName{Name: playground.Name, Namespace: playground.Namespace}, &updatePlayground); err != nil {
191+
return err
192+
}
193+
if len(updatePlayground.Status.Conditions) != 0 {
194+
return fmt.Errorf("playground status conditions should be empty, got %v", updatePlayground.Status.Conditions)
195+
}
196+
return nil
197+
}, 3*util.Interval, util.Interval).Should(gomega.Succeed())
198+
},
199+
},
200+
{
201+
// create the model after playground is created.
202+
playgroundUpdateFn: func(_ *inferenceapi.Playground) {
203+
gomega.Expect(k8sClient.Create(ctx, model)).To(gomega.Succeed())
204+
},
205+
checkPlayground: func(ctx context.Context, k8sClient client.Client, playground *inferenceapi.Playground) {
206+
validation.ValidatePlaygroundStatusEqualTo(ctx, k8sClient, playground, inferenceapi.PlaygroundAvailable, "PlaygroundReady", metav1.ConditionTrue)
207+
},
208+
},
209+
},
210+
}),
158211
)
159212
})

0 commit comments

Comments
 (0)