diff options
11 files changed, 374 insertions, 53 deletions
@@ -3,12 +3,12 @@ <modelVersion>4.0.0</modelVersion> <groupId>org.onap.dmaap.dbcapi</groupId> <artifactId>dbcapi</artifactId> - <version>${artifact.version}</version> + <version>1.0.0-SNAPSHOT</version> <name>dmaap-dbcapi</name> <parent> <groupId>org.onap.oparent</groupId> <artifactId>oparent</artifactId> - <version>0.1.0</version> + <version>0.1.1</version> </parent> <build> <finalName>dbcapi</finalName> @@ -73,7 +73,7 @@ A convention of this API is to return JSON responses per OpenStack style. </configuration> <executions> <execution> - <phase>compile</phase> + <phase>precompile</phase> <goals> <goal>generate</goal> </goals> diff --git a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafDecrypt.java b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafDecrypt.java index c478752..8728988 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/aaf/AafDecrypt.java +++ b/src/main/java/org/onap/dmaap/dbcapi/aaf/AafDecrypt.java @@ -31,7 +31,7 @@ public class AafDecrypt extends BaseLoggingClass { public AafDecrypt() { DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); - dClass = p.getProperty( "AafDecryption.Class", "org.openecomp.dmaapbc.aaf.ClearDecrypt"); + dClass = p.getProperty( "AafDecryption.Class", "org.onap.dmaap.dbcapi.aaf.ClearDecrypt"); try { dec = (DecryptionInterface) (Class.forName(dClass).newInstance()); dec.init( p.getProperty("CredentialCodecKeyfile", "LocalKey")); diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/Dmaap.java b/src/main/java/org/onap/dmaap/dbcapi/model/Dmaap.java index 3f2ef82..ba7fd42 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/model/Dmaap.java +++ b/src/main/java/org/onap/dmaap/dbcapi/model/Dmaap.java @@ -37,7 +37,6 @@ public class Dmaap extends DmaapObject { private String accessKeyOwner; - // no-op constructor used by framework public Dmaap() { @@ -60,6 +59,7 @@ public class Dmaap extends DmaapObject { this.nodeKey = nk; this.accessKeyOwner = ako; this.setStatus( DmaapObject_Status.NEW ); + } public String getVersion() { @@ -128,5 +128,4 @@ public class Dmaap extends DmaapObject { this.loggingUrl = loggingUrl; } - } diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/FqtnType.java b/src/main/java/org/onap/dmaap/dbcapi/model/FqtnType.java new file mode 100644 index 0000000..697e9b8 --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/model/FqtnType.java @@ -0,0 +1,68 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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.dmaap.dbcapi.model; + +import java.util.HashMap; +import java.util.Map; + +import javax.xml.bind.annotation.XmlRootElement; + + +@XmlRootElement +public enum FqtnType { + FQTN_NOT_SPECIFIED(0), + FQTN_LEGACY_FORMAT(1), + FQTN_PROJECTID_FORMAT(2), + FQTN_PROJECTID_VERSION_FORMAT(3); + + + private int value; + private static Map map = new HashMap<>(); + + private FqtnType(int value) { + this.value = value; + } + + static { + for (FqtnType repType : FqtnType.values()) { + map.put(repType.value, repType); + } + } + + public static FqtnType valueOf(int repType) { + return (FqtnType) map.get(repType); + } + + public int getValue() { + return value; + } + + static public FqtnType Validator( String input ){ + + FqtnType t; + try { + t = FqtnType.valueOf( input ); + } catch ( IllegalArgumentException e ) { + t = FQTN_NOT_SPECIFIED; + } + return t; + } + +}
\ No newline at end of file diff --git a/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java b/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java index 712c2eb..7c957dc 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java +++ b/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java @@ -26,6 +26,9 @@ import java.util.Date; import javax.xml.bind.annotation.XmlRootElement; + +import org.onap.dmaap.dbcapi.util.DmaapConfig; + import org.onap.dmaap.dbcapi.service.DmaapService; @@ -40,23 +43,57 @@ public class Topic extends DmaapObject { private String formatUuid; private ReplicationType replicationCase; private String globalMrURL; // optional: URL of global MR to replicate to/from + private FqtnType fqtnStyle; + private String version; private ArrayList<MR_Client> clients; private static Dmaap dmaap = new DmaapService().getDmaap(); - + + // during unit testing, discovered that presence of dots in some values + // creates an unplanned topic namespace as we compose the FQTN. + // this may create sensitivity (i.e. 403) for subsequent creation of AAF perms, so best to not allow it + private static String removeDots( String source, String def ) { + if ( source == null || source.isEmpty()) { + return def; + } + return source.replaceAll("\\.", "_"); + } // // utility function to generate the FQTN of a topic - public static String genFqtn( String name ) { + public String genFqtn( ) { + DmaapConfig dc = (DmaapConfig)DmaapConfig.getConfig(); + String projectId = dc.getProperty("MR.projectID", "99999"); CharSequence signal = "."; String ret; - if ( name.contains( signal )) { + if ( this.getTopicName().contains( signal )) { // presence of a dot indicates the name is already fully qualified - ret = name; + ret = this.getTopicName(); } else { - ret = dmaap.getTopicNsRoot() + "." + dmaap.getDmaapName() + "." + name; + // these vars may not contain dots + String p = removeDots( projectId, "90909"); + String v = removeDots( this.getVersion(), "v1"); + switch( this.getFqtnStyle() ) { + case FQTN_PROJECTID_VERSION_FORMAT: + + ret = dmaap.getTopicNsRoot() + "." + dmaap.getDmaapName() + "." + p + "-" + this.getTopicName() + "-" + v; + break; + + case FQTN_PROJECTID_FORMAT: + + ret = dmaap.getTopicNsRoot() + "." + dmaap.getDmaapName() + "." + p + "-" + this.getTopicName(); + break; + + case FQTN_LEGACY_FORMAT: + default: // for backwards compatibility + ret = dmaap.getTopicNsRoot() + "." + dmaap.getDmaapName() + "." + this.getTopicName(); + break; + + + } + } return ret; } @@ -83,6 +120,7 @@ public class Topic extends DmaapObject { this.setLastMod(); this.setStatus( DmaapObject_Status.NEW ); this.replicationCase = ReplicationType.Validator("none"); + this.fqtnStyle = FqtnType.Validator("none"); logger.debug( "Topic constructor " + this.getLastMod() ); } public String getFqtn() { @@ -162,7 +200,14 @@ public class Topic extends DmaapObject { public void setReplicationCase(ReplicationType t) { this.replicationCase = t; } + public FqtnType getFqtnStyle() { + return fqtnStyle; + } + + public void setFqtnStyle(FqtnType t) { + this.fqtnStyle = t; + } public String getGlobalMrURL() { return globalMrURL; @@ -176,6 +221,18 @@ public class Topic extends DmaapObject { + public String getVersion() { + return version; + } + + + + public void setVersion(String version) { + this.version = version; + } + + + public String toProvJSON() { StringBuilder str = new StringBuilder(); str.append("{ \"topicName\": \""); diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java index 5003801..4796217 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java @@ -29,6 +29,7 @@ import java.util.List; import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.PUT; import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import javax.ws.rs.Produces; @@ -61,56 +62,123 @@ public class BridgeResource extends BaseLoggingClass { @GET @ApiOperation( value = "return BrTopic details", - notes = "Returns array of `BrTopic` objects.", + notes = "Returns array of `BrTopic` objects. If source and target query params are specified, only report on that bridge. If detail param is true, list topics names, else just a count is returned", response = BrTopic.class) @ApiResponses( value = { @ApiResponse( code = 200, message = "Success", response = Dmaap.class), @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) public Response getBridgedTopics(@QueryParam("source") String source, - @QueryParam("target") String target){ + @QueryParam("target") String target, + @QueryParam("detail") Boolean detailFlag ){ ApiService check = new ApiService(); - BrTopic brTopic = new BrTopic(); - - logger.info( "getBridgeTopics():" + " source=" + source + ", target=" + target); -// System.out.println("getBridgedTopics() " + "source=" + source + ", target=" + target ); - if (source != null && target != null) { // get topics between 2 bridged locations - brTopic.setBrSource(source); - brTopic.setBrTarget(target); - MirrorMaker mm = mmService.getMirrorMaker(source, target); - if ( mm != null ) { - brTopic.setTopicCount( mm.getTopicCount() ); - } - - logger.info( "topicCount [2 locations]: " + brTopic.getTopicCount() ); - } - else if (source == null && target == null ) { - List<String> mmList = mmService.getAllMirrorMakers(); - brTopic.setBrSource("all"); - brTopic.setBrTarget("all"); - int totCnt = 0; - for( String key: mmList ) { - int mCnt = 0; - MirrorMaker mm = mmService.getMirrorMaker(key); - if ( mm != null ) { - mCnt = mm.getTopicCount(); + if ( ! Boolean.TRUE.equals(detailFlag)) { + BrTopic brTopic = new BrTopic(); + + logger.info( "getBridgeTopics():" + " source=" + source + ", target=" + target); + // System.out.println("getBridgedTopics() " + "source=" + source + ", target=" + target ); + if (source != null && target != null) { // get topics between 2 bridged locations + brTopic.setBrSource(source); + brTopic.setBrTarget(target); + MirrorMaker mm = mmService.getMirrorMaker(source, target); + if ( mm != null ) { + brTopic.setTopicCount( mm.getTopicCount() ); + } + + logger.info( "topicCount [2 locations]: " + brTopic.getTopicCount() ); + } + else if (source == null && target == null ) { + List<String> mmList = mmService.getAllMirrorMakers(); + brTopic.setBrSource("all"); + brTopic.setBrTarget("all"); + int totCnt = 0; + for( String key: mmList ) { + int mCnt = 0; + MirrorMaker mm = mmService.getMirrorMaker(key); + if ( mm != null ) { + mCnt = mm.getTopicCount(); + } + logger.info( "Count for "+ key + ": " + mCnt); + totCnt += mCnt; } - logger.info( "Count for "+ key + ": " + mCnt); - totCnt += mCnt; + + logger.info( "topicCount [all locations]: " + totCnt ); + brTopic.setTopicCount(totCnt); + + } + else { + + logger.error( "source or target is missing"); + check.setCode(Status.BAD_REQUEST.getStatusCode()); + check.setMessage("Either both source and target or neither must be provided"); + return check.error(); } + return check.success(brTopic); + } else { + - logger.info( "topicCount [all locations]: " + totCnt ); - brTopic.setTopicCount(totCnt); + logger.info( "getBridgeTopics() detail:" + " source=" + source + ", target=" + target); + + if (source != null && target != null) { // get topics between 2 bridged locations + + MirrorMaker mm = mmService.getMirrorMaker(source, target); + if ( mm == null ) { + return check.notFound(); + } + + return check.success(mm); + } + else { + + logger.error( "source and target are required when detail=true"); + check.setCode(Status.BAD_REQUEST.getStatusCode()); + check.setMessage("source and target are required when detail=true"); + return check.error(); + } + } + } + + @PUT + @ApiOperation( value = "update MirrorMaker details", + notes = "replace the topic list for a specific Bridge. Use JSON Body for value to replace whitelist, but if refreshFlag param is true, simply refresh using existing whitelist", + response = MirrorMaker.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Dmaap.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response putBridgedTopics(@QueryParam("source") String source, + @QueryParam("target") String target, + @QueryParam("refresh") Boolean refreshFlag, + MirrorMaker newBridge ){ + ApiService check = new ApiService(); + + logger.info( "putBridgeTopics() detail:" + " source=" + source + ", target=" + target); + + if (source != null && target != null) { // get topics between 2 bridged locations + + MirrorMaker mm = mmService.getMirrorMaker(source, target); + if ( mm == null ) { + return check.notFound(); + } + if ( refreshFlag != null && refreshFlag == false ) { + logger.info( "setting whitelist from message body"); + mm.setTopics( newBridge.getTopics() ); + } else { + logger.info( "refreshing whitelist from memory"); + } + mmService.updateMirrorMaker(mm); + return check.success(mm); } + else { - logger.error( "source or target is missing"); + logger.error( "source and target are required when detail=true"); check.setCode(Status.BAD_REQUEST.getStatusCode()); - check.setMessage("Either 2 locations or no location must be provided"); + check.setMessage("source and target are required when detail=true"); return check.error(); } - return check.success(brTopic); + } } diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java index 361491a..417b18a 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java @@ -37,6 +37,7 @@ import javax.ws.rs.PUT; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.GenericEntity; import javax.ws.rs.core.MediaType; @@ -92,12 +93,16 @@ public class FeedResource extends BaseLoggingClass { @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), @ApiResponse( code = 400, message = "Error", response = ApiError.class ) }) - public Response getFeeds() { + public Response getFeeds( + @QueryParam("feedName") String feedName, + @QueryParam("version") String version, + @QueryParam("match") String match + ) { ApiService resp = new ApiService(); FeedService feedService = new FeedService(); - List<Feed> nfeeds = feedService.getAllFeeds(); + List<Feed> nfeeds = feedService.getAllFeeds( feedName, version, match ); GenericEntity<List<Feed>> list = new GenericEntity<List<Feed>>(nfeeds) { }; return resp.success(list); diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/InfoResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/InfoResource.java new file mode 100644 index 0000000..31c22ba --- /dev/null +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/InfoResource.java @@ -0,0 +1,78 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. 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========================================================= + */ + +// +// $Id$ + +package org.onap.dmaap.dbcapi.resources; + + + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriInfo; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.service.ApiService; +import org.onap.dmaap.dbcapi.service.DmaapService; + + + +@Path("/info") +@Api( value= "info", description = "Endpoint for this instance of DBCL. Returns health info." ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class InfoResource extends BaseLoggingClass { + + + DmaapService dmaapService = new DmaapService(); + + @GET + @ApiOperation( value = "return info details", notes = "returns the `info` object", response = Dmaap.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Dmaap.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + + public Response getInfo(@Context UriInfo uriInfo) { + ApiService check = new ApiService(); + + return check.success(204, null); + } + + + + +} diff --git a/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java b/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java index 0f99fb6..8221813 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java +++ b/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java @@ -44,9 +44,11 @@ import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; import org.onap.dmaap.dbcapi.model.ApiError; import org.onap.dmaap.dbcapi.model.DR_Pub; import org.onap.dmaap.dbcapi.model.ReplicationType; +import org.onap.dmaap.dbcapi.model.FqtnType; import org.onap.dmaap.dbcapi.model.Topic; import org.onap.dmaap.dbcapi.service.ApiService; import org.onap.dmaap.dbcapi.service.TopicService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; @Path("/topics") @Api( value= "topics", description = "Endpoint for retreiving MR Topics" ) @@ -54,8 +56,14 @@ import org.onap.dmaap.dbcapi.service.TopicService; @Produces(MediaType.APPLICATION_JSON) @Authorization public class TopicResource extends BaseLoggingClass { - + private static FqtnType defaultTopicStyle; TopicService mr_topicService = new TopicService(); + + public TopicResource() { + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + defaultTopicStyle = FqtnType.Validator( p.getProperty("MR.topicStyle", "FQTN_LEGACY_FORMAT")); + logger.info( "Setting defaultTopicStyle=" + defaultTopicStyle ); + } @GET @ApiOperation( value = "return Topic details", @@ -104,7 +112,11 @@ public class TopicResource extends BaseLoggingClass { if ( t == null || t == ReplicationType.REPLICATION_NOT_SPECIFIED ) { topic.setReplicationCase( mr_topicService.reviewTopic(topic)); } - + FqtnType ft = topic.getFqtnStyle(); + if ( ft == null || ft == FqtnType.FQTN_NOT_SPECIFIED ) { + logger.info( "setting defaultTopicStyle=" + defaultTopicStyle + " for topic " + topic.getTopicName() ); + topic.setFqtnStyle( defaultTopicStyle ); + } topic.setLastMod(); Topic mrc = mr_topicService.addTopic(topic, check.getErr()); diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java b/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java index f5ea4df..d36adc4 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java +++ b/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java @@ -63,11 +63,43 @@ public class FeedService extends BaseLoggingClass { f.setSubs(subs); } - public List<Feed> getAllFeeds() { + public List<Feed> getAllFeeds( String name, String ver, String match ) { + logger.info( "getAllFeeds: name=" + name + " ver=" + ver + " match=" + match); ArrayList<Feed> fatFeeds = new ArrayList<Feed>(); for( Feed f: feeds.values() ) { - getSubObjects(f); - fatFeeds.add(f); + boolean keep = true; + if ( name != null ) { + if ( match != null && match.equals("startsWith") ) { + if ( ! f.getFeedName().startsWith( name ) ) { + logger.info( "getAllFeeds: feedName=" + f.getFeedName() + " doesn't start with=" + name); + keep = false; + } + } else if ( match != null && match.equals("contains") ) { + if ( ! f.getFeedName().contains( name ) ) { + logger.info( "getAllFeeds: feedName=" + f.getFeedName() + " doesn't contain=" + name); + keep = false; + } + } else { + if ( ! f.getFeedName().equals( name ) ) { + logger.info( "getAllFeeds: feedName=" + f.getFeedName() + " doesn't equal=" + name); + keep = false; + } + } + + } + if ( keep && ver != null ) { + if ( ! f.getFeedVersion().equals(ver)) { + logger.info( "getAllFeeds: feedVersion=" + f.getFeedName() + " doesn't match " + ver); + keep = false; + } else { + logger.info( "getAllFeeds: feedVersion=" + f.getFeedName() + " matches " + ver); + } + } + + if (keep){ + getSubObjects(f); + fatFeeds.add(f); + } } return fatFeeds; } diff --git a/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java b/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java index 244fe37..7082b9b 100644 --- a/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java +++ b/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java @@ -94,7 +94,9 @@ public class TopicService extends BaseLoggingClass { public Topic addTopic( Topic topic, ApiError err ) { logger.info( "Entry: addTopic"); - String nFqtn = Topic.genFqtn( topic.getTopicName() ); + logger.info( "Topic name=" + topic.getTopicName() + " fqtnStyle=" + topic.getFqtnStyle() ); + String nFqtn = topic.genFqtn(); + logger.info( "FQTN=" + nFqtn ); if ( getTopic( nFqtn, err ) != null ) { String t = "topic already exists: " + nFqtn; logger.info( t ); @@ -104,7 +106,7 @@ public class TopicService extends BaseLoggingClass { return null; } err.reset(); // err filled with NOT_FOUND is expected case, but don't want to litter... - logger.info( "fqtn: " + nFqtn ); + topic.setFqtn( nFqtn ); AafService aaf = new AafService(ServiceType.AAF_TopicMgr); |