diff --git a/clouddriver-integration/src/test/java/com/netflix/spinnaker/clouddriver/BaseContainerTest.java b/clouddriver-integration/src/test/java/com/netflix/spinnaker/clouddriver/BaseContainerTest.java index 87bb3be9ed..e81a4699aa 100644 --- a/clouddriver-integration/src/test/java/com/netflix/spinnaker/clouddriver/BaseContainerTest.java +++ b/clouddriver-integration/src/test/java/com/netflix/spinnaker/clouddriver/BaseContainerTest.java @@ -40,7 +40,7 @@ public class BaseContainerTest { protected final Network network = Network.newNetwork(); - private static final int CLOUDDRIVER_PORT = 7002; + protected static final int CLOUDDRIVER_PORT = 7002; protected GenericContainer clouddriverContainer; diff --git a/clouddriver-integration/src/test/java/com/netflix/spinnaker/clouddriver/PostgresMigrationContainerTest.java b/clouddriver-integration/src/test/java/com/netflix/spinnaker/clouddriver/PostgresMigrationContainerTest.java new file mode 100644 index 0000000000..7ad1faadbb --- /dev/null +++ b/clouddriver-integration/src/test/java/com/netflix/spinnaker/clouddriver/PostgresMigrationContainerTest.java @@ -0,0 +1,136 @@ +/* + * Copyright 2024 Salesforce, Inc. + * + * 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 com.netflix.spinnaker.clouddriver; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.time.Duration; +import java.util.Map; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.containers.output.Slf4jLogConsumer; +import org.testcontainers.containers.wait.strategy.Wait; +import org.testcontainers.junit.jupiter.Testcontainers; +import org.testcontainers.utility.DockerImageName; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@Testcontainers +public class PostgresMigrationContainerTest extends BaseContainerTest { + + private static final Logger logger = + LoggerFactory.getLogger(PostgresMigrationContainerTest.class); + + private static final String POSTGRES_NETWORK_ALIAS = "postgresHost"; + + private static final int POSTGRES_PORT = 5432; + + private PostgreSQLContainer postgres; + + private GenericContainer clouddriverInitialContainer; + + // this is the latest image that is still running on liquibase 3.10.3 which create the conditions + // similar to real scenario so that test identifies when validChecksums are not added in the later + // version of clouddriver where higher liquibase versions are used + private static final DockerImageName previousDockerImageName = + DockerImageName.parse( + "us-docker.pkg.dev/spinnaker-community/docker/clouddriver:5.82.2-dev-release-1.32.x-7a8e6e8b3-202406051721-unvalidated"); + + private String jdbcUrl = ""; + + @BeforeEach + void setup() throws Exception { + postgres = + new PostgreSQLContainer<>("postgres:15") + .withDatabaseName("clouddriver") + .withUsername("postgres") + .withPassword("postgres") + .withNetwork(network) + .withNetworkAliases(POSTGRES_NETWORK_ALIAS) + .withInitScript("postgres_init.sql") + .withReuse(true); + postgres.start(); + jdbcUrl = + String.format("jdbc:postgresql://%s:%d/clouddriver", POSTGRES_NETWORK_ALIAS, POSTGRES_PORT); + + // Start the first clouddriver(from previous release) container so that all the db changelog + // sets are executed + clouddriverInitialContainer = + new GenericContainer(previousDockerImageName) + .withNetwork(network) + .withExposedPorts(CLOUDDRIVER_PORT) + .waitingFor(Wait.forHealthcheck().withStartupTimeout(Duration.ofSeconds(120))) + .dependsOn(postgres) + .withEnv("SPRING_APPLICATION_JSON", getSpringApplicationJson()); + clouddriverInitialContainer.start(); + Slf4jLogConsumer logConsumer = new Slf4jLogConsumer(logger); + clouddriverInitialContainer.followOutput(logConsumer); + clouddriverInitialContainer.stop(); + + // Start the second clouddriver(latest) container to validate migration + clouddriverContainer + .dependsOn(postgres) + .withEnv("SPRING_APPLICATION_JSON", getSpringApplicationJson()) + .start(); + + clouddriverContainer.followOutput(logConsumer); + } + + private String getSpringApplicationJson() throws JsonProcessingException { + logger.info("----------- jdbcUrl: '{}'", jdbcUrl); + Map connectionPool = + Map.of("jdbcUrl", jdbcUrl, "user", "clouddriver_service", "password", "c10uddriver"); + Map migration = + Map.of("jdbcUrl", jdbcUrl, "user", "clouddriver_migrate", "password", "c10uddriver"); + + Map properties = + Map.of( + "sql.enabled", + "true", + "services.fiat.baseUrl", + "http://nowhere", + "sql.connectionPool", + connectionPool, + "redis.enabled", + "false", + "sql.migration", + migration); + ObjectMapper mapper = new ObjectMapper(); + return mapper.writeValueAsString(properties); + } + + @AfterAll + void cleanupOnce() { + if (clouddriverContainer != null) { + clouddriverContainer.stop(); + } + + if (postgres != null) { + postgres.stop(); + } + } + + @Test + void testHealthCheckWithPostgres() throws Exception { + super.testHealthCheck(); + } +} diff --git a/clouddriver-sql/src/main/resources/db/changelog/20180919-initial-schema.yml b/clouddriver-sql/src/main/resources/db/changelog/20180919-initial-schema.yml index 968a7cf4cc..2423d12ca8 100644 --- a/clouddriver-sql/src/main/resources/db/changelog/20180919-initial-schema.yml +++ b/clouddriver-sql/src/main/resources/db/changelog/20180919-initial-schema.yml @@ -82,6 +82,7 @@ databaseChangeLog: tableName: task_states - changeSet: + validCheckSum: 8:f0bfebd55de9168e38a8ef9c7217c610 id: mysql-change-state-stauts-to-enum-type author: robzienert changes: @@ -171,6 +172,7 @@ databaseChangeLog: tableName: task_results - changeSet: + validCheckSum: 8:d6f5eedc195011826620cc0355e8352d id: mysql-revert-change-state-stauts-to-enum-type author: afeldman changes: diff --git a/clouddriver-sql/src/main/resources/db/changelog/20181120-cats.yml b/clouddriver-sql/src/main/resources/db/changelog/20181120-cats.yml index 3da4c55d33..07e9e4ac52 100644 --- a/clouddriver-sql/src/main/resources/db/changelog/20181120-cats.yml +++ b/clouddriver-sql/src/main/resources/db/changelog/20181120-cats.yml @@ -216,6 +216,7 @@ databaseChangeLog: newDataType: varchar(255) - changeSet: + validCheckSum: 8:03b00d0af09f2e7081d187f246ea4d26 id: application-index author: afeldman changes: diff --git a/clouddriver-sql/src/main/resources/db/changelog/20190913-task-sagaids.yml b/clouddriver-sql/src/main/resources/db/changelog/20190913-task-sagaids.yml index 325e3456d6..7b15d45e8a 100644 --- a/clouddriver-sql/src/main/resources/db/changelog/20190913-task-sagaids.yml +++ b/clouddriver-sql/src/main/resources/db/changelog/20190913-task-sagaids.yml @@ -4,6 +4,7 @@ databaseChangeLog: dbms: postgresql remove: afterColumn - changeSet: + validCheckSum: 8:91cfabe4a8fa0517124436ef9675708e id: add-task-sagaids-column author: robzienert changes: @@ -19,6 +20,7 @@ databaseChangeLog: columnName: saga_ids - changeSet: + validCheckSum: 8:9601af668599fbc12e338b9b84c66f56 id: mysql-update-state-enum-values author: robzienert changes: