github.com/weaviate/weaviate@v1.24.6/test/docker/compose.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 docker
    13  
    14  import (
    15  	"context"
    16  	"fmt"
    17  	"os"
    18  
    19  	"github.com/pkg/errors"
    20  	tescontainersnetwork "github.com/testcontainers/testcontainers-go/network"
    21  	modstgazure "github.com/weaviate/weaviate/modules/backup-azure"
    22  	modstgfilesystem "github.com/weaviate/weaviate/modules/backup-filesystem"
    23  	modstggcs "github.com/weaviate/weaviate/modules/backup-gcs"
    24  	modstgs3 "github.com/weaviate/weaviate/modules/backup-s3"
    25  	modgenerativeanyscale "github.com/weaviate/weaviate/modules/generative-anyscale"
    26  	modgenerativeaws "github.com/weaviate/weaviate/modules/generative-aws"
    27  	modgenerativecohere "github.com/weaviate/weaviate/modules/generative-cohere"
    28  	modgenerativeopenai "github.com/weaviate/weaviate/modules/generative-openai"
    29  	modgenerativepalm "github.com/weaviate/weaviate/modules/generative-palm"
    30  	modmulti2vecpalm "github.com/weaviate/weaviate/modules/multi2vec-palm"
    31  	modqnaopenai "github.com/weaviate/weaviate/modules/qna-openai"
    32  	modrerankercohere "github.com/weaviate/weaviate/modules/reranker-cohere"
    33  	modaws "github.com/weaviate/weaviate/modules/text2vec-aws"
    34  	modcohere "github.com/weaviate/weaviate/modules/text2vec-cohere"
    35  	modhuggingface "github.com/weaviate/weaviate/modules/text2vec-huggingface"
    36  	modopenai "github.com/weaviate/weaviate/modules/text2vec-openai"
    37  	modpalm "github.com/weaviate/weaviate/modules/text2vec-palm"
    38  	modvoyageai "github.com/weaviate/weaviate/modules/text2vec-voyageai"
    39  )
    40  
    41  const (
    42  	// envTestWeaviateImage can be passed to tests to spin up docker compose with given image
    43  	envTestWeaviateImage = "TEST_WEAVIATE_IMAGE"
    44  	// envTestText2vecTransformersImage adds ability to pass a custom image to module tests
    45  	envTestText2vecTransformersImage = "TEST_TEXT2VEC_TRANSFORMERS_IMAGE"
    46  	// envTestText2vecContextionaryImage adds ability to pass a custom image to module tests
    47  	envTestText2vecContextionaryImage = "TEST_TEXT2VEC_CONTEXTIONARY_IMAGE"
    48  	// envTestQnATransformersImage adds ability to pass a custom image to module tests
    49  	envTestQnATransformersImage = "TEST_QNA_TRANSFORMERS_IMAGE"
    50  	// envTestSUMTransformersImage adds ability to pass a custom image to module tests
    51  	envTestSUMTransformersImage = "TEST_SUM_TRANSFORMERS_IMAGE"
    52  	// envTestMulti2VecCLIPImage adds ability to pass a custom CLIP image to module tests
    53  	envTestMulti2VecCLIPImage = "TEST_MULTI2VEC_CLIP_IMAGE"
    54  	// envTestMulti2VecBindImage adds ability to pass a custom BIND image to module tests
    55  	envTestMulti2VecBindImage = "TEST_MULTI2VEC_BIND_IMAGE"
    56  	// envTestImg2VecNeuralImage adds ability to pass a custom Im2Vec Neural image to module tests
    57  	envTestImg2VecNeuralImage = "TEST_IMG2VEC_NEURAL_IMAGE"
    58  	// envTestRerankerTransformersImage adds ability to pass a custom image to module tests
    59  	envTestRerankerTransformersImage = "TEST_RERANKER_TRANSFORMERS_IMAGE"
    60  )
    61  
    62  const (
    63  	Ref2VecCentroid = "ref2vec-centroid"
    64  )
    65  
    66  type Compose struct {
    67  	enableModules                 []string
    68  	defaultVectorizerModule       string
    69  	withMinIO                     bool
    70  	withGCS                       bool
    71  	withAzurite                   bool
    72  	withBackendFilesystem         bool
    73  	withBackendS3                 bool
    74  	withBackendS3Bucket           string
    75  	withBackendGCS                bool
    76  	withBackendGCSBucket          string
    77  	withBackendAzure              bool
    78  	withBackendAzureContainer     string
    79  	withTransformers              bool
    80  	withContextionary             bool
    81  	withQnATransformers           bool
    82  	withWeaviate                  bool
    83  	withWeaviateExposeGRPCPort    bool
    84  	withSecondWeaviate            bool
    85  	withWeaviateAuth              bool
    86  	withWeaviateBasicAuth         bool
    87  	withWeaviateBasicAuthUsername string
    88  	withWeaviateBasicAuthPassword string
    89  	withWeaviateCluster           bool
    90  	withSUMTransformers           bool
    91  	withCentroid                  bool
    92  	withCLIP                      bool
    93  	withMulti2VecPaLM             bool
    94  	withPaLMApiKey                string
    95  	withBind                      bool
    96  	withImg2Vec                   bool
    97  	withRerankerTransformers      bool
    98  	weaviateEnvs                  map[string]string
    99  }
   100  
   101  func New() *Compose {
   102  	return &Compose{enableModules: []string{}, weaviateEnvs: make(map[string]string)}
   103  }
   104  
   105  func (d *Compose) WithMinIO() *Compose {
   106  	d.withMinIO = true
   107  	d.enableModules = append(d.enableModules, modstgs3.Name)
   108  	return d
   109  }
   110  
   111  func (d *Compose) WithGCS() *Compose {
   112  	d.withGCS = true
   113  	d.enableModules = append(d.enableModules, modstggcs.Name)
   114  	return d
   115  }
   116  
   117  func (d *Compose) WithAzurite() *Compose {
   118  	d.withAzurite = true
   119  	d.enableModules = append(d.enableModules, modstgazure.Name)
   120  	return d
   121  }
   122  
   123  func (d *Compose) WithText2VecTransformers() *Compose {
   124  	d.withTransformers = true
   125  	d.enableModules = append(d.enableModules, Text2VecTransformers)
   126  	d.defaultVectorizerModule = Text2VecTransformers
   127  	return d
   128  }
   129  
   130  func (d *Compose) WithText2VecContextionary() *Compose {
   131  	d.withContextionary = true
   132  	d.enableModules = append(d.enableModules, Text2VecContextionary)
   133  	d.defaultVectorizerModule = Text2VecContextionary
   134  	return d
   135  }
   136  
   137  func (d *Compose) WithQnATransformers() *Compose {
   138  	d.withQnATransformers = true
   139  	d.enableModules = append(d.enableModules, QnATransformers)
   140  	return d
   141  }
   142  
   143  func (d *Compose) WithBackendFilesystem() *Compose {
   144  	d.withBackendFilesystem = true
   145  	d.enableModules = append(d.enableModules, modstgfilesystem.Name)
   146  	return d
   147  }
   148  
   149  func (d *Compose) WithBackendS3(bucket string) *Compose {
   150  	d.withBackendS3 = true
   151  	d.withBackendS3Bucket = bucket
   152  	d.withMinIO = true
   153  	d.enableModules = append(d.enableModules, modstgs3.Name)
   154  	return d
   155  }
   156  
   157  func (d *Compose) WithBackendGCS(bucket string) *Compose {
   158  	d.withBackendGCS = true
   159  	d.withBackendGCSBucket = bucket
   160  	d.withGCS = true
   161  	d.enableModules = append(d.enableModules, modstggcs.Name)
   162  	return d
   163  }
   164  
   165  func (d *Compose) WithBackendAzure(container string) *Compose {
   166  	d.withBackendAzure = true
   167  	d.withBackendAzureContainer = container
   168  	d.withAzurite = true
   169  	d.enableModules = append(d.enableModules, modstgazure.Name)
   170  	return d
   171  }
   172  
   173  func (d *Compose) WithSUMTransformers() *Compose {
   174  	d.withSUMTransformers = true
   175  	d.enableModules = append(d.enableModules, SUMTransformers)
   176  	return d
   177  }
   178  
   179  func (d *Compose) WithMulti2VecCLIP() *Compose {
   180  	d.withCLIP = true
   181  	d.enableModules = append(d.enableModules, Multi2VecCLIP)
   182  	return d
   183  }
   184  
   185  func (d *Compose) WithMulti2VecPaLM(apiKey string) *Compose {
   186  	d.withMulti2VecPaLM = true
   187  	d.withPaLMApiKey = apiKey
   188  	d.enableModules = append(d.enableModules, modmulti2vecpalm.Name)
   189  	return d
   190  }
   191  
   192  func (d *Compose) WithMulti2VecBind() *Compose {
   193  	d.withBind = true
   194  	d.enableModules = append(d.enableModules, Multi2VecBind)
   195  	return d
   196  }
   197  
   198  func (d *Compose) WithImg2VecNeural() *Compose {
   199  	d.withImg2Vec = true
   200  	d.enableModules = append(d.enableModules, Img2VecNeural)
   201  	return d
   202  }
   203  
   204  func (d *Compose) WithRef2VecCentroid() *Compose {
   205  	d.withCentroid = true
   206  	d.enableModules = append(d.enableModules, Ref2VecCentroid)
   207  	return d
   208  }
   209  
   210  func (d *Compose) WithText2VecOpenAI() *Compose {
   211  	d.enableModules = append(d.enableModules, modopenai.Name)
   212  	return d
   213  }
   214  
   215  func (d *Compose) WithText2VecCohere() *Compose {
   216  	d.enableModules = append(d.enableModules, modcohere.Name)
   217  	return d
   218  }
   219  
   220  func (d *Compose) WithText2VecVoyageAI() *Compose {
   221  	d.enableModules = append(d.enableModules, modvoyageai.Name)
   222  	return d
   223  }
   224  
   225  func (d *Compose) WithText2VecPaLM() *Compose {
   226  	d.enableModules = append(d.enableModules, modpalm.Name)
   227  	return d
   228  }
   229  
   230  func (d *Compose) WithText2VecAWS() *Compose {
   231  	d.enableModules = append(d.enableModules, modaws.Name)
   232  	return d
   233  }
   234  
   235  func (d *Compose) WithText2VecHuggingFace() *Compose {
   236  	d.enableModules = append(d.enableModules, modhuggingface.Name)
   237  	return d
   238  }
   239  
   240  func (d *Compose) WithGenerativeOpenAI() *Compose {
   241  	d.enableModules = append(d.enableModules, modgenerativeopenai.Name)
   242  	return d
   243  }
   244  
   245  func (d *Compose) WithGenerativeAWS() *Compose {
   246  	d.enableModules = append(d.enableModules, modgenerativeaws.Name)
   247  	return d
   248  }
   249  
   250  func (d *Compose) WithGenerativeCohere() *Compose {
   251  	d.enableModules = append(d.enableModules, modgenerativecohere.Name)
   252  	return d
   253  }
   254  
   255  func (d *Compose) WithGenerativePaLM() *Compose {
   256  	d.enableModules = append(d.enableModules, modgenerativepalm.Name)
   257  	return d
   258  }
   259  
   260  func (d *Compose) WithGenerativeAnyscale() *Compose {
   261  	d.enableModules = append(d.enableModules, modgenerativeanyscale.Name)
   262  	return d
   263  }
   264  
   265  func (d *Compose) WithQnAOpenAI() *Compose {
   266  	d.enableModules = append(d.enableModules, modqnaopenai.Name)
   267  	return d
   268  }
   269  
   270  func (d *Compose) WithRerankerCohere() *Compose {
   271  	d.enableModules = append(d.enableModules, modrerankercohere.Name)
   272  	return d
   273  }
   274  
   275  func (d *Compose) WithRerankerTransformers() *Compose {
   276  	d.withRerankerTransformers = true
   277  	d.enableModules = append(d.enableModules, RerankerTransformers)
   278  	return d
   279  }
   280  
   281  func (d *Compose) WithWeaviate() *Compose {
   282  	d.withWeaviate = true
   283  	return d
   284  }
   285  
   286  func (d *Compose) WithWeaviateWithGRPC() *Compose {
   287  	d.withWeaviate = true
   288  	d.withWeaviateExposeGRPCPort = true
   289  	return d
   290  }
   291  
   292  func (d *Compose) WithSecondWeaviate() *Compose {
   293  	d.withSecondWeaviate = true
   294  	return d
   295  }
   296  
   297  func (d *Compose) WithWeaviateCluster() *Compose {
   298  	d.withWeaviate = true
   299  	d.withWeaviateCluster = true
   300  	return d
   301  }
   302  
   303  func (d *Compose) WithWeaviateClusterWithGRPC() *Compose {
   304  	d.withWeaviate = true
   305  	d.withWeaviateCluster = true
   306  	d.withWeaviateExposeGRPCPort = true
   307  	return d
   308  }
   309  
   310  func (d *Compose) WithWeaviateClusterWithBasicAuth(username, password string) *Compose {
   311  	d.withWeaviate = true
   312  	d.withWeaviateCluster = true
   313  	d.withWeaviateBasicAuth = true
   314  	d.withWeaviateBasicAuthUsername = username
   315  	d.withWeaviateBasicAuthPassword = password
   316  	return d
   317  }
   318  
   319  func (d *Compose) WithWeaviateAuth() *Compose {
   320  	d.withWeaviate = true
   321  	d.withWeaviateAuth = true
   322  	return d
   323  }
   324  
   325  func (d *Compose) WithWeaviateEnv(name, value string) *Compose {
   326  	d.weaviateEnvs[name] = value
   327  	return d
   328  }
   329  
   330  func (d *Compose) Start(ctx context.Context) (*DockerCompose, error) {
   331  	d.weaviateEnvs["DISABLE_TELEMETRY"] = "true"
   332  	network, err := tescontainersnetwork.New(
   333  		ctx,
   334  		tescontainersnetwork.WithCheckDuplicate(),
   335  		tescontainersnetwork.WithAttachable(),
   336  	)
   337  	networkName := network.Name
   338  	if err != nil {
   339  		return nil, errors.Wrapf(err, "network: %s", networkName)
   340  	}
   341  	envSettings := make(map[string]string)
   342  	containers := []*DockerContainer{}
   343  	if d.withMinIO {
   344  		container, err := startMinIO(ctx, networkName)
   345  		if err != nil {
   346  			return nil, errors.Wrapf(err, "start %s", MinIO)
   347  		}
   348  		containers = append(containers, container)
   349  		if d.withBackendS3 {
   350  			for k, v := range container.envSettings {
   351  				envSettings[k] = v
   352  			}
   353  			envSettings["BACKUP_S3_BUCKET"] = d.withBackendS3Bucket
   354  		}
   355  	}
   356  	if d.withGCS {
   357  		container, err := startGCS(ctx, networkName)
   358  		if err != nil {
   359  			return nil, errors.Wrapf(err, "start %s", GCS)
   360  		}
   361  		containers = append(containers, container)
   362  		if d.withBackendGCS {
   363  			for k, v := range container.envSettings {
   364  				envSettings[k] = v
   365  			}
   366  			envSettings["BACKUP_GCS_BUCKET"] = d.withBackendGCSBucket
   367  		}
   368  	}
   369  	if d.withAzurite {
   370  		container, err := startAzurite(ctx, networkName)
   371  		if err != nil {
   372  			return nil, errors.Wrapf(err, "start %s", Azurite)
   373  		}
   374  		containers = append(containers, container)
   375  		if d.withBackendAzure {
   376  			for k, v := range container.envSettings {
   377  				envSettings[k] = v
   378  			}
   379  			envSettings["BACKUP_AZURE_CONTAINER"] = d.withBackendAzureContainer
   380  		}
   381  	}
   382  	if d.withBackendFilesystem {
   383  		envSettings["BACKUP_FILESYSTEM_PATH"] = "/tmp/backups"
   384  	}
   385  	if d.withTransformers {
   386  		image := os.Getenv(envTestText2vecTransformersImage)
   387  		container, err := startT2VTransformers(ctx, networkName, image)
   388  		if err != nil {
   389  			return nil, errors.Wrapf(err, "start %s", Text2VecTransformers)
   390  		}
   391  		for k, v := range container.envSettings {
   392  			envSettings[k] = v
   393  		}
   394  		containers = append(containers, container)
   395  	}
   396  	if d.withContextionary {
   397  		image := os.Getenv(envTestText2vecContextionaryImage)
   398  		container, err := startT2VContextionary(ctx, networkName, image)
   399  		if err != nil {
   400  			return nil, errors.Wrapf(err, "start %s", Text2VecContextionary)
   401  		}
   402  		for k, v := range container.envSettings {
   403  			envSettings[k] = v
   404  		}
   405  		containers = append(containers, container)
   406  	}
   407  	if d.withQnATransformers {
   408  		image := os.Getenv(envTestQnATransformersImage)
   409  		container, err := startQnATransformers(ctx, networkName, image)
   410  		if err != nil {
   411  			return nil, errors.Wrapf(err, "start %s", QnATransformers)
   412  		}
   413  		for k, v := range container.envSettings {
   414  			envSettings[k] = v
   415  		}
   416  		containers = append(containers, container)
   417  	}
   418  	if d.withSUMTransformers {
   419  		image := os.Getenv(envTestSUMTransformersImage)
   420  		container, err := startSUMTransformers(ctx, networkName, image)
   421  		if err != nil {
   422  			return nil, errors.Wrapf(err, "start %s", SUMTransformers)
   423  		}
   424  		for k, v := range container.envSettings {
   425  			envSettings[k] = v
   426  		}
   427  		containers = append(containers, container)
   428  	}
   429  	if d.withCLIP {
   430  		image := os.Getenv(envTestMulti2VecCLIPImage)
   431  		container, err := startM2VClip(ctx, networkName, image)
   432  		if err != nil {
   433  			return nil, errors.Wrapf(err, "start %s", Multi2VecCLIP)
   434  		}
   435  		for k, v := range container.envSettings {
   436  			envSettings[k] = v
   437  		}
   438  		containers = append(containers, container)
   439  	}
   440  	if d.withMulti2VecPaLM {
   441  		envSettings["PALM_APIKEY"] = d.withPaLMApiKey
   442  	}
   443  	if d.withBind {
   444  		image := os.Getenv(envTestMulti2VecBindImage)
   445  		container, err := startM2VBind(ctx, networkName, image)
   446  		if err != nil {
   447  			return nil, errors.Wrapf(err, "start %s", Multi2VecBind)
   448  		}
   449  		for k, v := range container.envSettings {
   450  			envSettings[k] = v
   451  		}
   452  		containers = append(containers, container)
   453  	}
   454  	if d.withImg2Vec {
   455  		image := os.Getenv(envTestImg2VecNeuralImage)
   456  		container, err := startI2VNeural(ctx, networkName, image)
   457  		if err != nil {
   458  			return nil, errors.Wrapf(err, "start %s", Img2VecNeural)
   459  		}
   460  		for k, v := range container.envSettings {
   461  			envSettings[k] = v
   462  		}
   463  		containers = append(containers, container)
   464  	}
   465  	if d.withRerankerTransformers {
   466  		image := os.Getenv(envTestRerankerTransformersImage)
   467  		container, err := startRerankerTransformers(ctx, networkName, image)
   468  		if err != nil {
   469  			return nil, errors.Wrapf(err, "start %s", RerankerTransformers)
   470  		}
   471  		for k, v := range container.envSettings {
   472  			envSettings[k] = v
   473  		}
   474  		containers = append(containers, container)
   475  	}
   476  	if d.withWeaviate {
   477  		image := os.Getenv(envTestWeaviateImage)
   478  		hostname := Weaviate
   479  		if d.withWeaviateCluster {
   480  			envSettings["CLUSTER_HOSTNAME"] = "node1"
   481  			envSettings["CLUSTER_GOSSIP_BIND_PORT"] = "7100"
   482  			envSettings["CLUSTER_DATA_BIND_PORT"] = "7101"
   483  		}
   484  		if d.withWeaviateBasicAuth {
   485  			envSettings["CLUSTER_BASIC_AUTH_USERNAME"] = d.withWeaviateBasicAuthUsername
   486  			envSettings["CLUSTER_BASIC_AUTH_PASSWORD"] = d.withWeaviateBasicAuthPassword
   487  		}
   488  		if d.withWeaviateAuth {
   489  			envSettings["AUTHENTICATION_OIDC_ENABLED"] = "true"
   490  			envSettings["AUTHENTICATION_OIDC_CLIENT_ID"] = "wcs"
   491  			envSettings["AUTHENTICATION_OIDC_ISSUER"] = "https://auth.wcs.api.semi.technology/auth/realms/SeMI"
   492  			envSettings["AUTHENTICATION_OIDC_USERNAME_CLAIM"] = "email"
   493  			envSettings["AUTHENTICATION_OIDC_GROUPS_CLAIM"] = "groups"
   494  			envSettings["AUTHORIZATION_ADMINLIST_ENABLED"] = "true"
   495  			envSettings["AUTHORIZATION_ADMINLIST_USERS"] = "ms_2d0e007e7136de11d5f29fce7a53dae219a51458@existiert.net"
   496  		}
   497  		for k, v := range d.weaviateEnvs {
   498  			envSettings[k] = v
   499  		}
   500  		container, err := startWeaviate(ctx, d.enableModules, d.defaultVectorizerModule,
   501  			envSettings, networkName, image, hostname, d.withWeaviateExposeGRPCPort)
   502  		if err != nil {
   503  			return nil, errors.Wrapf(err, "start %s", hostname)
   504  		}
   505  		containers = append(containers, container)
   506  	}
   507  	if d.withWeaviateCluster {
   508  		image := os.Getenv(envTestWeaviateImage)
   509  		hostname := WeaviateNode2
   510  		envSettings["CLUSTER_HOSTNAME"] = "node2"
   511  		envSettings["CLUSTER_GOSSIP_BIND_PORT"] = "7102"
   512  		envSettings["CLUSTER_DATA_BIND_PORT"] = "7103"
   513  		envSettings["CLUSTER_JOIN"] = fmt.Sprintf("%s:7100", Weaviate)
   514  		for k, v := range d.weaviateEnvs {
   515  			envSettings[k] = v
   516  		}
   517  		container, err := startWeaviate(ctx, d.enableModules, d.defaultVectorizerModule,
   518  			envSettings, networkName, image, hostname, d.withWeaviateExposeGRPCPort)
   519  		if err != nil {
   520  			return nil, errors.Wrapf(err, "start %s", hostname)
   521  		}
   522  		containers = append(containers, container)
   523  	}
   524  
   525  	if d.withSecondWeaviate {
   526  		image := os.Getenv(envTestWeaviateImage)
   527  		hostname := SecondWeaviate
   528  		secondWeaviateSettings := envSettings
   529  		// Ensure second weaviate doesn't get cluster settings from the first cluster if any.
   530  		delete(secondWeaviateSettings, "CLUSTER_HOSTNAME")
   531  		delete(secondWeaviateSettings, "CLUSTER_GOSSIP_BIND_PORT")
   532  		delete(secondWeaviateSettings, "CLUSTER_DATA_BIND_PORT")
   533  		delete(secondWeaviateSettings, "CLUSTER_JOIN")
   534  		for k, v := range d.weaviateEnvs {
   535  			envSettings[k] = v
   536  		}
   537  		container, err := startWeaviate(ctx, d.enableModules, d.defaultVectorizerModule,
   538  			envSettings, networkName, image, hostname, d.withWeaviateExposeGRPCPort)
   539  		if err != nil {
   540  			return nil, errors.Wrapf(err, "start %s", hostname)
   541  		}
   542  		containers = append(containers, container)
   543  	}
   544  
   545  	return &DockerCompose{network, containers}, nil
   546  }