diff options
author | puthuparambil.aditya <aditya.puthuparambil@bell.ca> | 2020-10-20 12:23:34 +0100 |
---|---|---|
committer | puthuparambil.aditya <aditya.puthuparambil@bell.ca> | 2020-10-27 11:32:30 +0000 |
commit | 252b950552a9815f2680c457e7bd0e8af9f610f7 (patch) | |
tree | 1a956446177afc5b47f80446d16460675422f9dc | |
parent | f7ba359b048cb6f7dc12a00df872b9c19eda76ba (diff) |
VSE: Upload modules (a model file) to a (new) dataspace
1. Schema.sql modified to include modules and json_data tables which can be removed after the PoC
2. URI changed as per the proposal to '/dataspaces/{dataspace_name}/modules'
3. Dataspace name corresponding to a model is passed as a parameter.
4. In case the dataspace doesnt exist in the dataspace table, a new entry for the passed dataspace is created.
5. The corresponding dataspace_id is also stored as a reference in the modules table.
6. Test case for Rest API will be pushed as another review.
JIRA: https://jira.onap.org/browse/CCSDK-2897
Issue-ID: CCSDK-2897
Change-Id: Ic9caa39b5a7afca28c0365cdb4f492848d0ead3e
Signed-off-by: puthuparambil.aditya <aditya.puthuparambil@bell.ca>
14 files changed, 145 insertions, 51 deletions
diff --git a/cps/README.md b/cps/README.md index 791015ef19..d1bf49d8cf 100644 --- a/cps/README.md +++ b/cps/README.md @@ -1,7 +1,7 @@ -# Configuration & Persistency Service +# Configuration Persistence Service This folder contains all files for -[Configuration & Persistency Service](https://wiki.onap.org/pages/viewpage.action?pageId=81406119). +[Configuration Persistence Service](https://wiki.onap.org/pages/viewpage.action?pageId=81406119). The code here is related to CPS POC, then it must be kept self contained in this cps folder to prevent any impact on current ccsdk components and to be ready to be moved in its own repo once CPS becomes a standalone project. diff --git a/cps/cps-rest/src/main/java/org/onap/cps/rest/controller/RestController.java b/cps/cps-rest/src/main/java/org/onap/cps/rest/controller/RestController.java index 18e24b4377..703e77823a 100644 --- a/cps/cps-rest/src/main/java/org/onap/cps/rest/controller/RestController.java +++ b/cps/cps-rest/src/main/java/org/onap/cps/rest/controller/RestController.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2020 Nordix Foundation + * Modifications Copyright (C) 2020 Bell Canada. 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. @@ -22,8 +23,6 @@ package org.onap.cps.rest.controller; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import java.io.File; -import java.io.IOException; -import java.io.InputStream; import javax.persistence.PersistenceException; import javax.validation.Valid; import javax.ws.rs.Consumes; @@ -36,10 +35,9 @@ import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; -import javax.ws.rs.core.SecurityContext; import org.apache.cxf.jaxrs.ext.multipart.Attachment; -import org.glassfish.jersey.media.multipart.FormDataContentDisposition; import org.glassfish.jersey.media.multipart.FormDataParam; +import org.hibernate.exception.ConstraintViolationException; import org.onap.cps.api.CpService; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.parser.api.YangParserException; @@ -110,19 +108,21 @@ public class RestController implements CpsResourceApi { * Upload a yang model file. * * @param uploadedFile the yang model file. + * @param dataspaceName the dataspace name linked to the model. * @return a http response code. */ @POST - @Path("/upload-yang-model-file") + @Path("/dataspaces/{dataspace_name}/modules") @Produces(MediaType.APPLICATION_JSON) @Consumes(MediaType.MULTIPART_FORM_DATA) - public final Response uploadYangModelFile(@FormDataParam("file") File uploadedFile) throws IOException { + public final Response uploadYangModelFile(@FormDataParam("file") File uploadedFile, + @PathParam("dataspace_name") String dataspaceName) { try { final File fileToParse = renameFileIfNeeded(uploadedFile); final SchemaContext schemaContext = cpService.parseAndValidateModel(fileToParse); - cpService.storeSchemaContext(schemaContext); - return Response.status(Status.OK).entity("Yang File Parsed").build(); - } catch (final YangParserException e) { + cpService.storeSchemaContext(schemaContext, dataspaceName); + return Response.status(Status.CREATED).entity("Resource successfully created").build(); + } catch (final YangParserException | ConstraintViolationException e) { return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); } catch (final Exception e) { return Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); diff --git a/cps/cps-ri/src/main/java/org/onap/cps/spi/entities/Dataspace.java b/cps/cps-ri/src/main/java/org/onap/cps/spi/entities/Dataspace.java index 8f37692b1d..627a14467d 100644 --- a/cps/cps-ri/src/main/java/org/onap/cps/spi/entities/Dataspace.java +++ b/cps/cps-ri/src/main/java/org/onap/cps/spi/entities/Dataspace.java @@ -31,6 +31,7 @@ import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; + /** * Entity to store a dataspace. */ @@ -49,4 +50,13 @@ public class Dataspace { @NotNull @Column(columnDefinition = "text") private String name; -} + + /** + * Initialize a Dataspace . + * + * @param name the Dataspace name. + */ + public Dataspace(String name) { + this.name = name; + } +}
\ No newline at end of file diff --git a/cps/cps-ri/src/main/java/org/onap/cps/spi/entities/ModuleEntity.java b/cps/cps-ri/src/main/java/org/onap/cps/spi/entities/ModuleEntity.java index f786c58f1d..d2130aeec1 100644 --- a/cps/cps-ri/src/main/java/org/onap/cps/spi/entities/ModuleEntity.java +++ b/cps/cps-ri/src/main/java/org/onap/cps/spi/entities/ModuleEntity.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2020 Nordix Foundation + * Modifications Copyright (C) 2020 Bell Canada. 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. @@ -21,10 +22,14 @@ package org.onap.cps.spi.entities; import javax.persistence.Column; import javax.persistence.Entity; +import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; import javax.persistence.Table; +import javax.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -39,32 +44,41 @@ import lombok.Setter; @Entity @AllArgsConstructor @NoArgsConstructor -@Table(name = "modules") +@Table(name = "module") public class ModuleEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; - @Column - private String name; - + @NotNull @Column private String moduleContent; + @NotNull @Column private String revision; + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "dataspace_id", referencedColumnName = "ID") + private Dataspace dataspace; + + @NotNull + @Column + private String namespace; + /** * Initialize a module entity. * - * @param name the module name. + * @param namespace the module namespace. * @param moduleContent the module content. * @param revision the revision number of the module. + * @param dataspace the dataspace related to the module. */ - public ModuleEntity(String name, String moduleContent, String revision) { - this.name = name; + public ModuleEntity(String namespace, String moduleContent, String revision, Dataspace dataspace) { + this.namespace = namespace; this.moduleContent = moduleContent; this.revision = revision; + this.dataspace = dataspace; } }
\ No newline at end of file diff --git a/cps/cps-ri/src/main/java/org/onap/cps/spi/impl/ModelPersistencyServiceImpl.java b/cps/cps-ri/src/main/java/org/onap/cps/spi/impl/ModelPersistencyServiceImpl.java index 14085c7cf9..01c7a7b53b 100644 --- a/cps/cps-ri/src/main/java/org/onap/cps/spi/impl/ModelPersistencyServiceImpl.java +++ b/cps/cps-ri/src/main/java/org/onap/cps/spi/impl/ModelPersistencyServiceImpl.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2020 Nordix Foundation + * Modifications Copyright (C) 2020 Bell Canada. 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. @@ -20,7 +21,9 @@ package org.onap.cps.spi.impl; import org.onap.cps.spi.ModelPersistencyService; +import org.onap.cps.spi.entities.Dataspace; import org.onap.cps.spi.entities.ModuleEntity; +import org.onap.cps.spi.repository.DataspaceRepository; import org.onap.cps.spi.repository.ModuleRepository; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -31,15 +34,24 @@ public class ModelPersistencyServiceImpl implements ModelPersistencyService { private final ModuleRepository moduleRepository; + private final DataspaceRepository dataspaceRepository; + @Autowired - public ModelPersistencyServiceImpl(final ModuleRepository moduleRepository) { + public ModelPersistencyServiceImpl(final ModuleRepository moduleRepository, + final DataspaceRepository dataspaceRepository) { this.moduleRepository = moduleRepository; + this.dataspaceRepository = dataspaceRepository; } @Override - public void storeModule(final String name, final String moduleContent, final String revision) { - final ModuleEntity moduleEntity = new ModuleEntity(name, moduleContent, revision); + public void storeModule(final String namespace, final String moduleContent, final String revision, + final String dataspaceName) { + final Dataspace dataspace = new Dataspace(dataspaceName); + if (Boolean.FALSE.equals(dataspaceRepository.existsByName(dataspaceName))) { + dataspaceRepository.save(dataspace); + } + dataspace.setId(dataspaceRepository.findByName(dataspaceName).getId()); + final ModuleEntity moduleEntity = new ModuleEntity(namespace, moduleContent, revision, dataspace); moduleRepository.save(moduleEntity); - } } diff --git a/cps/cps-ri/src/main/java/org/onap/cps/spi/repository/DataspaceRepository.java b/cps/cps-ri/src/main/java/org/onap/cps/spi/repository/DataspaceRepository.java new file mode 100644 index 0000000000..46a5266103 --- /dev/null +++ b/cps/cps-ri/src/main/java/org/onap/cps/spi/repository/DataspaceRepository.java @@ -0,0 +1,32 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2020 Bell Canada. 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.spi.repository; + + +import org.onap.cps.spi.entities.Dataspace; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface DataspaceRepository extends JpaRepository<Dataspace, Integer> { + Boolean existsByName(String name); //Checks if there are any records by name() + + Dataspace findByName(String name); +}
\ No newline at end of file diff --git a/cps/cps-ri/src/main/java/org/onap/cps/spi/repository/ModuleRepository.java b/cps/cps-ri/src/main/java/org/onap/cps/spi/repository/ModuleRepository.java index 0fe53b6212..f9078d7c14 100644 --- a/cps/cps-ri/src/main/java/org/onap/cps/spi/repository/ModuleRepository.java +++ b/cps/cps-ri/src/main/java/org/onap/cps/spi/repository/ModuleRepository.java @@ -26,5 +26,4 @@ import org.springframework.stereotype.Repository; @Repository public interface ModuleRepository extends JpaRepository<ModuleEntity, Integer> { - }
\ No newline at end of file diff --git a/cps/cps-ri/src/main/resources/schema.sql b/cps/cps-ri/src/main/resources/schema.sql index 05d31d92fa..6a76fbd191 100644 --- a/cps/cps-ri/src/main/resources/schema.sql +++ b/cps/cps-ri/src/main/resources/schema.sql @@ -17,12 +17,6 @@ CREATE TABLE IF NOT EXISTS SCHEMA_NODE ID SERIAL PRIMARY KEY
);
-CREATE TABLE IF NOT EXISTS MODULE_SET
-(
- MODULE_SET_REFERENCE TEXT NOT NULL,
- ID SERIAL PRIMARY KEY
-);
-
CREATE TABLE IF NOT EXISTS FRAGMENT
(
ID BIGSERIAL PRIMARY KEY,
@@ -45,6 +39,17 @@ CREATE TABLE IF NOT EXISTS RELATION CONSTRAINT RELATION_PKEY PRIMARY KEY (TO_FRAGMENT_ID, FROM_FRAGMENT_ID, RELATION_TYPE_ID)
);
+CREATE TABLE IF NOT EXISTS MODULE
+(
+ NAMESPACE TEXT NOT NULL,
+ REVISION TEXT NOT NULL,
+ MODULE_CONTENT TEXT NOT NULL,
+ DATASPACE_ID BIGINT NOT NULL,
+ ID SERIAL PRIMARY KEY,
+ UNIQUE (NAMESPACE, REVISION),
+ CONSTRAINT module_dataspace FOREIGN KEY (DATASPACE_ID) REFERENCES DATASPACE (id) ON UPDATE CASCADE ON DELETE CASCADE
+);
+
CREATE INDEX IF NOT EXISTS "FKI_FRAGMENT_DATASPACE_ID_FK" ON FRAGMENT USING BTREE(DATASPACE_ID) ;
CREATE INDEX IF NOT EXISTS "FKI_FRAGMENT_MODULE_SET_ID_FK" ON FRAGMENT USING BTREE(MODULE_SET_ID) ;
CREATE INDEX IF NOT EXISTS "FKI_FRAGMENT_PARENT_ID_FK" ON FRAGMENT USING BTREE(PARENT_ID) ;
diff --git a/cps/cps-service/pom.xml b/cps/cps-service/pom.xml index 731873420c..ea1bdad39b 100644 --- a/cps/cps-service/pom.xml +++ b/cps/cps-service/pom.xml @@ -60,25 +60,19 @@ </dependency>
<!-- T E S T D E P E N D E N C I E S -->
-
<dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
- <version>${groovy.version}</version>
- <scope>test</scope>
</dependency>
<dependency>
<groupId>org.spockframework</groupId>
<artifactId>spock-core</artifactId>
- <version>${spock-core.version}</version>
- <scope>test</scope>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
- <version>3.1</version>
- <scope>test</scope>
</dependency>
+
</dependencies>
</project>
diff --git a/cps/cps-service/src/main/java/org/onap/cps/api/CpService.java b/cps/cps-service/src/main/java/org/onap/cps/api/CpService.java index 177fc043a9..2f735abc7d 100644 --- a/cps/cps-service/src/main/java/org/onap/cps/api/CpService.java +++ b/cps/cps-service/src/main/java/org/onap/cps/api/CpService.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2020 Nordix Foundation + * Modifications Copyright (C) 2020 Bell Canada. 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. @@ -49,8 +50,9 @@ public interface CpService { * Store schema context for a yang model. * * @param schemaContext the schema context + * @param dataspaceName the dataspace name */ - void storeSchemaContext(final SchemaContext schemaContext); + void storeSchemaContext(final SchemaContext schemaContext, final String dataspaceName); /** * Store the JSON structure in the database. diff --git a/cps/cps-service/src/main/java/org/onap/cps/api/impl/CpServiceImpl.java b/cps/cps-service/src/main/java/org/onap/cps/api/impl/CpServiceImpl.java index 80a685b092..45aad3e446 100644 --- a/cps/cps-service/src/main/java/org/onap/cps/api/impl/CpServiceImpl.java +++ b/cps/cps-service/src/main/java/org/onap/cps/api/impl/CpServiceImpl.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2020 Nordix Foundation + * Modifications Copyright (C) 2020 Bell Canada. 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. @@ -19,20 +20,19 @@ package org.onap.cps.api.impl; - import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; +import java.util.Optional; import org.onap.cps.api.CpService; import org.onap.cps.spi.DataPersistencyService; import org.onap.cps.spi.ModelPersistencyService; import org.onap.cps.utils.YangUtils; +import org.opendaylight.yangtools.yang.common.Revision; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.parser.api.YangParserException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -40,15 +40,12 @@ import org.springframework.stereotype.Component; @Component public class CpServiceImpl implements CpService { - private static final Logger LOGGER = LoggerFactory.getLogger(CpServiceImpl.class); - @Autowired private ModelPersistencyService modelPersistencyService; @Autowired private DataPersistencyService dataPersistencyService; - @Override public final SchemaContext parseAndValidateModel(final String yangModelContent) throws IOException, YangParserException { @@ -76,13 +73,16 @@ public class CpServiceImpl implements CpService { @Override public void deleteJsonById(int jsonObjectId) { - dataPersistencyService.deleteJsonById(jsonObjectId);; + dataPersistencyService.deleteJsonById(jsonObjectId); } @Override - public final void storeSchemaContext(final SchemaContext schemaContext) { + public final void storeSchemaContext(final SchemaContext schemaContext, final String dataspaceName) { for (final Module module : schemaContext.getModules()) { - modelPersistencyService.storeModule(module.getName(), module.toString(), module.getRevision().toString()); + Optional<Revision> optionalRevision = module.getRevision(); + String revisionValue = optionalRevision.isPresent() ? optionalRevision.get().toString() : null; + modelPersistencyService.storeModule(module.getNamespace().toString(), module.toString(), + revisionValue, dataspaceName); } } } diff --git a/cps/cps-service/src/main/java/org/onap/cps/spi/ModelPersistencyService.java b/cps/cps-service/src/main/java/org/onap/cps/spi/ModelPersistencyService.java index f88c6b241b..2afdaa82a8 100644 --- a/cps/cps-service/src/main/java/org/onap/cps/spi/ModelPersistencyService.java +++ b/cps/cps-service/src/main/java/org/onap/cps/spi/ModelPersistencyService.java @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2020 Nordix Foundation + * Modifications Copyright (C) 2020 Bell Canada. 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. @@ -27,10 +28,12 @@ public interface ModelPersistencyService { /** * Store the module from a yang model in the database. * - * @param name module name + * @param namespace module namespace * @param moduleContent module content * @param revision module revision + * @param dataspaceName the name of the dataspace the module is associated with */ - void storeModule(final String name, final String moduleContent, final String revision); + void storeModule(final String namespace, final String moduleContent, final String revision, + final String dataspaceName); } diff --git a/cps/cps-service/src/test/groovy/org/onap/cps/api/impl/CpServiceImplSpec.groovy b/cps/cps-service/src/test/groovy/org/onap/cps/api/impl/CpServiceImplSpec.groovy index a2f9b35437..5e6fccb7a1 100644 --- a/cps/cps-service/src/test/groovy/org/onap/cps/api/impl/CpServiceImplSpec.groovy +++ b/cps/cps-service/src/test/groovy/org/onap/cps/api/impl/CpServiceImplSpec.groovy @@ -1,6 +1,7 @@ /* * ============LICENSE_START======================================================= * Copyright (C) 2020 Nordix Foundation + * Modifications Copyright (C) 2020 Bell Canada. 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. @@ -21,6 +22,7 @@ package org.onap.cps.api.impl import org.onap.cps.TestUtils import org.onap.cps.spi.DataPersistencyService + import org.opendaylight.yangtools.yang.common.Revision import org.opendaylight.yangtools.yang.model.api.SchemaContext import org.opendaylight.yangtools.yang.model.parser.api.YangParserException @@ -32,7 +34,7 @@ class CpServiceImplSpec extends Specification { def objectUnderTest = new CpServiceImpl() def setup() { - objectUnderTest.dataPersistencyService = mockDataPersistencyService; + objectUnderTest.dataPersistencyService = mockDataPersistencyService } def 'Cps Service provides to its client the id assigned by the system when storing a data structure'() { @@ -77,7 +79,7 @@ class CpServiceImplSpec extends Specification { def 'Store a SchemaContext'() { expect: 'No exception to be thrown when a valid model (schema) is stored' - objectUnderTest.storeSchemaContext(Stub(SchemaContext.class)) + objectUnderTest.storeSchemaContext(Stub(SchemaContext.class), "sampleDataspace") } def 'Read a JSON object with a valid identifier'(){ diff --git a/cps/pom.xml b/cps/pom.xml index dd98ca586c..892492d2d2 100644 --- a/cps/pom.xml +++ b/cps/pom.xml @@ -45,6 +45,27 @@ <type>pom</type>
<scope>import</scope>
</dependency>
+
+ <!-- T E S T D E P E N D E N C I E S -->
+ <dependency>
+ <groupId>org.codehaus.groovy</groupId>
+ <artifactId>groovy</artifactId>
+ <version>${groovy.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.spockframework</groupId>
+ <artifactId>spock-core</artifactId>
+ <version>${spock-core.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib-nodep</artifactId>
+ <version>3.1</version>
+ <scope>test</scope>
+ </dependency>
+
</dependencies>
</dependencyManagement>
|