Skip to content

Commit

Permalink
Generate test application with pgvector and spring-ai if pgvector is …
Browse files Browse the repository at this point in the history
…selected

See gh-1420
  • Loading branch information
eddumelendez authored and mhalbritter committed Mar 25, 2024
1 parent 9fde8e4 commit 852ffbd
Show file tree
Hide file tree
Showing 7 changed files with 162 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ public SimpleDockerServiceResolver() {
this.dockerServices.put("neo4j", neo4j());
this.dockerServices.put("oracleFree", oracleFree());
this.dockerServices.put("oracleXe", oracleXe());
this.dockerServices.put("pgvector", pgvector());
this.dockerServices.put("postgres", postgres());
this.dockerServices.put("pulsar", pulsar());
this.dockerServices.put("rabbit", rabbit());
Expand Down Expand Up @@ -127,6 +128,13 @@ private static DockerService oracleXe() {
.build();
}

private static DockerService pgvector() {
return DockerService.withImageAndTag("pgvector/pgvector:pg16")
.website("https://hub.docker.com/r/pgvector/pgvector")
.ports(5432)
.build();
}

private static DockerService postgres() {
return DockerService.withImageAndTag("postgres")
.website("https://hub.docker.com/_/postgres")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright 2012-2024 the original author or authors.
*
* 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
*
* https://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 io.spring.start.site.extension.dependency.postgresql;

import java.util.Map;

import io.spring.initializr.generator.condition.ConditionalOnRequestedDependency;
import io.spring.initializr.generator.project.ProjectDescription;
import io.spring.initializr.generator.version.Version;
import io.spring.initializr.generator.version.VersionParser;
import io.spring.initializr.generator.version.VersionRange;
import io.spring.initializr.versionresolver.MavenVersionResolver;
import io.spring.start.site.container.ComposeFileCustomizer;
import io.spring.start.site.container.DockerServiceResolver;
import io.spring.start.site.container.ServiceConnections.ServiceConnection;
import io.spring.start.site.container.ServiceConnectionsCustomizer;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
* Configuration for generation of projects that depend on PgVector.
*
* @author Eddú Meléndez
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnRequestedDependency("spring-ai-vectordb-pgvector")
class PgVectorProjectGenerationConfiguration {

private static final String TESTCONTAINERS_CLASS_NAME = "org.testcontainers.containers.PostgreSQLContainer";

private static final VersionRange TESTCONTAINERS_1_19_7_OR_LATER = VersionParser.DEFAULT.parseRange("1.19.7");

private final MavenVersionResolver versionResolver;

private final ProjectDescription description;

PgVectorProjectGenerationConfiguration(MavenVersionResolver versionResolver, ProjectDescription description) {
this.versionResolver = versionResolver;
this.description = description;
}

@Bean
@ConditionalOnRequestedDependency("testcontainers")
ServiceConnectionsCustomizer pgvectorServiceConnectionsCustomizer(DockerServiceResolver serviceResolver) {
Map<String, String> resolve = this.versionResolver.resolveDependencies("org.springframework.boot",
"spring-boot-dependencies", this.description.getPlatformVersion().toString());
String testcontainersVersion = resolve.get("org.testcontainers:testcontainers");

return (serviceConnections) -> {
if (TESTCONTAINERS_1_19_7_OR_LATER.match(Version.parse(testcontainersVersion))) {
serviceResolver.doWith("pgvector", (service) -> serviceConnections.addServiceConnection(
ServiceConnection.ofContainer("pgvector", service, TESTCONTAINERS_CLASS_NAME)));
}
};
}

@Bean
@ConditionalOnRequestedDependency("docker-compose")
ComposeFileCustomizer pgvectorComposeFileCustomizer(DockerServiceResolver serviceResolver) {
return (composeFile) -> serviceResolver.doWith("pgvector",
(service) -> composeFile.services()
.add("pgvector",
service.andThen((builder) -> builder.environment("POSTGRES_USER", "myuser")
.environment("POSTGRES_DB", "mydatabase")
.environment("POSTGRES_PASSWORD", "secret")
.label("org.springframework.boot.service-connection", "postgres"))));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ static Iterable<ImplicitDependency> create(Version platformVersion) {
builders.add(onDependencies("oracle").customizeBuild(addModule("oracle-xe"))
.customizeHelpDocument(addReferenceLink("Oracle-XE Module", "databases/oraclexe/")));
}
builders.add(onDependencies("postgresql").customizeBuild(addModule("postgresql"))
builders.add(onDependencies("postgresql", "spring-ai-vectordb-pgvector").customizeBuild(addModule("postgresql"))
.customizeHelpDocument(addReferenceLink("Postgres Module", "databases/postgres/")));
builders.add(onDependencies("pulsar", "pulsar-reactive").customizeBuild(addModule("pulsar"))
.customizeHelpDocument(addReferenceLink("Pulsar Module", "pulsar/")));
Expand Down
1 change: 1 addition & 0 deletions start-site/src/main/resources/META-INF/spring.factories
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ io.spring.start.site.extension.dependency.neo4j.Neo4jProjectGenerationConfigurat
io.spring.start.site.extension.dependency.observability.ObservabilityProjectGenerationConfiguration,\
io.spring.start.site.extension.dependency.oracle.OracleProjectGenerationConfiguration,\
io.spring.start.site.extension.dependency.picocli.PicocliProjectGenerationConfiguration,\
io.spring.start.site.extension.dependency.postgresql.PgVectorProjectGenerationConfiguration,\
io.spring.start.site.extension.dependency.postgresql.PostgresqlProjectGenerationConfiguration,\
io.spring.start.site.extension.dependency.redis.RedisProjectGenerationConfiguration,\
io.spring.start.site.extension.dependency.solace.SolaceProjectGenerationConfiguration,\
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2012-2024 the original author or authors.
*
* 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
*
* https://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 io.spring.start.site.extension.dependency.postgresql;

import io.spring.initializr.generator.test.project.ProjectStructure;
import io.spring.initializr.web.project.ProjectRequest;
import io.spring.start.site.extension.AbstractExtensionTests;
import org.junit.jupiter.api.Test;

import org.springframework.core.io.ClassPathResource;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Tests for {@link PgVectorProjectGenerationConfiguration}.
*
* @author Eddú Meléndez
*/
class PgVectorProjectGenerationConfigurationTests extends AbstractExtensionTests {

@Test
void doesNothingWithoutDockerCompose() {
ProjectRequest request = createProjectRequest("web", "spring-ai-vectordb-pgvector");
ProjectStructure structure = generateProject(request);
assertThat(structure.getProjectDirectory().resolve("compose.yaml")).doesNotExist();
}

@Test
void createsPostgresService() {
ProjectRequest request = createProjectRequest("docker-compose", "spring-ai-vectordb-pgvector");
assertThat(composeFile(request)).hasSameContentAs(new ClassPathResource("compose/pgvector.yaml"));
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,15 @@ static Stream<Arguments> supportedEntriesBuild() {
Arguments.arguments("data-couchbase-reactive", "couchbase"),
Arguments.arguments("data-elasticsearch", "elasticsearch"),
Arguments.arguments("data-mongodb", "mongodb"), Arguments.arguments("data-mongodb-reactive", "mongodb"),
Arguments.arguments("data-neo4j", "neo4j"), Arguments.arguments("spring-ai-vectordb-neo4j", "neo4j"),
Arguments.arguments("data-r2dbc", "r2dbc"), Arguments.arguments("db2", "db2"),
Arguments.arguments("kafka", "kafka"), Arguments.arguments("kafka-streams", "kafka"),
Arguments.arguments("mariadb", "mariadb"), Arguments.arguments("mysql", "mysql"),
Arguments.arguments("postgresql", "postgresql"), Arguments.arguments("oracle", "oracle-xe"),
Arguments.arguments("pulsar", "pulsar"), Arguments.arguments("pulsar-reactive", "pulsar"),
Arguments.arguments("solace", "solace"), Arguments.arguments("sqlserver", "mssqlserver"));
Arguments.arguments("data-neo4j", "neo4j"), Arguments.arguments("data-r2dbc", "r2dbc"),
Arguments.arguments("db2", "db2"), Arguments.arguments("kafka", "kafka"),
Arguments.arguments("kafka-streams", "kafka"), Arguments.arguments("mariadb", "mariadb"),
Arguments.arguments("mysql", "mysql"), Arguments.arguments("postgresql", "postgresql"),
Arguments.arguments("oracle", "oracle-xe"), Arguments.arguments("pulsar", "pulsar"),
Arguments.arguments("pulsar-reactive", "pulsar"), Arguments.arguments("solace", "solace"),
Arguments.arguments("spring-ai-vectordb-neo4j", "neo4j"),
Arguments.arguments("spring-ai-vectordb-pgvector", "postgresql"),
Arguments.arguments("sqlserver", "mssqlserver"));
}

static Stream<Arguments> supportedTestcontainersActiveMQEntriesBuild() {
Expand Down
11 changes: 11 additions & 0 deletions start-site/src/test/resources/compose/pgvector.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
services:
pgvector:
image: 'pgvector/pgvector:pg16'
environment:
- 'POSTGRES_DB=mydatabase'
- 'POSTGRES_PASSWORD=secret'
- 'POSTGRES_USER=myuser'
labels:
- "org.springframework.boot.service-connection=postgres"
ports:
- '5432'

0 comments on commit 852ffbd

Please sign in to comment.