From: Bruno Sakoto Date: Tue, 20 Apr 2021 12:22:56 +0000 (-0400) Subject: Implement db schema with liquibase X-Git-Tag: 0.0.1~22 X-Git-Url: https://gerrit.onap.org/r/gitweb?a=commitdiff_plain;h=05855d531b912698ee63b1fd9de4303baff83670;p=cps%2Fcps-temporal.git Implement db schema with liquibase Issue-ID: CPS-193 Signed-off-by: Bruno Sakoto Change-Id: Ieabee4b86bbe7a42c05bb225499487cfcc9deb1d --- diff --git a/README.md b/README.md index e0f8ffb..45ebd4e 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,26 @@ # CPS Temporal Service -For now, this repo contains a very minimalist skeleton of the application. \ No newline at end of file +For now, this repo contains a very minimalist skeleton of the application. + +## Local DB setup + +A Postgres instance with Timescale extension can be started by running the following command: + +``` +docker run --name postgres-cps-temporal -p 5433:5432 -d \ + -e POSTGRES_DB=cpstemporaldb \ + -e POSTGRES_USER=cpstemporal \ + -e POSTGRES_PASSWORD=cpstemporal \ + timescale/timescaledb:2.1.1-pg13 +``` + +[Liquibase](https://www.liquibase.org/) is used to manage database schema changes and versions. +Then, the database schema is updated when the application is started or by running the following command: + +``` +mvn org.liquibase:liquibase-maven-plugin:4.3.2:update \ + -Dliquibase.url=jdbc:postgresql://localhost:5433/cpstemporaldb \ + -Dliquibase.username=cpstemporal \ + -Dliquibase.password=cpstemporal \ + -Dliquibase.changeLogFile=db/changelog/changelog-master.xml +``` diff --git a/pom.xml b/pom.xml index 8648046..e9a68a5 100644 --- a/pom.xml +++ b/pom.xml @@ -67,6 +67,21 @@ org.springframework.boot spring-boot-starter-web + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.liquibase + liquibase-core + 4.3.2 + + + + org.postgresql + postgresql + runtime + org.codehaus.groovy @@ -89,6 +104,18 @@ spock-core test + + org.testcontainers + junit-jupiter + 1.15.2 + test + + + org.testcontainers + postgresql + 1.15.2 + test + @@ -96,6 +123,7 @@ org.springframework.boot spring-boot-maven-plugin + 2.3.3.RELEASE + true + diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..0db1792 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,23 @@ +# ============LICENSE_START======================================================= +# Copyright (c) 2021 Bell Canada. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= + +spring: + datasource: + url: jdbc:postgresql://${DB_HOST}:${DB_PORT}/${DB_NAME} + username: ${DB_USERNAME} + password: ${DB_PASSWORD} + liquibase: + change-log: classpath:/db/changelog/changelog-master.xml diff --git a/src/main/resources/db/changelog/changelog-master.xml b/src/main/resources/db/changelog/changelog-master.xml new file mode 100644 index 0000000..630d399 --- /dev/null +++ b/src/main/resources/db/changelog/changelog-master.xml @@ -0,0 +1,29 @@ + + + + + + + + + diff --git a/src/main/resources/db/changelog/data/02-init-data.dat b/src/main/resources/db/changelog/data/02-init-data.dat new file mode 100644 index 0000000..338444b --- /dev/null +++ b/src/main/resources/db/changelog/data/02-init-data.dat @@ -0,0 +1,537 @@ +timestamp|dataspace|schema_set|anchor|version|payload +(select now())|NFP-Operational|cps-ran-schema-model|ran-network-simulation|(select now())|' +{ + "NearRTRIC": [ + { + "idNearRTRIC": "22", + "GNBCUUPFunction": [ + { + "idGNBCUUPFunction": "2222", + "attributes": { + "gNBId": 98763.0 + } + } + ], + "GNBDUFunction": [ + { + "idGNBDUFunction": "5", + "NRCellDU": [ + { + "idNRCellDU": "13910", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 13910.0 + } + }, + { + "idNRCellDU": "10897", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 10897.0 + } + }, + { + "idNRCellDU": "14656", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 14656.0 + } + }, + { + "idNRCellDU": "13905", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 13905.0 + } + }, + { + "idNRCellDU": "14655", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 14655.0 + } + } + ], + "attributes": { + "gNBDUId": 5.0, + "gNBDUName": "gnduserver5", + "gNBIdLength": 32.0 + } + }, + { + "idGNBDUFunction": "4", + "NRCellDU": [ + { + "idNRCellDU": "11569", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 11569.0 + } + }, + { + "idNRCellDU": "11568", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 11568.0 + } + }, + { + "idNRCellDU": "11561", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 11561.0 + } + }, + { + "idNRCellDU": "10896", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 10896.0 + } + }, + { + "idNRCellDU": "11562", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 11562.0 + } + } + ], + "attributes": { + "gNBDUId": 4.0, + "gNBDUName": "gnduserver4", + "gNBIdLength": 32.0 + } + }, + { + "idGNBDUFunction": "6", + "NRCellDU": [ + { + "idNRCellDU": "14427", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 14427.0 + } + }, + { + "idNRCellDU": "15361", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15361.0 + } + }, + { + "idNRCellDU": "15548", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15548.0 + } + }, + { + "idNRCellDU": "15360", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15360.0 + } + }, + { + "idNRCellDU": "15549", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15549.0 + } + } + ], + "attributes": { + "gNBDUId": 6.0, + "gNBDUName": "gnduserver6", + "gNBIdLength": 32.0 + } + } + ], + "GNBCUCPFunction": [ + { + "idGNBCUCPFunction": "cucpserver2", + "NRCellCU": [ + { + "idNRCellCU": "13910", + "attributes": { + "cellLocalId": 13910.0 + } + }, + { + "idNRCellCU": "14656", + "attributes": { + "cellLocalId": 14656.0 + } + }, + { + "idNRCellCU": "10897", + "attributes": { + "cellLocalId": 10897.0 + } + }, + { + "idNRCellCU": "14655", + "attributes": { + "cellLocalId": 14655.0 + } + }, + { + "idNRCellCU": "11561", + "attributes": { + "cellLocalId": 11561.0 + } + }, + { + "idNRCellCU": "11569", + "attributes": { + "cellLocalId": 11569.0 + } + }, + { + "idNRCellCU": "13905", + "attributes": { + "cellLocalId": 13905.0 + } + }, + { + "idNRCellCU": "15549", + "attributes": { + "cellLocalId": 15549.0 + } + }, + { + "idNRCellCU": "15361", + "attributes": { + "cellLocalId": 15361.0 + } + }, + { + "idNRCellCU": "15548", + "attributes": { + "cellLocalId": 15548.0 + } + }, + { + "idNRCellCU": "15360", + "attributes": { + "cellLocalId": 15360.0 + } + }, + { + "idNRCellCU": "14427", + "attributes": { + "cellLocalId": 14427.0 + } + }, + { + "idNRCellCU": "11562", + "attributes": { + "cellLocalId": 11562.0 + } + }, + { + "idNRCellCU": "11568", + "attributes": { + "cellLocalId": 11568.0 + } + }, + { + "idNRCellCU": "10896", + "attributes": { + "cellLocalId": 10896.0 + } + } + ], + "attributes": { + "gNBId": 98763.0, + "gNBCUName": "cucpserver2", + "gNBIdLength": 32.0 + } + } + ] + }, + { + "idNearRTRIC": "11", + "GNBCUUPFunction": [ + { + "idGNBCUUPFunction": "1111", + "attributes": { + "gNBId": 98763.0 + } + } + ], + "GNBDUFunction": [ + { + "idGNBDUFunction": "1", + "NRCellDU": [ + { + "idNRCellDU": "15289", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15289.0 + } + }, + { + "idNRCellDU": "15290", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15290.0 + } + }, + { + "idNRCellDU": "15689", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15689.0 + } + }, + { + "idNRCellDU": "15687", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15687.0 + } + }, + { + "idNRCellDU": "15296", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15296.0 + } + } + ], + "attributes": { + "gNBDUId": 1.0, + "gNBDUName": "gnduserver1", + "gNBIdLength": 32.0 + } + }, + { + "idGNBDUFunction": "2", + "NRCellDU": [ + { + "idNRCellDU": "15175", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15175.0 + } + }, + { + "idNRCellDU": "15176", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15176.0 + } + }, + { + "idNRCellDU": "15155", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15155.0 + } + }, + { + "idNRCellDU": "15825", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15825.0 + } + }, + { + "idNRCellDU": "15174", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15174.0 + } + } + ], + "attributes": { + "gNBDUId": 2.0, + "gNBDUName": "gnduserver2", + "gNBIdLength": 32.0 + } + }, + { + "idGNBDUFunction": "3", + "NRCellDU": [ + { + "idNRCellDU": "15826", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15826.0 + } + }, + { + "idNRCellDU": "15425", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15425.0 + } + }, + { + "idNRCellDU": "14000", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 14000.0 + } + }, + { + "idNRCellDU": "13999", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 13999.0 + } + }, + { + "idNRCellDU": "15426", + "attributes": { + "nRPCI": 12.0, + "nRTAC": 310.0, + "cellLocalId": 15426.0 + } + } + ], + "attributes": { + "gNBDUId": 3.0, + "gNBDUName": "gnduserver3", + "gNBIdLength": 32.0 + } + } + ], + "GNBCUCPFunction": [ + { + "idGNBCUCPFunction": "cucpserver1", + "NRCellCU": [ + { + "idNRCellCU": "15176", + "attributes": { + "cellLocalId": 15176.0 + } + }, + { + "idNRCellCU": "15296", + "attributes": { + "cellLocalId": 15296.0 + } + }, + { + "idNRCellCU": "15174", + "attributes": { + "cellLocalId": 15174.0 + } + }, + { + "idNRCellCU": "15290", + "attributes": { + "cellLocalId": 15290.0 + } + }, + { + "idNRCellCU": "15825", + "attributes": { + "cellLocalId": 15825.0 + } + }, + { + "idNRCellCU": "15689", + "attributes": { + "cellLocalId": 15689.0 + } + }, + { + "idNRCellCU": "15175", + "attributes": { + "cellLocalId": 15175.0 + } + }, + { + "idNRCellCU": "15426", + "attributes": { + "cellLocalId": 15426.0 + } + }, + { + "idNRCellCU": "15687", + "attributes": { + "cellLocalId": 15687.0 + } + }, + { + "idNRCellCU": "15826", + "attributes": { + "cellLocalId": 15826.0 + } + }, + { + "idNRCellCU": "14000", + "attributes": { + "cellLocalId": 14000.0 + } + }, + { + "idNRCellCU": "15425", + "attributes": { + "cellLocalId": 15425.0 + } + }, + { + "idNRCellCU": "15289", + "attributes": { + "cellLocalId": 15289.0 + } + }, + { + "idNRCellCU": "13999", + "attributes": { + "cellLocalId": 13999.0 + } + }, + { + "idNRCellCU": "15155", + "attributes": { + "cellLocalId": 15155.0 + } + } + ], + "attributes": { + "gNBId": 98763.0, + "gNBCUName": "cucpserver1", + "gNBIdLength": 32.0 + } + } + ] + } + ] +} +' diff --git a/src/main/resources/db/changelog/data/02-init-data.xml b/src/main/resources/db/changelog/data/02-init-data.xml new file mode 100644 index 0000000..24898ba --- /dev/null +++ b/src/main/resources/db/changelog/data/02-init-data.xml @@ -0,0 +1,51 @@ + + + + + + + Create initialization data + + + + + + + + + + + + dataspace = 'NFP-Operational' + and schema_set = 'cps-ran-schema-model' + and anchor ='ran-network-simulation' + + + + + + diff --git a/src/main/resources/db/changelog/schema/01-init-schema.xml b/src/main/resources/db/changelog/schema/01-init-schema.xml new file mode 100644 index 0000000..b10cd00 --- /dev/null +++ b/src/main/resources/db/changelog/schema/01-init-schema.xml @@ -0,0 +1,92 @@ + + + + + + + Create network data timescale table + + + + + + + + + + + + + + + + + + + + + + SELECT create_hypertable('network_data', 'timestamp', chunk_time_interval => interval '1 minute'); + + + + DROP table network_data; + + + + + + Create indexes on network data + + + + + + + + + + + + + + Create GIN index on network data payload + + CREATE INDEX network_data_payload_idx ON network_data USING GIN (payload); + + + + DROP INDEX network_data_payload_idx; + + + + + diff --git a/src/test/java/org/onap/cps/temporal/ApplicationTest.java b/src/test/java/org/onap/cps/temporal/ApplicationTest.java index 842b94a..bae6e65 100644 --- a/src/test/java/org/onap/cps/temporal/ApplicationTest.java +++ b/src/test/java/org/onap/cps/temporal/ApplicationTest.java @@ -1,7 +1,6 @@ /* * ============LICENSE_START======================================================= * Copyright (c) 2021 Bell Canada. - * Modifications Copyright (C) 2021 Bell Canada. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,6 +20,7 @@ package org.onap.cps.temporal; import org.assertj.core.util.Arrays; import org.junit.jupiter.api.Test; +import org.onap.cps.temporal.repository.TimescaleContainer; import org.springframework.boot.test.context.SpringBootTest; // This test class without any assertion is obviously not really useful. @@ -29,6 +29,12 @@ import org.springframework.boot.test.context.SpringBootTest; @SpringBootTest class ApplicationTest { + private static final TimescaleContainer TIMESCALE_CONTAINER = TimescaleContainer.getInstance(); + + static { + TIMESCALE_CONTAINER.start(); + } + @Test void testMain() { Application.main(Arrays.array()); diff --git a/src/test/java/org/onap/cps/temporal/repository/TimescaleContainer.java b/src/test/java/org/onap/cps/temporal/repository/TimescaleContainer.java new file mode 100644 index 0000000..73b8c13 --- /dev/null +++ b/src/test/java/org/onap/cps/temporal/repository/TimescaleContainer.java @@ -0,0 +1,68 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (c) 2021 Bell Canada. + * ================================================================================ + * 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. + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.temporal.repository; + +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.utility.DockerImageName; + +/** + * Container for timescale database. + */ +public class TimescaleContainer extends PostgreSQLContainer { + + private static final String IMAGE_NAME = "timescale/timescaledb:2.1.1-pg13"; + private static final DockerImageName DOCKER_IMAGE_NAME = + DockerImageName.parse(IMAGE_NAME).asCompatibleSubstituteFor("postgres"); + + private static TimescaleContainer container; + + private TimescaleContainer() { + super(DOCKER_IMAGE_NAME); + } + + /** + * Get the unique container instance. + * @return the container instance. + */ + public static TimescaleContainer getInstance() { + if (container == null) { + container = new TimescaleContainer(); + Runtime.getRuntime().addShutdownHook(new Thread(container::terminate)); + } + return container; + } + + @Override + public void start() { + super.start(); + System.setProperty("DB_URL", container.getJdbcUrl()); + System.setProperty("DB_USERNAME", container.getUsername()); + System.setProperty("DB_PASSWORD", container.getPassword()); + } + + @Override + public void stop() { + // Do nothing on test completion, container removal is performed via terminate() on JVM shutdown. + } + + private void terminate() { + super.stop(); + } + +} diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml new file mode 100644 index 0000000..5f64bd9 --- /dev/null +++ b/src/test/resources/application.yml @@ -0,0 +1,23 @@ +# ============LICENSE_START======================================================= +# Copyright (c) 2021 Bell Canada. +# ================================================================================ +# 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. +# ============LICENSE_END========================================================= + +spring: + datasource: + url: ${DB_URL} + password: ${DB_PASSWORD} + username: ${DB_USERNAME} + liquibase: + change-log: classpath:/db/changelog/changelog-master.xml