Skip to content

Commit

Permalink
update status for model
Browse files Browse the repository at this point in the history
  • Loading branch information
ukclivecox committed Dec 10, 2021
1 parent 1703863 commit d127e19
Show file tree
Hide file tree
Showing 26 changed files with 1,177 additions and 740 deletions.
3 changes: 3 additions & 0 deletions operator/apis/mlops/v1alpha1/model_types.go
Expand Up @@ -113,6 +113,9 @@ func (m Model) AsModelDetails() (*scheduler.ModelDetails, error) {
Requirements: m.Spec.Requirements,
Server: m.Spec.Server,
LogPayloads: m.Spec.Logger != nil, // Simple boolean switch at present
KubernetesConfig: &scheduler.KubernetesConfig{
Namespace: m.Namespace,
},
}
// Add storage secret if specified
if m.Spec.SecretName != nil {
Expand Down
10 changes: 6 additions & 4 deletions operator/apis/mlops/v1alpha1/model_types_test.go
Expand Up @@ -31,6 +31,7 @@ func TestAsModelDetails(t *testing.T) {
model: &Model{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "default",
ResourceVersion: "1",
},
Spec: ModelSpec{
Expand All @@ -40,10 +41,11 @@ func TestAsModelDetails(t *testing.T) {
},
},
modelDetails: &scheduler.ModelDetails{
Name: "foo",
Version: "1",
Uri: "gs://test",
Replicas: 1,
Name: "foo",
Version: "1",
Uri: "gs://test",
Replicas: 1,
KubernetesConfig: &scheduler.KubernetesConfig{Namespace: "default"},
},
},
{
Expand Down
4 changes: 2 additions & 2 deletions operator/apis/mlops/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

49 changes: 49 additions & 0 deletions operator/config/crd/bases/mlops.seldon.io_models.yaml
Expand Up @@ -95,6 +95,55 @@ spec:
type: object
status:
description: ModelStatus defines the observed state of Model
properties:
annotations:
additionalProperties:
type: string
description: Annotations is additional Status fields for the Resource
to save some additional State as well as convey more information
to the user. This is roughly akin to Annotations on any k8s resource,
just the reconciler conveying richer information outwards.
type: object
conditions:
description: Conditions the latest available observations of a resource's
current state.
items:
description: 'Condition defines a readiness condition for a Knative
resource. See: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties'
properties:
lastTransitionTime:
description: LastTransitionTime is the last time the condition
transitioned from one status to another. We use VolatileTime
in place of metav1.Time to exclude this from creating equality.Semantic
differences (all other things held constant).
type: string
message:
description: A human readable message indicating details about
the transition.
type: string
reason:
description: The reason for the condition's last transition.
type: string
severity:
description: Severity with which to treat failures of this type
of condition. When this is not specified, it defaults to Error.
type: string
status:
description: Status of the condition, one of True, False, Unknown.
type: string
type:
description: Type of condition.
type: string
required:
- status
- type
type: object
type: array
observedGeneration:
description: ObservedGeneration is the 'Generation' of the Service
that was last processed by the controller.
format: int64
type: integer
type: object
type: object
served: true
Expand Down
12 changes: 6 additions & 6 deletions operator/config/crd/bases/mlops.seldon.io_pipelines.yaml
Expand Up @@ -47,20 +47,20 @@ spec:
description: Condition specification to satisfy for this step
to be run
type: string
name:
description: Name of the step
type: string
previous:
inputs:
description: Previous step to receive data from
items:
type: string
type: array
ref:
model:
description: Reference to model artifact
type: string
name:
description: Name of the step
type: string
required:
- model
- name
- ref
type: object
type: array
required:
Expand Down
33 changes: 33 additions & 0 deletions operator/config/rbac/role.yaml
Expand Up @@ -6,6 +6,13 @@ metadata:
creationTimestamp: null
name: manager-role
rules:
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
- apiGroups:
- mlops.seldon.io
resources:
Expand All @@ -32,6 +39,32 @@ rules:
- get
- patch
- update
- apiGroups:
- mlops.seldon.io
resources:
- models
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- mlops.seldon.io
resources:
- models/finalizers
verbs:
- update
- apiGroups:
- mlops.seldon.io
resources:
- models/status
verbs:
- get
- patch
- update
- apiGroups:
- mlops.seldon.io
resources:
Expand Down
1 change: 1 addition & 0 deletions operator/controllers/mlops/explainer_controller.go
Expand Up @@ -36,6 +36,7 @@ type ExplainerReconciler struct {
//+kubebuilder:rbac:groups=mlops.seldon.io,resources=explainers,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=mlops.seldon.io,resources=explainers/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=mlops.seldon.io,resources=explainers/finalizers,verbs=update
//+kubebuilder:rbac:groups="",resources=events,verbs=create;patch

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
Expand Down
42 changes: 39 additions & 3 deletions operator/controllers/mlops/model_controller.go
Expand Up @@ -18,6 +18,10 @@ package mlops

import (
"context"
"k8s.io/apimachinery/pkg/api/equality"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/tools/record"
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

"github.com/seldonio/seldon-core/operatorv2/pkg/utils"
Expand All @@ -37,14 +41,14 @@ type ModelReconciler struct {
client.Client
Scheme *runtime.Scheme
Scheduler *scheduler.SchedulerClient
Recorder record.EventRecorder
}

//+kubebuilder:rbac:groups=mlops.seldon.io,resources=models,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=mlops.seldon.io,resources=models/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=mlops.seldon.io,resources=models/finalizers,verbs=update
//
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.10.0/pkg/reconcile
//+kubebuilder:rbac:groups="",resources=events,verbs=create;patch

func (r *ModelReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := log.FromContext(ctx).WithName("Reconcile")

Expand Down Expand Up @@ -97,9 +101,41 @@ func (r *ModelReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl
return ctrl.Result{}, nil
}

func (r *ModelReconciler) updateStatus(model *mlopsv1alpha1.Model) error {
existingModel := &mlopsv1alpha1.Model{}
namespacedName := types.NamespacedName{Name: model.Name, Namespace: model.Namespace}
if err := r.Get(context.TODO(), namespacedName, existingModel); err != nil {
return err
}
//ready := modelReady(existingModel.Status)
if equality.Semantic.DeepEqual(existingModel.Status, model.Status) {
// Do nothing
} else if err := r.Status().Update(context.TODO(), model); err != nil {
//r.l.Error(err, "Failed to update InferenceService status", "InferenceService", model.Name)
//r.Recorder.Eventf(model, v1.EventTypeWarning, "UpdateFailed",
// "Failed to update status for InferenceService %q: %v", desiredService.Name, err)
return err
} else {
// If there was a difference and there was no error.
//isReady := modelReady(model.Status)
//if ready && !isReady { // Moved to NotReady State
// r.Recorder.Eventf(desiredService, v1.EventTypeWarning, string(InferenceServiceNotReadyState),
// fmt.Sprintf("InferenceService [%v] is no longer Ready", desiredService.GetName()))
//} else if !wasReady && isReady { // Moved to Ready State
// r.Recorder.Eventf(desiredService, v1.EventTypeNormal, string(InferenceServiceReadyState),
// fmt.Sprintf("InferenceService [%v] is Ready", desiredService.GetName()))
//}
}
return nil
}

// SetupWithManager sets up the controller with the Manager.
// Uses https://github.com/kubernetes-sigs/kubebuilder/issues/618#issuecomment-698018831
// This ensures we don't reconcile when just the status is updated by checking if generation changed
func (r *ModelReconciler) SetupWithManager(mgr ctrl.Manager) error {
pred := predicate.GenerationChangedPredicate{}
return ctrl.NewControllerManagedBy(mgr).
For(&mlopsv1alpha1.Model{}).
WithEventFilter(pred).
Complete(r)
}
1 change: 1 addition & 0 deletions operator/controllers/mlops/pipeline_controller.go
Expand Up @@ -36,6 +36,7 @@ type PipelineReconciler struct {
//+kubebuilder:rbac:groups=mlops.seldon.io,resources=pipelines,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=mlops.seldon.io,resources=pipelines/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=mlops.seldon.io,resources=pipelines/finalizers,verbs=update
//+kubebuilder:rbac:groups="",resources=events,verbs=create;patch

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
Expand Down
1 change: 1 addition & 0 deletions operator/controllers/mlops/server_controller.go
Expand Up @@ -36,6 +36,7 @@ type ServerReconciler struct {
//+kubebuilder:rbac:groups=mlops.seldon.io,resources=servers,verbs=get;list;watch;create;update;patch;delete
//+kubebuilder:rbac:groups=mlops.seldon.io,resources=servers/status,verbs=get;update;patch
//+kubebuilder:rbac:groups=mlops.seldon.io,resources=servers/finalizers,verbs=update
//+kubebuilder:rbac:groups="",resources=events,verbs=create;patch

// Reconcile is part of the main kubernetes reconciliation loop which aims to
// move the current state of the cluster closer to the desired state.
Expand Down
8 changes: 7 additions & 1 deletion operator/main.go
Expand Up @@ -19,11 +19,13 @@ package main
import (
"context"
"flag"
"k8s.io/client-go/tools/record"
"os"

mlopsv1alpha1 "github.com/seldonio/seldon-core/operatorv2/apis/mlops/v1alpha1"
mlopscontrollers "github.com/seldonio/seldon-core/operatorv2/controllers/mlops"
"github.com/seldonio/seldon-core/operatorv2/scheduler"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
Expand Down Expand Up @@ -81,8 +83,10 @@ func main() {
setupLog.Error(err, "unable to start manager")
os.Exit(1)
}
eventBroadcaster := record.NewBroadcaster()

schedulerClient := scheduler.NewSchedulerClient(logger)
schedulerClient := scheduler.NewSchedulerClient(logger, mgr.GetClient(), eventBroadcaster.NewRecorder(
mgr.GetScheme(), v1.EventSource{Component: "scheduler-client"}))
err = schedulerClient.ConnectToScheduler(schedulerHost, schedulerPort)
if err != nil {
setupLog.Error(err, "unable to connect to scheduler")
Expand All @@ -100,6 +104,8 @@ func main() {
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Scheduler: schedulerClient,
Recorder: eventBroadcaster.NewRecorder(
mgr.GetScheme(), v1.EventSource{Component: "model-controller"}),
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Model")
os.Exit(1)
Expand Down

0 comments on commit d127e19

Please sign in to comment.