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

Commit

Permalink
Standalone CLI: sub (#232)
Browse files Browse the repository at this point in the history
Add a standalone CLI: `sub`

Replaces the current kubectl plugins.
  • Loading branch information
nstogner authored Oct 1, 2023
1 parent 236293f commit 9463df2
Show file tree
Hide file tree
Showing 84 changed files with 4,092 additions and 1,268 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/integration-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@ jobs:
steps:
- name: Check out repository code
uses: actions/checkout@v3
- name: Setup Go 1.21.x
uses: actions/setup-go@v4
with:
go-version: '1.21.x'
- run: make test-integration
27 changes: 6 additions & 21 deletions .goreleaser.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,9 @@ before:
release:
prerelease: "true"
builds:
- id: kubectl-applybuild
binary: kubectl-applybuild
main: ./kubectl/cmd/applybuild/
ldflags: "-X 'main.Version={{.Version}}'"
env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm64
- arm
- id: kubectl-notebook
binary: kubectl-notebook
main: ./kubectl/cmd/notebook/
- id: sub
binary: sub
main: ./cmd/sub/
ldflags: "-X 'main.Version={{.Version}}'"
env:
- CGO_ENABLED=0
Expand Down Expand Up @@ -61,13 +47,12 @@ archives:
format_overrides:
- goos: windows
format: zip
- id: kubectl-plugins
- id: sub
builds:
- kubectl-applybuild
- kubectl-notebook
- sub
format: tar.gz
name_template: >-
kubectl-plugins-
sub-
{{- .Os }}-
{{- .Arch }}
# use zip for windows archives
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Build the manager binary
FROM golang:1.19 as builder
FROM golang:1.21 as builder
ARG TARGETOS
ARG TARGETARCH

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.sci-gcp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Start from the latest go base image
FROM golang:1.20-bookworm AS builder
FROM golang:1.21-bookworm AS builder
ARG TARGETOS=linux
ARG TARGETARCH=amd64

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.sci-kind
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Start from the latest go base image
FROM golang:1.19 AS builder
FROM golang:1.21 AS builder
ARG TARGETOS=linux
ARG TARGETARCH=amd64

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ dev-down-aws: build-installer
.PHONY: dev-run-gcp
# Controller manager configuration #
dev-run-gcp: export CLOUD=gcp
dev-run-gcp: PROJECT_ID ?= $(shell gcloud config get project)
dev-run-gcp: export PROJECT_ID=$(shell gcloud config get project)
dev-run-gcp: export CLUSTER_NAME=substratus
dev-run-gcp: export CLUSTER_LOCATION=us-central1
dev-run-gcp: export PRINCIPAL=substratus@${PROJECT_ID}.iam.gserviceaccount.com
Expand Down
6 changes: 3 additions & 3 deletions api/v1/conditions.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ package v1
const (
ConditionUploaded = "Uploaded"
ConditionBuilt = "Built"
ConditionLoaded = "Loaded"
ConditionModelled = "Modelled"
ConditionDeployed = "Deployed"
ConditionComplete = "Complete"
ConditionServing = "Serving"
)

const (
Expand All @@ -20,6 +19,7 @@ const (

ReasonJobNotComplete = "JobNotComplete"
ReasonJobComplete = "JobComplete"
ReasonJobFailed = "JobFailed"
ReasonDeploymentReady = "DeploymentReady"
ReasonDeploymentNotReady = "DeploymentNotReady"
ReasonPodReady = "PodReady"
Expand Down
7 changes: 4 additions & 3 deletions api/v1/model_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ type ModelSpec struct {
// Resources are the compute resources required by the container.
Resources *Resources `json:"resources,omitempty"`

// BaseModel should be set in order to mount another model to be
// Model should be set in order to mount another model to be
// used for transfer learning.
BaseModel *ObjectRef `json:"baseModel,omitempty"`
Model *ObjectRef `json:"model,omitempty"`

// Dataset to mount for training.
TrainingDataset *ObjectRef `json:"trainingDataset,omitempty"`
Dataset *ObjectRef `json:"dataset,omitempty"`

// Parameters are passing into the model training/loading container as environment variables.
// Environment variable name will be `"PARAM_" + uppercase(key)`.
Expand All @@ -42,6 +42,7 @@ func (m *Model) GetParams() map[string]intstr.IntOrString {
func (m *Model) GetBuild() *Build {
return m.Spec.Build
}

func (m *Model) SetBuild(b *Build) {
m.Spec.Build = b
}
Expand Down
8 changes: 8 additions & 0 deletions api/v1/notebook_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ func (n *Notebook) GetParams() map[string]intstr.IntOrString {
func (n *Notebook) GetBuild() *Build {
return n.Spec.Build
}

func (n *Notebook) SetBuild(b *Build) {
n.Spec.Build = b
}
Expand Down Expand Up @@ -79,6 +80,10 @@ func (n *Notebook) GetStatusUpload() UploadStatus {
return n.Status.BuildUpload
}

func (n *Notebook) GetStatusArtifacts() ArtifactsStatus {
return n.Status.Artifacts
}

func (n *Notebook) IsSuspended() bool {
return n.Spec.Suspend != nil && *n.Spec.Suspend
}
Expand All @@ -92,6 +97,9 @@ type NotebookStatus struct {
// Conditions is the list of conditions that describe the current state of the Notebook.
Conditions []metav1.Condition `json:"conditions,omitempty"`

// Artifacts status.
Artifacts ArtifactsStatus `json:"artifacts,omitempty"`

// BuildUpload contains the status of the build context upload.
BuildUpload UploadStatus `json:"buildUpload,omitempty"`
}
Expand Down
9 changes: 5 additions & 4 deletions api/v1/zz_generated.deepcopy.go

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

8 changes: 2 additions & 6 deletions cmd/controllermanager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,14 @@ import (
"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/kubernetes"
_ "k8s.io/client-go/plugin/pkg/client/auth"

"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/kubernetes"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
_ "k8s.io/client-go/plugin/pkg/client/auth"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
Expand All @@ -26,7 +23,6 @@ import (
"github.com/substratusai/substratus/internal/cloud"
"github.com/substratusai/substratus/internal/controller"
"github.com/substratusai/substratus/internal/sci"
//+kubebuilder:scaffold:imports
)

var (
Expand Down
16 changes: 16 additions & 0 deletions cmd/sub/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package main

import (
"log"

"github.com/substratusai/substratus/internal/cli"
)

var Version = "development"

func main() {
cli.Version = Version
if err := cli.Command().Execute(); err != nil {
log.Fatal(err)
}
}
38 changes: 19 additions & 19 deletions config/crd/bases/substratus.ai_models.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,6 @@ spec:
spec:
description: Spec is the desired state of the Model.
properties:
baseModel:
description: BaseModel should be set in order to mount another model
to be used for transfer learning.
properties:
name:
description: Name of Kubernetes object.
type: string
required:
- name
type: object
build:
description: Build specifies how to build an image.
properties:
Expand Down Expand Up @@ -113,6 +103,15 @@ spec:
items:
type: string
type: array
dataset:
description: Dataset to mount for training.
properties:
name:
description: Name of Kubernetes object.
type: string
required:
- name
type: object
env:
additionalProperties:
type: string
Expand All @@ -121,6 +120,16 @@ spec:
image:
description: Image that contains model code and dependencies.
type: string
model:
description: Model should be set in order to mount another model to
be used for transfer learning.
properties:
name:
description: Name of Kubernetes object.
type: string
required:
- name
type: object
params:
additionalProperties:
anyOf:
Expand Down Expand Up @@ -161,15 +170,6 @@ spec:
format: int64
type: integer
type: object
trainingDataset:
description: Dataset to mount for training.
properties:
name:
description: Name of Kubernetes object.
type: string
required:
- name
type: object
type: object
status:
description: Status is the observed state of the Model.
Expand Down
6 changes: 6 additions & 0 deletions config/crd/bases/substratus.ai_notebooks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ spec:
status:
description: Status is the observed state of the Notebook.
properties:
artifacts:
description: Artifacts status.
properties:
url:
type: string
type: object
buildUpload:
description: BuildUpload contains the status of the build context
upload.
Expand Down
36 changes: 31 additions & 5 deletions containertools/cmd/nbwatch/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@ import (
"path/filepath"
"strings"

"k8s.io/klog/v2"

"github.com/fsnotify/fsnotify"
)

var Version = "development"

func main() {
log.SetOutput(os.Stderr)
log.Println("Starting")

if len(os.Args) == 2 && os.Args[1] == "version" {
fmt.Printf("nbwatch %s\n", Version)
os.Exit(0)
Expand All @@ -33,7 +34,31 @@ func run() error {
}
defer w.Close()

w.Add("/content/src")
const contentDir = "/content"

// NOTE: Watch is non-recursive.
log.Printf("Watching: %v", contentDir)
w.Add(contentDir)

entries, err := os.ReadDir(contentDir)
if err != nil {
return fmt.Errorf("reading dir: %w", err)
}
for _, e := range entries {
if !e.IsDir() {
continue
}

switch name := e.Name(); name {
case "data", "model", "artifacts":
default:
if !strings.HasPrefix(name, ".") {
p := filepath.Join(contentDir, name)
log.Printf("Watching: %v", p)
w.Add(p)
}
}
}

watchLoop(w)

Expand All @@ -49,7 +74,7 @@ func watchLoop(w *fsnotify.Watcher) {
if !ok { // Channel was closed (i.e. Watcher.Close() was called).
return
}
klog.Error(err)
log.Printf("error: %v", err)
// Read from Events.
case e, ok := <-w.Events:
if !ok { // Channel was closed (i.e. Watcher.Close() was called).
Expand All @@ -59,9 +84,10 @@ func watchLoop(w *fsnotify.Watcher) {
i++
path := e.Name

base := filepath.Base(path)
// Covers ".git", ".gitignore", ".gitmodules", ".gitattributes", ".ipynb_checkpoints"
// and also temporary files that Jupyter writes on save like: ".~hello.py"
if strings.HasPrefix(filepath.Base(path), ".") {
if strings.HasPrefix(base, ".") {
continue
}

Expand Down
Loading

0 comments on commit 9463df2

Please sign in to comment.