diff options
author | aravind.est <aravindhan.a@est.tech> | 2024-08-14 17:35:33 +0100 |
---|---|---|
committer | aravind.est <aravindhan.a@est.tech> | 2024-08-15 13:32:49 +0100 |
commit | b15c0ce6de0a226a5850977af717ef0b85d3c759 (patch) | |
tree | 5a128b3cb22702323bd1f9cff767bd9cebe5cd81 /a1-policy-management/src | |
parent | ecd99896ee598c29a228c8acbf2e72f81310a42e (diff) |
Add database support
Postgres database support added.
Issue-ID: CCSDK-4033
Change-Id: I1bd74a4b7f4454accb0a9b04cd37fe5d95700885
Signed-off-by: aravind.est <aravindhan.a@est.tech>
Diffstat (limited to 'a1-policy-management/src')
14 files changed, 833 insertions, 3 deletions
diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java index 71eae06f..0f077a13 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java @@ -3,6 +3,7 @@ * ONAP : ccsdk oran * ====================================================================== * Copyright (C) 2019-2020 Nordix Foundation. All rights reserved. + * Copyright (C) 2023-2024 OpenInfra Foundation Europe. All rights reserved. * ====================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +37,7 @@ import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactor import org.springframework.boot.web.reactive.server.ReactiveWebServerFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; @Configuration public class BeanFactory { @@ -54,6 +56,7 @@ public class BeanFactory { } @Bean + @DependsOn("springContextProvider") public Services getServices(@Autowired ApplicationConfig applicationConfig) { Services services = new Services(applicationConfig); services.restoreFromDatabase().subscribe(); @@ -61,6 +64,7 @@ public class BeanFactory { } @Bean + @DependsOn("springContextProvider") public PolicyTypes getPolicyTypes(@Autowired ApplicationConfig applicationConfig) { PolicyTypes types = new PolicyTypes(applicationConfig); types.restoreFromDatabase().blockLast(); @@ -68,6 +72,7 @@ public class BeanFactory { } @Bean + @DependsOn("springContextProvider") public Policies getPolicies(@Autowired ApplicationConfig applicationConfig) { return new Policies(applicationConfig); } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/SpringContextProvider.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/SpringContextProvider.java new file mode 100644 index 00000000..925e0c57 --- /dev/null +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/SpringContextProvider.java @@ -0,0 +1,41 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved. + * ====================================================================== + * 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.ccsdk.oran.a1policymanagementservice; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class SpringContextProvider implements ApplicationContextAware { + private static ApplicationContext localApplicationContext; + + @SuppressWarnings("java:S2696") + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + localApplicationContext = applicationContext; + } + + public static ApplicationContext getSpringContext() { + return localApplicationContext; + } +} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java index 3de674bd..d3b51461 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationConfig.java @@ -3,6 +3,7 @@ * ONAP : ccsdk oran * ====================================================================== * Copyright (C) 2019-2020 Nordix Foundation. All rights reserved. + * Copyright (C) 2023-2024 OpenInfra Foundation Europe. All rights reserved. * ====================================================================== * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -104,6 +105,11 @@ public class ApplicationConfig { @Value("${app.authorization-provider:}") private String authProviderUrl; + @Getter + @Setter + @Value("${app.database-enabled:}") + private boolean databaseEnabled; + private Map<String, RicConfig> ricConfigs = new HashMap<>(); private WebClientConfig webClientConfig = null; @@ -188,4 +194,8 @@ public class ApplicationConfig { public boolean isS3Enabled() { return !(Strings.isNullOrEmpty(s3EndpointOverride) || Strings.isNullOrEmpty(s3Bucket)); } + + public boolean isDatabaseEnabled() { + return databaseEnabled; + } } diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/ExcludeDatabaseAutoConfiguration.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/ExcludeDatabaseAutoConfiguration.java new file mode 100644 index 00000000..799a8cb2 --- /dev/null +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/ExcludeDatabaseAutoConfiguration.java @@ -0,0 +1,32 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved. + * ====================================================================== + * 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.ccsdk.oran.a1policymanagementservice.database; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration; +import org.springframework.context.annotation.Configuration; + +@Configuration +@ConditionalOnProperty(prefix = "app", name = "database-enabled", havingValue = "false") +@EnableAutoConfiguration(exclude = R2dbcAutoConfiguration.class) +public class ExcludeDatabaseAutoConfiguration { +} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/entities/BaseSchema.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/entities/BaseSchema.java new file mode 100644 index 00000000..0713cdd3 --- /dev/null +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/entities/BaseSchema.java @@ -0,0 +1,50 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved. + * ====================================================================== + * 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.ccsdk.oran.a1policymanagementservice.database.entities; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.Transient; +import org.springframework.data.domain.Persistable; + +@RequiredArgsConstructor +public class BaseSchema implements Persistable<String> { + @Id + final String id; + @Getter + final String payload; + + @Transient + @Setter + boolean isNew = true; + + @Override + public String getId() { + return id; + } + + @Override + public boolean isNew() { + return isNew; + } +} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/entities/Policy.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/entities/Policy.java new file mode 100644 index 00000000..e3e61d3b --- /dev/null +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/entities/Policy.java @@ -0,0 +1,30 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved. + * ====================================================================== + * 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.ccsdk.oran.a1policymanagementservice.database.entities; + +import org.springframework.data.relational.core.mapping.Table; + +@Table("policies") +public class Policy extends BaseSchema { + public Policy(String id, String payload) { + super(id, payload); + } +} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/entities/PolicyType.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/entities/PolicyType.java new file mode 100644 index 00000000..8dca3ce5 --- /dev/null +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/entities/PolicyType.java @@ -0,0 +1,30 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved. + * ====================================================================== + * 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.ccsdk.oran.a1policymanagementservice.database.entities; + +import org.springframework.data.relational.core.mapping.Table; + +@Table("policy_types") +public class PolicyType extends BaseSchema { + public PolicyType(String id, String payload) { + super(id, payload); + } +} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/entities/Service.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/entities/Service.java new file mode 100644 index 00000000..cc402854 --- /dev/null +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/entities/Service.java @@ -0,0 +1,30 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved. + * ====================================================================== + * 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.ccsdk.oran.a1policymanagementservice.database.entities; + +import org.springframework.data.relational.core.mapping.Table; + +@Table("services") +public class Service extends BaseSchema { + public Service(String id, String payload) { + super(id, payload); + } +} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/repositories/PoliciesRepository.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/repositories/PoliciesRepository.java new file mode 100644 index 00000000..0fb6c55e --- /dev/null +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/repositories/PoliciesRepository.java @@ -0,0 +1,29 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved. + * ====================================================================== + * 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.ccsdk.oran.a1policymanagementservice.database.repositories; + +import org.onap.ccsdk.oran.a1policymanagementservice.database.entities.Policy; +import org.springframework.data.repository.reactive.ReactiveCrudRepository; +import reactor.core.publisher.Flux; + +public interface PoliciesRepository extends ReactiveCrudRepository<Policy, String> { + Flux<Policy> findByIdStartingWith(String prefix); +} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/repositories/PolicyTypesRepository.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/repositories/PolicyTypesRepository.java new file mode 100644 index 00000000..2083a9fc --- /dev/null +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/repositories/PolicyTypesRepository.java @@ -0,0 +1,27 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved. + * ====================================================================== + * 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.ccsdk.oran.a1policymanagementservice.database.repositories; + +import org.onap.ccsdk.oran.a1policymanagementservice.database.entities.PolicyType; +import org.springframework.data.repository.reactive.ReactiveCrudRepository; + +public interface PolicyTypesRepository extends ReactiveCrudRepository<PolicyType, String> { +} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/repositories/ServicesRepository.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/repositories/ServicesRepository.java new file mode 100644 index 00000000..97259694 --- /dev/null +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/database/repositories/ServicesRepository.java @@ -0,0 +1,27 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved. + * ====================================================================== + * 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.ccsdk.oran.a1policymanagementservice.database.repositories; + +import org.onap.ccsdk.oran.a1policymanagementservice.database.entities.Service; +import org.springframework.data.repository.reactive.ReactiveCrudRepository; + +public interface ServicesRepository extends ReactiveCrudRepository<Service, String> { +} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/DataStore.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/DataStore.java index 51b57dee..4f0a98e2 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/DataStore.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/DataStore.java @@ -21,9 +21,7 @@ package org.onap.ccsdk.oran.a1policymanagementservice.datastore; import com.google.common.base.Strings; - import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig; - import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -42,7 +40,9 @@ public interface DataStore { public Mono<String> deleteAllObjects(); public static DataStore create(ApplicationConfig appConfig, String location) { - if (appConfig.isS3Enabled()) { + if (appConfig.isDatabaseEnabled()) { + return new DatabaseStore(location); + } else if (appConfig.isS3Enabled()) { return new S3ObjectStore(appConfig, location); } else if (!Strings.isNullOrEmpty(appConfig.getVardataDirectory())) { return new FileStore(appConfig, location); diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/DatabaseStore.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/DatabaseStore.java new file mode 100644 index 00000000..5c0d00da --- /dev/null +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/DatabaseStore.java @@ -0,0 +1,148 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved. + * ====================================================================== + * 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.ccsdk.oran.a1policymanagementservice.datastore; + +import java.lang.invoke.MethodHandles; +import org.onap.ccsdk.oran.a1policymanagementservice.SpringContextProvider; +import org.onap.ccsdk.oran.a1policymanagementservice.database.entities.BaseSchema; +import org.onap.ccsdk.oran.a1policymanagementservice.database.entities.Policy; +import org.onap.ccsdk.oran.a1policymanagementservice.database.entities.PolicyType; +import org.onap.ccsdk.oran.a1policymanagementservice.database.entities.Service; +import org.onap.ccsdk.oran.a1policymanagementservice.database.repositories.PoliciesRepository; +import org.onap.ccsdk.oran.a1policymanagementservice.database.repositories.PolicyTypesRepository; +import org.onap.ccsdk.oran.a1policymanagementservice.database.repositories.ServicesRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +public class DatabaseStore implements DataStore { + private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + private static final String OK = "OK"; + + private final OperationTarget operationTarget; + private final PoliciesRepository policiesRepository; + private final ServicesRepository servicesRepository; + private final PolicyTypesRepository policyTypesRepository; + + private enum OperationTarget { + POLICYTYPES, + SERVICES, + POLICIES + } + + public DatabaseStore(String target) { + this.operationTarget = OperationTarget.valueOf(target.toUpperCase()); + this.policiesRepository = SpringContextProvider.getSpringContext().getBean(PoliciesRepository.class); + this.servicesRepository = SpringContextProvider.getSpringContext().getBean(ServicesRepository.class); + this.policyTypesRepository = SpringContextProvider.getSpringContext().getBean(PolicyTypesRepository.class); + } + + @Override + public Flux<String> listObjects(String prefix) { + logger.debug("Listing objects for prefix {} and target {}", prefix, operationTarget.name()); + return Flux.just(operationTarget).flatMap(localOperationTarget -> { + if (localOperationTarget == OperationTarget.POLICIES) { + return policiesRepository.findByIdStartingWith(prefix).map(BaseSchema::getId); + } else if (localOperationTarget == OperationTarget.POLICYTYPES) { + return policyTypesRepository.findAll().map(BaseSchema::getId); + } else { + return servicesRepository.findAll().map(BaseSchema::getId); + } + }); + } + + @Override + public Mono<byte[]> readObject(String name) { + logger.debug("Reading object {} for target {}", name, operationTarget.name()); + return Mono.just(operationTarget).flatMap(localOperationTarget -> { + if (localOperationTarget == OperationTarget.POLICIES) { + return policiesRepository.findById(name).map(policy -> policy.getPayload().getBytes()); + } else if (localOperationTarget == OperationTarget.POLICYTYPES) { + return policyTypesRepository.findById(name).map(policyType -> policyType.getPayload().getBytes()); + } else { + return servicesRepository.findById(name).map(service -> service.getPayload().getBytes()); + } + }); + } + + @Override + public Mono<byte[]> writeObject(String name, byte[] fileData) { + logger.debug("Writing object {} for target {}", name, operationTarget.name()); + return Mono.just(operationTarget).flatMap(localOperationTarget -> { + if (localOperationTarget == OperationTarget.POLICIES) { + return policiesRepository.findById(name).map(policy -> Boolean.FALSE).defaultIfEmpty(Boolean.TRUE) + .flatMap(isNewPolicy -> { + Policy policy = new Policy(name, new String(fileData)); + policy.setNew(isNewPolicy); + return policiesRepository.save(policy).map(savedPolicy -> fileData); + }); + } else if (localOperationTarget == OperationTarget.POLICYTYPES) { + return policyTypesRepository.findById(name).map(policyType -> Boolean.FALSE).defaultIfEmpty(Boolean.TRUE) + .flatMap(isNewPolicyType -> { + PolicyType policyType = new PolicyType(name, new String(fileData)); + policyType.setNew(isNewPolicyType); + return policyTypesRepository.save(policyType).map(savedPolicyType -> fileData); + }); + } else { + return servicesRepository.findById(name).map(service -> Boolean.FALSE).defaultIfEmpty(Boolean.TRUE) + .flatMap(isNewService -> { + Service service = new Service(name, new String(fileData)); + service.setNew(isNewService); + return servicesRepository.save(service).map(savedService -> fileData); + }); + } + }); + } + + @Override + public Mono<Boolean> deleteObject(String name) { + logger.debug("Deleting object {} for target {}", name, operationTarget.name()); + return Mono.just(operationTarget).flatMap(localOperationTarget -> { + if (localOperationTarget == OperationTarget.POLICIES) { + return policiesRepository.deleteById(name).thenReturn(Boolean.TRUE); + } else if (localOperationTarget == OperationTarget.POLICYTYPES) { + return policyTypesRepository.deleteById(name).thenReturn(Boolean.TRUE); + } else { + return servicesRepository.deleteById(name).thenReturn(Boolean.TRUE); + } + }); + } + + @Override + public Mono<String> createDataStore() { + return Mono.just(OK); + } + + @Override + public Mono<String> deleteAllObjects() { + logger.debug("Deleting All objects for target {}", operationTarget.name()); + return Mono.just(operationTarget).flatMap(localOperationTarget -> { + if (localOperationTarget == OperationTarget.POLICIES) { + return policiesRepository.deleteAll().thenReturn(OK); + } else if (localOperationTarget == OperationTarget.POLICYTYPES) { + return policyTypesRepository.deleteAll().thenReturn(OK); + } else { + return servicesRepository.deleteAll().thenReturn(OK); + } + }); + } +} diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/DatabaseStoreTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/DatabaseStoreTest.java new file mode 100644 index 00000000..31797c49 --- /dev/null +++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/datastore/DatabaseStoreTest.java @@ -0,0 +1,371 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved. + * ====================================================================== + * 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.ccsdk.oran.a1policymanagementservice.datastore; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.ccsdk.oran.a1policymanagementservice.SpringContextProvider; +import org.onap.ccsdk.oran.a1policymanagementservice.database.entities.BaseSchema; +import org.onap.ccsdk.oran.a1policymanagementservice.database.entities.Policy; +import org.onap.ccsdk.oran.a1policymanagementservice.database.entities.PolicyType; +import org.onap.ccsdk.oran.a1policymanagementservice.database.entities.Service; +import org.onap.ccsdk.oran.a1policymanagementservice.database.repositories.PoliciesRepository; +import org.onap.ccsdk.oran.a1policymanagementservice.database.repositories.PolicyTypesRepository; +import org.onap.ccsdk.oran.a1policymanagementservice.database.repositories.ServicesRepository; +import org.springframework.context.ApplicationContext; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; +import reactor.test.StepVerifier; + +@ExtendWith(MockitoExtension.class) +public class DatabaseStoreTest { + + public static final String OK = "OK"; + @Mock + PoliciesRepository policiesRepository; + @Mock + ServicesRepository servicesRepository; + @Mock + PolicyTypesRepository policyTypesRepository; + @Mock + ApplicationContext applicationContext; + @InjectMocks + SpringContextProvider springContextProvider; + + private enum OperationTarget { + POLICYTYPES("policytypes"), + SERVICES("services"), + POLICIES("policies"); + + final String label; + + OperationTarget(String label) { + this.label = label; + } + } + + @BeforeEach + void initialize() { + when(applicationContext.getBean(PoliciesRepository.class)).thenReturn(policiesRepository); + when(applicationContext.getBean(PolicyTypesRepository.class)).thenReturn(policyTypesRepository); + when(applicationContext.getBean(ServicesRepository.class)).thenReturn(servicesRepository); + springContextProvider.setApplicationContext(applicationContext); + } + + @Test + void testCreateDataStore() { + DatabaseStore databaseStore = new DatabaseStore(OperationTarget.POLICYTYPES.name()); + StepVerifier.create(databaseStore.createDataStore()).expectNext(OK).verifyComplete(); + } + + @ParameterizedTest + @EnumSource(OperationTarget.class) + void testListObjectsSuccess(OperationTarget operationTarget) { + DatabaseStore databaseStore = new DatabaseStore(operationTarget.name()); + if (operationTarget == OperationTarget.POLICIES) { + String prefix = "ric1"; + Policy policy1 = new Policy(prefix + "/listpolicy1.json", "{}"); + Policy policy2 = new Policy(prefix + "/listpolicy2.json", "{}"); + when(policiesRepository.findByIdStartingWith(any())).thenReturn(Flux.just(policy1, policy2)); + StepVerifier.create(databaseStore.listObjects(prefix)).expectNext(policy1.getId()).expectNext(policy2.getId()) + .verifyComplete(); + } else if (operationTarget == OperationTarget.POLICYTYPES) { + PolicyType policyType1 = new PolicyType("/listpolicytype1.json", "{}"); + PolicyType policyType2 = new PolicyType("/listpolicytype2.json", "{}"); + when(policyTypesRepository.findAll()).thenReturn(Flux.just(policyType1, policyType2)); + StepVerifier.create(databaseStore.listObjects("")).expectNext(policyType1.getId()) + .expectNext(policyType2.getId()).verifyComplete(); + } else if (operationTarget == OperationTarget.SERVICES) { + Service service1 = new Service("/listservice1.json", "{}"); + Service service2 = new Service("/listservice2.json", "{}"); + when(servicesRepository.findAll()).thenReturn(Flux.just(service1, service2)); + StepVerifier.create(databaseStore.listObjects("")).expectNext(service1.getId()).expectNext(service2.getId()) + .verifyComplete(); + } + } + + @ParameterizedTest + @EnumSource(OperationTarget.class) + void testListObjectsFailure(OperationTarget operationTarget) { + DatabaseStore databaseStore = new DatabaseStore(operationTarget.name()); + String errorMessage = "Unable to list the objects of type " + operationTarget.name(); + if (operationTarget == OperationTarget.POLICIES) { + String prefix = "ric1"; + when(policiesRepository.findByIdStartingWith(any())).thenReturn(Flux.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.listObjects(prefix)).expectErrorMessage(errorMessage).verify(); + } else if (operationTarget == OperationTarget.POLICYTYPES) { + when(policyTypesRepository.findAll()).thenReturn(Flux.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.listObjects("")).expectErrorMessage(errorMessage).verify(); + } else if (operationTarget == OperationTarget.SERVICES) { + when(servicesRepository.findAll()).thenReturn(Flux.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.listObjects("")).expectErrorMessage(errorMessage).verify(); + } + } + + @ParameterizedTest + @EnumSource(OperationTarget.class) + void testReadObjectSuccess(OperationTarget operationTarget) { + DatabaseStore databaseStore = new DatabaseStore(operationTarget.name()); + if (operationTarget == OperationTarget.POLICIES) { + String policyName = "ric1/readpolicy1.json"; + String policyPayload = "{\"name\":\"readpolicy1\"}"; + Policy policy1 = new Policy(policyName, policyPayload); + when(policiesRepository.findById(anyString())).thenReturn(Mono.just(policy1)); + StepVerifier.create(databaseStore.readObject(policyName)).consumeNextWith(bytes -> { + assertArrayEquals(bytes, policyPayload.getBytes()); + }).verifyComplete(); + } else if (operationTarget == OperationTarget.POLICYTYPES) { + String policyTypeName = "readpolicytype1.json"; + String policyTypePayload = "{\"name\":\"readpolicytype1\"}"; + PolicyType policyType1 = new PolicyType(policyTypeName, policyTypePayload); + when(policyTypesRepository.findById(anyString())).thenReturn(Mono.just(policyType1)); + StepVerifier.create(databaseStore.readObject(policyTypeName)).consumeNextWith(bytes -> { + assertArrayEquals(bytes, policyTypePayload.getBytes()); + }).verifyComplete(); + } else if (operationTarget == OperationTarget.SERVICES) { + String serviceName = "readservice1.json"; + String servicePayload = "{\"name\":\"readservice1\"}"; + Service service1 = new Service(serviceName, servicePayload); + when(servicesRepository.findById(anyString())).thenReturn(Mono.just(service1)); + StepVerifier.create(databaseStore.readObject(serviceName)).consumeNextWith(bytes -> { + assertArrayEquals(bytes, servicePayload.getBytes()); + }).verifyComplete(); + } + } + + @ParameterizedTest + @EnumSource(OperationTarget.class) + void testReadObjectFailure(OperationTarget operationTarget) { + DatabaseStore databaseStore = new DatabaseStore(operationTarget.name()); + String errorMessage = "Unable to read the objects of type " + operationTarget.name(); + if (operationTarget == OperationTarget.POLICIES) { + String policyName = "ric1/readpolicy1.json"; + when(policiesRepository.findById(anyString())).thenReturn(Mono.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.readObject(policyName)).expectErrorMessage(errorMessage).verify(); + when(policiesRepository.findById(anyString())).thenReturn(Mono.empty()); + StepVerifier.create(databaseStore.readObject(policyName)).verifyComplete(); + } else if (operationTarget == OperationTarget.POLICYTYPES) { + String policyTypeName = "readpolicytype1.json"; + when(policyTypesRepository.findById(anyString())).thenReturn(Mono.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.readObject(policyTypeName)).expectErrorMessage(errorMessage).verify(); + when(policyTypesRepository.findById(anyString())).thenReturn(Mono.empty()); + StepVerifier.create(databaseStore.readObject(policyTypeName)).verifyComplete(); + } else if (operationTarget == OperationTarget.SERVICES) { + String serviceName = "readservice1.json"; + when(servicesRepository.findById(anyString())).thenReturn(Mono.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.readObject(serviceName)).expectErrorMessage(errorMessage).verify(); + when(servicesRepository.findById(anyString())).thenReturn(Mono.empty()); + StepVerifier.create(databaseStore.readObject(serviceName)).verifyComplete(); + } + } + + @ParameterizedTest + @EnumSource(OperationTarget.class) + void testWriteObjectInsertSuccess(OperationTarget operationTarget) { + DatabaseStore databaseStore = new DatabaseStore(operationTarget.name()); + if (operationTarget == OperationTarget.POLICIES) { + String policyName = "ric1/writeinserpolicy1.json"; + String policyPayload = "{\"name\":\"writeinserpolicy1\"}"; + Policy policy1 = new Policy(policyName, policyPayload); + when(policiesRepository.findById(anyString())).thenReturn(Mono.empty()); + when(policiesRepository.save(any(Policy.class))).thenReturn(Mono.just(policy1)); + StepVerifier.create(databaseStore.writeObject(policyName, policyPayload.getBytes())).consumeNextWith(bytes -> { + assertArrayEquals(bytes, policyPayload.getBytes()); + verify(policiesRepository).save(argThat(BaseSchema::isNew)); + }).verifyComplete(); + } else if (operationTarget == OperationTarget.POLICYTYPES) { + String policyTypeName = "writeinsertpolicytype1.json"; + String policyTypePayload = "{\"name\":\"writeinsertpolicytype1\"}"; + PolicyType policyType1 = new PolicyType(policyTypeName, policyTypePayload); + when(policyTypesRepository.findById(anyString())).thenReturn(Mono.empty()); + when(policyTypesRepository.save(any(PolicyType.class))).thenReturn(Mono.just(policyType1)); + StepVerifier.create(databaseStore.writeObject(policyTypeName, policyTypePayload.getBytes())) + .consumeNextWith(bytes -> { + assertArrayEquals(bytes, policyTypePayload.getBytes()); + verify(policyTypesRepository).save(argThat(BaseSchema::isNew)); + }).verifyComplete(); + } else if (operationTarget == OperationTarget.SERVICES) { + String serviceName = "writeinsertservice1.json"; + String servicePayload = "{\"name\":\"writeinsertservice1\"}"; + Service service1 = new Service(serviceName, servicePayload); + when(servicesRepository.findById(anyString())).thenReturn(Mono.empty()); + when(servicesRepository.save(any(Service.class))).thenReturn(Mono.just(service1)); + StepVerifier.create(databaseStore.writeObject(serviceName, servicePayload.getBytes())) + .consumeNextWith(bytes -> { + assertArrayEquals(bytes, servicePayload.getBytes()); + verify(servicesRepository).save(argThat(BaseSchema::isNew)); + }).verifyComplete(); + } + } + + @ParameterizedTest + @EnumSource(OperationTarget.class) + void testWriteObjectUpdateSuccess(OperationTarget operationTarget) { + DatabaseStore databaseStore = new DatabaseStore(operationTarget.name()); + if (operationTarget == OperationTarget.POLICIES) { + String policyName = "ric1/writeupdatepolicy1.json"; + String policyPayload = "{\"name\":\"writeupdatepolicy1\"}"; + Policy policy1 = new Policy(policyName, policyPayload); + when(policiesRepository.findById(anyString())).thenReturn(Mono.just(policy1)); + when(policiesRepository.save(any(Policy.class))).thenReturn(Mono.just(policy1)); + StepVerifier.create(databaseStore.writeObject(policyName, policyPayload.getBytes())).consumeNextWith(bytes -> { + assertArrayEquals(bytes, policyPayload.getBytes()); + verify(policiesRepository).save(argThat(policy -> !policy.isNew())); + }).verifyComplete(); + } else if (operationTarget == OperationTarget.POLICYTYPES) { + String policyTypeName = "writeupdatepolicytype1.json"; + String policyTypePayload = "{\"name\":\"writeupdatepolicytype1\"}"; + PolicyType policyType1 = new PolicyType(policyTypeName, policyTypePayload); + when(policyTypesRepository.findById(anyString())).thenReturn(Mono.just(policyType1)); + when(policyTypesRepository.save(any(PolicyType.class))).thenReturn(Mono.just(policyType1)); + StepVerifier.create(databaseStore.writeObject(policyTypeName, policyTypePayload.getBytes())) + .consumeNextWith(bytes -> { + assertArrayEquals(bytes, policyTypePayload.getBytes()); + verify(policyTypesRepository).save(argThat(policy -> !policy.isNew())); + }).verifyComplete(); + } else if (operationTarget == OperationTarget.SERVICES) { + String serviceName = "writeupdateservice1.json"; + String servicePayload = "{\"name\":\"writeupdateservice1\"}"; + Service service1 = new Service(serviceName, servicePayload); + when(servicesRepository.findById(anyString())).thenReturn(Mono.just(service1)); + when(servicesRepository.save(any(Service.class))).thenReturn(Mono.just(service1)); + StepVerifier.create(databaseStore.writeObject(serviceName, servicePayload.getBytes())) + .consumeNextWith(bytes -> { + assertArrayEquals(bytes, servicePayload.getBytes()); + verify(servicesRepository).save(argThat(policy -> !policy.isNew())); + }).verifyComplete(); + } + } + + @ParameterizedTest + @EnumSource(OperationTarget.class) + void testWriteObjectFailure(OperationTarget operationTarget) { + DatabaseStore databaseStore = new DatabaseStore(operationTarget.name()); + String errorMessage = "Unable to write the objects of type " + operationTarget.name(); + if (operationTarget == OperationTarget.POLICIES) { + String policyName = "ric1/writepolicy1.json"; + String policyPayload = "{\"name\":\"writepolicy1\"}"; + when(policiesRepository.findById(anyString())).thenReturn(Mono.empty()); + when(policiesRepository.save(any(Policy.class))).thenReturn(Mono.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.writeObject(policyName, policyPayload.getBytes())) + .expectErrorMessage(errorMessage).verify(); + } else if (operationTarget == OperationTarget.POLICYTYPES) { + String policyTypeName = "writepolicytype1.json"; + String policyTypePayload = "{\"name\":\"writepolicytype1\"}"; + when(policyTypesRepository.findById(anyString())).thenReturn(Mono.empty()); + when(policyTypesRepository.save(any(PolicyType.class))).thenReturn(Mono.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.writeObject(policyTypeName, policyTypePayload.getBytes())) + .expectErrorMessage(errorMessage).verify(); + } else if (operationTarget == OperationTarget.SERVICES) { + String serviceName = "writeservice1.json"; + String servicePayload = "{\"name\":\"writeservice1\"}"; + when(servicesRepository.findById(anyString())).thenReturn(Mono.empty()); + when(servicesRepository.save(any(Service.class))).thenReturn(Mono.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.writeObject(serviceName, servicePayload.getBytes())) + .expectErrorMessage(errorMessage).verify(); + } + } + + @ParameterizedTest + @EnumSource(OperationTarget.class) + void testDeleteObjectSuccess(OperationTarget operationTarget) { + DatabaseStore databaseStore = new DatabaseStore(operationTarget.name()); + if (operationTarget == OperationTarget.POLICIES) { + String policyName = "ric1/deletepolicy1.json"; + when(policiesRepository.deleteById(anyString())).thenReturn(Mono.just("").then()); + StepVerifier.create(databaseStore.deleteObject(policyName)).expectNext(true).verifyComplete(); + } else if (operationTarget == OperationTarget.POLICYTYPES) { + String policyTypeName = "deletepolicytype1.json"; + when(policyTypesRepository.deleteById(anyString())).thenReturn(Mono.just("").then()); + StepVerifier.create(databaseStore.deleteObject(policyTypeName)).expectNext(true).verifyComplete(); + } else if (operationTarget == OperationTarget.SERVICES) { + String serviceName = "deleteservice1.json"; + when(servicesRepository.deleteById(anyString())).thenReturn(Mono.just("").then()); + StepVerifier.create(databaseStore.deleteObject(serviceName)).expectNext(true).verifyComplete(); + } + } + + @ParameterizedTest + @EnumSource(OperationTarget.class) + void testDeleteObjectFailure(OperationTarget operationTarget) { + DatabaseStore databaseStore = new DatabaseStore(operationTarget.name()); + String errorMessage = "Unable to delete the objects of type " + operationTarget.name(); + if (operationTarget == OperationTarget.POLICIES) { + String policyName = "ric1/deletepolicy1.json"; + when(policiesRepository.deleteById(anyString())).thenReturn(Mono.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.deleteObject(policyName)).expectErrorMessage(errorMessage).verify(); + } else if (operationTarget == OperationTarget.POLICYTYPES) { + String policyTypeName = "deletepolicytype1.json"; + when(policyTypesRepository.deleteById(anyString())).thenReturn(Mono.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.deleteObject(policyTypeName)).expectErrorMessage(errorMessage).verify(); + } else if (operationTarget == OperationTarget.SERVICES) { + String serviceName = "deleteservice1.json"; + when(servicesRepository.deleteById(anyString())).thenReturn(Mono.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.deleteObject(serviceName)).expectErrorMessage(errorMessage).verify(); + } + } + + @ParameterizedTest + @EnumSource(OperationTarget.class) + void testDeleteAllObjectSuccess(OperationTarget operationTarget) { + DatabaseStore databaseStore = new DatabaseStore(operationTarget.name()); + if (operationTarget == OperationTarget.POLICIES) { + when(policiesRepository.deleteAll()).thenReturn(Mono.just("").then()); + StepVerifier.create(databaseStore.deleteAllObjects()).expectNext(OK).verifyComplete(); + } else if (operationTarget == OperationTarget.POLICYTYPES) { + when(policyTypesRepository.deleteAll()).thenReturn(Mono.just("").then()); + StepVerifier.create(databaseStore.deleteAllObjects()).expectNext(OK).verifyComplete(); + } else if (operationTarget == OperationTarget.SERVICES) { + when(servicesRepository.deleteAll()).thenReturn(Mono.just("").then()); + StepVerifier.create(databaseStore.deleteAllObjects()).expectNext(OK).verifyComplete(); + } + } + + @ParameterizedTest + @EnumSource(OperationTarget.class) + void testDeleteAllObjectFailure(OperationTarget operationTarget) { + DatabaseStore databaseStore = new DatabaseStore(operationTarget.name()); + String errorMessage = "Unable to delete all the objects of type " + operationTarget.name(); + if (operationTarget == OperationTarget.POLICIES) { + when(policiesRepository.deleteAll()).thenReturn(Mono.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.deleteAllObjects()).expectErrorMessage(errorMessage).verify(); + } else if (operationTarget == OperationTarget.POLICYTYPES) { + when(policyTypesRepository.deleteAll()).thenReturn(Mono.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.deleteAllObjects()).expectErrorMessage(errorMessage).verify(); + } else if (operationTarget == OperationTarget.SERVICES) { + when(servicesRepository.deleteAll()).thenReturn(Mono.error(new Throwable(errorMessage))); + StepVerifier.create(databaseStore.deleteAllObjects()).expectErrorMessage(errorMessage).verify(); + } + } + +}
\ No newline at end of file |