github.com/weaviate/weaviate@v1.24.6/adapters/handlers/rest/clusterapi/schema_component_test.go (about) 1 // _ _ 2 // __ _____ __ ___ ___ __ _| |_ ___ 3 // \ \ /\ / / _ \/ _` \ \ / / |/ _` | __/ _ \ 4 // \ V V / __/ (_| |\ V /| | (_| | || __/ 5 // \_/\_/ \___|\__,_| \_/ |_|\__,_|\__\___| 6 // 7 // Copyright © 2016 - 2024 Weaviate B.V. All rights reserved. 8 // 9 // CONTACT: hello@weaviate.io 10 // 11 12 package clusterapi_test 13 14 import ( 15 "context" 16 "net/http" 17 "net/http/httptest" 18 "net/url" 19 "testing" 20 21 "github.com/sirupsen/logrus/hooks/test" 22 "github.com/stretchr/testify/assert" 23 "github.com/stretchr/testify/require" 24 "github.com/weaviate/weaviate/adapters/clients" 25 "github.com/weaviate/weaviate/adapters/handlers/rest/clusterapi" 26 "github.com/weaviate/weaviate/entities/models" 27 "github.com/weaviate/weaviate/usecases/cluster" 28 "github.com/weaviate/weaviate/usecases/config" 29 "github.com/weaviate/weaviate/usecases/scaler" 30 schemauc "github.com/weaviate/weaviate/usecases/schema" 31 "github.com/weaviate/weaviate/usecases/sharding" 32 ) 33 34 // This is a cross-package test that tests the schema manager in a distributed 35 // settings including some of its dependencies, such as the REST API and 36 // clients. This setup pretends that replication was one-way for simplicity 37 // sake, but uses the same components on either side to make sure that it 38 // would work in both directions. 39 func TestComponentCluster(t *testing.T) { 40 t.Run("add class", func(t *testing.T) { 41 localManager, remoteManager := setupManagers(t) 42 43 ctx := context.Background() 44 45 err := localManager.AddClass(ctx, nil, testClass()) 46 require.Nil(t, err) 47 48 localClass, err := localManager.GetClass(ctx, nil, testClass().Class) 49 require.Nil(t, err) 50 remoteClass, err := remoteManager.GetClass(ctx, nil, testClass().Class) 51 require.Nil(t, err) 52 53 assert.Equal(t, localClass, remoteClass) 54 }) 55 56 t.Run("add class and extend property", func(t *testing.T) { 57 localManager, remoteManager := setupManagers(t) 58 59 ctx := context.Background() 60 61 err := localManager.AddClass(ctx, nil, testClass()) 62 require.Nil(t, err) 63 64 err = localManager.AddClassProperty(ctx, nil, testClass().Class, testProperty()) 65 require.Nil(t, err) 66 67 localClass, err := localManager.GetClass(ctx, nil, testClass().Class) 68 require.Nil(t, err) 69 remoteClass, err := remoteManager.GetClass(ctx, nil, testClass().Class) 70 require.Nil(t, err) 71 72 assert.Equal(t, localClass, remoteClass) 73 }) 74 75 t.Run("delete class", func(t *testing.T) { 76 localManager, remoteManager := setupManagers(t) 77 78 ctx := context.Background() 79 80 err := localManager.AddClass(ctx, nil, testClass()) 81 require.Nil(t, err) 82 83 err = localManager.DeleteClass(ctx, nil, testClass().Class) 84 require.Nil(t, err) 85 86 localSchema, err := localManager.GetSchema(nil) 87 require.Nil(t, err) 88 remoteSchema, err := remoteManager.GetSchema(nil) 89 require.Nil(t, err) 90 91 assert.Equal(t, localSchema, remoteSchema) 92 }) 93 94 t.Run("add class update config", func(t *testing.T) { 95 localManager, remoteManager := setupManagers(t) 96 97 ctx := context.Background() 98 99 err := localManager.AddClass(ctx, nil, testClass()) 100 require.Nil(t, err) 101 102 updated := testClass() 103 updated.VectorIndexConfig.(map[string]interface{})["secondKey"] = "added" 104 105 err = localManager.UpdateClass(ctx, nil, testClass().Class, updated) 106 require.Nil(t, err) 107 108 localClass, err := localManager.GetClass(ctx, nil, testClass().Class) 109 require.Nil(t, err) 110 remoteClass, err := remoteManager.GetClass(ctx, nil, testClass().Class) 111 require.Nil(t, err) 112 113 assert.Equal(t, localClass, remoteClass) 114 }) 115 } 116 117 func setupManagers(t *testing.T) (*schemauc.Manager, *schemauc.Manager) { 118 remoteManager := newSchemaManagerWithClusterStateAndClient( 119 &fakeClusterState{hosts: []string{"node1"}}, nil) 120 121 schemaHandlers := clusterapi.NewSchema(remoteManager.TxManager(), clusterapi.NewNoopAuthHandler()) 122 mux := http.NewServeMux() 123 mux.Handle("/schema/transactions/", http.StripPrefix("/schema/transactions/", 124 schemaHandlers.Transactions())) 125 server := httptest.NewServer(mux) 126 127 client := clients.NewClusterSchema(&http.Client{}) 128 parsedURL, err := url.Parse(server.URL) 129 require.Nil(t, err) 130 state := &fakeClusterState{hosts: []string{parsedURL.Host}} 131 localManager := newSchemaManagerWithClusterStateAndClient(state, client) 132 133 // this will also mark the tx managers as ready 134 localManager.StartServing(context.Background()) 135 remoteManager.StartServing(context.Background()) 136 137 return localManager, remoteManager 138 } 139 140 func testClass() *models.Class { 141 return &models.Class{ 142 Class: "MyClass", 143 Properties: []*models.Property{ 144 { 145 Name: "propOne", DataType: []string{"text"}, 146 }, 147 }, 148 VectorIndexConfig: map[string]interface{}{ 149 "foo": "bar", 150 }, 151 } 152 } 153 154 func testProperty() *models.Property { 155 return &models.Property{ 156 Name: "propTwo", DataType: []string{"int"}, 157 } 158 } 159 160 // New Local Schema *Manager 161 func newSchemaManagerWithClusterStateAndClient(clusterState *fakeClusterState, 162 client cluster.Client, 163 ) *schemauc.Manager { 164 logger, _ := test.NewNullLogger() 165 vectorizerValidator := &fakeVectorizerValidator{ 166 valid: []string{"text2vec-contextionary", "model1", "model2"}, 167 } 168 sm, err := schemauc.NewManager(&NilMigrator{}, newFakeRepo(), logger, &fakeAuthorizer{}, 169 config.Config{DefaultVectorizerModule: config.VectorizerModuleNone}, 170 dummyParseVectorConfig, // only option for now 171 vectorizerValidator, dummyValidateInvertedConfig, 172 &fakeModuleConfig{}, clusterState, client, &fakeTxPersistence{}, 173 &fakeScaleOutManager{}, 174 ) 175 if err != nil { 176 panic(err.Error()) 177 } 178 179 return sm 180 } 181 182 type fakeScaleOutManager struct{} 183 184 func (f *fakeScaleOutManager) Scale(ctx context.Context, 185 className string, updated sharding.Config, _, _ int64, 186 ) (*sharding.State, error) { 187 return nil, nil 188 } 189 190 func (f *fakeScaleOutManager) SetSchemaManager(sm scaler.SchemaManager) { 191 } 192 193 // does nothing as this component test does not involve crashes 194 type fakeTxPersistence struct{} 195 196 func (f *fakeTxPersistence) StoreTx(ctx context.Context, 197 tx *cluster.Transaction, 198 ) error { 199 return nil 200 } 201 202 func (f *fakeTxPersistence) DeleteTx(ctx context.Context, 203 txID string, 204 ) error { 205 return nil 206 } 207 208 func (f *fakeTxPersistence) IterateAll(ctx context.Context, 209 cb func(tx *cluster.Transaction), 210 ) error { 211 return nil 212 }