Skip to content
This repository has been archived by the owner on Aug 28, 2024. It is now read-only.

Commit

Permalink
Refactor to match current design doc (#109)
Browse files Browse the repository at this point in the history
* Refactor cloud switch conditions into interfaces within the `cloud`
pkg
* Update all bucket URLs to use hashes
* Add support for `params.json` (fixes #114)

---------

Co-authored-by: Sam Stoelinga <[email protected]>
  • Loading branch information
nstogner and samos123 authored Jul 21, 2023
1 parent f7901d5 commit a94bc63
Show file tree
Hide file tree
Showing 69 changed files with 1,265 additions and 792 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,8 @@ dist/

# envsubst rendered templates
gcpmanager-skaffold.yaml

/controllermanager
/gcpmanager
gcpmanager-dependencies.yaml
skaffold-dependencies.sh
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

# Image URL to use all building/pushing image targets
IMG ?= docker.io/substratusai/controller-manager:v0.4.2-alpha
IMG ?= docker.io/substratusai/controller-manager:v0.5.0-alpha
# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.26.1

Expand Down Expand Up @@ -114,8 +114,8 @@ dev: manifests kustomize install-crds
go run ./cmd/controllermanager/main.go

.PHONY: run
run: manifests generate fmt vet ## Run a controller from your host.
go run ./cmd/controllermanager/main.go
run: ## Run a controller from your host.
go run ./cmd/controllermanager/main.go --config-dump-path=/tmp/substratus-config.yaml

# If you wish built the manager image targeting other platforms you can use the --platform flag.
# (i.e. docker build --platform linux/arm64 ). However, you must enable docker buildKit for it.
Expand Down
4 changes: 4 additions & 0 deletions api/v1/common_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,7 @@ type GPUResources struct {
// Count is the number of GPUs.
Count int64 `json:"count,omitempty"`
}

type ArtifactsStatus struct {
URL string `json:"url,omitempty"`
}
19 changes: 12 additions & 7 deletions api/v1/dataset_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ type DatasetSpec struct {
// Command to run in the container.
Command []string `json:"command,omitempty"`

// Filename is the name of the file when it is downloaded.
Filename string `json:"filename"`

// Image that contains dataset loading code and dependencies.
Image Image `json:"image"`

Expand All @@ -23,6 +20,10 @@ type DatasetSpec struct {
Params map[string]intstr.IntOrString `json:"params,omitempty"`
}

func (d *Dataset) GetParams() map[string]intstr.IntOrString {
return d.Spec.Params
}

func (d *Dataset) GetImage() *Image {
return &d.Spec.Image
}
Expand All @@ -39,6 +40,10 @@ func (d *Dataset) SetStatusReady(r bool) {
d.Status.Ready = r
}

func (d *Dataset) GetStatusArtifacts() ArtifactsStatus {
return d.Status.Artifacts
}

func (d *Dataset) SetStatusImage(us ImageStatus) {
d.Status.Image = us
}
Expand All @@ -56,11 +61,11 @@ type DatasetStatus struct {
// Conditions is the list of conditions that describe the current state of the Dataset.
Conditions []metav1.Condition `json:"conditions,omitempty"`

// URL of the loaded data.
URL string `json:"url,omitempty"`
// Artifacts status.
Artifacts ArtifactsStatus `json:"artifacts,omitempty"`

// Upload contains details the controller returns from a requested signed upload URL.
Image ImageStatus `json:"upload,omitempty"`
// Image contains the status of the image. Upload URL is reported here.
Image ImageStatus `json:"image,omitempty"`
}

//+kubebuilder:resource:categories=ai
Expand Down
16 changes: 12 additions & 4 deletions api/v1/model_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ type ModelSpec struct {
Params map[string]intstr.IntOrString `json:"params,omitempty"`
}

func (m *Model) GetParams() map[string]intstr.IntOrString {
return m.Spec.Params
}

func (m *Model) GetImage() *Image {
return &m.Spec.Image
}
Expand All @@ -44,6 +48,10 @@ func (m *Model) SetStatusReady(r bool) {
m.Status.Ready = r
}

func (m *Model) GetStatusArtifacts() ArtifactsStatus {
return m.Status.Artifacts
}

func (m *Model) SetStatusImage(us ImageStatus) {
m.Status.Image = us
}
Expand All @@ -61,11 +69,11 @@ type ModelStatus struct {
// Conditions is the list of conditions that describe the current state of the Model.
Conditions []metav1.Condition `json:"conditions,omitempty"`

// URL of model artifacts.
URL string `json:"url,omitempty"`
// Artifacts status.
Artifacts ArtifactsStatus `json:"artifacts,omitempty"`

// Upload contains details the controller returns from a requested signed upload URL.
Image ImageStatus `json:"upload,omitempty"`
// Image contains the status of the image. Upload URL is reported here.
Image ImageStatus `json:"image,omitempty"`
}

//+kubebuilder:resource:categories=ai
Expand Down
8 changes: 6 additions & 2 deletions api/v1/notebook_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ type NotebookSpec struct {
Params map[string]intstr.IntOrString `json:"params,omitempty"`
}

func (n *Notebook) GetParams() map[string]intstr.IntOrString {
return n.Spec.Params
}

func (n *Notebook) GetImage() *Image {
return &n.Spec.Image
}
Expand Down Expand Up @@ -62,8 +66,8 @@ type NotebookStatus struct {
// Conditions is the list of conditions that describe the current state of the Notebook.
Conditions []metav1.Condition `json:"conditions,omitempty"`

// Upload contains details the controller returns from a requested signed upload URL.
Image ImageStatus `json:"upload,omitempty"`
// Image contains the status of the image. Upload URL is reported here.
Image ImageStatus `json:"image,omitempty"`
}

//+kubebuilder:resource:categories=ai
Expand Down
4 changes: 2 additions & 2 deletions api/v1/server_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ type ServerStatus struct {
// Conditions is the list of conditions that describe the current state of the Server.
Conditions []metav1.Condition `json:"conditions,omitempty"`

// Upload contains details the controller returns from a requested signed upload URL.
Image ImageStatus `json:"upload,omitempty"`
// Image contains the status of the image. Upload URL is reported here.
Image ImageStatus `json:"image,omitempty"`
}

//+kubebuilder:resource:categories=ai
Expand Down
17 changes: 17 additions & 0 deletions api/v1/zz_generated.deepcopy.go

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

94 changes: 66 additions & 28 deletions cmd/controllermanager/main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
package main

import (
"bytes"
"context"
"flag"
"io/ioutil"
"os"

// Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
// to ensure that exec-entrypoint and run can make use of them.
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"gopkg.in/yaml.v2"
_ "k8s.io/client-go/plugin/pkg/client/auth"

"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -40,6 +44,8 @@ func main() {
var metricsAddr string
var enableLeaderElection bool
var probeAddr string
var configDumpPath string
flag.StringVar(&configDumpPath, "config-dump-path", "", "The filepath to dump the running config to.")
flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.")
flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
flag.BoolVar(&enableLeaderElection, "leader-elect", false,
Expand Down Expand Up @@ -79,12 +85,21 @@ func main() {

// NOTE: NewCloudContext() will look up environment variables (intended for local development)
// and if they are not specified, it will try to use metadata servers on the cloud.
cloudContext, err := cloud.NewContext()
cld, err := cloud.New(context.Background())
if err != nil {
setupLog.Error(err, "unable to determine cloud context")
setupLog.Error(err, "unable to determine cloud configuration")
os.Exit(1)
}

if configDumpPath != "" {
if err := dumpConfigToFile(configDumpPath, struct {
Cloud cloud.Cloud
}{Cloud: cld}); err != nil {
setupLog.Error(err, "unable to dump config to path")
os.Exit(1)
}
}

// TODO(any): setup TLS
conn, err := grpc.Dial(
// "localhost:10080",
Expand All @@ -100,15 +115,19 @@ func main() {
gc := sci.NewControllerClient(conn)

if err = (&controller.ModelReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
CloudContext: cloudContext,
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Cloud: cld,
ContainerImageReconciler: &controller.ContainerImageReconciler{
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
CloudContext: cloudContext,
CloudManagerGrpcClient: gc,
Kind: "Model",
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
Cloud: cld,
SCI: gc,
Kind: "Model",
},
ParamsReconciler: &controller.ParamsReconciler{
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
},
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Model")
Expand All @@ -118,11 +137,11 @@ func main() {
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
ContainerImageReconciler: &controller.ContainerImageReconciler{
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
CloudContext: cloudContext,
CloudManagerGrpcClient: gc,
Kind: "Server",
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
Cloud: cld,
SCI: gc,
Kind: "Server",
},
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Server")
Expand All @@ -133,26 +152,34 @@ func main() {
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
ContainerImageReconciler: &controller.ContainerImageReconciler{
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
CloudContext: cloudContext,
CloudManagerGrpcClient: gc,
Kind: "Notebook",
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
Cloud: cld,
SCI: gc,
Kind: "Notebook",
},
ParamsReconciler: &controller.ParamsReconciler{
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
},
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Notebook")
os.Exit(1)
}
if err = (&controller.DatasetReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
CloudContext: cloudContext,
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
Cloud: cld,
ContainerImageReconciler: &controller.ContainerImageReconciler{
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
CloudContext: cloudContext,
CloudManagerGrpcClient: gc,
Kind: "Dataset",
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
Cloud: cld,
SCI: gc,
Kind: "Dataset",
},
ParamsReconciler: &controller.ParamsReconciler{
Scheme: mgr.GetScheme(),
Client: mgr.GetClient(),
},
}).SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Dataset")
Expand All @@ -175,3 +202,14 @@ func main() {
os.Exit(1)
}
}

func dumpConfigToFile(path string, config interface{}) error {
var buf bytes.Buffer
if err := yaml.NewEncoder(&buf).Encode(config); err != nil {
return err
}
if err := ioutil.WriteFile(path, buf.Bytes(), 0644); err != nil {
return err
}
return nil
}
17 changes: 10 additions & 7 deletions cmd/gcpmanager/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,20 @@ package main_test
// $URL

// the following function was successfully used to exercise gcpmanager.Server.CreateSignedURL()
// func invokeManually(s *gcpmanager.Server) {
// func invokeManually(storageClient *storage.Client) {
// payload := sci.CreateSignedURLRequest{
// BucketName: "substratus-ai-001-substratus-notebooks",
// ObjectName: "notebook.tar.gz",
// ExpirationSeconds: 300,
// }
// serv := gcpmanager.Server{
// StorageClient: storageClient,
// }
// fmt.Println("calling CreateSignedURL with payload:")

// resp, err := s.CreateSignedURL(context.Background(), &payload)
// if err != nil {
// log.Fatalf("failed to create signed URL: %v", err)
// }
// fmt.Printf("signed URL: %v\n", resp.Url)
// }
// resp, err := serv.CreateSignedURL(context.Background(), &payload)
// if err != nil {
// log.Fatalf("failed to create signed URL: %v", err)
// }
// fmt.Printf("signed URL: %v\n", resp.Url)
// }
Loading

0 comments on commit a94bc63

Please sign in to comment.