test(ws): Ensure test files exist in backend for any executed code #381
Signed-off-by: Hen Schwartz (EXT-Nokia) <hen.schwartz.ext@nokia.com>
This commit is contained in:
parent
b2bee1d04b
commit
7d23ad1682
|
|
@ -31,3 +31,10 @@ const (
|
||||||
ServiceStatusHealthy ServiceStatus = "Healthy"
|
ServiceStatusHealthy ServiceStatus = "Healthy"
|
||||||
ServiceStatusUnhealthy ServiceStatus = "Unhealthy"
|
ServiceStatusUnhealthy ServiceStatus = "Unhealthy"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func NewHealthCheck(status ServiceStatus, version string) HealthCheck {
|
||||||
|
return HealthCheck{
|
||||||
|
Status: status,
|
||||||
|
SystemInfo: SystemInfo{Version: version},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,288 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package workspacekinds_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
kubefloworgv1beta1 "github.com/kubeflow/notebooks/workspaces/controller/api/v1beta1"
|
||||||
|
. "github.com/onsi/ginkgo/v2"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/utils/ptr"
|
||||||
|
|
||||||
|
workspacekinds "github.com/kubeflow/notebooks/workspaces/backend/internal/models/workspacekinds"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWorkspaceKinds(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
RunSpecs(t, "WorkspaceKinds Suite")
|
||||||
|
}
|
||||||
|
|
||||||
|
type workspaceKindTestCase struct {
|
||||||
|
name string
|
||||||
|
workspaceKind *kubefloworgv1beta1.WorkspaceKind
|
||||||
|
expectedName string
|
||||||
|
expectedDisplayName string
|
||||||
|
expectedDescription string
|
||||||
|
expectedDeprecated bool
|
||||||
|
expectedDeprecationMsg string
|
||||||
|
expectedHidden bool
|
||||||
|
expectedIconURL string
|
||||||
|
expectedLogoURL string
|
||||||
|
expectedPodLabels map[string]string
|
||||||
|
expectedPodAnnotations map[string]string
|
||||||
|
additionalValidations func(result workspacekinds.WorkspaceKind)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = Describe("WorkspaceKind Types", func() {
|
||||||
|
Describe("NewWorkspaceKindModelFromWorkspaceKind", func() {
|
||||||
|
DescribeTable("should create WorkspaceKind models correctly",
|
||||||
|
func(tc workspaceKindTestCase) {
|
||||||
|
result := workspacekinds.NewWorkspaceKindModelFromWorkspaceKind(tc.workspaceKind)
|
||||||
|
|
||||||
|
// Basic assertions that apply to all test cases
|
||||||
|
Expect(result).ToNot(BeNil())
|
||||||
|
Expect(result.Name).To(Equal(tc.expectedName))
|
||||||
|
Expect(result.DisplayName).To(Equal(tc.expectedDisplayName))
|
||||||
|
Expect(result.Description).To(Equal(tc.expectedDescription))
|
||||||
|
Expect(result.Deprecated).To(Equal(tc.expectedDeprecated))
|
||||||
|
Expect(result.DeprecationMessage).To(Equal(tc.expectedDeprecationMsg))
|
||||||
|
Expect(result.Hidden).To(Equal(tc.expectedHidden))
|
||||||
|
Expect(result.Icon.URL).To(Equal(tc.expectedIconURL))
|
||||||
|
Expect(result.Logo.URL).To(Equal(tc.expectedLogoURL))
|
||||||
|
|
||||||
|
// Pod metadata assertions
|
||||||
|
if tc.expectedPodLabels != nil {
|
||||||
|
for key, value := range tc.expectedPodLabels {
|
||||||
|
Expect(result.PodTemplate.PodMetadata.Labels).To(HaveKeyWithValue(key, value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tc.expectedPodAnnotations != nil {
|
||||||
|
for key, value := range tc.expectedPodAnnotations {
|
||||||
|
Expect(result.PodTemplate.PodMetadata.Annotations).To(HaveKeyWithValue(key, value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run any additional custom validations
|
||||||
|
if tc.additionalValidations != nil {
|
||||||
|
tc.additionalValidations(result)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
Entry("complete WorkspaceKind with all fields", workspaceKindTestCase{
|
||||||
|
name: "complete WorkspaceKind",
|
||||||
|
workspaceKind: &kubefloworgv1beta1.WorkspaceKind{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "test-workspacekind",
|
||||||
|
Namespace: "kubeflow",
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "workspacekind",
|
||||||
|
"version": "v1",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"description": "Complete workspacekind",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: kubefloworgv1beta1.WorkspaceKindSpec{
|
||||||
|
Spawner: kubefloworgv1beta1.WorkspaceKindSpawner{
|
||||||
|
DisplayName: "Complete Workspacekind",
|
||||||
|
Description: "A complete test workspacekind with all features",
|
||||||
|
Deprecated: ptr.To(false),
|
||||||
|
Hidden: ptr.To(false),
|
||||||
|
Icon: kubefloworgv1beta1.WorkspaceKindIcon{
|
||||||
|
Url: ptr.To("/workspaces/backend/api/v1/workspacekinds/test-workspacekind/assets/icon"),
|
||||||
|
},
|
||||||
|
Logo: kubefloworgv1beta1.WorkspaceKindIcon{
|
||||||
|
Url: ptr.To("/workspaces/backend/api/v1/workspacekinds/test-workspacekind/assets/logo"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
PodTemplate: kubefloworgv1beta1.WorkspaceKindPodTemplate{
|
||||||
|
PodMetadata: &kubefloworgv1beta1.WorkspaceKindPodMetadata{
|
||||||
|
Labels: map[string]string{
|
||||||
|
"app": "test-workspacekind",
|
||||||
|
},
|
||||||
|
Annotations: map[string]string{
|
||||||
|
"annotation-key": "annotation-value",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedName: "test-workspacekind",
|
||||||
|
expectedDisplayName: "Complete Workspacekind",
|
||||||
|
expectedDescription: "A complete test workspacekind with all features",
|
||||||
|
expectedDeprecated: false,
|
||||||
|
expectedDeprecationMsg: "",
|
||||||
|
expectedHidden: false,
|
||||||
|
expectedIconURL: "/workspaces/backend/api/v1/workspacekinds/test-workspacekind/assets/icon",
|
||||||
|
expectedLogoURL: "/workspaces/backend/api/v1/workspacekinds/test-workspacekind/assets/logo",
|
||||||
|
expectedPodLabels: map[string]string{"app": "test-workspacekind"},
|
||||||
|
expectedPodAnnotations: map[string]string{"annotation-key": "annotation-value"},
|
||||||
|
}),
|
||||||
|
|
||||||
|
Entry("empty strings in required fields", workspaceKindTestCase{
|
||||||
|
name: "empty strings in required fields",
|
||||||
|
workspaceKind: &kubefloworgv1beta1.WorkspaceKind{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "empty-fields-workspace",
|
||||||
|
},
|
||||||
|
Spec: kubefloworgv1beta1.WorkspaceKindSpec{
|
||||||
|
Spawner: kubefloworgv1beta1.WorkspaceKindSpawner{
|
||||||
|
DisplayName: "",
|
||||||
|
Description: "",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedName: "empty-fields-workspace",
|
||||||
|
expectedDisplayName: "",
|
||||||
|
expectedDescription: "",
|
||||||
|
expectedDeprecated: false,
|
||||||
|
expectedDeprecationMsg: "",
|
||||||
|
expectedHidden: false,
|
||||||
|
expectedIconURL: "/workspaces/backend/api/v1/workspacekinds/empty-fields-workspace/assets/icon",
|
||||||
|
expectedLogoURL: "/workspaces/backend/api/v1/workspacekinds/empty-fields-workspace/assets/logo",
|
||||||
|
}),
|
||||||
|
|
||||||
|
Entry("special characters in names", workspaceKindTestCase{
|
||||||
|
name: "special characters in names",
|
||||||
|
workspaceKind: &kubefloworgv1beta1.WorkspaceKind{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "special-chars_workspace-123",
|
||||||
|
},
|
||||||
|
Spec: kubefloworgv1beta1.WorkspaceKindSpec{
|
||||||
|
Spawner: kubefloworgv1beta1.WorkspaceKindSpawner{
|
||||||
|
DisplayName: "Special-Chars_Workspace 123!",
|
||||||
|
Description: "Workspace with special characters in name",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedName: "special-chars_workspace-123",
|
||||||
|
expectedDisplayName: "Special-Chars_Workspace 123!",
|
||||||
|
expectedDescription: "Workspace with special characters in name",
|
||||||
|
expectedDeprecated: false,
|
||||||
|
expectedDeprecationMsg: "",
|
||||||
|
expectedHidden: false,
|
||||||
|
expectedIconURL: "/workspaces/backend/api/v1/workspacekinds/special-chars_workspace-123/assets/icon",
|
||||||
|
expectedLogoURL: "/workspaces/backend/api/v1/workspacekinds/special-chars_workspace-123/assets/logo",
|
||||||
|
}),
|
||||||
|
|
||||||
|
Entry("long descriptions", workspaceKindTestCase{
|
||||||
|
name: "long descriptions",
|
||||||
|
workspaceKind: &kubefloworgv1beta1.WorkspaceKind{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "long-description-workspace",
|
||||||
|
},
|
||||||
|
Spec: kubefloworgv1beta1.WorkspaceKindSpec{
|
||||||
|
Spawner: kubefloworgv1beta1.WorkspaceKindSpawner{
|
||||||
|
DisplayName: "Long Description Workspace",
|
||||||
|
Description: "This is a very long description that contains multiple sentences. " +
|
||||||
|
"It describes a workspace kind that has many features and capabilities. " +
|
||||||
|
"The description should be preserved exactly as provided without truncation. " +
|
||||||
|
"This tests the ability to handle larger text fields in the workspace kind model.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedName: "long-description-workspace",
|
||||||
|
expectedDisplayName: "Long Description Workspace",
|
||||||
|
expectedDescription: "This is a very long description that contains multiple sentences. " +
|
||||||
|
"It describes a workspace kind that has many features and capabilities. " +
|
||||||
|
"The description should be preserved exactly as provided without truncation. " +
|
||||||
|
"This tests the ability to handle larger text fields in the workspace kind model.",
|
||||||
|
expectedDeprecated: false,
|
||||||
|
expectedDeprecationMsg: "",
|
||||||
|
expectedHidden: false,
|
||||||
|
expectedIconURL: "/workspaces/backend/api/v1/workspacekinds/long-description-workspace/assets/icon",
|
||||||
|
expectedLogoURL: "/workspaces/backend/api/v1/workspacekinds/long-description-workspace/assets/logo",
|
||||||
|
additionalValidations: func(result workspacekinds.WorkspaceKind) {
|
||||||
|
Expect(len(result.Description)).To(BeNumerically(">", 200))
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
|
||||||
|
Entry("deprecated WorkspaceKind", workspaceKindTestCase{
|
||||||
|
name: "deprecated WorkspaceKind",
|
||||||
|
workspaceKind: &kubefloworgv1beta1.WorkspaceKind{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "deprecated-workspace",
|
||||||
|
},
|
||||||
|
Spec: kubefloworgv1beta1.WorkspaceKindSpec{
|
||||||
|
Spawner: kubefloworgv1beta1.WorkspaceKindSpawner{
|
||||||
|
DisplayName: "Deprecated Workspace",
|
||||||
|
Description: "This workspace kind is deprecated",
|
||||||
|
Deprecated: ptr.To(true),
|
||||||
|
DeprecationMessage: ptr.To("Use new-workspace instead"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedName: "deprecated-workspace",
|
||||||
|
expectedDisplayName: "Deprecated Workspace",
|
||||||
|
expectedDescription: "This workspace kind is deprecated",
|
||||||
|
expectedDeprecated: true,
|
||||||
|
expectedDeprecationMsg: "Use new-workspace instead",
|
||||||
|
expectedHidden: false,
|
||||||
|
expectedIconURL: "/workspaces/backend/api/v1/workspacekinds/deprecated-workspace/assets/icon",
|
||||||
|
expectedLogoURL: "/workspaces/backend/api/v1/workspacekinds/deprecated-workspace/assets/logo",
|
||||||
|
}),
|
||||||
|
|
||||||
|
Entry("hidden WorkspaceKind", workspaceKindTestCase{
|
||||||
|
name: "hidden WorkspaceKind",
|
||||||
|
workspaceKind: &kubefloworgv1beta1.WorkspaceKind{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "hidden-workspace",
|
||||||
|
},
|
||||||
|
Spec: kubefloworgv1beta1.WorkspaceKindSpec{
|
||||||
|
Spawner: kubefloworgv1beta1.WorkspaceKindSpawner{
|
||||||
|
DisplayName: "Hidden Workspace",
|
||||||
|
Description: "This workspace kind is hidden from UI",
|
||||||
|
Hidden: ptr.To(true),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedName: "hidden-workspace",
|
||||||
|
expectedDisplayName: "Hidden Workspace",
|
||||||
|
expectedDescription: "This workspace kind is hidden from UI",
|
||||||
|
expectedDeprecated: false,
|
||||||
|
expectedDeprecationMsg: "",
|
||||||
|
expectedHidden: true,
|
||||||
|
expectedIconURL: "/workspaces/backend/api/v1/workspacekinds/hidden-workspace/assets/icon",
|
||||||
|
expectedLogoURL: "/workspaces/backend/api/v1/workspacekinds/hidden-workspace/assets/logo",
|
||||||
|
}),
|
||||||
|
|
||||||
|
Entry("minimal WorkspaceKind with only required fields", workspaceKindTestCase{
|
||||||
|
name: "minimal WorkspaceKind",
|
||||||
|
workspaceKind: &kubefloworgv1beta1.WorkspaceKind{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "minimal-workspace",
|
||||||
|
},
|
||||||
|
Spec: kubefloworgv1beta1.WorkspaceKindSpec{
|
||||||
|
Spawner: kubefloworgv1beta1.WorkspaceKindSpawner{
|
||||||
|
DisplayName: "Minimal Workspace",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expectedName: "minimal-workspace",
|
||||||
|
expectedDisplayName: "Minimal Workspace",
|
||||||
|
expectedDescription: "",
|
||||||
|
expectedDeprecated: false,
|
||||||
|
expectedDeprecationMsg: "",
|
||||||
|
expectedHidden: false,
|
||||||
|
expectedIconURL: "/workspaces/backend/api/v1/workspacekinds/minimal-workspace/assets/icon",
|
||||||
|
expectedLogoURL: "/workspaces/backend/api/v1/workspacekinds/minimal-workspace/assets/logo",
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,574 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package workspaces_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
kubefloworgv1beta1 "github.com/kubeflow/notebooks/workspaces/controller/api/v1beta1"
|
||||||
|
. "github.com/onsi/ginkgo/v2"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
|
"k8s.io/utils/ptr"
|
||||||
|
|
||||||
|
workspaces "github.com/kubeflow/notebooks/workspaces/backend/internal/models/workspaces"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Test constants
|
||||||
|
const (
|
||||||
|
testWorkspaceName = "test-workspace"
|
||||||
|
testNamespace = "test-namespace"
|
||||||
|
testWorkspaceKindName = "jupyter-notebook"
|
||||||
|
testUID = "test-uid"
|
||||||
|
testHomePVC = "home-pvc"
|
||||||
|
testHomeMountPath = "/home/jovyan"
|
||||||
|
testDataPVC1 = "data-pvc-1"
|
||||||
|
testDataPVC2 = "data-pvc-2"
|
||||||
|
testDataMountPath1 = "/data1"
|
||||||
|
testDataMountPath2 = "/data2"
|
||||||
|
testImageConfigID = "default-image"
|
||||||
|
testPodConfigID = "default-pod"
|
||||||
|
testDesiredImageID = "desired-image"
|
||||||
|
testDesiredPodID = "desired-pod"
|
||||||
|
testOldImageID = "old-image"
|
||||||
|
testOldPodID = "old-pod"
|
||||||
|
testNewImageID = "new-image"
|
||||||
|
testNewPodID = "new-pod"
|
||||||
|
testStateMessage = "Running successfully"
|
||||||
|
testAppLabel = "test-app"
|
||||||
|
testAnnotationKey = "annotation-key"
|
||||||
|
testAnnotationValue = "annotation-value"
|
||||||
|
testEnvironmentLabel = "environment"
|
||||||
|
testPythonValue = "python"
|
||||||
|
testSizeLabel = "size"
|
||||||
|
testSmallValue = "small"
|
||||||
|
testJupyterPortID = "jupyter"
|
||||||
|
testJupyterDisplayName = "Jupyter"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Test data structures
|
||||||
|
type WorkspaceBuilder struct {
|
||||||
|
workspace *kubefloworgv1beta1.Workspace
|
||||||
|
}
|
||||||
|
|
||||||
|
type WorkspaceKindBuilder struct {
|
||||||
|
workspaceKind *kubefloworgv1beta1.WorkspaceKind
|
||||||
|
}
|
||||||
|
|
||||||
|
type TestExpectations struct {
|
||||||
|
Name string
|
||||||
|
Namespace string
|
||||||
|
WorkspaceKindName string
|
||||||
|
WorkspaceKindMissing bool
|
||||||
|
State workspaces.WorkspaceState
|
||||||
|
StateMessage string
|
||||||
|
DeferUpdates bool
|
||||||
|
Paused bool
|
||||||
|
PendingRestart bool
|
||||||
|
HomePVCName string
|
||||||
|
HomeMountPath string
|
||||||
|
HomeReadOnly bool
|
||||||
|
DataVolumeCount int
|
||||||
|
ImageConfigID string
|
||||||
|
PodConfigID string
|
||||||
|
ServiceCount int
|
||||||
|
Labels map[string]string
|
||||||
|
Annotations map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Workspace builder functions
|
||||||
|
func NewWorkspaceBuilder() *WorkspaceBuilder {
|
||||||
|
return &WorkspaceBuilder{
|
||||||
|
workspace: &kubefloworgv1beta1.Workspace{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: testWorkspaceName,
|
||||||
|
Namespace: testNamespace,
|
||||||
|
},
|
||||||
|
Spec: kubefloworgv1beta1.WorkspaceSpec{
|
||||||
|
Kind: testWorkspaceKindName,
|
||||||
|
DeferUpdates: ptr.To(false),
|
||||||
|
Paused: ptr.To(false),
|
||||||
|
},
|
||||||
|
Status: kubefloworgv1beta1.WorkspaceStatus{
|
||||||
|
State: kubefloworgv1beta1.WorkspaceStateRunning,
|
||||||
|
StateMessage: testStateMessage,
|
||||||
|
PendingRestart: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithName(name string) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Name = name
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithNamespace(namespace string) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Namespace = namespace
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithKind(kind string) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Spec.Kind = kind
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithState(state kubefloworgv1beta1.WorkspaceState) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Status.State = state
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithStateMessage(message string) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Status.StateMessage = message
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithPodMetadata(labels, annotations map[string]string) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Spec.PodTemplate.PodMetadata = &kubefloworgv1beta1.WorkspacePodMetadata{
|
||||||
|
Labels: labels,
|
||||||
|
Annotations: annotations,
|
||||||
|
}
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithHomeVolume(pvcName string) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Spec.PodTemplate.Volumes.Home = ptr.To(pvcName)
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithoutHomeVolume() *WorkspaceBuilder {
|
||||||
|
wb.workspace.Spec.PodTemplate.Volumes.Home = nil
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithDataVolumes(volumes []kubefloworgv1beta1.PodVolumeMount) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Spec.PodTemplate.Volumes.Data = volumes
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithImageConfig(imageConfig string) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Spec.PodTemplate.Options.ImageConfig = imageConfig
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithPodConfig(podConfig string) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Spec.PodTemplate.Options.PodConfig = podConfig
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithDesiredImageConfig(desired string) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Status.PodTemplateOptions.ImageConfig.Desired = desired
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithDesiredPodConfig(desired string) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Status.PodTemplateOptions.PodConfig.Desired = desired
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithImageRedirectChain(chain []kubefloworgv1beta1.WorkspacePodOptionRedirectStep) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Status.PodTemplateOptions.ImageConfig.RedirectChain = chain
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithPodRedirectChain(chain []kubefloworgv1beta1.WorkspacePodOptionRedirectStep) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Status.PodTemplateOptions.PodConfig.RedirectChain = chain
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) WithActivity(lastActivity, lastUpdate int64) *WorkspaceBuilder {
|
||||||
|
wb.workspace.Status.Activity = kubefloworgv1beta1.WorkspaceActivity{
|
||||||
|
LastActivity: lastActivity,
|
||||||
|
LastUpdate: lastUpdate,
|
||||||
|
}
|
||||||
|
return wb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wb *WorkspaceBuilder) Build() *kubefloworgv1beta1.Workspace {
|
||||||
|
return wb.workspace
|
||||||
|
}
|
||||||
|
|
||||||
|
// WorkspaceKind builder functions
|
||||||
|
func NewWorkspaceKindBuilder() *WorkspaceKindBuilder {
|
||||||
|
return &WorkspaceKindBuilder{
|
||||||
|
workspaceKind: &kubefloworgv1beta1.WorkspaceKind{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: testWorkspaceKindName,
|
||||||
|
UID: types.UID(testUID),
|
||||||
|
},
|
||||||
|
Spec: kubefloworgv1beta1.WorkspaceKindSpec{
|
||||||
|
Spawner: kubefloworgv1beta1.WorkspaceKindSpawner{
|
||||||
|
DisplayName: "Jupyter Notebook",
|
||||||
|
Description: "A Jupyter notebook workspace",
|
||||||
|
},
|
||||||
|
PodTemplate: kubefloworgv1beta1.WorkspaceKindPodTemplate{
|
||||||
|
VolumeMounts: kubefloworgv1beta1.WorkspaceKindVolumeMounts{
|
||||||
|
Home: testHomeMountPath,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wkb *WorkspaceKindBuilder) WithName(name string) *WorkspaceKindBuilder {
|
||||||
|
wkb.workspaceKind.Name = name
|
||||||
|
return wkb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wkb *WorkspaceKindBuilder) WithUID(uid string) *WorkspaceKindBuilder {
|
||||||
|
wkb.workspaceKind.UID = types.UID(uid)
|
||||||
|
return wkb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wkb *WorkspaceKindBuilder) WithoutUID() *WorkspaceKindBuilder {
|
||||||
|
wkb.workspaceKind.UID = ""
|
||||||
|
return wkb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wkb *WorkspaceKindBuilder) WithHomeMountPath(path string) *WorkspaceKindBuilder {
|
||||||
|
wkb.workspaceKind.Spec.PodTemplate.VolumeMounts.Home = path
|
||||||
|
return wkb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wkb *WorkspaceKindBuilder) WithImageConfigs(configs []kubefloworgv1beta1.ImageConfigValue) *WorkspaceKindBuilder {
|
||||||
|
wkb.workspaceKind.Spec.PodTemplate.Options.ImageConfig.Values = configs
|
||||||
|
return wkb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wkb *WorkspaceKindBuilder) WithPodConfigs(configs []kubefloworgv1beta1.PodConfigValue) *WorkspaceKindBuilder {
|
||||||
|
wkb.workspaceKind.Spec.PodTemplate.Options.PodConfig.Values = configs
|
||||||
|
return wkb
|
||||||
|
}
|
||||||
|
|
||||||
|
func (wkb *WorkspaceKindBuilder) Build() *kubefloworgv1beta1.WorkspaceKind {
|
||||||
|
return wkb.workspaceKind
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper functions for creating common test data
|
||||||
|
func createDefaultDataVolumes() []kubefloworgv1beta1.PodVolumeMount {
|
||||||
|
return []kubefloworgv1beta1.PodVolumeMount{
|
||||||
|
{
|
||||||
|
PVCName: testDataPVC1,
|
||||||
|
MountPath: testDataMountPath1,
|
||||||
|
ReadOnly: ptr.To(false),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PVCName: testDataPVC2,
|
||||||
|
MountPath: testDataMountPath2,
|
||||||
|
ReadOnly: ptr.To(true),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDefaultPodMetadata() (map[string]string, map[string]string) {
|
||||||
|
labels := map[string]string{testAppLabel: testAppLabel}
|
||||||
|
annotations := map[string]string{testAnnotationKey: testAnnotationValue}
|
||||||
|
return labels, annotations
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDefaultImageConfigs() []kubefloworgv1beta1.ImageConfigValue {
|
||||||
|
return []kubefloworgv1beta1.ImageConfigValue{
|
||||||
|
{
|
||||||
|
Id: testImageConfigID,
|
||||||
|
Spawner: kubefloworgv1beta1.OptionSpawnerInfo{
|
||||||
|
DisplayName: "Default Image",
|
||||||
|
Description: ptr.To("Default Jupyter image"),
|
||||||
|
Labels: []kubefloworgv1beta1.OptionSpawnerLabel{
|
||||||
|
{Key: testEnvironmentLabel, Value: testPythonValue},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Spec: kubefloworgv1beta1.ImageConfigSpec{
|
||||||
|
Ports: []kubefloworgv1beta1.ImagePort{
|
||||||
|
{
|
||||||
|
Id: testJupyterPortID,
|
||||||
|
DisplayName: testJupyterDisplayName,
|
||||||
|
Protocol: kubefloworgv1beta1.ImagePortProtocolHTTP,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id: testOldImageID,
|
||||||
|
Spawner: kubefloworgv1beta1.OptionSpawnerInfo{
|
||||||
|
DisplayName: "Old Image",
|
||||||
|
Description: ptr.To("Deprecated image"),
|
||||||
|
},
|
||||||
|
Redirect: &kubefloworgv1beta1.OptionRedirect{
|
||||||
|
To: testNewImageID,
|
||||||
|
Message: &kubefloworgv1beta1.RedirectMessage{
|
||||||
|
Text: "This image has been deprecated",
|
||||||
|
Level: kubefloworgv1beta1.RedirectMessageLevelWarning,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDefaultPodConfigs() []kubefloworgv1beta1.PodConfigValue {
|
||||||
|
return []kubefloworgv1beta1.PodConfigValue{
|
||||||
|
{
|
||||||
|
Id: testPodConfigID,
|
||||||
|
Spawner: kubefloworgv1beta1.OptionSpawnerInfo{
|
||||||
|
DisplayName: "Default Pod Config",
|
||||||
|
Description: ptr.To("Default pod configuration"),
|
||||||
|
Labels: []kubefloworgv1beta1.OptionSpawnerLabel{
|
||||||
|
{Key: testSizeLabel, Value: testSmallValue},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Id: testOldPodID,
|
||||||
|
Spawner: kubefloworgv1beta1.OptionSpawnerInfo{
|
||||||
|
DisplayName: "Old Pod Config",
|
||||||
|
Description: ptr.To("Deprecated pod config"),
|
||||||
|
},
|
||||||
|
Redirect: &kubefloworgv1beta1.OptionRedirect{
|
||||||
|
To: testNewPodID,
|
||||||
|
Message: &kubefloworgv1beta1.RedirectMessage{
|
||||||
|
Text: "This pod config has been deprecated",
|
||||||
|
Level: kubefloworgv1beta1.RedirectMessageLevelDanger,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDefaultRedirectChain() []kubefloworgv1beta1.WorkspacePodOptionRedirectStep {
|
||||||
|
return []kubefloworgv1beta1.WorkspacePodOptionRedirectStep{
|
||||||
|
{Source: testOldImageID, Target: testNewImageID},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assertion helper functions
|
||||||
|
func expectBasicWorkspaceFields(result *workspaces.Workspace, expectations *TestExpectations) {
|
||||||
|
Expect(result.Name).To(Equal(expectations.Name))
|
||||||
|
Expect(result.Namespace).To(Equal(expectations.Namespace))
|
||||||
|
Expect(result.WorkspaceKind.Name).To(Equal(expectations.WorkspaceKindName))
|
||||||
|
Expect(result.WorkspaceKind.Missing).To(Equal(expectations.WorkspaceKindMissing))
|
||||||
|
Expect(result.State).To(Equal(expectations.State))
|
||||||
|
Expect(result.StateMessage).To(Equal(expectations.StateMessage))
|
||||||
|
Expect(result.DeferUpdates).To(Equal(expectations.DeferUpdates))
|
||||||
|
Expect(result.Paused).To(Equal(expectations.Paused))
|
||||||
|
Expect(result.PendingRestart).To(Equal(expectations.PendingRestart))
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectHomeVolume(result *workspaces.Workspace, expectations *TestExpectations) {
|
||||||
|
if expectations.HomePVCName == "" {
|
||||||
|
Expect(result.PodTemplate.Volumes.Home).To(BeNil())
|
||||||
|
} else {
|
||||||
|
Expect(result.PodTemplate.Volumes.Home).ToNot(BeNil())
|
||||||
|
Expect(result.PodTemplate.Volumes.Home.PVCName).To(Equal(expectations.HomePVCName))
|
||||||
|
Expect(result.PodTemplate.Volumes.Home.MountPath).To(Equal(expectations.HomeMountPath))
|
||||||
|
Expect(result.PodTemplate.Volumes.Home.ReadOnly).To(Equal(expectations.HomeReadOnly))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectDataVolumes(result *workspaces.Workspace, expectations *TestExpectations) {
|
||||||
|
Expect(result.PodTemplate.Volumes.Data).To(HaveLen(expectations.DataVolumeCount))
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectPodMetadata(result *workspaces.Workspace, expectations *TestExpectations) {
|
||||||
|
if expectations.Labels != nil {
|
||||||
|
for key, value := range expectations.Labels {
|
||||||
|
Expect(result.PodTemplate.PodMetadata.Labels).To(HaveKeyWithValue(key, value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if expectations.Annotations != nil {
|
||||||
|
for key, value := range expectations.Annotations {
|
||||||
|
Expect(result.PodTemplate.PodMetadata.Annotations).To(HaveKeyWithValue(key, value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func expectServices(result *workspaces.Workspace, expectations *TestExpectations) {
|
||||||
|
if expectations.ServiceCount == 0 {
|
||||||
|
Expect(result.Services).To(BeNil())
|
||||||
|
} else {
|
||||||
|
Expect(result.Services).To(HaveLen(expectations.ServiceCount))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateWorkspaceModel(result *workspaces.Workspace, expectations *TestExpectations) {
|
||||||
|
expectBasicWorkspaceFields(result, expectations)
|
||||||
|
expectHomeVolume(result, expectations)
|
||||||
|
expectDataVolumes(result, expectations)
|
||||||
|
expectPodMetadata(result, expectations)
|
||||||
|
expectServices(result, expectations)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = Describe("Workspace Functions", func() {
|
||||||
|
var testTime = metav1.NewTime(time.Now())
|
||||||
|
|
||||||
|
Describe("NewWorkspaceModelFromWorkspace", func() {
|
||||||
|
DescribeTable("should create workspace models correctly",
|
||||||
|
func(
|
||||||
|
workspaceBuilder func() *kubefloworgv1beta1.Workspace,
|
||||||
|
workspaceKindBuilder func() *kubefloworgv1beta1.WorkspaceKind,
|
||||||
|
expectations TestExpectations,
|
||||||
|
) {
|
||||||
|
workspace := workspaceBuilder()
|
||||||
|
workspaceKind := workspaceKindBuilder()
|
||||||
|
|
||||||
|
result := workspaces.NewWorkspaceModelFromWorkspace(workspace, workspaceKind)
|
||||||
|
validateWorkspaceModel(&result, &expectations)
|
||||||
|
},
|
||||||
|
|
||||||
|
Entry("complete workspace with matching workspace kind",
|
||||||
|
func() *kubefloworgv1beta1.Workspace {
|
||||||
|
labels, annotations := createDefaultPodMetadata()
|
||||||
|
return NewWorkspaceBuilder().
|
||||||
|
WithPodMetadata(labels, annotations).
|
||||||
|
WithHomeVolume(testHomePVC).
|
||||||
|
WithDataVolumes(createDefaultDataVolumes()).
|
||||||
|
WithImageConfig(testImageConfigID).
|
||||||
|
WithPodConfig(testPodConfigID).
|
||||||
|
WithDesiredImageConfig(testDesiredImageID).
|
||||||
|
WithDesiredPodConfig(testDesiredPodID).
|
||||||
|
WithImageRedirectChain(createDefaultRedirectChain()).
|
||||||
|
WithPodRedirectChain(createDefaultRedirectChain()).
|
||||||
|
WithActivity(testTime.Unix(), testTime.Unix()).
|
||||||
|
Build()
|
||||||
|
},
|
||||||
|
func() *kubefloworgv1beta1.WorkspaceKind {
|
||||||
|
return NewWorkspaceKindBuilder().
|
||||||
|
WithImageConfigs(createDefaultImageConfigs()).
|
||||||
|
WithPodConfigs(createDefaultPodConfigs()).
|
||||||
|
Build()
|
||||||
|
},
|
||||||
|
TestExpectations{
|
||||||
|
Name: testWorkspaceName,
|
||||||
|
Namespace: testNamespace,
|
||||||
|
WorkspaceKindName: testWorkspaceKindName,
|
||||||
|
WorkspaceKindMissing: false,
|
||||||
|
State: workspaces.WorkspaceStateRunning,
|
||||||
|
StateMessage: testStateMessage,
|
||||||
|
DeferUpdates: false,
|
||||||
|
Paused: false,
|
||||||
|
PendingRestart: false,
|
||||||
|
HomePVCName: testHomePVC,
|
||||||
|
HomeMountPath: testHomeMountPath,
|
||||||
|
HomeReadOnly: false,
|
||||||
|
DataVolumeCount: 2,
|
||||||
|
ServiceCount: 1,
|
||||||
|
Labels: map[string]string{testAppLabel: testAppLabel},
|
||||||
|
Annotations: map[string]string{testAnnotationKey: testAnnotationValue},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
Entry("workspace with nil workspace kind",
|
||||||
|
func() *kubefloworgv1beta1.Workspace {
|
||||||
|
return NewWorkspaceBuilder().
|
||||||
|
WithHomeVolume(testHomePVC).
|
||||||
|
Build()
|
||||||
|
},
|
||||||
|
func() *kubefloworgv1beta1.WorkspaceKind {
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
TestExpectations{
|
||||||
|
Name: testWorkspaceName,
|
||||||
|
Namespace: testNamespace,
|
||||||
|
WorkspaceKindName: testWorkspaceKindName,
|
||||||
|
WorkspaceKindMissing: true,
|
||||||
|
State: workspaces.WorkspaceStateRunning,
|
||||||
|
StateMessage: testStateMessage,
|
||||||
|
HomePVCName: testHomePVC,
|
||||||
|
HomeMountPath: workspaces.UnknownHomeMountPath,
|
||||||
|
HomeReadOnly: false,
|
||||||
|
DataVolumeCount: 0,
|
||||||
|
ServiceCount: 0,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
Entry("workspace kind without UID",
|
||||||
|
func() *kubefloworgv1beta1.Workspace {
|
||||||
|
return NewWorkspaceBuilder().
|
||||||
|
WithHomeVolume(testHomePVC).
|
||||||
|
Build()
|
||||||
|
},
|
||||||
|
func() *kubefloworgv1beta1.WorkspaceKind {
|
||||||
|
return NewWorkspaceKindBuilder().
|
||||||
|
WithoutUID().
|
||||||
|
Build()
|
||||||
|
},
|
||||||
|
TestExpectations{
|
||||||
|
Name: testWorkspaceName,
|
||||||
|
Namespace: testNamespace,
|
||||||
|
WorkspaceKindName: testWorkspaceKindName,
|
||||||
|
WorkspaceKindMissing: true,
|
||||||
|
State: workspaces.WorkspaceStateRunning,
|
||||||
|
StateMessage: testStateMessage,
|
||||||
|
HomePVCName: testHomePVC,
|
||||||
|
HomeMountPath: workspaces.UnknownHomeMountPath,
|
||||||
|
HomeReadOnly: false,
|
||||||
|
DataVolumeCount: 0,
|
||||||
|
ServiceCount: 0,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
Entry("workspace without home volume",
|
||||||
|
func() *kubefloworgv1beta1.Workspace {
|
||||||
|
return NewWorkspaceBuilder().
|
||||||
|
WithoutHomeVolume().
|
||||||
|
Build()
|
||||||
|
},
|
||||||
|
func() *kubefloworgv1beta1.WorkspaceKind {
|
||||||
|
return NewWorkspaceKindBuilder().Build()
|
||||||
|
},
|
||||||
|
TestExpectations{
|
||||||
|
Name: testWorkspaceName,
|
||||||
|
Namespace: testNamespace,
|
||||||
|
WorkspaceKindName: testWorkspaceKindName,
|
||||||
|
WorkspaceKindMissing: false,
|
||||||
|
State: workspaces.WorkspaceStateRunning,
|
||||||
|
StateMessage: testStateMessage,
|
||||||
|
HomePVCName: "", // Empty means nil home volume
|
||||||
|
DataVolumeCount: 0,
|
||||||
|
ServiceCount: 0,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
DescribeTable("should map workspace states correctly",
|
||||||
|
func(inputState kubefloworgv1beta1.WorkspaceState, expectedState workspaces.WorkspaceState) {
|
||||||
|
workspace := NewWorkspaceBuilder().WithState(inputState).Build()
|
||||||
|
workspaceKind := NewWorkspaceKindBuilder().Build()
|
||||||
|
|
||||||
|
result := workspaces.NewWorkspaceModelFromWorkspace(workspace, workspaceKind)
|
||||||
|
Expect(result.State).To(Equal(expectedState))
|
||||||
|
},
|
||||||
|
Entry("Running", kubefloworgv1beta1.WorkspaceStateRunning, workspaces.WorkspaceStateRunning),
|
||||||
|
Entry("Terminating", kubefloworgv1beta1.WorkspaceStateTerminating, workspaces.WorkspaceStateTerminating),
|
||||||
|
Entry("Paused", kubefloworgv1beta1.WorkspaceStatePaused, workspaces.WorkspaceStatePaused),
|
||||||
|
Entry("Pending", kubefloworgv1beta1.WorkspaceStatePending, workspaces.WorkspaceStatePending),
|
||||||
|
Entry("Error", kubefloworgv1beta1.WorkspaceStateError, workspaces.WorkspaceStateError),
|
||||||
|
Entry("Unknown", kubefloworgv1beta1.WorkspaceStateUnknown, workspaces.WorkspaceStateUnknown),
|
||||||
|
)
|
||||||
|
|
||||||
|
Context("error cases", func() {
|
||||||
|
It("should panic when workspace kind name doesn't match", func() {
|
||||||
|
workspace := NewWorkspaceBuilder().Build()
|
||||||
|
workspaceKind := NewWorkspaceKindBuilder().WithName("different-kind").Build()
|
||||||
|
|
||||||
|
Expect(func() {
|
||||||
|
workspaces.NewWorkspaceModelFromWorkspace(workspace, workspaceKind)
|
||||||
|
}).To(Panic())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package workspaces_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo/v2"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestWorkspaces(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
RunSpecs(t, "Workspaces Suite")
|
||||||
|
}
|
||||||
|
|
@ -27,14 +27,7 @@ func NewHealthCheckRepository() *HealthCheckRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *HealthCheckRepository) HealthCheck(version string) (models.HealthCheck, error) {
|
func (r *HealthCheckRepository) HealthCheck(version string) (models.HealthCheck, error) {
|
||||||
|
|
||||||
var res = models.HealthCheck{
|
|
||||||
// TODO: implement actual health check logic
|
// TODO: implement actual health check logic
|
||||||
Status: models.ServiceStatusHealthy,
|
res := models.NewHealthCheck(models.ServiceStatusHealthy, version)
|
||||||
SystemInfo: models.SystemInfo{
|
|
||||||
Version: version,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
Copyright 2024.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package health_check_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo/v2"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
models "github.com/kubeflow/notebooks/workspaces/backend/internal/models/health_check"
|
||||||
|
repo "github.com/kubeflow/notebooks/workspaces/backend/internal/repositories"
|
||||||
|
health_check "github.com/kubeflow/notebooks/workspaces/backend/internal/repositories/health_check"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHealthCheckRepositories(t *testing.T) {
|
||||||
|
RegisterFailHandler(Fail)
|
||||||
|
RunSpecs(t, "HealthCheck Repositories Suite")
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ = Describe("HealthCheckRepository", func() {
|
||||||
|
var (
|
||||||
|
repos *repo.Repositories
|
||||||
|
healthRepo *health_check.HealthCheckRepository
|
||||||
|
)
|
||||||
|
|
||||||
|
BeforeEach(func() {
|
||||||
|
repos = repo.NewRepositories(nil)
|
||||||
|
healthRepo = repos.HealthCheck
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("Repository Initialization", func() {
|
||||||
|
It("should initialize with non-nil repository", func() {
|
||||||
|
Expect(repos).ToNot(BeNil())
|
||||||
|
Expect(healthRepo).ToNot(BeNil())
|
||||||
|
Expect(healthRepo).To(BeAssignableToTypeOf(&health_check.HealthCheckRepository{}))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
Context("HealthCheck Functionality", func() {
|
||||||
|
It("should return healthy status with valid version", func() {
|
||||||
|
version := "1.0.0"
|
||||||
|
result, err := healthRepo.HealthCheck(version)
|
||||||
|
Expect(err).ToNot(HaveOccurred())
|
||||||
|
Expect(result.Status).To(Equal(models.ServiceStatusHealthy))
|
||||||
|
Expect(result.SystemInfo.Version).To(Equal(version))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
Loading…
Reference in New Issue