Skip to content

Commit

Permalink
Set up DB config; update README
Browse files Browse the repository at this point in the history
  • Loading branch information
danlysiak committed Oct 24, 2023
1 parent b85d989 commit 3e7fee9
Show file tree
Hide file tree
Showing 22 changed files with 299 additions and 68 deletions.
80 changes: 55 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,41 @@
# opal-account-enquiry
# Opal Account Enquiry

## Getting Started

### Prerequisites
- [JDK 17](https://java.com)
- [Docker](https://docker.com)

## Building and deploying the application

### Building the application
### Running the application

The project uses [Gradle](https://gradle.org) as a build tool. It already contains
`./gradlew` wrapper script, so there's no need to install gradle.
#### Approach 1: Dev Application (No existing dependencies)

To build the project execute the following command:
The simplest way to run the application is using the `bootTestRun` Gradle task:

```bash
./gradlew build
./gradlew bootTestRun
```

### Running the application
This task has no dependencies and starts up a Postgres database in Docker using [Testcontainers](https://testcontainers.com).
The database is available on `jdbc:postgresql://localhost:5432/opal_db` with username and password `opal`.

To persist the database between application restarts set the environment variable `TESTCONTAINERS_REUSE_ENABLE` to `true`.
Note this does **not** persist data if the Docker container is manually stopped, or through laptop restarts).

#### Approach 2: Dev Application (With existing dependencies)

Use the standard Spring Boot `run` Gradle task:

```bash
./gradlew run
```

This approach can be used if a database is already running and may be preferred if the lack of long-term data persistence
from the previous approach is an issue for development.

#### Approach 3: Docker

Create the image of the application by executing the following command:

Expand All @@ -34,24 +56,7 @@ by executing the following command:
docker-compose up
```

This will start the API container exposing the application's port
(set to `4550` in this template app).

In order to test if the application is up, you can call its health endpoint:

```bash
curl http://localhost:4550/health
```

You should get a response similar to this:

```
{"status":"UP","diskSpace":{"status":"UP","total":249644974080,"free":137188298752,"threshold":10485760}}
```

### Alternative script to run application

To skip all the setting up and building, just execute the following command:
To skip all the setting up and building with Docker, just execute the following command:

```bash
./bin/run-in-docker.sh
Expand Down Expand Up @@ -79,6 +84,31 @@ docker image rm <image-id>

There is no need to remove postgres and java or similar core images.

### Verifying application startup

Regardless of approach followed for starting the application, in order to test if the application is up, you can call its health endpoint:

```bash
curl http://localhost:4550/health
```

You should get a response similar to this:

```
{"status":"UP","diskSpace":{"status":"UP","total":249644974080,"free":137188298752,"threshold":10485760}}
```

### Building the application

The project uses [Gradle](https://gradle.org) as a build tool. It already contains
`./gradlew` wrapper script, so there's no need to install gradle.

To build the project execute the following command:

```bash
./gradlew build
```

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details
Expand Down
37 changes: 37 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ plugins {
id 'com.github.ben-manes.versions' version '0.49.0'
id 'org.sonarqube' version '4.4.1.3373'
id 'uk.gov.hmcts.java' version '0.12.47'
id 'org.flywaydb.flyway' version '9.22.3'
}

group = 'uk.gov.hmcts'
Expand Down Expand Up @@ -130,6 +131,10 @@ dependencyUpdates {
}
}

dependencyCheck {
suppressionFile = 'config/owasp/suppressions.xml'
}

repositories {
mavenLocal()
mavenCentral()
Expand All @@ -149,6 +154,7 @@ dependencies {
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-actuator'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-aop'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-json'
implementation group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa'
implementation group: 'org.springdoc', name: 'springdoc-openapi-starter-webmvc-ui', version: '2.2.0'

implementation group: 'com.github.hmcts.java-logging', name: 'logging', version: '6.0.1'
Expand All @@ -158,6 +164,13 @@ dependencies {

implementation group: 'io.rest-assured', name: 'rest-assured'

implementation 'org.flywaydb:flyway-core'
implementation 'org.postgresql:postgresql'

testImplementation 'org.springframework.boot:spring-boot-devtools'
testImplementation 'org.springframework.boot:spring-boot-testcontainers'
testImplementation 'org.testcontainers:junit-jupiter:1.19.1'
testImplementation 'org.testcontainers:postgresql'
testImplementation(platform('org.junit:junit-bom:5.10.0'))
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine'
testImplementation group: 'org.springframework.boot', name: 'spring-boot-starter-test', {
Expand All @@ -181,6 +194,30 @@ rootProject.tasks.named("processSmokeTestResources") {
duplicatesStrategy = 'include'
}

rootProject.tasks.named("processFunctionalTestResources") {
duplicatesStrategy = 'include'
}

rootProject.tasks.named("processIntegrationTestResources") {
duplicatesStrategy = 'include'
}

wrapper {
distributionType = Wrapper.DistributionType.ALL
}

flyway {
url = System.getenv('FLYWAY_URL')
user = System.getenv('FLYWAY_USER')
password = System.getenv('FLYWAY_PASSWORD')
baselineOnMigrate = true
baselineVersion = '000'
}

task migratePostgresDatabase(type: org.flywaydb.gradle.task.FlywayMigrateTask) {
baselineOnMigrate = true
if (project.hasProperty("dburl")) {
url = "jdbc:postgresql://${dburl}"
}
}

4 changes: 2 additions & 2 deletions charts/opal-account-enquiry/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
apiVersion: v2
appVersion: "1.0"
description: A Helm chart for opal-account-enquiry App
description: A Helm chart for opal-account-enquiry app
name: opal-account-enquiry
home: https://github.com/hmcts/opal-account-enquiry
version: 0.0.10
maintainers:
- name: HMCTS OPAL Team
- name: HMCTS Opal Team
dependencies:
- name: java
version: 5.0.0
Expand Down
10 changes: 10 additions & 0 deletions charts/opal-account-enquiry/values.preview.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,13 @@ java:
# Don't modify below here
image: ${IMAGE_NAME}
ingressHost: ${SERVICE_FQDN}
environment:
OPAL_DB_HOST: "{{ .Release.Name }}-postgresql"
OPAL_DB_NAME: "{{ .Values.postgresql.auth.database}}"
OPAL_DB_USERNAME: "{{ .Values.postgresql.auth.username}}"
OPAL_DB_PASSWORD: "{{ .Values.postgresql.auth.password}}"
OPAL_DB_OPTIONS: "?stringtype=unspecified"
OPAL_DB_PORT: 5432
RUN_DB_MIGRATION_ON_STARTUP: true
postgresql:
enabled: true
1 change: 1 addition & 0 deletions charts/opal-account-enquiry/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ java:
# - name: AppInsightsInstrumentationKey
# alias: azure.application-insights.instrumentation-key
environment:
RUN_DB_MIGRATION_ON_STARTUP: false
8 changes: 1 addition & 7 deletions config/owasp/suppressions.xml
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
<!--Please add all the false positives under the below section-->
<suppress>
<notes>False Positive
<![CDATA[file name: jackson-databind-2.15.2.jar]]>
</notes>
<packageUrl regex="true">^pkg:maven/com\.fasterxml\.jackson\.core/jackson\-databind@.*$</packageUrl>
<cve>CVE-2023-35116</cve>
</suppress>

<!--End of false positives section -->
</suppressions>
18 changes: 18 additions & 0 deletions src/functionalTest/java/uk/gov/hmcts/opal/BaseFunctionalTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package uk.gov.hmcts.opal;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.test.context.ActiveProfiles;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

@Testcontainers
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles({"functional"})
public class BaseFunctionalTest {

@ServiceConnection
@Container
static PostgreSQLContainer databaseContainer = new PostgreSQLContainer<>("postgres:15-alpine");
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,15 @@
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import uk.gov.hmcts.opal.BaseFunctionalTest;

import static io.restassured.RestAssured.given;

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
class SampleFunctionalTest {
class SampleFunctionalTest extends BaseFunctionalTest {
protected static final String CONTENT_TYPE_VALUE = "application/json";

@Value("${TEST_URL:http://localhost:8080}")
@Value("${TEST_URL:http://localhost:4550}")
private String testUrl;

@BeforeEach
Expand Down
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package uk.gov.hmcts.opal;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.test.context.ActiveProfiles;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;

@Testcontainers
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ActiveProfiles({"integration"})
public class BaseIntegrationTest {

@ServiceConnection
@Container
static PostgreSQLContainer databaseContainer = new PostgreSQLContainer<>("postgres:15-alpine");
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,10 @@

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import uk.gov.hmcts.opal.BaseIntegrationTest;

import java.io.OutputStream;
import java.nio.file.Files;
Expand All @@ -20,10 +18,8 @@
* Built-in feature which saves service's swagger specs in temporary directory.
* Each CI run on master should automatically save and upload (if updated) documentation.
*/
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@AutoConfigureMockMvc
class OpenAPIPublisherTest {
class OpenAPIPublisherTest extends BaseIntegrationTest {

@Autowired
private MockMvc mvc;
Expand Down
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ public class OpenAPIConfiguration {
@Bean
public OpenAPI openAPI() {
return new OpenAPI()
.info(new Info().title("OPAL Account Enquiry")
.description("OPAL Account Enquiry")
.info(new Info().title("Opal Account Enquiry")
.description("Opal Account Enquiry")
.version("v0.0.1")
.license(new License().name("MIT").url("https://opensource.org/licenses/MIT")))
.externalDocs(new ExternalDocumentation()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package uk.gov.hmcts.opal.config.db.migration;

import org.flywaydb.core.Flyway;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationStrategy;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@AutoConfigureAfter({
DataSourceAutoConfiguration.class,
HibernateJpaAutoConfiguration.class
})
@AutoConfigureBefore(FlywayAutoConfiguration.class)
@Configuration
@ConditionalOnClass(Flyway.class)
@ConditionalOnProperty(prefix = "dbMigration", name = "runOnStartup", havingValue = "false")
public class FlywayConfiguration {

@Bean
public FlywayMigrationStrategy flywayMigrationStrategy() {
return new FlywayNoOpStrategy();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package uk.gov.hmcts.opal.config.db.migration;

import org.flywaydb.core.Flyway;
import org.springframework.boot.autoconfigure.flyway.FlywayMigrationStrategy;

import java.util.stream.Stream;

public class FlywayNoOpStrategy implements FlywayMigrationStrategy {

@Override
public void migrate(Flyway flyway) {
Stream.of(flyway.info().all())
.filter(info -> !info.getState().isApplied())
.findFirst()
.ifPresent(info -> {
throw new PendingMigrationScriptException(info.getScript());
});
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package uk.gov.hmcts.opal.config.db.migration;

public class PendingMigrationScriptException extends RuntimeException {

public PendingMigrationScriptException(String script) {
super("Found migration not yet applied: " + script);
}
}
Loading

0 comments on commit 3e7fee9

Please sign in to comment.