Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
bin/
app.log
117 changes: 117 additions & 0 deletions cli/api/api_client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
package cli

import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)

type APIClient struct {
BaseURL string
}

// Make new API client
func NewAPIClient(baseURL string) *APIClient{
return &APIClient{BaseURL: baseURL}
}

func (c *APIClient) SubmitJob(script string, compute string) (string, error) {
payload := map[string]string{
"script": script,
"compute": compute,
}

bodyBytes, err := json.Marshal(payload)
if err != nil {
return "", err
}

url := c.BaseURL + "/jobs"
resp, err := http.Post(url, "application.json", bytes.NewBuffer(bodyBytes))

if err != nil {
return "", err
}
defer resp.Body.Close()

respBody, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}

return string(respBody), nil
}

func (c *APIClient) GetJobStatus(jobID string) (string, error){
url := fmt.Sprintf("%s/jobs/status?id=%s", c.BaseURL, jobID)

resp, err := http.Get(url)
if err != nil {
return "", err
}

defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}

if resp.StatusCode != http.StatusOK{
return "", fmt.Errorf("server return %s: %s", resp.Status, body)
}

return string(body), nil
}

func (c *APIClient) GetSupervisors(active bool) (string, error){
url := c.BaseURL + "/supervisors"
if active {
url += "?active=true"
}

resp, err := http.Get(url)
if err != nil {
return "", err
}

defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
}

func (c * APIClient) GetAllSupervisorsStatuses() (string, error) {
url := c.BaseURL + "/supervisors/status"

resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
}

func (c * APIClient) GetSupervisorStatusByID(id string) (string, error) {
url := fmt.Sprintf("%s/supervisors/status/%s", c.BaseURL, id)
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()

body, err := io.ReadAll(resp.Body)
if err != nil {
return "", err
}
return string(body), nil
}
2 changes: 1 addition & 1 deletion cli/cmd/job_cancel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package cmd

import (
"testing"
"fmt"
// "fmt"
)


Expand Down
80 changes: 48 additions & 32 deletions cli/cmd/job_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,62 @@ package cmd

import (
"fmt"
"os"
"text/tabwriter"
"time"
// "os"
// "text/tabwriter"
// "time"
"mist/cli/api"
)

type JobStatusCmd struct {
ID string `arg:"" help:"The ID of the job to check the status for"`
}

func (j *JobStatusCmd) Run() error {
// Mock data - pull from API in real implementation
jobs := []Job{{
ID: "ID:1",
Name: "docker_container_name_1",
Status: "Running",
GPUType: "AMD",
CreatedAt: time.Now(),
}}

job, err := findJobByID(jobs, j.ID)
// Mock data implementatino
// jobs := []Job{{
// ID: "ID:1",
// Name: "docker_container_name_1",
// Status: "Running",
// GPUType: "AMD",
// CreatedAt: time.Now(),
// }}

// job, err := findJobByID(jobs, j.ID)
// if err != nil {
// fmt.Printf("%s does not exist in your jobs.\n", j.ID)
// fmt.Printf("Use the command \"job list\" for your list of jobs.")
// return nil
// }

// println("Checking status for job ID:", j.ID)
// w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
// fmt.Fprintln(w, "Job ID\tName\tStatus\tGPU Type\tCreated At")
// fmt.Fprintln(w, "--------------------------------------------------------------")

// fmt.Fprintf(
// w,
// "%s\t%s\t%s\t%s\t%s\n",
// job.ID,
// job.Name,
// job.Status,
// job.GPUType,
// job.CreatedAt.Format(time.RFC1123),
// )
// w.Flush()
// return nil

client := cli.NewAPIClient("http://localhost:3000")

fmt.Println("Checking status for job ID: ", j.ID)
status, err := client.GetJobStatus(j.ID)

if err != nil {
fmt.Printf("%s does not exist in your jobs.\n", j.ID)
fmt.Printf("Use the command \"job list\" for your list of jobs.")
return nil
fmt.Println("Error fetching job status:", err)
return nil
}

println("Checking status for job ID:", j.ID)
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Fprintln(w, "Job ID\tName\tStatus\tGPU Type\tCreated At")
fmt.Fprintln(w, "--------------------------------------------------------------")

fmt.Fprintf(
w,
"%s\t%s\t%s\t%s\t%s\n",
job.ID,
job.Name,
job.Status,
job.GPUType,
job.CreatedAt.Format(time.RFC1123),
)
w.Flush()
return nil
fmt.Println("Server response:")
fmt.Println(status)

return nil
}
20 changes: 17 additions & 3 deletions cli/cmd/job_submit.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"os"
"strings"
"mist/cli/api"
)

