Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(ws): update JSON payload for listing workspaces #134

Merged
87 changes: 63 additions & 24 deletions workspaces/backend/api/workspaces_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,13 @@ var _ = Describe("Workspaces Handler", func() {
workspace3 := &kubefloworgv1beta1.Workspace{}
Expect(k8sClient.Get(ctx, workspaceKey3, workspace3)).To(Succeed())

workspaceKind := &kubefloworgv1beta1.WorkspaceKind{}
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: workspaceKindName}, workspaceKind)).To(Succeed())

expectedWorkspaces := []models.WorkspaceModel{
models.NewWorkspaceModelFromWorkspace(workspace1),
models.NewWorkspaceModelFromWorkspace(workspace2),
models.NewWorkspaceModelFromWorkspace(workspace3),
repositories.NewWorkspaceModelFromWorkspace(workspace1, workspaceKind),
repositories.NewWorkspaceModelFromWorkspace(workspace2, workspaceKind),
repositories.NewWorkspaceModelFromWorkspace(workspace3, workspaceKind),
}
Expect(workspaces).To(ConsistOf(expectedWorkspaces))

Expand Down Expand Up @@ -255,9 +258,12 @@ var _ = Describe("Workspaces Handler", func() {
workspace2 := &kubefloworgv1beta1.Workspace{}
Expect(k8sClient.Get(ctx, workspaceKey2, workspace2)).To(Succeed())

workspaceKind := &kubefloworgv1beta1.WorkspaceKind{}
Expect(k8sClient.Get(ctx, types.NamespacedName{Name: workspaceKindName}, workspaceKind)).To(Succeed())

expectedWorkspaces := []models.WorkspaceModel{
models.NewWorkspaceModelFromWorkspace(workspace1),
models.NewWorkspaceModelFromWorkspace(workspace2),
repositories.NewWorkspaceModelFromWorkspace(workspace1, workspaceKind),
repositories.NewWorkspaceModelFromWorkspace(workspace2, workspaceKind),
}
Expect(workspaces).To(ConsistOf(expectedWorkspaces))

Expand Down Expand Up @@ -379,26 +385,60 @@ var _ = Describe("Workspaces Handler", func() {
By("creating the workspace via the API")
workspaceName := "dora"
workspaceModel := models.WorkspaceModel{
Name: workspaceName,
Namespace: namespaceNameCrud,
Paused: false,
Name: workspaceName,
Namespace: namespaceNameCrud,
WorkspaceKind: models.WorkspaceKind{
Name: workspaceKindName,
Type: "POD_TEMPLATE",
},
DeferUpdates: false,
Kind: "jupyterlab",
ImageConfig: "jupyterlab_scipy_190",
PodConfig: "tiny_cpu",
HomeVolume: "workspace-home-bella",
DataVolumes: []models.DataVolumeModel{
{
PvcName: "workspace-data-bella",
MountPath: "/data/my-data",
ReadOnly: false,
Paused: false,
PausedTime: 0,
State: "",
StateMessage: "",
PodTemplate: models.PodTemplate{
PodMetadata: &models.PodMetadata{
Labels: map[string]string{
"app": "dora",
},
Annotations: map[string]string{
"app": "dora",
},
},
Volumes: &models.Volumes{
Home: &models.DataVolumeModel{
PvcName: "my-data-pvc",
MountPath: "/home/jovyan",
ReadOnly: false,
},
Data: []models.DataVolumeModel{
{
PvcName: "my-data-pvc",
MountPath: "/data",
ReadOnly: false,
},
},
},
ImageConfig: &models.ImageConfig{
Current: "WorkspaceKind",
Desired: "", // Status is coming with empty value
RedirectChain: []*models.RedirectChain{},
},
PodConfig: &models.PodConfig{
Current: "WorkspaceKind",
Desired: "WorkspaceKind",
RedirectChain: []*models.RedirectChain{},
},
},
Labels: map[string]string{
"app": "jupyter",
},
Annotations: map[string]string{
"environment": "dev",
Activity: models.Activity{
LastActivity: 0,
LastUpdate: 0,
LastProbe: &models.Probe{
StartTimeMs: 0,
EndTimeMs: 0,
Result: "default_result",
Message: "default_message",
},
},
}

Expand Down Expand Up @@ -461,8 +501,7 @@ var _ = Describe("Workspaces Handler", func() {
err = json.Unmarshal(body, &response)
Expect(err).NotTo(HaveOccurred(), "Error unmarshalling response JSON")

// remove auto generated fields from comparison
response.Data.LastActivity = ""
response.Data.Activity.LastActivity = 0

By("checking if the retrieved workspace matches the expected workspace")
retrievedWorkspaceJSON, err := json.Marshal(response.Data)
Expand Down
108 changes: 59 additions & 49 deletions workspaces/backend/internal/models/workspaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,61 +16,71 @@ limitations under the License.

package models

import (
"time"
type WorkspaceModel struct {
Name string `json:"name"`
Namespace string `json:"namespace"`
WorkspaceKind WorkspaceKind `json:"workspace_kind"`
DeferUpdates bool `json:"defer_updates"`
Paused bool `json:"paused"`
PausedTime int64 `json:"paused_time"`
State string `json:"state"`
StateMessage string `json:"state_message"`
PodTemplate PodTemplate `json:"pod_template"`
Activity Activity `json:"activity"`
}
type PodTemplate struct {
PodMetadata *PodMetadata `json:"pod_metadata"`
Volumes *Volumes `json:"volumes"`
ImageConfig *ImageConfig `json:"image_config"`
PodConfig *PodConfig `json:"pod_config"`
}

type PodMetadata struct {
Labels map[string]string `json:"labels"`
Annotations map[string]string `json:"annotations"`
}
type Volumes struct {
Home *DataVolumeModel `json:"home"`
Data []DataVolumeModel `json:"data"`
}

kubefloworgv1beta1 "github.com/kubeflow/notebooks/workspaces/controller/api/v1beta1"
)
type ImageConfig struct {
Current string `json:"current"`
Desired string `json:"desired"`
RedirectChain []*RedirectChain `json:"redirect_chain"`
}

type WorkspaceModel struct {
Namespace string `json:"namespace"`
Name string `json:"name"`
Paused bool `json:"paused"`
DeferUpdates bool `json:"defer_updates"`
Kind string `json:"kind"`
ImageConfig string `json:"image_config"`
PodConfig string `json:"pod_config"`
HomeVolume string `json:"home_volume"`
DataVolumes []DataVolumeModel `json:"data_volumes"`
Labels map[string]string `json:"labels,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
Status string `json:"status"`
LastActivity string `json:"last_activity"`
type PodConfig struct {
Current string `json:"current"`
Desired string `json:"desired"`
RedirectChain []*RedirectChain `json:"redirect_chain"`
}

type RedirectChain struct {
Source string `json:"source"`
Target string `json:"target"`
}

type Activity struct {
LastActivity int64 `json:"last_activity"` // Unix Epoch time
LastUpdate int64 `json:"last_update"` // Unix Epoch time
LastProbe *Probe `json:"last_probe"`
}

type Probe struct {
StartTimeMs int64 `json:"start_time_ms"` // Unix Epoch time in milliseconds
EndTimeMs int64 `json:"end_time_ms"` // Unix Epoch time in milliseconds
Result string `json:"result"`
Message string `json:"message"`
}

type WorkspaceKind struct {
Name string `json:"name"`
Type string `json:"type"`
}

type DataVolumeModel struct {
PvcName string `json:"pvc_name"`
MountPath string `json:"mount_path"`
ReadOnly bool `json:"read_only"`
}

func NewWorkspaceModelFromWorkspace(item *kubefloworgv1beta1.Workspace) WorkspaceModel {
t := time.Unix(item.Status.Activity.LastActivity, 0)
formattedLastActivity := t.Format("2006-01-02 15:04:05 MST")

dataVolumes := make([]DataVolumeModel, len(item.Spec.PodTemplate.Volumes.Data))
for i, volume := range item.Spec.PodTemplate.Volumes.Data {
dataVolumes[i] = DataVolumeModel{
PvcName: volume.PVCName,
MountPath: volume.MountPath,
ReadOnly: *volume.ReadOnly,
}
}
// TODO: review all fields
workspaceModel := WorkspaceModel{
Namespace: item.Namespace,
Name: item.ObjectMeta.Name,
Paused: *item.Spec.Paused,
DeferUpdates: *item.Spec.DeferUpdates,
Kind: item.Spec.Kind,
ImageConfig: item.Spec.PodTemplate.Options.ImageConfig,
PodConfig: item.Spec.PodTemplate.Options.PodConfig,
HomeVolume: *item.Spec.PodTemplate.Volumes.Home,
DataVolumes: dataVolumes,
Labels: item.ObjectMeta.Labels,
Annotations: item.ObjectMeta.Annotations,
Status: string(item.Status.State),
LastActivity: formattedLastActivity,
}
return workspaceModel
}
Loading
Loading