File size: 5,238 Bytes
0f07ba7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
package services_test
import (
"context"
"os"
"path/filepath"
"github.com/mudler/LocalAI/core/config"
"github.com/mudler/LocalAI/core/services"
"github.com/mudler/LocalAI/pkg/model"
"github.com/mudler/LocalAI/pkg/system"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"gopkg.in/yaml.v2"
)
var _ = Describe("InstallExternalBackend", func() {
var (
tempDir string
galleries []config.Gallery
ml *model.ModelLoader
systemState *system.SystemState
)
BeforeEach(func() {
var err error
tempDir, err = os.MkdirTemp("", "backends-service-test-*")
Expect(err).NotTo(HaveOccurred())
systemState, err = system.GetSystemState(system.WithBackendPath(tempDir))
Expect(err).NotTo(HaveOccurred())
ml = model.NewModelLoader(systemState)
// Setup test gallery
galleries = []config.Gallery{
{
Name: "test-gallery",
URL: "file://" + filepath.Join(tempDir, "test-gallery.yaml"),
},
}
})
AfterEach(func() {
os.RemoveAll(tempDir)
})
Context("with gallery backend name", func() {
BeforeEach(func() {
// Create a test gallery file with a test backend
testBackend := []map[string]interface{}{
{
"name": "test-backend",
"uri": "https://gist.githubusercontent.com/mudler/71d5376bc2aa168873fa519fa9f4bd56/raw/testbackend/run.sh",
},
}
data, err := yaml.Marshal(testBackend)
Expect(err).NotTo(HaveOccurred())
err = os.WriteFile(filepath.Join(tempDir, "test-gallery.yaml"), data, 0644)
Expect(err).NotTo(HaveOccurred())
})
It("should fail when name or alias is provided for gallery backend", func() {
err := services.InstallExternalBackend(
context.Background(),
galleries,
systemState,
ml,
nil,
"test-backend", // gallery name
"custom-name", // name should not be allowed
"",
)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("specifying a name or alias is not supported for gallery backends"))
})
It("should fail when backend is not found in gallery", func() {
err := services.InstallExternalBackend(
context.Background(),
galleries,
systemState,
ml,
nil,
"non-existent-backend",
"",
"",
)
Expect(err).To(HaveOccurred())
})
})
Context("with OCI image", func() {
It("should fail when name is not provided for OCI image", func() {
err := services.InstallExternalBackend(
context.Background(),
galleries,
systemState,
ml,
nil,
"oci://quay.io/mudler/tests:localai-backend-test",
"", // name is required for OCI images
"",
)
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("specifying a name is required for OCI images"))
})
})
Context("with directory path", func() {
var testBackendPath string
BeforeEach(func() {
// Create a test backend directory with required files
testBackendPath = filepath.Join(tempDir, "source-backend")
err := os.MkdirAll(testBackendPath, 0750)
Expect(err).NotTo(HaveOccurred())
// Create run.sh
err = os.WriteFile(filepath.Join(testBackendPath, "run.sh"), []byte("#!/bin/bash\necho test"), 0755)
Expect(err).NotTo(HaveOccurred())
})
It("should infer name from directory path when name is not provided", func() {
// This test verifies that the function attempts to install using the directory name
// The actual installation may fail due to test environment limitations
err := services.InstallExternalBackend(
context.Background(),
galleries,
systemState,
ml,
nil,
testBackendPath,
"", // name should be inferred as "source-backend"
"",
)
// The function should at least attempt to install with the inferred name
// Even if it fails for other reasons, it shouldn't fail due to missing name
if err != nil {
Expect(err.Error()).NotTo(ContainSubstring("name is required"))
}
})
It("should use provided name when specified", func() {
err := services.InstallExternalBackend(
context.Background(),
galleries,
systemState,
ml,
nil,
testBackendPath,
"custom-backend-name",
"",
)
// The function should use the provided name
if err != nil {
Expect(err.Error()).NotTo(ContainSubstring("name is required"))
}
})
It("should support alias when provided", func() {
err := services.InstallExternalBackend(
context.Background(),
galleries,
systemState,
ml,
nil,
testBackendPath,
"custom-backend-name",
"custom-alias",
)
// The function should accept alias for directory paths
if err != nil {
Expect(err.Error()).NotTo(ContainSubstring("alias is not supported"))
}
})
})
})
var _ = Describe("GalleryOp with External Backend", func() {
It("should have external backend fields in GalleryOp", func() {
// Test that the GalleryOp struct has the new external backend fields
op := services.GalleryOp[string, string]{
ExternalURI: "oci://example.com/backend:latest",
ExternalName: "test-backend",
ExternalAlias: "test-alias",
}
Expect(op.ExternalURI).To(Equal("oci://example.com/backend:latest"))
Expect(op.ExternalName).To(Equal("test-backend"))
Expect(op.ExternalAlias).To(Equal("test-alias"))
})
})
|