type JobSubmitCmd struct {
Expand Down Expand Up @@ -47,10 +48,23 @@ func (j *JobSubmitCmd) Run() error {
if input == "y" || input == "yes" {
fmt.Println("Confirmed, proceeding...")

// Using API Client
client := cli.NewAPIClient("http://localhost:3000")
resp, err := client.SubmitJob(j.Script, j.Compute)
if err != nil {
fmt.Println("Error submitting job:", err)
return err
}


// CONFIRMED LOGIC
fmt.Println("Submitting job with script:", j.Script)
fmt.Println("Requested GPU type:", j.Compute)
println("Job submitted successfully with ID: job_12345")
// fmt.Println("Submitting job with script:", j.Script)
// fmt.Println("Requested GPU type:", j.Compute)
// println("Job submitted successfully with ID: job_12345")

// CONFIRMED JOB SUBMISSION
fmt.Println("Job submitted successfully!!!")
fmt.Println("Server response:", resp)

return nil

Expand Down
1 change: 1 addition & 0 deletions cli/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type CLI struct {
// Config ConfigCmd `cmd:"" help:"Configuration commands"`
Help HelpCmd `cmd:"" help:"Show help information"`
Config ConfigCmd `cmd:"" help: "Display Cluster Configuration"`
Supervisor SupervisorCmd `cmd:"" help:"Supervisor commands"`
}

func Main() {
Expand Down
10 changes: 10 additions & 0 deletions cli/cmd/supervisor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package cmd

type SupervisorCmd struct {
List SupervisorListCmd `cmd:"" help:"List all supervisors"`
Status SupervisorStatusCmd `cmd:"" help:"View supervisor status"`
}

func(s *SupervisorCmd) Run() error{
return nil
}
26 changes: 26 additions & 0 deletions cli/cmd/supervisor_list.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package cmd
import (
// "encoding/json"
"fmt"
// "strings"
"mist/cli/api"
)

type SupervisorListCmd struct {
// --active flag
Active bool "help: Show only active supervisors"
}

func (s *SupervisorListCmd) Run() error {
client := cli.NewAPIClient("http://localhost:3000")

raw, err := client.GetSupervisors(s.Active)
if err != nil {
fmt.Println("Error: ", err)
return nil
}

fmt.Println("Supervisor List Response: ", raw)
return nil
// We can pretty this up later, hence raw
}
19 changes: 19 additions & 0 deletions cli/cmd/supervisor_list_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package cmd

import (
"testing"
// "fmt"
)

// Right now supervisors should be empty! Add more in the future.
func TestSupervisorDoesNotExist(t *testing.T){
cmd := &SupervisorListCmd{Active: true}
output := CaptureOutput( func() {
_ = cmd.Run()
})

want := "Supervisor List Response: {\"active_only\":true,\"count\":0,\"supervisors\":null}\n\n"
if !contains(output, want){
t.Errorf("expected output to contain %q, got %q", want, output)
}
}
37 changes: 37 additions & 0 deletions cli/cmd/supervisor_status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package cmd
import (
"fmt"
"mist/cli/api"
// "strings"
)

// Support both /status and /status/ID endpoints
type SupervisorStatusCmd struct {
ID string `arg:"" optional help: "Supervisor ID (optional)"`
}

func(s *SupervisorStatusCmd) Run() error {
client := cli.NewAPIClient("http://localhost:3000")

if s.ID == "" {
raw, err := client.GetAllSupervisorsStatuses()
if err != nil {
fmt.Println("Error: ", err)
return nil
}

fmt.Println("All Supervisor Status Response: ", raw)
return nil
}

raw, err := client.GetSupervisorStatusByID(s.ID)
if err != nil {
fmt.Println("Error: ", err)
return nil
}

fmt.Println("Supervisor Status by ID Response: ", raw)
return nil

// We can pretty this up later, most likely to JSON format, hence raw
}
Loading