diff options
Diffstat (limited to 'dmaap-bc')
193 files changed, 24780 insertions, 847 deletions
diff --git a/dmaap-bc/README.md b/dmaap-bc/README.md new file mode 100644 index 0000000..14ebef1 --- /dev/null +++ b/dmaap-bc/README.md @@ -0,0 +1,172 @@ +# +# ============LICENSE_START========================================== +# org.onap.dmaap +# =================================================================== +# Copyright © 2018 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============================================ +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# +# +DMaaP Bus Controller API +======================= + +Data Movement as a Platform (DMaaP) Bus Controller provides an API for other ONAP infrastructure components to provision DMaaP resources. +A typical DMaaP resource is a Data Router Feed or a Message Router Topic, and their associated publishers and subscribers. +Other infrastucture resources such as DR Nodes and MR Clusters are also provisioned through this API. + +### Build Instructions for a Continuous Integration environment using Jenkins + +When this component is included in a Continuous Integration environment, such as structured by the Linux Foundation, the artifacts can be created and deployed via Jenkins. The following maven targets are currently supported in the Build step: +``` +clean install +javadoc:javadoc +sonar:sonar +``` + +### Build Instructions for external developers + +This project is organized as a mvn project for a jar package. +After cloning from this git repo: + +``` +mvn clean install javadoc:javadoc +``` + +A description of the API is generated, and found in targets/generated-source/swagger.json. + +### Properties File + +This section is intended to describe the behavior customization of Bus Controller that can be obtained via properties file used by the dbcapi library. +By default, this file is located in etc/dmaapbc.properties. +However, a java argument -DConfigFile can be set to a different path. (Our kubernetes deployment relies on this and points to a configmap, for example.) + +The table below lists all the settings, default values (if not set), and shows any explicit setting in ONAP oom kubernetes deployment. + +|-|-|-|-| +| Property | Description | Default | ONAP Kubernetes Setting | +|-|-|-|-| +|UseAAF | Flag for whether AAF authz API is to be used | false | false | +|-|-|-|-| +|csit | Flag for stubbing out many southbound calls in a CSIT environment | No | No | +|-|-|-|-| +|DR.provhost | FQDN of Data Router Provisioning Server (deprecated - now set via API) | notSet | dcae-drps.domain.not.set | +|-|-|-|-| +|ProvisioningURI | URI to retrieve dynamic DR configuration | /internal/prov | /internal/prov | +|-|-|-|-| +|Feed.deleteHandling | indicator for handling feed delete request | DeleteOnDR | SimulateDelete | +| | DeleteOnDR - means use the DR API to DELETE a feed. (default for backwards compatibility) | | | +| | SimulateDelete - means preserve the feed on DR (after cleaning it up), and mark as DELETED in DBCL. | | | +|-|-|-|-| +|UsePGSQL | flag indicates whether to retain data in Postgresql | false | true | +| | when false, objects will be kept in memory but will be | | | +| | lost on restart and not shared between instances | | | +|-|-|-|-| +|DB.host | FQDN or service name of Postresql host | dcae-pstg-write-ftl.domain.notset.com | dbc-pg-primary | +|-|-|-|-| +|DB.name | name of Postresql database | dmaap | | +|-|-|-|-| +|DB.schema | name of database schema | public | | +|-|-|-|-| +|DB.user | username for Postgresql access | dmaap_admin | | +|-|-|-|-| +|DB.cred | password for Postrgresql access | test234-ftl | onapdemodb | +|-|-|-|-| +|MR.multisite | Indicates if there can be multiple sites (locations) where MR is deployed | true | false | +|-|-|-|-| +|MR.CentralCname | FQDN or service name of MR (deployed in central if multilocation is true) | MRcname.not.set | message-router | +|-|-|-|-| +|MR ClientDeleteLevel | MR Client Delete thoroughness | 0 | 1 | +| | 0 = don't delete | | | +| | 1 = delete from persistent store (PG) | | | +| | 2 = delete from persistent store (PG) and authorization store (AAF) | | | +|-|-|-|-| +|MR.TopicFactoryNS | AAF namespace used to create perms for MR topics | MR.topicFactoryNS.not.set | org.onap.dmaap.mr.topicFactory | +|-|-|-|-| +|MR.TopicMgrRole | AAF Role used by Buscontroller to create topics on MR | MR.TopicMgrRole.not.set | org.onap.dmaap-bc-topic-mgr.client | +|-|-|-|-| +|MR.projectID | Value for some constructs of fully qualified topic names | 99999 | ONAP | +|-|-|-|-| +|MR.hostnameVerify | Indicates if we want to relax hostname verification on SSL connection | true | false | +|-|-|-|-| +|MR.authentication | Authentication method used when connecting to MR | none | basicAuth | +| | none = no creds sent (default) | | | +| | basicAuth = formulate Basic Auth HTTP Header using name and pwd credentials | | | +| | cert = use client certificate | | | +|-|-|-|-| +|cadi.properties | Path to CADI properties file | /opt/app/osaaf/local/org.onap.dmaap-bc.props | /opt/app/osaaf/lcoal/org.onap.dmaap-bc.props | +|-|-|-|-| +|aaf.URL | URL of the AAF server | https://authentication.domain.netset.com:8100/proxy/ | https://aaf-service.onap:8100/ | +|-|-|-|-| +|aaf.TopicMgrUser | AAF Identity of Topic Mgr | noMechId@domain.netset.com | dmaap-bc-topic-mgr@dmaap-bc-topic-mgr.onap.org | +|-|-|-|-| +|aaf.TopicMgrPassword | AAF Credential for Topic Mgr | notSet | demo123456! | +|-|-|-|-| +|aaf.AdminUser | AAF Identity of user with Admin role for API namespace | noMechId@domain.netset.com | aaf_admin@people.osaaf.org | +|-|-|-|-| +|aaf.AdminPassword | AAF credential of AdminUser | notSet | demo123456! | +|-|-|-|-| +|aaf.NsOwnerIdentity | AAF Identity to be used as topic Namespace owner | notSet | aaf_admin@people.osaaf.org | +|topicNsRoot | AAF namespace value used to create FQTN | org.onap.dcae.dmaap | org.onap.dcae.dmaap | +|-|-|-|-| +|CredentialCodeKeyfile | location of the codec keyfile used to decrypt passwords | LocalKey | etc/LocalKey | +| | in this properties file before they are passed to AAF | LocalKey | etc/LocalKey | +|-|-|-|-| +|AafDecryption.Class | Specifies the Class to be used for decryption | org.onap.dmaap.dbcapi.aaf.ClearDecrypt | | +|-|-|-|-| +|ApiNamespace | Root namespace for AAF perms related to dbcapi access | apiNamespace.not.set | org.onap.dmaap-bc.api | +|-|-|-|-| +|ApiPermission.Class | the Class that determines if a call to API is authorized| allow | | +|-|-|-|-| +|MM.ProvRole | AAF Role of client publishing MM prov cmds | notSet | org.onap.dmaap-bc-mm-prov.prov | +|-|-|-|-| +|MM.ProvUserMechId | AAF Identity when publishing to MM command topic | notSet | dmaap-bc-mm-prov@dmaap-bc-mm-prov.onap.org| +|-|-|-|-| +|MM.ProvUserPwd | AAF credenital for ProvUserMechId | notSet | demo123456! | +|-|-|-|-| +|MM.AgentRole | AAF Role of client susbcribing to MM command topic | notSet | org.onal.dmaap-bc-mm-prov.agent | +|-|-|-|-| +|DR.provApi | Version name of DR API (ONAP or AT&T) | ONAP | ONAP | +|-|-|-|-| +|DR.onBehalfHeader | String for "On Behalf Of" HTTP Header in DR API | X-DR-ON-BEHALF-OF | X-DR-ON-BEHALF-OF | +|-|-|-|-| +|DR.feedContentType | Value for Content-Type Header in DR Feed API | application/vnd.dr.feed | application/vnd.dr.feed | +|-|-|-|-| +|DR subContentType | Value for Content-Type Header in DR Subscription API | application/vnd.dr.subscription | application/vnd.dr.subscription | +|-|-|-|-| +|HttpAllowed | flag indicating whether http is supported | false | true | +|-|-|-|-| +|IntHttpPort | Internal port for http service | 80 | 8080 | +|-|-|-|-| +|IntHttpsPort | Internal port for https service (0 if no cert is avail) | 443 | 8443 | +|-|-|-|-| +|ExtHttpsPort | Externally advertised port for https service (deprecated)| 443 | 443 | +|-|-|-|-| +|KeyStoreType | Format of Java keystore | jks | jks | +|-|-|-|-| +|KeyStoreFile | Path to java keystore | etc/keystore | etc/keystore | +|-|-|-|-| +|KeyStorePassword | Password for keystore | changeit | <provided by Certificate Authority> | +|-|-|-|-| +|KeyPassword | Password for private key in the https keystore | changeit | <provided by Certificate Authority> | +|-|-|-|-| +|TrustStoreType | Format of Trust Store file | jks | jks | +|-|-|-|-| +|TrustStoreFile | Path to Trust Store file | | etc/org.onap.dmaap-bc.trust.jks | +|-|-|-|-| +|TrustStorePassword | Password for Trust Store | | <provided by Certificate Authority> | +|-|-|-|-| +|QuiesceFile | Path to file which signals needs to queiesce | | etc/SHUTDOWN | +|-|-|-|-| + diff --git a/dmaap-bc/misc/dbc-api.jks b/dmaap-bc/misc/dbc-api.jks Binary files differdeleted file mode 100644 index 66142d3..0000000 --- a/dmaap-bc/misc/dbc-api.jks +++ /dev/null diff --git a/dmaap-bc/misc/opensource.env b/dmaap-bc/misc/opensource.env deleted file mode 100644 index a74d333..0000000 --- a/dmaap-bc/misc/opensource.env +++ /dev/null @@ -1,120 +0,0 @@ -# -# -# ============LICENSE_START========================================== -# org.onap.dmaap -# =================================================================== -# Copyright © 2018 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============================================ -# ECOMP is a trademark and service mark of AT&T Intellectual Property. -# -# -# The Controller domain -# -CONT_DOMAIN=simpledemo.onap.org -# -# The https port -# set to 0 if certificate is not ready -DMAAPBC_INT_HTTPS_PORT=0 - -# -# The path to the keystore for https -# -DMAAPBC_KSTOREFILE=/opt/app/dcae-certificates - -# The password for the https keystore -# -DMAAPBC_KSTOREPASS=foofoofoo -# -# The password for the private key in the https keystore -# -DMAAPBC_PVTKEYPASS=barbarbar -# -# Flag for whether we are using PG connection for persistence -# -DMAAPBC_PG_ENABLED=false -# -# The host for postgres access -# -DMAAPBC_PGHOST=zldciad1vipstg00.${CONT_DOMAIN} -# -# For postgres access -# -DMAAPBC_PGCRED=test234-ftl -# -# Name of this environment -# -DMAAPBC_INSTANCE_NAME=onap1 -# -# Name of DR prov server -# -DMAAPBC_DRPROV_FQDN=dcae-drps.${CONT_DOMAIN} - -################# -# AAF Properties: -# -# regarding password encryption: -# In the dependencies that Maven retrieves (e.g., under dcae_dmaapbc/target/deps/ is a jar file cadi-core-version.jar. Generate the key file with: -# -# java \u2013jar wherever/cadi-core-*.jar keygen keyfilename -# chmod 400 keyfilename -# -# To encrypt a key: -# -# java \u2013jar wherever/cadi-core-*.jar digest password-to-encrypt keyfilename -# -# This will generate a string. Put \u201Cenc:\u201D on the front of the string, and put the result in this properties file. -# -# Location of the Codec Keyfile which is used to decrypt passwords in this properties file before they are passed to AAF -# -# REF: https://wiki.domain.notset.com/display/cadi/CADI+Deployment -# -# URL of AAF environment to use. -# -DMAAPBC_AAF_URL=https://aafapi.${CONT_DOMAIN}:8100/proxy/ -# -# TopicMgr mechid@namespace -# -DMAAPBC_TOPICMGR_USER=m99751@dmaapBC.onap.org -# -# TopicMgr password -# -DMAAPBC_TOPICMGR_PWD=enc:zyRL9zbI0py3rJAjMS0dFOnYfEw_mJhO -# -# Bus Controller Namespace Admin mechid@namespace -# -DMAAPBC_ADMIN_USER=m99501@dcae.onap.org -# -# Bus Controller Namespace Admin password -# -DMAAPBC_ADMIN_PWD=enc:YEaHwOJrwhDY8a6usetlhbB9mEjUq9m - -# -# endof AAF Properties -################# - -################# -# PolicyEngine Properties - -# -# Flag to turn on/off Authentication -DMAAPBC_PE_ENABLED=false -# -# Argument to decisionAttributes.put("AAF_ENVIRONMENT", X); -# where X is: TEST= UAT, PROD = PROD, DEVL = TEST -# -DMAAPBC_PE_AAF_ENV=DEMO - -# endof PolicyEngineProperties -################# diff --git a/dmaap-bc/misc/policyLogger.properties b/dmaap-bc/misc/policyLogger.properties deleted file mode 100644 index 6b9ad99..0000000 --- a/dmaap-bc/misc/policyLogger.properties +++ /dev/null @@ -1,45 +0,0 @@ -# -# ============LICENSE_START========================================== -# org.onap.dmaap -# =================================================================== -# Copyright © 2018 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============================================ -# ECOMP is a trademark and service mark of AT&T Intellectual Property. -# -# -################################### Set concurrentHashMap and timer info ####################### -#Timer initial delay and the delay between in milliseconds before task is to be execute. -timer.delay.time=1000 -#Timer scheduleAtFixedRate period - time in milliseconds between successive task executions. -check.interval= 30000 -#Longest time an event info can be stored in the concurrentHashMap for logging - in seconds. -event.expired.time=86400 -#Size of the concurrentHashMap which stores the event starting time, etc - when its size reaches this limit, the Timer gets executed -#to remove all expired records from this concurrentHashMap. -concurrentHashMap.limit=5000 -#Size of the concurrentHashMap - when its size drops to this point, stop the Timer -stop.check.point=2500 -################################### Set logging format ############################################# -# set EELF for EELF logging format, set LOG4J for using log4j, set SYSTEMOUT for using system.out.println -logger.type=EELF -#################################### Set level for EELF or SYSTEMOUT logging ################################## -# Set level for debug file. Set DEBUG to enable .info, .warn and .debug; set INFO for enable .info and .warn; set OFF to disable all -debugLogger.level=OFF -# Set level for metrics file. Set OFF to disable; set ON to enable -metricsLogger.level=ON -# Set level for error file. Set OFF to disable; set ON to enable -error.level=ON -# Set level for audit file. Set OFF to disable; set ON to enable -audit.level=ON diff --git a/dmaap-bc/pom.xml b/dmaap-bc/pom.xml index ded2cc2..e141100 100644 --- a/dmaap-bc/pom.xml +++ b/dmaap-bc/pom.xml @@ -19,298 +19,40 @@ ============LICENSE_END============================================ ECOMP is a trademark and service mark of AT&T Intellectual Property. --> -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <artifactId>dmaap-bc</artifactId> <version>${revision}</version> <name>dmaap-bc</name> + <packaging>jar</packaging> <parent> <groupId>org.onap.dmaap.buscontroller</groupId> <artifactId>parent</artifactId> <version>${revision}</version> <relativePath>../pom.xml</relativePath> </parent> - <build> - <finalName>dmaap-bc</finalName> - - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-enforcer-plugin</artifactId> - <executions> - <execution> - <id>enforce-no-snapshots</id> - <goals> - <goal>enforce</goal> - </goals> - <configuration> - <rules> - <requireReleaseDeps> - <message>No Snapshots Allowed!</message> - <excludes> -<!-- for example, these might be needed... - <exclude>org.onap.dmaap.dbcapi:dbcapi</exclude> - <exclude>org.onap.aaf.authz:aaf-cadi-client</exclude> - <exclude>org.onap.aaf.authz:aaf-misc-env</exclude> - <exclude>org.onap.aaf.authz:aaf-cadi-aaf</exclude> - <exclude>org.onap.aaf.authz:aaf-auth-client</exclude> - <exclude>org.onap.aaf.authz:aaf-cadi-core</exclude> - <exclude>org.onap.aaf.authz:aaf-misc-rosetta</exclude> ---> - </excludes> - </requireReleaseDeps> - </rules> - <fail>true</fail> - </configuration> - </execution> - </executions> - </plugin> - - <!-- Package an Uber jar --> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-shade-plugin</artifactId> - <version>2.4.3</version> - <executions> - <!-- Run shade goal on package phase --> - <execution> - <phase>package</phase> - <goals> - <goal>shade</goal> - </goals> - <configuration> - <createDependencyReducedPom>false</createDependencyReducedPom> - <!-- this filter section is needed to avoid runtime error: - java.lang.SecurityException: Invalid signature file digest for Manifest main attributes - suggestion found at: https://stackoverflow.com/q/999489 - --> - <filters> - <filter> - <artifact>*:*</artifact> - <excludes> - <exclude>META-INF/*.SF</exclude> - <exclude>META-INF/*.DSA</exclude> - <exclude>META-INF/*.RSA</exclude> - </excludes> - </filter> - </filters> - <transformers> - <!-- NOTE: Need the following transformer else gets "Could not resolve type id 'https' into a subtype" error - Solution found from here: - http://stackoverflow.com/questions/27543060/why-does-dropwizard-configuration-is-not-working - Some more context here: - https://github.com/dropwizard/dropwizard/issues/455 --> - <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/> - <!-- add Main-Class to manifest file --> - <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> - <mainClass>org.onap.dmaap.dbcapi.server.Main</mainClass> - </transformer> - </transformers> - </configuration> - </execution> - </executions> - </plugin> - - <!-- for Distribution management --> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-site-plugin</artifactId> - <dependencies> - <dependency> - <groupId>org.apache.maven.wagon</groupId> - <artifactId>wagon-webdav-jackrabbit</artifactId> - <version>2.10</version> - </dependency> - </dependencies> - </plugin> - - </plugins> - <pluginManagement> - <plugins> - <!--This plugin's configuration is used to store Eclipse m2e settings only. It has no influence on the Maven build itself.--> - <plugin> - <groupId>org.eclipse.m2e</groupId> - <artifactId>lifecycle-mapping</artifactId> - <version>1.0.0</version> - <configuration> - <lifecycleMappingMetadata> - <pluginExecutions> - <pluginExecution> - <pluginExecutionFilter> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-dependency-plugin</artifactId> - <versionRange>[2.10,)</versionRange> - <phase>install</phase> - <goals> - <goal>copy-dependencies</goal> - </goals> - </pluginExecutionFilter> - <action> - <ignore/> - </action> - </pluginExecution> - </pluginExecutions> - </lifecycleMappingMetadata> - </configuration> - </plugin> - </plugins> - </pluginManagement> - </build> - <profiles> - <profile> - <id>docker</id> - <properties> - <skipDockerBuild>false</skipDockerBuild> - <skipDockerTag>false</skipDockerTag> - <skipTests>true</skipTests> - </properties> - <build> - <!-- Copy files to docker-stage to be included in image --> - <resources> - <resource> - <targetPath>${basedir}/target/docker-stage</targetPath> - <directory>${basedir}/src/main/resources</directory> - <includes> - <include>Dockerfile</include> - </includes> - </resource> - <resource> - <targetPath>${basedir}/target/docker-stage/opt/app/dmaapbc/etc</targetPath> - <directory>${basedir}/misc</directory> - <includes> - <include>LocalKey</include> - <include>logback.xml</include> - </includes> - </resource> - - <resource> - <targetPath>${basedir}/target/docker-stage/opt/app/dmaapbc/etc</targetPath> - <directory>${multiproject.basedir}</directory> - <includes> - <include>version.properties</include> - </includes> - </resource> - <resource> - <targetPath>${basedir}/target/docker-stage/opt/app/dmaapbc/misc</targetPath> - <directory>${basedir}/misc</directory> - <includes> - <include>opensource.env</include> - <include>*.tmpl</include> - </includes> - </resource> - <resource> - <targetPath>${basedir}/target/docker-stage/opt/app/dmaapbc/bin</targetPath> - <directory>${basedir}/misc</directory> - <includes> - <include>dmaapbc</include> - </includes> - </resource> - </resources> - <plugins> - <!-- Copy jar to docker-stage to be included in image --> - <plugin> - <artifactId>maven-resources-plugin</artifactId> - <version>2.7</version> - <executions> - <execution> - <id>copy-jar</id> - <phase>package</phase> - <goals> - <goal>copy-resources</goal> - </goals> - <configuration> - <outputDirectory>${basedir}/target/docker-stage/opt/app/dmaapbc/lib</outputDirectory> - <resources> - <resource> - <directory>${multiproject.basedir}/dmaap-bc/target</directory> - <includes> - <include>dmaap-bc.jar</include> - </includes> - </resource> - </resources> - </configuration> - </execution> - </executions> - </plugin> - - <!-- Setup image tags per https://wiki.onap.org/display/DW/Independent+Versioning+and+Release+Process#IndependentVersioningandReleaseProcess-StandardizedDockerTagging --> - <plugin> - <groupId>org.codehaus.groovy.maven</groupId> - <artifactId>gmaven-plugin</artifactId> - <executions> - <execution> - <phase>validate</phase> - <goals> - <goal>execute</goal> - </goals> - <configuration> - <properties> - <ver>${project.version}</ver> - <timestamp>${maven.build.timestamp}</timestamp> - </properties> - <source> - println 'ver: ' + project.properties['ver']; - if ( project.properties['ver'].endsWith("-SNAPSHOT") ) { - project.properties['dockertag1']=project.properties['ver'] + "-latest"; - project.properties['dockertag2']=project.properties['ver'] + "-" + project.properties['timestamp']; - } else { - project.properties['dockertag1']=project.properties['ver'] + "-STAGING-latest"; - project.properties['dockertag2']=project.properties['ver'] + "-STAGING-" + project.properties['timestamp']; - } - println 'docker tag 1: ' + project.properties['dockertag1']; - println 'docker tag 2: ' + project.properties['dockertag2']; - </source> - </configuration> - </execution> - </executions> - </plugin> + <description>Data Movement as a Platform (DMaaP) Bus Controller provides a REST API for other + DCAE infrastructure components to provision DMaaP resources. A DMaaP resource is a Data + Router Feed or a Message Router Topic, and their associated publishers and subscribers. + </description> + <properties> + <sitePath>/content/sites/site/${project.groupId}/${project.artifactId}/${project.version} + </sitePath> + <eelf.version>1.0.0</eelf.version> + <dmaapbc.image.name>${docker.image.root}${project.artifactId}</dmaapbc.image.name> + <swagger.version>1.5.19</swagger.version> + <jackson.version>2.9.5</jackson.version> + <jersey.version>2.29</jersey.version> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <jettyVersion>9.4.40.v20210413</jettyVersion> + <eelf.version>1.0.0</eelf.version> + <junit.version>4.12</junit.version> + <sonar.exclusions>**/gen/**,**/generated-sources/**,**/yang-gen**,**/pax/**</sonar.exclusions> + <docker-stage.target.path>/target/docker-stage/opt/app/dmaapbc/</docker-stage.target.path> + </properties> - <plugin> - <groupId>io.fabric8</groupId> - <artifactId>docker-maven-plugin</artifactId> - <version>0.28.0</version> - <configuration> - <verbose>${docker.verbose}</verbose> - <apiVersion>${docker.apiVersion}</apiVersion> - <pullRegistry>${docker.pull.registry}</pullRegistry> - <pushRegistry>${docker.push.registry}</pushRegistry> - <images> - <image> - <name>${docker.image}</name> - <build> - <cleanup>try</cleanup> - <dockerFileDir>${basedir}/target/docker-stage</dockerFileDir> - <dockerFile>Dockerfile</dockerFile> - <tags> - <tag>${dockertag1}</tag> - <tag>${dockertag2}</tag> - </tags> - </build> - </image> - </images> - </configuration> - <executions> - <execution> - <id>generate-images</id> - <phase>install</phase> - <goals> - <goal>build</goal> - </goals> - </execution> - <execution> - <id>push-images</id> - <phase>deploy</phase> - <goals> - <goal>push</goal> - </goals> - </execution> - </executions> - </plugin> - </plugins> - </build> - </profile> - </profiles> <dependencyManagement> <dependencies> <dependency> @@ -322,8 +64,35 @@ </dependency> </dependencies> </dependencyManagement> + <dependencies> <dependency> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-json-jackson</artifactId> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.containers</groupId> + <artifactId>jersey-container-servlet-core</artifactId> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.media</groupId> + <artifactId>jersey-media-moxy</artifactId> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.test-framework.providers</groupId> + <!-- use this if compatibility issues with jetty artifactId: + <artifactId>jersey-test-framework-provider-jetty</artifactId> + <version>${jersey.version}</version> + --> + <artifactId>jersey-test-framework-provider-jdk-http</artifactId> + <version>2.29.1</version> + </dependency> + <dependency> + <groupId>org.glassfish.jersey.inject</groupId> + <artifactId>jersey-hk2</artifactId> + <version>2.29.1</version> + </dependency> + <dependency> <groupId>org.onap.aaf.authz</groupId> <artifactId>aaf-cadi-aaf</artifactId> <version>2.1.7</version> @@ -332,12 +101,12 @@ <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> - <version>2.9.5</version> + <version>${jackson.version}</version> </dependency> <dependency> <groupId>com.fasterxml.jackson.dataformat</groupId> <artifactId>jackson-dataformat-yaml</artifactId> - <version>2.9.5</version> + <version>${jackson.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> @@ -349,6 +118,10 @@ <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> + <!-- DMAAP-656: + - override this dependency because it utilized a third party + - lib called com.google.guava:20.0 which had severe security threat identified. + --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> @@ -358,6 +131,12 @@ <groupId>io.swagger</groupId> <artifactId>swagger-core</artifactId> <version>${swagger.version}</version> + <exclusions> + <exclusion> + <groupId>com.fasterxml.jackson.core</groupId> + <artifactId>jackson-databind</artifactId> + </exclusion> + </exclusions> </dependency> <dependency> <groupId>io.swagger</groupId> @@ -370,29 +149,10 @@ <version>${swagger.version}</version> </dependency> <dependency> - <groupId>org.glassfish.jersey.containers</groupId> - <artifactId>jersey-container-servlet-core</artifactId> - <!-- use the following artifactId if you don't need servlet 2.x compatibility --> - <!-- artifactId>jersey-container-servlet</artifactId --> - </dependency> - <dependency> - <groupId>org.glassfish.jersey.media</groupId> - <artifactId>jersey-media-moxy</artifactId> - </dependency> - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-api</artifactId> - <version>${log4j.version}</version> - </dependency> - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-core</artifactId> - <version>${log4j.version}</version> - </dependency> - <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> <version>${jettyVersion}</version> + <scope>compile</scope> </dependency> <dependency> <groupId>org.eclipse.jetty</groupId> @@ -424,50 +184,20 @@ <version>42.2.14</version> </dependency> <dependency> - <groupId>org.onap.dmaap.dbcapi</groupId> - <artifactId>dbcapi</artifactId> - <version>2.0.4</version> - </dependency> - <dependency> - <groupId>com.att.eelf</groupId> - <artifactId>eelf-core</artifactId> - <version>${eelf.version}</version> - </dependency> - <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.22</version> </dependency> <dependency> - <groupId>org.glassfish.jersey.test-framework.providers</groupId> - <!-- use this if compatibility issues with jetty artifactId: - <artifactId>jersey-test-framework-provider-jetty</artifactId> - <version>${jersey.version}</version> - --> - <artifactId>jersey-test-framework-provider-jdk-http</artifactId> - <version>2.29.1</version> - </dependency> - <dependency> - <groupId>org.glassfish.jersey.inject</groupId> - <artifactId>jersey-hk2</artifactId> - <version>2.29.1</version> - </dependency> - <dependency> <!-- use 2.3.1 to avoid this issue: https://github.com/eclipse-ee4j/jaxb-ri/issues/1222 --> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId> <version>2.3.1</version> </dependency> <dependency> - <groupId>javax.activation</groupId> - <artifactId>javax.activation-api</artifactId> - <version>1.2.0</version> - </dependency> - - <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> - <version>4.12</version> + <version>${junit.version}</version> <scope>test</scope> </dependency> <dependency> @@ -476,12 +206,264 @@ <version>1.1.0</version> <scope>test</scope> </dependency> + <!-- https://mvnrepository.com/artifact/org.mockito/mockito-core --> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>3.9.0</version> + <scope>test</scope> + </dependency> <dependency> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-enforcer-plugin</artifactId> <version>3.0.0-M3</version> </dependency> + <dependency> + <groupId>com.att.eelf</groupId> + <artifactId>eelf-core</artifactId> + <version>${eelf.version}</version> + <exclusions> + <exclusion> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + </exclusion> + <exclusion> + <groupId>org.powermock</groupId> + <artifactId>powermock-module-junit4</artifactId> + </exclusion> + <exclusion> + <groupId>org.powermock</groupId> + <artifactId>powermock-api-mockito</artifactId> + </exclusion> + </exclusions> + </dependency> </dependencies> + <build> + <finalName>dmaap-bc</finalName> + <!-- Copy files to docker-stage to be included in image --> + <resources> + <resource> + <targetPath>${basedir}/target/docker-stage</targetPath> + <directory>${basedir}/src/main/resources/docker</directory> + <includes> + <include>Dockerfile</include> + </includes> + </resource> + <resource> + <targetPath>${basedir}${docker-stage.target.path}etc</targetPath> + <directory>${basedir}/src/main/resources/misc</directory> + <includes> + <include>logback.xml</include> + <include>LocalKey</include> + </includes> + </resource> + <resource> + <targetPath>${basedir}${docker-stage.target.path}etc</targetPath> + <directory>${multiproject.basedir}</directory> + <includes> + <include>version.properties</include> + </includes> + </resource> + <resource> + <targetPath>${basedir}${docker-stage.target.path}misc</targetPath> + <directory>${basedir}/src/main/resources/misc</directory> + <includes> + <include>*.tmpl</include> + </includes> + </resource> + <resource> + <targetPath>${basedir}${docker-stage.target.path}bin</targetPath> + <directory>${basedir}/src/main/resources/misc</directory> + <includes> + <include>dmaapbc</include> + </includes> + </resource> + <resource> + <targetPath>${basedir}${docker-stage.target.path}misc</targetPath> + <directory>${basedir}/src/main/resources/misc</directory> + <includes> + <include>schema_all.sql</include> + </includes> + </resource> + </resources> + <plugins> + <plugin> + <artifactId>maven-assembly-plugin</artifactId> + <version>2.4</version> + <configuration> + <descriptorRefs> + <descriptorRef>jar-with-dependencies</descriptorRef> + </descriptorRefs> + <outputDirectory>${basedir}/target/docker-stage/opt/app/dmaapbc/lib</outputDirectory> + <archive> + <manifest> + <addClasspath>true</addClasspath> + <mainClass>org.onap.dmaap.dbcapi.server.Main</mainClass> + </manifest> + </archive> + <finalName>dmaap-bc.jar</finalName> + <appendAssemblyId>false</appendAssemblyId> + </configuration> + <executions> + <execution> + <id>make-assembly</id> + <!-- this is used for inheritance merges --> + <phase>package</phase> + <!-- bind to the packaging phase --> + <goals> + <goal>single</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-checkstyle-plugin</artifactId> + <executions> + <execution> + <id>onap-java-style</id> + <configuration> + <consoleOutput>false</consoleOutput> + </configuration> + </execution> + </executions> + </plugin> + <!-- reference: https://tech.homeaway.com/development/2016/06/02/generating-swagger-spec.html --> + <plugin> + <groupId>com.github.kongchen</groupId> + <artifactId>swagger-maven-plugin</artifactId> + <version>3.1.5</version> + <configuration> + <apiSources> + <apiSource> + <springmvc>false</springmvc> + <locations> + <location>org.onap.dmaap.dbcapi.resources</location> + </locations> + <schemes> + <scheme>http</scheme> + <scheme>https</scheme> + </schemes> + <host>www.[host]:[port]</host> + <basePath>/webapi</basePath> + <info> + <title>DMaaP Bus Controller REST API</title> + <version>1.1.0</version> + <description> + provides an API for OpenDCAE components which need to provision + underlying DMaaP technologies (Data Router and Message Router). + Primary clients for this API are anticipated to be the OpenDCAE + Controller, OpenDCAE Orchestrator, OpenDCAE Inventory and the + ECOMP Portal. + + Objects managed by DMaaP are deployed in a dcaeLocation which is + a unique identifier for an OpenStack tenant for a dcaeLayer, + opendcae-central (aka ecomp) or opendcae-local-ntc (aka edge). + + A dcaeEnvironment (e.g. FTL or prod) has a single DMaaP. A + DMaaP is managed by a one or more stateless DMaaP Bus + Controller(s), though Bus Controller relies on PGaaS for + persistence. Each DMaaP has a single instance of Data Router, + which has 1 or more DR_Nodes deployed at each dcaeLocation. DR + Clients of type DR_Pub generally publish to a DR_Node that is + local to its dcaeLocation. Routing for a Feed is determined by + the dcaelocation of its DR_Sub clients. + + A DMaaP may have many Message Router instances. Each instance is + deployed as an MR_Cluster. One MR_Cluster is deployed at each + dcaeLocation. MR_Clients generally communicate to the + MR_Cluster at the same dcaeLocation. Replication of messages + between MR_Clusters is accomplished by MR Bridge, which is + provioned by DMaaP Bus Controller based on Topic attributes. + + Therefore, the role of DMaaP Bus Controller is to support other + DCAE infrastructure components to dynamically provision DMaaP + services on behalf of DMaaP clients, and to assist in any + management or discovery activity of its clients. + + A convention of this API is to return JSON responses per + OpenStack style. + </description> + <termsOfService> + http://www.apache.org/licenses/LICENSE-2.0 + </termsOfService> + <contact> + <url>http://www.onap.org</url> + </contact> + <license> + <url>http://www.apache.org/licenses/LICENSE-2.0</url> + <name>Licensed under the Apache License, Version 2.0</name> + </license> + </info> + <swaggerDirectory>target/generated-sources/</swaggerDirectory> + </apiSource> + </apiSources> + </configuration> + <executions> + <execution> + <phase>compile</phase> + <goals> + <goal>generate</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + <profiles> + <profile> + <id>docker</id> + <properties> + <skipDockerBuild>${skip.docker.build}</skipDockerBuild> + <skipDockerTag>${skip.docker.tag}</skipDockerTag> + <skipTests>false</skipTests> + </properties> + <build> + <plugins> + <plugin> + <groupId>io.fabric8</groupId> + <artifactId>docker-maven-plugin</artifactId> + <version>0.28.0</version> + <configuration> + <verbose>${docker.verbose}</verbose> + <apiVersion>${docker.apiVersion}</apiVersion> + <pullRegistry>${docker.pull.registry}</pullRegistry> + <pushRegistry>${docker.push.registry}</pushRegistry> + <images> + <image> + <name>${dmaapbc.image.name}</name> + <build> + <cleanup>try</cleanup> + <dockerFileDir>${basedir}/target/docker-stage</dockerFileDir> + <dockerFile>Dockerfile</dockerFile> + <tags> + <tag>${dockertag1}</tag> + <tag>${dockertag2}</tag> + </tags> + </build> + </image> + </images> + </configuration> + <executions> + <execution> + <id>generate-images</id> + <phase>install</phase> + <goals> + <goal>build</goal> + </goals> + </execution> + <execution> + <id>push-images</id> + <phase>deploy</phase> + <goals> + <goal>push</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> + </profile> + </profiles> <reporting> <plugins> <plugin> @@ -502,45 +484,10 @@ </plugin> </plugins> </reporting> - <distributionManagement> <site> <id>ecomp-site</id> <url>dav:${nexusproxy}${sitePath}</url> </site> </distributionManagement> - <properties> - <multiproject.basedir>${basedir}/..</multiproject.basedir> - <docker.maven.plugin.version>1.0.0</docker.maven.plugin.version> - <jersey.version>2.29</jersey.version> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - <log4j.version>2.13.3</log4j.version> - <jettyVersion>9.4.36.v20210114</jettyVersion> - <eelf.version>1.0.0</eelf.version> - <swagger.version>1.5.19</swagger.version> - <timestamp>${maven.build.timestamp}</timestamp> - <maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format> - <!-- SONAR --> - <jacoco.version>0.7.7.201606060606</jacoco.version> - <sonar-jacoco-listeners.version>3.2</sonar-jacoco-listeners.version> - <sonar.core.codeCoveragePlugin>jacoco</sonar.core.codeCoveragePlugin> - <!-- Default Sonar configuration --> - <sonar.jacoco.reportPath>target/code-coverage/jacoco-ut.exec</sonar.jacoco.reportPath> - <sonar.jacoco.itReportPath>target/code-coverage/jacoco-it.exec</sonar.jacoco.itReportPath> - <!-- Note: This list should match jacoco-maven-plugin's exclusion list below --> - <sonar.exclusions>**/gen/**,**/generated-sources/**,**/yang-gen**,**/pax/**</sonar.exclusions> - - <!-- docker image --> - <docker.image>onap/dmaap/dmaap-bc</docker.image> - - <nexusproxy>https://nexus.onap.org</nexusproxy> - <docker.push.registry>10.12.5.45:5000</docker.push.registry> - - <timestamp>${maven.build.timestamp}</timestamp> - <maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format> - - <!-- for Distribution Management --> - <sitePath>/content/sites/site/org/onap/dmaap/dmaap-bc/${revision}</sitePath> - </properties> - <description>Packaging Platform (DMaaP) Bus Controller API as a Docker container.</description> </project> diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafConnection.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafConnection.java new file mode 100644 index 0000000..934e541 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafConnection.java @@ -0,0 +1,329 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.aaf; + + + + + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.ProtocolException; +import java.net.URL; +import java.net.UnknownHostException; +import java.net.ConnectException; + +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLHandshakeException; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import org.apache.commons.codec.binary.Base64; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + + +public class AafConnection extends BaseLoggingClass { + + + + + + private String aafCred; + private String unit_test; + + + private HttpsURLConnection uc; + + + public AafConnection( String cred ) { + aafCred = cred; + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + unit_test = p.getProperty( "UnitTest", "No" ); + + } + + + private boolean makeConnection( String pURL ) { + + try { + URL u = new URL( pURL ); + uc = (HttpsURLConnection) u.openConnection(); + uc.setInstanceFollowRedirects(false); + logger.info( "successful connect to " + pURL ); + return(true); + } catch ( UnknownHostException uhe ) { + errorLogger.error(DmaapbcLogMessageEnum.UNKNOWN_HOST_EXCEPTION, pURL, uhe.getMessage() ); + logger.error("Error", uhe); + return(false); + } catch (Exception e) { + logger.error("Error", e); + errorLogger.error(DmaapbcLogMessageEnum.HTTP_CONNECTION_ERROR, pURL, e.getMessage()); + return(false); + } + + } + + static String bodyToString( InputStream is ) { + StringBuilder sb = new StringBuilder(); + BufferedReader br = new BufferedReader( new InputStreamReader(is)); + String line; + try { + while ((line = br.readLine()) != null ) { + sb.append( line ); + } + } catch (IOException ex ) { + errorLogger.error( DmaapbcLogMessageEnum.IO_EXCEPTION + ex.getMessage(),ex); + } + + return sb.toString(); + } + + + + public int postAaf( AafObject obj, String pURL ) { + logger.info( "entry: postAaf() to " + pURL ); + String auth = "Basic " + Base64.encodeBase64String(aafCred.getBytes()); + int rc = -1; + + + if ( ! makeConnection( pURL ) ) { + return rc; + }; + + + byte[] postData = obj.getBytes(); + //logger.info( "post fields=" + postData ); //byte isn't very readable + String responsemessage = null; + String responseBody = null; + + try { + if (auth != null) { + uc.setRequestProperty("Authorization", auth); + } + uc.setRequestMethod("POST"); + uc.setRequestProperty("Content-Type", "application/json"); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, trustAllCerts, new java.security.SecureRandom()); + uc.setSSLSocketFactory(sc.getSocketFactory()); + OutputStream os = null; + + + try { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } catch (ProtocolException pe) { + logger.error("Error", pe); + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + logger.error("Error", e); + } + } catch ( SSLHandshakeException she ) { + logger.error("Error", she); + errorLogger.error( DmaapbcLogMessageEnum.SSL_HANDSHAKE_ERROR, pURL); + } catch ( UnknownHostException uhe ) { + logger.error("Error", uhe); + errorLogger.error(DmaapbcLogMessageEnum.UNKNOWN_HOST_EXCEPTION, pURL, uhe.getMessage() ); + rc = 500; + return rc; + } catch ( ConnectException ce ) { + logger.error("Error", ce); + if ( "Yes".equals(unit_test) ) { + rc = 201; + return rc; + } + errorLogger.error(DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, pURL, ce.getMessage() ); + rc = 500; + return rc; + } + try { + rc = uc.getResponseCode(); + } catch ( SSLHandshakeException she ) { + logger.error("Error", she); + errorLogger.error( DmaapbcLogMessageEnum.SSL_HANDSHAKE_ERROR, pURL); + rc = 500; + return rc; + } + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + + if (responsemessage == null) { + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + responsemessage = h0.substring(j + 1); + } + } + } + if ( rc >= 200 && rc < 300 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + } else { + logger.warn( "Unsuccessful response: " + responsemessage ); + } + + } catch (Exception e) { + logger.error("Unable to read response "); + logger.error("Error", e); + } + finally { + try { + uc.disconnect(); + } catch ( Exception e ) { + logger.error("Error", e); + } + } + return rc; + + } + + public int delAaf(AafObject obj, String pURL) { + logger.info( "entry: delAaf() to " + pURL ); + String auth = "Basic " + Base64.encodeBase64String(aafCred.getBytes()); + int rc = -1; + + + if ( ! makeConnection( pURL ) ) { + return rc; + }; + + + byte[] postData = obj.getBytes(); + //logger.info( "post fields=" + postData ); //byte isn't very readable + String responsemessage = null; + String responseBody = null; + + try { + if (auth != null) { + uc.setRequestProperty("Authorization", auth); + } + uc.setRequestMethod("DELETE"); + uc.setRequestProperty("Content-Type", "application/json"); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + + + try { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } catch (ProtocolException pe) { + logger.error("Error", pe); + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + logger.error("Error", e); + } + } catch ( SSLHandshakeException she ) { + errorLogger.error( DmaapbcLogMessageEnum.SSL_HANDSHAKE_ERROR +"For:- "+pURL,she); + } + try { + rc = uc.getResponseCode(); + } catch ( SSLHandshakeException she ) { + logger.error("Error", she); + errorLogger.error( DmaapbcLogMessageEnum.SSL_HANDSHAKE_ERROR, pURL); + rc = 500; + return rc; + } + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + + if (responsemessage == null) { + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + responsemessage = h0.substring(j + 1); + } + } + } + if ( rc >= 200 && rc < 300 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + } else { + logger.warn( "Unsuccessful response: " + responsemessage ); + } + + } catch (Exception e) { + logger.error("Unable to read response "); + logger.error("Error", e); + } + return rc; + + } + + private TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + + @Override + public java.security.cert.X509Certificate[] getAcceptedIssuers() + { + return null; + } + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) + { + //No need to implement. + } + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) + { + //No need to implement. + } + } + }; + + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafDecrypt.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafDecrypt.java new file mode 100644 index 0000000..bf5ecf2 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafDecrypt.java @@ -0,0 +1,58 @@ +/*- + * ============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.aaf; + +import java.io.IOException; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class AafDecrypt extends BaseLoggingClass { + String dClass; + DecryptionInterface dec = null; + + public AafDecrypt() { + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + dClass = p.getProperty( "AafDecryption.Class", "org.onap.dmaap.dbcapi.aaf.ClearDecrypt"); + try { + dec = (DecryptionInterface) (Class.forName(dClass).newInstance()); + dec.init(p.getProperty("CredentialCodecKeyfile", "LocalKey")); + } catch (Exception ee ) { + logger.error("Error", ee); + errorLogger.error(DmaapbcLogMessageEnum.UNEXPECTED_CONDITION, "attempting to instantiate " + dClass ); + } + } + + public String decrypt( String encPwd ) { + + String pwd = "notDecrypted"; + try { + pwd = dec.decrypt( encPwd ); + } catch( IOException io ) { + logger.error("Error", io); + errorLogger.error(DmaapbcLogMessageEnum.DECRYPT_IO_ERROR, dClass, encPwd ); + } + + return pwd; + + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafEmpty.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafEmpty.java new file mode 100644 index 0000000..87e56c4 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafEmpty.java @@ -0,0 +1,28 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.aaf; + +class AafEmpty extends AafObject { + @Override + String toJSON() { + return ""; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafLurService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafLurService.java new file mode 100644 index 0000000..fa49ae8 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafLurService.java @@ -0,0 +1,140 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.aaf; + +import java.io.IOException; +import java.security.Principal; +import java.util.ArrayList; +import java.util.List; + +import org.onap.aaf.cadi.Access; +import org.onap.aaf.cadi.CadiException; +import org.onap.aaf.cadi.LocatorException; +import org.onap.aaf.cadi.Permission; +import org.onap.aaf.cadi.aaf.AAFPermission; +import org.onap.aaf.cadi.aaf.v2_0.AAFAuthn; +import org.onap.aaf.cadi.aaf.v2_0.AAFConHttp; +import org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm; +import org.onap.aaf.cadi.principal.UnAuthPrincipal; +import org.onap.aaf.misc.env.APIException; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; + +/* + * this service uses the AAF Lur object to lookup identities and perms + */ +public class AafLurService extends BaseLoggingClass { + + private static AAFConHttp aafcon; + private static AAFLurPerm aafLur; + private static AAFAuthn<?> aafAuthn; + + + /* + * singleton pattern suggested by AAF + */ + private static AafLurService singleton; + private AafLurService() {} + + + + private static void init( Access myAccess ) throws APIException, CadiException, LocatorException { + appLogger.info( "myAccess=" + myAccess ); + try { + aafcon = new AAFConHttp( myAccess ); + } catch ( CadiException | LocatorException e) { + appLogger.error( "Failure of AAFConHttp: " + e.getMessage() ); + errorLogger.error( "Failure of AAFConHttp: " + e.getMessage() ); + errorLogger.error(e.getMessage()); + + throw e; + } + try { + aafLur = aafcon.newLur(); + } catch ( CadiException e) { + appLogger.error( "Failure of newLur(): " + e.getMessage() ); + errorLogger.error( "Failure of newLur(): " + e.getMessage() ); + errorLogger.error(e.getMessage()); + + throw e; + } + aafAuthn = aafcon.newAuthn( aafLur ); + } + + public static synchronized AafLurService getInstance( Access myAccess ) throws APIException, CadiException, LocatorException{ + if ( singleton == null ) { + singleton = new AafLurService(); + try { + init( myAccess ); + } catch (APIException | CadiException | LocatorException e) { + errorLogger.error(e.getMessage()); + throw e; + } + + } + return singleton; + } + + + public boolean checkPerm(String ns, String fqi, String pwd, DmaapPerm p) throws IOException, CadiException { + + boolean rc = false; + + if ( aafAuthn == null ) { + appLogger.error( "AafLurService: aafAuthn not set as expected."); + return rc; + } + + String ok = aafAuthn.validate( fqi, pwd ); + if ( ok != null ) { + appLogger.info( "FAILED validation of fqi=" + fqi + "with response:" + ok ); + return rc; + } + + Principal principal = new UnAuthPrincipal( fqi ); + // if we pass ns as first arg to AAFPermission constructor it gets prpended to the instance... + // as in ns|instance|type|action. we don't want that. + Permission aafPerm = new AAFPermission( null, p.getPermission(), p.getPtype(), p.getAction()); + if ( aafLur == null ) { + appLogger.error( "AafLurService: aafLur not set as expected."); + return rc; + } + rc = aafLur.fish( principal, aafPerm ); + boolean flag = true; + if (rc == flag ) { + return rc; + } + + List<Permission> perms = new ArrayList<>(); + aafLur.fishAll( principal, perms); + String key = aafPerm.getKey(); + for ( Permission prm: perms ) { + if ( prm.getKey().equals( key )) { + appLogger.info( principal + " has MATCHING perm " + prm.getKey() ); + } else { + appLogger.info( principal + " has non-matching perm " + prm.getKey() ); + } + } + + return rc; + + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafNamespace.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafNamespace.java new file mode 100644 index 0000000..b6da523 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafNamespace.java @@ -0,0 +1,114 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.aaf; + +import java.util.ArrayList; +import java.util.Objects; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + + +public class AafNamespace extends AafObject { + + private String name; + private ArrayList<String> admin; + private ArrayList<String> responsible; + + // in some environments, an AAF Namespace must be owned by a human. + // So, when needed, this var can be set via a property + private static String NsOwnerIdentity; + + public AafNamespace(String ns, String identity ) { + super(); + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + NsOwnerIdentity = p.getProperty( "aaf.NsOwnerIdentity", ""); + this.admin = new ArrayList<>(); + this.responsible = new ArrayList<>(); + + this.name = ns; + this.admin.add( identity ); + this.responsible.add( NsOwnerIdentity ); + } + public void setName( String ns ) { + this.name = ns; + } + public String getName() { + return name; + } + public ArrayList<String> getAdmin() { + return admin; + } + public void setAdmin(ArrayList<String> admin) { + this.admin = admin; + } + public ArrayList<String> getResponsible() { + return responsible; + } + public void setResponsible(ArrayList<String> responsible) { + this.responsible = responsible; + } + + + // given an Array of Strings, return a String that is a separated list of quoted strings. + // e.g. input [ a, b, c ] + // output "a", "b", "c" + private String separatedList( ArrayList<String> list, String sep ) { + if (list.isEmpty()) return null; + String aList = ""; + String delim = ""; + for( String item: list) { + if( ! item.isEmpty()) { + aList += String.format( "%s\"%s\"", delim, item ); + delim = sep; + } + } + return aList; + } + + public String toJSON() { + + String postJSON = String.format(" { \"name\": \"%s\", \"admin\": [", + this.getName() + ); + postJSON += separatedList( this.getAdmin(), "," ); + postJSON += "], \"responsible\":["; + postJSON += separatedList( this.getResponsible(), ","); + postJSON += "]}"; + logger.info( "returning JSON: " + postJSON); + + return postJSON; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AafNamespace that = (AafNamespace) o; + return Objects.equals(name, that.name) && + Objects.equals(admin, that.admin) && + Objects.equals(responsible, that.responsible); + } + + @Override + public int hashCode() { + return Objects.hash(name, admin, responsible); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafObject.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafObject.java new file mode 100644 index 0000000..9c8f99e --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafObject.java @@ -0,0 +1,34 @@ +/*- + * ============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.aaf; + +import java.nio.charset.StandardCharsets; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; + +public abstract class AafObject extends BaseLoggingClass { + + abstract String toJSON(); + + public byte[] getBytes() { + return toJSON().getBytes(StandardCharsets.UTF_8); + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafRole.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafRole.java new file mode 100644 index 0000000..0997dd4 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafRole.java @@ -0,0 +1,74 @@ +/*- + * ============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.aaf; + +import java.util.Objects; + +public class AafRole extends AafObject { + + private String namespace; + private String role; + + public AafRole(String ns, String role) { + super(); + this.namespace = ns; + this.role = role; + } + public void setNamespace( String ns ) { + this.namespace = ns; + } + public String getNamespace() { + return namespace; + } + public void setRole(String role) { + this.role = role; + } + public String getRole() { + return role; + } + public String getFullyQualifiedRole() { + return namespace + "." + role; + } + + public String toJSON() { + + String postJSON = String.format(" { \"name\": \"%s.%s\"}", + this.getNamespace(), + this.getRole() ); + logger.info( "returning JSON: " + postJSON); + + return postJSON; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AafRole aafRole = (AafRole) o; + return Objects.equals(namespace, aafRole.namespace) && + Objects.equals(role, aafRole.role); + } + + @Override + public int hashCode() { + return Objects.hash(namespace, role); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafService.java new file mode 100644 index 0000000..3f009f8 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafService.java @@ -0,0 +1,47 @@ +/*- + * ============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.aaf; + +/* + * this service uses the AAF REST API endpoints to provision values in AAF + */ +public interface AafService { + enum ServiceType { + AAF_Admin, + AAF_TopicMgr + } + + String getIdentity(); + + int addPerm(DmaapPerm perm); + + int delPerm(DmaapPerm perm, boolean force); + + int addGrant(DmaapGrant grant); + + int addUserRole(AafUserRole ur); + + int addRole(AafRole role); + + int addNamespace(AafNamespace ns); + + int delNamespace(AafNamespace ns, boolean force); +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafServiceFactory.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafServiceFactory.java new file mode 100644 index 0000000..cfde19b --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafServiceFactory.java @@ -0,0 +1,86 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.aaf; + +import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class AafServiceFactory extends BaseLoggingClass { + + private final DmaapConfig dmaapConfig; + + public AafServiceFactory() { + this((DmaapConfig) DmaapConfig.getConfig()); + } + + AafServiceFactory(DmaapConfig dmaapConfig) { + this.dmaapConfig = dmaapConfig; + } + + public AafService initAafService(ServiceType serviceType) { + boolean useAaf = "true".equalsIgnoreCase(dmaapConfig.getProperty("UseAAF", "false")); + String aafUrl = dmaapConfig.getProperty("aaf.URL", "https://authentication.domain.netset.com:8100/proxy/"); + logger.info("AafService initAafService: useAaf={}, aafUrl={}", useAaf, aafUrl); + + AafCred cred = getCred(serviceType); + return new AafServiceImpl(useAaf, aafUrl, cred.getIdentity(), new AafConnection(cred.toString())); + } + + AafCred getCred(ServiceType ctype) { + String mechIdProperty; + String secretProperty; + AafDecrypt decryptor = new AafDecrypt(); + + if (ctype == ServiceType.AAF_Admin) { + mechIdProperty = "aaf.AdminUser"; + secretProperty = "aaf.AdminPassword"; + } else if (ctype == ServiceType.AAF_TopicMgr) { + mechIdProperty = "aaf.TopicMgrUser"; + secretProperty = "aaf.TopicMgrPassword"; + } else { + logger.error("Unexpected case for AAF credential type: " + ctype); + return null; + } + String identity = dmaapConfig.getProperty(mechIdProperty, "noMechId@domain.netset.com"); + String pwd = decryptor.decrypt(dmaapConfig.getProperty(secretProperty, "notSet")); + + return new AafCred(identity, pwd); + } + + class AafCred { + private final String identity; + private final String pwd; + + AafCred(String identity, String pwd) { + this.identity = identity; + this.pwd = pwd; + } + + public String getIdentity() { + return identity; + } + + public String toString() { + return identity + ":" + pwd; + } + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafServiceImpl.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafServiceImpl.java new file mode 100644 index 0000000..1491818 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafServiceImpl.java @@ -0,0 +1,163 @@ +/*- + * ============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.aaf; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; + +import static java.lang.String.format; + +public class AafServiceImpl extends BaseLoggingClass implements AafService { + + private static final int CREATED = 201; + private static final int OK = 200; + private static final String FORCE = "?force=true"; + private final String aafUrl; + private final String identity; + private final boolean useAAF; + private final AafConnection aafConnection; + + AafServiceImpl(boolean useAaf, String aafUrl, String identity, AafConnection aafConnection) { + this.useAAF = useAaf; + this.aafUrl = aafUrl; + this.identity = identity; + this.aafConnection = aafConnection; + } + + @Override + public String getIdentity() { + return identity; + } + + @Override + public int addPerm(DmaapPerm perm) { + logger.info("entry: addPerm() "); + return doPost(perm, "authz/perm", CREATED); + } + + @Override + public int delPerm(DmaapPerm perm, boolean force) { + logger.info("entry: delPerm()"); + return doDelete(new AafEmpty(), format( + "authz/perm/%s/%s/%s%s", + perm.getPermission(), perm.getPtype(), perm.getAction(), force ? FORCE : ""), OK); + } + + @Override + public int addGrant(DmaapGrant grant) { + logger.info("entry: addGrant() "); + return doPost(grant, "authz/role/perm", CREATED); + } + + @Override + public int addUserRole(AafUserRole ur) { + logger.info("entry: addUserRole() "); + return doPost(ur, "authz/userRole", CREATED); + } + + @Override + public int addRole(AafRole role) { + logger.info("entry: addRole() "); + return doPost(role, "authz/role", CREATED); + } + + @Override + public int addNamespace(AafNamespace ns) { + logger.info("entry: addNamespace() "); + return doPost(ns, "authz/ns", CREATED); + } + + @Override + public int delNamespace(AafNamespace ns, boolean force) { + logger.info("entry: delNamespace()"); + return doDelete(new AafEmpty(), format( + "authz/ns/%s%s", + ns.getName(), force ? FORCE : ""), OK); + } + + private int doPost(AafObject obj, String uri, int expect) { + int rc; + logger.info("entry: doPost() "); + String pURL = aafUrl + uri; + logger.info("doPost: useAAF=" + useAAF); + if (useAAF) { + logger.info("doPost: " + obj.toJSON()); + rc = aafConnection.postAaf(obj, pURL); + } else { + rc = expect; + } + switch (rc) { + case 401: + case 403: + errorLogger.error(DmaapbcLogMessageEnum.AAF_CREDENTIAL_ERROR, identity); + break; + case 409: + logger.warn("Object for " + uri + " already exists. Possible conflict."); + break; + default: + if (rc == expect) { + logger.info("expected response: " + rc); + } else { + logger.error("Unexpected response: " + rc); + } + break; + } + + return rc; + } + + private int doDelete(AafObject obj, String uri, int expect) { + int rc; + String pURL = aafUrl + uri; + if (useAAF) { + logger.info("doDelete: " + obj.toJSON()); + rc = aafConnection.delAaf(obj, pURL); + } else { + rc = expect; + } + switch (rc) { + case 401: + case 403: + errorLogger.error(DmaapbcLogMessageEnum.AAF_CREDENTIAL_ERROR, identity); + break; + case 404: + logger.warn("Object not found...ignore"); + break; + case OK: + logger.info("expected response"); + break; + default: + logger.error("Unexpected response: " + rc); + break; + } + + return rc; + } + + String getAafUrl() { + return aafUrl; + } + + boolean isUseAAF() { + return useAAF; + } + +}
\ No newline at end of file diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafUserRole.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafUserRole.java new file mode 100644 index 0000000..b948e61 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/AafUserRole.java @@ -0,0 +1,80 @@ +/*- + * ============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.aaf; + +import java.util.Objects; + + +public class AafUserRole extends AafObject { + + private String identity; + private String role; + + + + public AafUserRole(String identity, String role ) { + super(); + this.identity = identity; + this.role = role; + } + + public void setRole(String role) { + this.role = role; + } + public String getRole() { + return role; + } + + public String getIdentity() { + return identity; + } + + public void setIdentity(String identity) { + this.identity = identity; + } + + public String toJSON() { + + String postJSON = String.format(" { \"user\": \"%s\", \"role\": \"%s\" }", + this.getIdentity(), + this.getRole() + ); + logger.info( "returning JSON: " + postJSON); + + return postJSON; + } + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AafUserRole that = (AafUserRole) o; + return Objects.equals(identity, that.identity) && + Objects.equals(role, that.role); + } + + @Override + public int hashCode() { + + return Objects.hash(identity, role); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/ClearDecrypt.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/ClearDecrypt.java new file mode 100644 index 0000000..fe3e3e7 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/ClearDecrypt.java @@ -0,0 +1,42 @@ +/*- + * ============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.aaf; + +import java.io.IOException; + +public class ClearDecrypt implements DecryptionInterface { + + @Override + public String decrypt(String enc) throws IOException { + return enc; + } + + @Override + public String valueOf(String s) { + return s; + } + + @Override + public boolean init(String codecFname) { + return false; + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/DecryptionInterface.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/DecryptionInterface.java new file mode 100644 index 0000000..eda6465 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/DecryptionInterface.java @@ -0,0 +1,30 @@ +/*- + * ============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.aaf; + +import java.io.IOException; + +public interface DecryptionInterface { + public boolean init( String codecFname ); + public String decrypt(String enc) throws IOException; + public String valueOf( String s); + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/DmaapGrant.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/DmaapGrant.java new file mode 100644 index 0000000..e171b88 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/DmaapGrant.java @@ -0,0 +1,79 @@ +/*- + * ============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.aaf; + +import java.util.Objects; + +public class DmaapGrant extends AafObject { + + private DmaapPerm perm; + private String role; + + public DmaapGrant() { + + } + + public DmaapGrant(DmaapPerm p, String r) { + this.perm = p; + this.role = r; + } + + public DmaapPerm getPerm() { + return perm; + } + + public void setPerm(DmaapPerm perm) { + this.perm = perm; + } + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public String toJSON() { + + String postJSON = String.format(" { \"perm\": %s, \"role\": \"%s\"}", + this.perm.toJSON(), + this.getRole()); + logger.info("returning JSON: " + postJSON); + + return postJSON; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DmaapGrant that = (DmaapGrant) o; + return Objects.equals(perm, that.perm) && + Objects.equals(role, that.role); + } + + @Override + public int hashCode() { + + return Objects.hash(perm, role); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/DmaapPerm.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/DmaapPerm.java new file mode 100644 index 0000000..2f1765d --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/aaf/DmaapPerm.java @@ -0,0 +1,89 @@ +/*- + * ============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.aaf; + +import java.util.Objects; + + +public class DmaapPerm extends AafObject { + + private String permission; + private String ptype; + private String action; + + public DmaapPerm(String permission, String ptype, String action) { + super(); + this.permission = permission; + this.ptype = ptype; + this.action = action; + } + + public String getPermission() { + return permission; + } + + public void setPermission(String permission) { + this.permission = permission; + } + + public String getPtype() { + return ptype; + } + + public void setPtype(String ptype) { + this.ptype = ptype; + } + + public String getAction() { + return action; + } + + public void setAction(String action) { + this.action = action; + } + + public String toJSON() { + + String postJSON = String.format(" { \"type\": \"%s\", \"instance\": \"%s\", \"action\": \"%s\"}", + this.getPermission(), + this.getPtype(), + this.getAction()); + logger.info("returning JSON: " + postJSON); + + return postJSON; + } + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DmaapPerm dmaapPerm = (DmaapPerm) o; + return Objects.equals(permission, dmaapPerm.permission) && + Objects.equals(ptype, dmaapPerm.ptype) && + Objects.equals(action, dmaapPerm.action); + } + + @Override + public int hashCode() { + return Objects.hash(permission, ptype, action); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/AafLurAndFish.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/AafLurAndFish.java new file mode 100644 index 0000000..825b711 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/AafLurAndFish.java @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.authentication; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; +import org.onap.aaf.cadi.CadiException; +import org.onap.aaf.cadi.LocatorException; +import org.onap.aaf.cadi.PropAccess; +import org.onap.aaf.misc.env.APIException; +import org.onap.dmaap.dbcapi.aaf.AafLurService; +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + + +public class AafLurAndFish extends BaseLoggingClass implements ApiAuthorizationCheckInterface { + private AafLurService svc; + private static String apiNamespace; + private static final String ERROR="Error"; + + AafLurAndFish() throws AuthenticationErrorException { + + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + apiNamespace = p.getProperty( "ApiNamespace", "org.onap.dmaap-bc.api"); + + String cadiprop = p.getProperty( "cadi.properties", "/opt/app/osaaf/local/org.onap.dmaap-bc.props"); + logger.info( "cadiprops in " + cadiprop ); + Properties props = new Properties(); + try { + FileInputStream fis = new FileInputStream( cadiprop ); + try { + props.load( fis ); + } finally { + fis.close(); + } + } catch ( IOException e ) { + errorLogger.error( "Unable to load " + cadiprop ); + errorLogger.error(ERROR, e); + throw new AuthenticationErrorException( ); + } + try { + PropAccess myAccess = new PropAccess( props ); + + svc = AafLurService.getInstance(myAccess); + } catch (APIException | CadiException | LocatorException e ) { + errorLogger.error(ERROR, e); + errorLogger.error( e.toString() ); + throw new AuthenticationErrorException(); + } + + } + + public void check( String mechid, String pwd, DmaapPerm p ) throws AuthenticationErrorException { + + try { + if (mechid.isEmpty() || pwd.isEmpty()) { + throw new AuthenticationErrorException("No basic authorization value provided"); + } + + if (!svc.checkPerm( apiNamespace, mechid, pwd, p )) { + throw new AuthenticationErrorException(); + } + } catch ( IOException | CadiException e ) { + errorLogger.error(ERROR, e); + errorLogger.error( e.toString() ); + throw new AuthenticationErrorException(); + } + + } + + public static void main(String[] args) throws Exception { + AafLurAndFish alaf = new AafLurAndFish(); + DmaapPerm p = new DmaapPerm( "org.onap.dmaap-bc.api.dmaap", "boot", "GET"); + + try { + alaf.check("mmanager@people.osaaf.org", "demo123456!", p); + } catch (AuthenticationErrorException aee ) { + errorLogger.error(aee.getMessage()); + errorLogger.error( "Check failed for: " + p.toJSON()); + System.exit(-1); + } + errorLogger.info("Check succeeded for: " + p.toJSON()); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/AllowAll.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/AllowAll.java new file mode 100644 index 0000000..2e83e6c --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/AllowAll.java @@ -0,0 +1,29 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.authentication; + +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; + +public class AllowAll implements ApiAuthorizationCheckInterface { + @Override + public void check(String mechid, String pwd, DmaapPerm p) { + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/ApiAuthorizationCheckInterface.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/ApiAuthorizationCheckInterface.java new file mode 100644 index 0000000..1fef09d --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/ApiAuthorizationCheckInterface.java @@ -0,0 +1,29 @@ +/*- + * ============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.authentication; + +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; + +@FunctionalInterface +public interface ApiAuthorizationCheckInterface { + public void check( String mechid, String pwd, DmaapPerm p ) throws AuthenticationErrorException; + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/ApiPerms.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/ApiPerms.java new file mode 100644 index 0000000..b082102 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/ApiPerms.java @@ -0,0 +1,180 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2018 IBM. + * ================================================================================ + * 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.authentication; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import org.onap.dmaap.dbcapi.aaf.AafService; +import org.onap.dmaap.dbcapi.aaf.AafServiceFactory; +import org.onap.dmaap.dbcapi.aaf.DmaapGrant; +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.service.DmaapService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class ApiPerms extends BaseLoggingClass { + static String topic = "topics"; + static String mrClusters = "mr_clusters"; + static String mrClients = "mr_clients"; + static String feed = "feeds"; + static String drSubs = "dr_subs"; + static String drPubs = "dr_pubs"; + static String drNodes = "dr_nodes"; + static String dcaeLocations = "dcaeLocations"; + static String inventory = "Inventory"; + static String portalUser = "PortalUser"; + static String orchestrator = "Orchestrator"; + static String delete = "DELETE"; + static String dmaap = "dmaap"; + static String controller = "Controller"; + + private static class PermissionMap { + static final EELFLogger logger = EELFManager.getInstance().getLogger( PermissionMap.class ); + static final EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger(); + String uri; + String action; + String[] roles; + + private PermissionMap( String u, String a, String[] r ) { + this.setUri(u); + this.setAction(a); + this.setRoles(r); + } + + public String getUri() { + return uri; + } + public void setUri(String uri) { + this.uri = uri; + } + public String getAction() { + return action; + } + public void setAction(String action) { + this.action = action; + } + + public String[] getRoles() { + return roles; + } + public void setRoles(String[] roles) { + this.roles = roles; + } + + public static void initMap( PermissionMap[] pmap, String instance ) { + + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + String api = p.getProperty("ApiNamespace", "apiNamespace.not.set"); + + AafService aaf = new AafServiceFactory().initAafService(ServiceType.AAF_Admin); + + for ( int i = 0; i < pmap.length ; i++ ) { + String uri = new String( api + "." + pmap[i].getUri()); + DmaapPerm perm = new DmaapPerm( uri, instance, pmap[i].getAction() ); + int rc = aaf.addPerm( perm ); + if ( rc != 201 && rc != 409 ) { + errorLogger.error( DmaapbcLogMessageEnum.AAF_UNEXPECTED_RESPONSE, Integer.toString(rc), "add perm", perm.toString() ); + + } + for( String r: pmap[i].getRoles()) { + String fr = new String( api + "." + r ); + logger.debug( "i:" + i + " granting perm " + perm.toString()+ " to role=" + fr ); + DmaapGrant grant = new DmaapGrant( perm, fr ); + rc = aaf.addGrant( grant ); + if ( rc != 201 && rc != 409 ) { + errorLogger.error( DmaapbcLogMessageEnum.AAF_UNEXPECTED_RESPONSE, Integer.toString(rc), "grant perm", perm.toString() ); + } + } + + } + } + } + + static PermissionMap[] bootMap = { + new PermissionMap( dmaap, "GET", new String[] { controller }), + new PermissionMap( dmaap, "POST", new String[] { controller }), + new PermissionMap( dmaap, "PUT", new String[] { controller }), + new PermissionMap( dmaap, delete, new String[] { controller }) + + }; + + static PermissionMap[] envMap = { + new PermissionMap( dmaap, "GET", new String[] { controller, orchestrator, inventory, "Metrics", portalUser }), + new PermissionMap( dmaap, "POST", new String[] { controller } ), + new PermissionMap( dmaap, "PUT", new String[] { controller }), + new PermissionMap( dmaap, delete, new String[] { controller }), + new PermissionMap( "bridge", "GET", new String[] { "Metrics" }), + //new PermissionMap( "bridge", "POST", new String[] { "Metrics" } ), + //new PermissionMap( "bridge", "PUT", new String[] { "Metrics" }), + //new PermissionMap( "bridge", delete, new String[] { "Metrics" }), + new PermissionMap( dcaeLocations, "GET", new String[] { controller, orchestrator, inventory, "Metrics", portalUser }), + new PermissionMap( dcaeLocations, "POST", new String[] { controller } ), + new PermissionMap( dcaeLocations, "PUT", new String[] { controller }), + new PermissionMap( dcaeLocations, delete, new String[] { controller }), + new PermissionMap( drNodes, "GET", new String[] { controller, orchestrator, inventory, portalUser }), + new PermissionMap( drNodes, "POST", new String[] { controller } ), + new PermissionMap( drNodes, "PUT", new String[] { controller }), + new PermissionMap( drNodes, delete, new String[] { controller }), + new PermissionMap( drPubs, "GET", new String[] { controller, orchestrator, inventory, "Metrics", portalUser }), + new PermissionMap( drPubs, "POST", new String[] { controller, orchestrator,portalUser } ), + new PermissionMap( drPubs, "PUT", new String[] { controller, orchestrator,portalUser }), + new PermissionMap( drPubs, delete, new String[] { controller, orchestrator,portalUser }), + new PermissionMap( drSubs, "GET", new String[] { controller, orchestrator, inventory, "Metrics", portalUser }), + new PermissionMap( drSubs, "POST", new String[] { controller, orchestrator,portalUser } ), + new PermissionMap( drSubs, "PUT", new String[] { controller, orchestrator,portalUser }), + new PermissionMap( drSubs, delete, new String[] { controller, orchestrator,portalUser }), + new PermissionMap( feed, "GET", new String[] { controller, orchestrator, inventory, "Metrics", portalUser }), + new PermissionMap( feed, "POST", new String[] { controller, orchestrator,portalUser } ), + new PermissionMap( feed, "PUT", new String[] { controller, orchestrator, portalUser }), + new PermissionMap( feed, delete, new String[] { controller, portalUser }), + new PermissionMap( mrClients, "GET", new String[] { controller, orchestrator, inventory, "Metrics", portalUser }), + new PermissionMap( mrClients, "POST", new String[] { controller,orchestrator, portalUser } ), + new PermissionMap( mrClients, "PUT", new String[] { controller, orchestrator,portalUser }), + new PermissionMap( mrClients, delete, new String[] { controller,orchestrator, portalUser }), + new PermissionMap( mrClusters, "GET", new String[] { controller, orchestrator, inventory, "Metrics", portalUser }), + new PermissionMap( mrClusters, "POST", new String[] { controller } ), + new PermissionMap( mrClusters, "PUT", new String[] { controller }), + new PermissionMap( mrClusters, delete, new String[] { controller }), + new PermissionMap( topic, "GET", new String[] { controller, orchestrator, inventory, "Metrics", portalUser }), + new PermissionMap( topic, "POST", new String[] { controller, orchestrator } ), + new PermissionMap( topic, "PUT", new String[] { controller, orchestrator }), + new PermissionMap( topic, delete, new String[] { controller, orchestrator }) + }; + + public void setBootMap() { + String instance = "boot"; + PermissionMap.initMap( bootMap, instance ); + } + + public void setEnvMap() { + Dmaap dmaapVar = new DmaapService().getDmaap(); + String dmaapName = dmaapVar.getDmaapName(); + PermissionMap.initMap( envMap, dmaapName ); + } + + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/ApiPolicy.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/ApiPolicy.java new file mode 100644 index 0000000..16d0367 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/ApiPolicy.java @@ -0,0 +1,63 @@ +/*- + * ============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.authentication; + +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +import java.util.Properties; + +public class ApiPolicy extends BaseLoggingClass { + + private boolean permissionClassSet = true; + private ApiAuthorizationCheckInterface perm = null; + + public ApiPolicy() { + this(DmaapConfig.getConfig()); + } + + ApiPolicy(Properties p) { + String dClass = p.getProperty("ApiPermission.Class"); + logger.info("ApiPolicy implements " + dClass); + logger.info("dClass=" + dClass + " permissionClassSet=" + permissionClassSet); + + try { + perm = (ApiAuthorizationCheckInterface) (Class.forName(dClass).newInstance()); + } catch (Exception ee) { + errorLogger.error(DmaapbcLogMessageEnum.UNEXPECTED_CONDITION, "attempting to instantiate " + dClass); + errorLogger.error("trace is: " + ee); + permissionClassSet = false; + } + } + + public void check(String mechid, String pwd, DmaapPerm p) throws AuthenticationErrorException { + perm.check(mechid, pwd, p); + } + + public boolean isPermissionClassSet() { + return permissionClassSet; + } + + ApiAuthorizationCheckInterface getPerm() { + return perm; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/AuthenticationErrorException.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/AuthenticationErrorException.java new file mode 100644 index 0000000..01200f7 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/authentication/AuthenticationErrorException.java @@ -0,0 +1,35 @@ +/*- + * ============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.authentication; + +public class AuthenticationErrorException extends Exception { + /** + * + */ + private static final long serialVersionUID = 1L; + + public AuthenticationErrorException() { + } + + public AuthenticationErrorException(String s) { + super(s); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/client/DrProvConnection.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/client/DrProvConnection.java new file mode 100644 index 0000000..dffe830 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/client/DrProvConnection.java @@ -0,0 +1,1101 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.client; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.ConnectException; +import java.net.ProtocolException; +import java.net.SocketException; +import java.net.URL; +import java.util.Arrays; +import javax.net.ssl.HttpsURLConnection; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DR_Sub; +import org.onap.dmaap.dbcapi.model.Feed; +import org.onap.dmaap.dbcapi.service.DmaapService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + + + +public class DrProvConnection extends BaseLoggingClass { + + + private String provURL; + private String provApi; + private String behalfHeader; + private String feedContentType; + private String subContentType; + private String unit_test; + private String provURI; + + private HttpsURLConnection uc; + + + public DrProvConnection() { + provURL = new DmaapService().getDmaap().getDrProvUrl(); + if ( provURL.length() < 1 ) { + errorLogger.error( DmaapbcLogMessageEnum.PREREQ_DMAAP_OBJECT, "DmaapService().getDmaap().getDrProvUrl()"); + } + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + provApi = p.getProperty( "DR.provApi", "ONAP" ); + behalfHeader = p.getProperty( "DR.onBehalfHeader", "X-DMAAP-DR-ON-BEHALF-OF"); + feedContentType = p.getProperty( "DR.feedContentType", "application/vnd.dmaap-dr.feed"); + subContentType = p.getProperty( "DR.subContentType", "application/vnd.dmaap-dr.subscription"); + provURI = p.getProperty( "DR.ProvisioningURI", "/internal/prov"); + logger.info( "provURL=" + provURL + " provApi=" + provApi + " behalfHeader=" + behalfHeader + + " feedContentType=" + feedContentType + " subContentType=" + subContentType ); + unit_test = p.getProperty( "UnitTest", "No" ); + + } + + public boolean makeFeedConnection() { + return makeConnection( provURL ); + } + public boolean makeFeedConnection(String feedId) { + return makeConnection( provURL + "/feed/" + feedId ); + } + public boolean makeSubPostConnection( String subURL ) { + String[] parts = subURL.split("/"); + String revisedURL = provURL + "/" + parts[3] + "/" + parts[4]; + logger.info( "mapping " + subURL + " to " + revisedURL ); + return makeConnection( revisedURL ); + } + public boolean makeSubPutConnection( String subId ) { + String revisedURL = provURL + "/subs/" + subId; + logger.info( "mapping " + subId + " to " + revisedURL ); + return makeConnection( revisedURL ); + } + + public boolean makeIngressConnection( String feed, String user, String subnet, String nodep ) { + String uri = String.format("/internal/route/ingress/?feed=%s&user=%s&subnet=%s&nodepatt=%s", + feed, user, subnet, nodep ); + return makeConnection( provURL + uri ); + } + public boolean makeEgressConnection( String sub, String nodep ) { + String uri = String.format("/internal/route/egress/?sub=%s&node=%s", + sub, nodep ); + return makeConnection( provURL + uri ); + } + public boolean makeDumpConnection() { + String url = provURL + provURI; + return makeConnection( url ); + } + public boolean makeNodesConnection( String varName ) { + + String uri = String.format("/internal/api/%s", varName); + return makeConnection( provURL + uri ); + } + + public boolean makeNodesConnection( String varName, String val ) { + + if ( val == null ) { + return false; + } + String cv = val.replaceAll("\\|", "%7C"); + String uri = String.format( "/internal/api/%s?val=%s", varName, cv ); + + return makeConnection( provURL + uri ); + } + + private boolean makeConnection( String pURL ) { + + try { + URL u = new URL( pURL ); + uc = (HttpsURLConnection) u.openConnection(); + uc.setInstanceFollowRedirects(false); + logger.info( "successful connect to " + pURL ); + uc.setSSLSocketFactory(DmaapConfig.getSSLSocketFactory()); + return(true); + } catch (Exception e) { + errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_ERROR, pURL, e.getMessage() ); + return(false); + } + } + + public String bodyToString( InputStream is ) { + logger.info( "is=" + is ); + StringBuilder sb = new StringBuilder(); + BufferedReader br = new BufferedReader( new InputStreamReader(is)); + String line; + try { + while ((line = br.readLine()) != null ) { + sb.append( line ); + } + } catch (IOException ex ) { + errorLogger.error( DmaapbcLogMessageEnum.IO_EXCEPTION, ex.getMessage()); + } + + return sb.toString(); + } + + + public String doPostFeed( Feed postFeed, ApiError err ) { + + byte[] postData = postFeed.getBytes(); + logger.info( "post fields=" + Arrays.toString(postData) ); + String responsemessage = null; + String responseBody = null; + int rc = -1; + + try { + logger.info( "uc=" + uc ); + uc.setRequestMethod("POST"); + uc.setRequestProperty("Content-Type", feedContentType); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( behalfHeader, postFeed.getOwner() ); + uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + + try { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } catch (ProtocolException pe) { + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + if (responsemessage == null) { + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + responsemessage = h0.substring(j + 1); + } + } + } + if (rc == 201 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + + } else { + err.setCode( rc ); + err.setMessage(responsemessage); + } + + } catch (ConnectException ce) { + errorLogger.error(DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); + err.setCode( 500 ); + err.setMessage("Backend connection refused"); + } catch (SocketException se) { + errorLogger.error( DmaapbcLogMessageEnum.SOCKET_EXCEPTION, se.getMessage(), "response from prov server" ); + err.setCode( 500 ); + err.setMessage( "Unable to read response from DR"); + } catch (Exception e) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doPostFeed because unit_test =" + unit_test ); + } else { + logger.warn("Unable to read response " ); + errorLogger.error("Unable to read response ", e.getMessage()); + try { + err.setCode( uc.getResponseCode()); + err.setMessage(uc.getResponseMessage()); + } catch (Exception e2) { + err.setCode( 500 ); + err.setMessage("Unable to determine response message"); + } + } + } + finally { + try { + uc.disconnect(); + } catch ( Exception e ) { + logger.error(e.getMessage(), e); + } + } + return responseBody; + + } + + + // the POST for /internal/route/ingress doesn't return any data, so needs a different function + // the POST for /internal/route/egress doesn't return any data, so needs a different function + public int doXgressPost( ApiError err ) { + + String responsemessage = null; + int rc = -1; + + try { + uc.setRequestMethod("POST"); + + + try { + uc.connect(); + + } catch (ProtocolException pe) { + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + + + + if (rc < 200 || rc >= 300 ) { + err.setCode( rc ); + err.setMessage(responsemessage); + } + } catch (Exception e) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doXgressPost because unit_test =" + unit_test ); + } else { + logger.error("Unable to read response " ); + logger.error(e.getMessage(), e); + } + } + finally { + try { + uc.disconnect(); + } catch ( Exception e ) { + logger.error(e.getMessage(), e); + } + } + + return rc; + + } + + public String doPostDr_Sub( DR_Sub postSub, ApiError err ) { + logger.info( "entry: doPostDr_Sub() " ); + byte[] postData = postSub.getBytes(provApi ); + logger.info( "post fields=" + postData ); + String responsemessage = null; + String responseBody = null; + + try { + + uc.setRequestMethod("POST"); + + uc.setRequestProperty("Content-Type", subContentType ); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( behalfHeader, "DGL" ); + uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + int rc = -1; + + try { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } catch (ProtocolException pe) { + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + + + if (responsemessage == null) { + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + responsemessage = h0.substring(j + 1); + } + } + } + if (rc == 201 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + + } else { + err.setCode(rc); + err.setMessage(responsemessage); + } + + } catch (Exception e) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doPostDr_Sub because unit_test =" + unit_test ); + } else { + logger.error("Unable to read response ", e.getMessage()); + } + } + finally { + try { + uc.disconnect(); + } catch ( Exception e ) { + logger.error(e.getMessage(), e); + } + } + return responseBody; + + } + + + public String doPutFeed(Feed putFeed, ApiError err) { + byte[] postData = putFeed.getBytes(); + logger.info( "post fields=" + Arrays.toString(postData) ); + String responsemessage = null; + String responseBody = null; + + try { + logger.info( "uc=" + uc ); + uc.setRequestMethod("PUT"); + uc.setRequestProperty("Content-Type", feedContentType ); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( behalfHeader, putFeed.getOwner() ); + uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + int rc = -1; + + try { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } catch (ProtocolException pe) { + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + + + if (responsemessage == null) { + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + responsemessage = h0.substring(j + 1); + } + } + } + if (rc >= 200 && rc < 300 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + err.setCode( rc ); + } else if ( rc == 404 ) { + err.setCode( rc ); + err.setFields( "feedid"); + String message = "FeedId " + putFeed.getFeedId() + " not found on DR to update. Out-of-sync condition?"; + err.setMessage( message ); + errorLogger.error( DmaapbcLogMessageEnum.PROV_OUT_OF_SYNC, "Feed", putFeed.getFeedId() ); + + } else { + err.setCode( rc ); + err.setMessage(responsemessage); + } + + } catch (ConnectException ce) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doPutFeed because unit_test =" + unit_test ); + } else { + errorLogger.error(DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage()); + err.setCode(500); + err.setMessage("Backend connection refused"); + } + } catch (SocketException se) { + errorLogger.error( DmaapbcLogMessageEnum.SOCKET_EXCEPTION, se.getMessage(), "response from Prov server" ); + err.setCode( 500 ); + err.setMessage( "Unable to read response from DR"); + } catch (Exception e) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doPutFeed because unit_test =" + unit_test ); + } else { + logger.warn("Unable to read response " ); + logger.error(e.getMessage(), e); + } + try { + err.setCode( uc.getResponseCode()); + err.setMessage(uc.getResponseMessage()); + } catch (Exception e2) { + err.setCode( 500 ); + err.setMessage("Unable to determine response message"); + logger.error(e2.getMessage(), e2); + } + } finally { + try { + uc.disconnect(); + } catch ( Exception e ) { + logger.error(e.getMessage(), e); + } + } + return responseBody; + } + public String doPutDr_Sub(DR_Sub postSub, ApiError err) { + logger.info( "entry: doPutDr_Sub() " ); + byte[] postData = postSub.getBytes(provApi); + logger.info( "post fields=" + postData ); + String responsemessage = null; + String responseBody = null; + + try { + + uc.setRequestMethod("PUT"); + + uc.setRequestProperty("Content-Type", subContentType ); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( behalfHeader, "DGL" ); + uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + int rc = -1; + + try { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } catch (ProtocolException pe) { + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + + + if (responsemessage == null) { + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + responsemessage = h0.substring(j + 1); + } + } + } + if (rc == 200 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + + } else { + err.setCode(rc); + err.setMessage(responsemessage); + } + + } catch (ConnectException ce) { + errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); + err.setCode( 500 ); + err.setMessage("Backend connection refused"); + logger.error(ce.getMessage(), ce); + } catch (Exception e) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doPutDr_Sub because unit_test =" + unit_test ); + } else { + logger.error("Unable to read response " ); + logger.error(e.getMessage(), e); + } + } finally { + if(null != uc){ + uc.disconnect(); + } + } + return responseBody; + + } + + public String doGetNodes( ApiError err ) { + logger.info( "entry: doGetNodes() " ); + //byte[] postData = postSub.getBytes(); + //logger.info( "get fields=" + postData ); + String responsemessage = null; + String responseBody = null; + + try { + + uc.setRequestMethod("GET"); + int rc = -1; + + + try { + uc.connect(); + + + } catch (ProtocolException pe) { + + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } + + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + + if (responsemessage == null) { + + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + responsemessage = h0.substring(j + 1); + } + } + } + + err.setCode(rc); // may not really be an error, but we save rc + if (rc == 200 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + } else { + err.setMessage(responsemessage); + } + + + } catch (ConnectException ce) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doGetNodes because unit_test =" + unit_test ); + } else { + errorLogger.error(DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage()); + err.setCode(500); + err.setMessage("Backend connection refused"); + logger.error(ce.getMessage(), ce); + } + } catch (Exception e) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doGetNodes because unit_test =" + unit_test ); + } else { + logger.error("Unable to read response ", e.getMessage()); + } + } finally { + + if ( uc != null ) uc.disconnect(); + } + + return responseBody; + + } + public String doPutNodes( ApiError err ) { + logger.info( "entry: doPutNodes() " ); + String responsemessage = null; + String responseBody = null; + + try { + uc.setRequestMethod("PUT"); + uc.setUseCaches(false); + int rc = -1; + + try { + uc.connect(); + } catch (ProtocolException pe) { + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + + + if (responsemessage == null) { + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + responsemessage = h0.substring(j + 1); + } + } + } + err.setCode(rc); + if (rc == 200 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + + } else { + + err.setMessage(responsemessage); + } + + } catch (Exception e) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doPutNodes because unit_test =" + unit_test ); + } else { + logger.error("Unable to read response ", e.getMessage()); + } + } finally { + if ( uc != null ) { + uc.disconnect(); + } + } + return responseBody; + + } + + public String doDeleteFeed(Feed putFeed, ApiError err) { + String responsemessage = null; + String responseBody = null; + + try { + logger.info( "uc=" + uc ); + uc.setRequestMethod("DELETE"); + uc.setRequestProperty("Content-Type", feedContentType ); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( behalfHeader, putFeed.getOwner() ); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + int rc = -1; + + try { + uc.connect(); + os = uc.getOutputStream(); + //os.write( postData ); + + } catch (ProtocolException pe) { + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + + + if (responsemessage == null) { + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + responsemessage = h0.substring(j + 1); + } + } + } + if (rc >= 200 && rc < 300 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + + } else if ( rc == 404 ) { + err.setCode( rc ); + err.setFields( "feedid"); + String message = "FeedId " + putFeed.getFeedId() + " not found on DR to update. Out-of-sync condition?"; + err.setMessage( message ); + errorLogger.error( DmaapbcLogMessageEnum.PROV_OUT_OF_SYNC, "Feed", putFeed.getFeedId() ); + + } else { + err.setCode( rc ); + err.setMessage(responsemessage); + } + + } catch (ConnectException ce) { + errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); + err.setCode( 500 ); + err.setMessage("Backend connection refused"); + logger.error(ce.getMessage(), ce); + } catch (SocketException se) { + errorLogger.error( DmaapbcLogMessageEnum.SOCKET_EXCEPTION, se.getMessage(), "response from Prov server" ); + err.setCode( 500 ); + err.setMessage( "Unable to read response from DR"); + logger.error(se.getMessage(), se); + } catch (Exception e) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doDeleteFeed because unit_test =" + unit_test ); + } else { + logger.warn("Unable to read response " ); + logger.error(e.getMessage(), e); + try { + err.setCode( uc.getResponseCode()); + err.setMessage(uc.getResponseMessage()); + } catch (Exception e2) { + err.setCode( 500 ); + err.setMessage("Unable to determine response message"); + logger.error(e2.getMessage(), e2); + } + } + } finally { + try { + if(uc != null) { + uc.disconnect(); + } + } catch ( Exception e ) { + logger.error(e.getMessage(), e); + } + } + return responseBody; + } + + public String doDeleteDr_Sub(DR_Sub delSub, ApiError err) { + logger.info( "entry: doDeleteDr_Sub() " ); + byte[] postData = delSub.getBytes(provApi); + logger.info( "post fields=" + Arrays.toString(postData)); + String responsemessage = null; + String responseBody = null; + + try { + + uc.setRequestMethod("DELETE"); + + uc.setRequestProperty("Content-Type", subContentType); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( behalfHeader, "DGL" ); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + int rc = -1; + + try { + uc.connect(); + os = uc.getOutputStream(); + //os.write( postData ); + + } catch (ProtocolException pe) { + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + + + if (responsemessage == null) { + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + responsemessage = h0.substring(j + 1); + } + } + } + err.setCode(rc); + if (rc == 204 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + } else { + err.setMessage(responsemessage); + } + + } catch (ConnectException ce) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doDeleteDr_Sub because unit_test =" + unit_test ); + } else { + errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); + err.setCode( 500 ); + err.setMessage("Backend connection refused"); + } + } catch (Exception e) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doDeleteDr_Sub because unit_test =" + unit_test ); + } else { + logger.error("Unable to read response ", e.getMessage()); + } + } finally { + if(uc != null){ + uc.disconnect(); + } + } + return responseBody; + + } + + // add double-quotes around a value + // hope his is easier to read than in-line escaping... + private String dq( String v ) { + return ( "\"" + v + "\""); + } + private String dq( String k, String v) { + return( dq(k) + ":" + dq(v)); + } + private String dqc( String k, String v) { + return( dq(k) + ":" + dq(v) + ","); + } + + private String dumpSimulation() { + logger.info( "enter dumpSimulation()"); + String responseBody = + "{" + + dq("feeds") + ":[" + + "{" + dq( "suspend") + ":false," + + dq( "groupid") + ":0," + + dqc( "description", "Some description" ) + + dqc( "version", "m1.1") + + dq( "authorization") + ":" + + "{" + dq( "endpoint_addrs" ) + ":[]," + + dq( "classification", "unclassified") + + dq( "endpoint_ids") + ":[{" + + dqc( "password", "dradmin" ) + + dq( "id", "dradmin") + + "}]}" + + dq( "last_mod") + ":1553738110000," + + dq( "deleted") + ":false," + + dq( "feedid") + ":1," + + dqc( "name", "Default PM Feed") + + dq( "business_description") + ":\"\"," + + dqc( "publisher", "onap") + + dq( "links") + ":{" + + dqc( "subscribe", "https://dmaap-dr-prov/subscribe/1") + + dqc( "log", "https://dmaap-dr-prov/feedlog/1") + + dqc( "publish", "https://dmaap-dr-prov/publish/1") + + dq( "self", "https:/dmaap-dr-prov/feed/1") + + "}" + + dq( "created_date") + ":1553738110000 }" + + "]," + + dq( "groups") + ":[" + + "]," + + dq( "subscriptions") + ":[" + + "]," + + dq( "ingress") + ":[" + + "]," + + dq( "egress") + ":{" + + "}," + + dq( "routing") + ":[" + + "]," + + "}"; + return responseBody; + } + + public String doGetDump( ApiError err ) { + logger.info( "entry: doGetDump() " ); + + String responsemessage = null; + String responseBody = null; + + try { + + uc.setRequestMethod("GET"); + int rc = -1; + + + try { + uc.connect(); + + + } catch (ProtocolException pe) { + + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + logger.error(e.getMessage(), e); + } + } catch (Exception e) { + logger.info( "Exception: " + e.getMessage() ); + e.printStackTrace(); + } + + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + + + + if (responsemessage == null) { + + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + responsemessage = h0.substring(j + 1); + } + } + } + + err.setCode(rc); // may not really be an error, but we save rc + if (rc == 200 ) { + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + } else { + err.setMessage(responsemessage); + } + + + } catch (ConnectException ce) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doGetNodes because unit_test =" + unit_test ); + responseBody = dumpSimulation(); + + } else { + errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, ce.getMessage() ); + err.setCode( 500 ); + err.setMessage("Backend connection refused"); + logger.error(ce.getMessage(), ce); + } + } catch (Exception e) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doGetNodes because unit_test =" + unit_test ); + responseBody = dumpSimulation(); + + } else { + logger.error("Unable to read response ", e.getMessage()); + } + } finally { + + if ( uc != null ) uc.disconnect(); + } + + return responseBody; + + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/client/MrProvConnection.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/client/MrProvConnection.java new file mode 100644 index 0000000..9c3fa4e --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/client/MrProvConnection.java @@ -0,0 +1,271 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.client; + +import org.apache.commons.codec.binary.Base64; +import org.onap.dmaap.dbcapi.aaf.AafDecrypt; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; + +import java.io.*; +import java.net.*; +import java.util.Arrays; + +public class MrProvConnection extends BaseLoggingClass{ + + private String provURL; + + private HttpURLConnection uc; + + + private String topicMgrCred; + private String authMethod; + private String user; + private String encPwd; + private String unit_test; + private boolean hostnameVerify; + + public MrProvConnection() { + String mechIdProperty = "aaf.TopicMgrUser"; + String pwdProperty = "aaf.TopicMgrPassword"; + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + user = p.getProperty( mechIdProperty, "noMechId@domain.netset.com" ); + encPwd = p.getProperty( pwdProperty, "notSet" ); + authMethod = p.getProperty("MR.authentication", "none"); + topicMgrCred = getCred(); + hostnameVerify= "true".equalsIgnoreCase(p.getProperty("MR.hostnameVerify", "true")); + unit_test = p.getProperty( "UnitTest", "No" ); + + } + + private String getCred( ) { + + + String pwd = ""; + AafDecrypt decryptor = new AafDecrypt(); + pwd = decryptor.decrypt(encPwd); + return user + ":" + pwd; + } + + + public boolean makeTopicConnection( MR_Cluster cluster ) { + boolean rc = false; + logger.info( "connect to cluster: " + cluster.getDcaeLocationName()); + + + provURL = cluster.getTopicProtocol() + "://" + cluster.getFqdn() + ":" + cluster.getTopicPort() + "/topics/create"; + + if ( cluster.getTopicProtocol().equals( "https" ) ) { + rc = makeSecureConnection( provURL ); + } else { + rc = makeConnection( provURL ); + } + if ( rc && unit_test.equals( "Yes" ) ) { + // set timeouts low so we don't hold up unit tests in build process + uc.setReadTimeout(5); + uc.setConnectTimeout(5); + } + return rc; + + } + + private boolean makeSecureConnection( String pURL ) { + logger.info( "makeConnection to " + pURL ); + + try { + + HostnameVerifier hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify( String hostname, SSLSession session ) { + return true; + } + + }; + URL u = new URL( pURL ); + uc = (HttpsURLConnection) u.openConnection(); + uc.setInstanceFollowRedirects(false); + if ( ! hostnameVerify ) { + HttpsURLConnection ucs = (HttpsURLConnection) uc; + ucs.setHostnameVerifier(hostnameVerifier); + } + logger.info( "open secure connect to " + pURL ); + return(true); + } catch( UnknownHostException uhe ){ + logger.error( "Caught UnknownHostException for " + pURL); + return(false); + } catch (Exception e) { + logger.error("Unexpected error during openConnection of " + pURL ); + logger.error("Unexpected error during openConnection of ",e ); + return(false); + } + + } + private boolean makeConnection( String pURL ) { + logger.info( "makeConnection to " + pURL ); + + try { + URL u = new URL( pURL ); + uc = (HttpURLConnection) u.openConnection(); + uc.setInstanceFollowRedirects(false); + + logger.info( "open connect to " + pURL ); + return(true); + } catch( UnknownHostException uhe ){ + logger.error( "Caught UnknownHostException for " + pURL); + return(false); + } catch (Exception e) { + logger.error("Unexpected error during openConnection of " + pURL ); + logger.error("Unexpected error during openConnection of ",e ); + return(false); + } + + } + + static String bodyToString( InputStream is ) { + StringBuilder sb = new StringBuilder(); + BufferedReader br = new BufferedReader( new InputStreamReader(is)); + String line; + try { + while ((line = br.readLine()) != null ) { + sb.append( line ); + } + } catch (IOException ex ) { + errorLogger.error( "IOexception:" + ex); + } + + return sb.toString(); + } + + public String doPostTopic( Topic postTopic, ApiError err ) { + String auth = "Basic " + Base64.encodeBase64String(topicMgrCred.getBytes()); + + + String responsemessage = null; + int rc = -1; + + + try { + byte[] postData = postTopic.getBytes(); + logger.info( "post fields=" + Arrays.toString(postData)); + + if ( authMethod.equalsIgnoreCase("basicAuth") ) { + uc.setRequestProperty("Authorization", auth); + logger.info( "Authenticating with " + auth ); + } else if ( authMethod.equalsIgnoreCase("cert")) { + logger.error( "MR.authentication set for client certificate. Not supported yet."); + } + uc.setRequestMethod("POST"); + uc.setRequestProperty("Content-Type", "application/json"); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + + + try { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } catch (ProtocolException pe) { + // Rcvd error instead of 100-Continue + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + } + } catch ( UnknownHostException uhe ) { + errorLogger.error( DmaapbcLogMessageEnum.UNKNOWN_HOST_EXCEPTION , "Unknown Host Exception" , provURL ); + err.setCode(500); + err.setMessage("Unknown Host Exception"); + err.setFields( uc.getURL().getHost()); + return new String( "500: " + uhe.getMessage()); + }catch ( ConnectException ce ) { + if ( unit_test.equals( "Yes" ) ) { + err.setCode(200); + err.setMessage( "simulated response"); + logger.info( "artificial 200 response from doPostMessage because unit_test =" + unit_test ); + } else { + errorLogger.error( DmaapbcLogMessageEnum.HTTP_CONNECTION_EXCEPTION, provURL, "HTTP Connection Exception" ); + err.setCode(500); + err.setMessage("HTTP Connection Exception"); + err.setFields( uc.getURL().getHost()); + return new String( "500: " + ce.getMessage()); + } + } + rc = uc.getResponseCode(); + logger.info( "http response code:" + rc ); + err.setCode(rc); + responsemessage = uc.getResponseMessage(); + logger.info( "responsemessage=" + responsemessage ); + err.setMessage(responsemessage); + + + if (responsemessage == null) { + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + responsemessage = h0.substring(j + 1); + } + } + } + if (rc >= 200 && rc < 300 ) { + String responseBody = null; + responseBody = bodyToString( uc.getInputStream() ); + logger.info( "responseBody=" + responseBody ); + return responseBody; + + } + + } catch (Exception e) { + errorLogger.error("Unable to read response: " + e.getMessage() ); + + } + finally { + try { + uc.disconnect(); + } catch ( Exception e ) { + errorLogger.error("Unable to disconnect"); + } + } + return new String( rc +": " + responsemessage ); + + } + + + + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/client/MrTopicConnection.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/client/MrTopicConnection.java new file mode 100644 index 0000000..b3f713f --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/client/MrTopicConnection.java @@ -0,0 +1,239 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.client; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.ProtocolException; +import java.net.URL; +import java.net.HttpURLConnection; + +import javax.net.ssl.HostnameVerifier; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLException; +import javax.net.ssl.SSLSession; + +import org.apache.commons.codec.binary.Base64; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class MrTopicConnection extends BaseLoggingClass { + private String topicURL; + + private HttpURLConnection uc; + + + private String mmProvCred; + private String unit_test; + private String authMethod; + private boolean hostnameVerify; + + public MrTopicConnection(String user, String pwd ) { + mmProvCred = new String( user + ":" + pwd ); + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + unit_test = p.getProperty( "UnitTest", "No" ); + authMethod = p.getProperty("MR.authentication", "none"); + hostnameVerify= "true".equalsIgnoreCase(p.getProperty("MR.hostnameVerify", "true")); + } + + public boolean makeTopicConnection( MR_Cluster cluster, String topic, String overrideFqdn ) { + String fqdn = overrideFqdn != null ? overrideFqdn : cluster.getFqdn(); + logger.info( "connect to cluster: " + fqdn + " for topic: " + topic ); + + + topicURL = cluster.getTopicProtocol() + "://" + fqdn + ":" + cluster.getTopicPort() + "/events/" + topic ; + + if ( "https".equals(cluster.getTopicProtocol())) { + return makeSecureConnection( topicURL ); + } + return makeConnection( topicURL ); + } + + + private boolean makeSecureConnection( String pURL ) { + logger.info( "makeConnection to " + pURL ); + + try { + HostnameVerifier hostnameVerifier = new HostnameVerifier() { + @Override + public boolean verify( String hostname, SSLSession session ) { + return true; + } + + }; + + + URL u = new URL( pURL ); + uc = (HttpsURLConnection) u.openConnection(); + uc.setInstanceFollowRedirects(false); + if ( ! hostnameVerify ) { + HttpsURLConnection ucs = (HttpsURLConnection) uc; + ucs.setHostnameVerifier(hostnameVerifier); + } + + logger.info( "open connection to " + pURL ); + return(true); + } catch (Exception e) { + logger.error("Unexpected error during openConnection of " + pURL ); + logger.error("Error", e);; + return(false); + } + + } + private boolean makeConnection( String pURL ) { + logger.info( "makeConnection to " + pURL ); + + try { + URL u = new URL( pURL ); + uc = (HttpURLConnection) u.openConnection(); + uc.setInstanceFollowRedirects(false); + logger.info( "open connection to " + pURL ); + return(true); + } catch (Exception e) { + logger.error("Unexpected error during openConnection of " + pURL ); + logger.error("error", e); + return(false); + } + + } + + static String bodyToString( InputStream is ) { + StringBuilder sb = new StringBuilder(); + BufferedReader br = new BufferedReader( new InputStreamReader(is)); + String line; + try { + while ((line = br.readLine()) != null ) { + sb.append( line ); + } + } catch (IOException ex ) { + errorLogger.error( "IOexception:" + ex); + } + + return sb.toString(); + } + + public ApiError doPostMessage( String postMessage ) { + ApiError response = new ApiError(); + String auth = "Basic " + Base64.encodeBase64String(mmProvCred.getBytes()); + + + + try { + byte[] postData = postMessage.getBytes(); + logger.info( "post fields=" + postMessage ); + if ( authMethod.equalsIgnoreCase("basicAuth") ) { + uc.setRequestProperty("Authorization", auth); + logger.info( "Authenticating with " + auth ); + } else if ( authMethod.equalsIgnoreCase("cert")) { + logger.error( "MR.authentication set for client certificate. Not supported yet."); + } + uc.setRequestMethod("POST"); + uc.setRequestProperty("Content-Type", "application/json"); + uc.setRequestProperty( "charset", "utf-8"); + uc.setRequestProperty( "Content-Length", Integer.toString( postData.length )); + uc.setUseCaches(false); + uc.setDoOutput(true); + OutputStream os = null; + + + try { + uc.connect(); + os = uc.getOutputStream(); + os.write( postData ); + + } catch (ProtocolException pe) { + // Rcvd error instead of 100-Continue + callSetDoOutputOnError(); + + } catch ( SSLException se ) { + logger.error("Error", se); + response.setCode(500); + response.setMessage( se.getMessage()); + return response; + + } + response.setCode( uc.getResponseCode()); + logger.info( "http response code:" + response.getCode()); + response.setMessage( uc.getResponseMessage() ); + logger.info( "response message=" + response.getMessage() ); + + + if ( response.getMessage() == null) { + // work around for glitch in Java 1.7.0.21 and likely others + // When Expect: 100 is set and a non-100 response is received, the response message is not set but the response code is + String h0 = uc.getHeaderField(0); + if (h0 != null) { + int i = h0.indexOf(' '); + int j = h0.indexOf(' ', i + 1); + if (i != -1 && j != -1) { + response.setMessage( h0.substring(j + 1) ); + } + } + } + if ( response.is2xx() ) { + response.setFields( bodyToString( uc.getInputStream() ) ); + logger.info( "responseBody=" + response.getFields() ); + return response; + + } + + } catch (Exception e) { + if ( unit_test.equals( "Yes" ) ) { + response.setCode(201); + response.setMessage( "simulated response"); + logger.info( "artificial 201 response from doPostMessage because unit_test =" + unit_test ); + } else { + + response.setCode(500); + response.setMessage( "Unable to read response"); + logger.warn( response.getMessage() ); + logger.error("Error", e); + } + } + finally { + try { + uc.disconnect(); + } catch ( Exception e ) { + logger.error("Error", e); + } + } + return response; + + } + + public void callSetDoOutputOnError() { + try { + // work around glitch in Java 1.7.0.21 and likely others + // without this, Java will connect multiple times to the server to run the same request + uc.setDoOutput(false); + } catch (Exception e) { + logger.error("Error", e); + } + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/ConnWrapper.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/ConnWrapper.java new file mode 100644 index 0000000..2317fe4 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/ConnWrapper.java @@ -0,0 +1,83 @@ +/*- + * ============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.database; + +import java.sql.*; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + + +public abstract class ConnWrapper<T, U> { + EELFLogger logger = EELFManager.getInstance().getLogger( ConnWrapper.class ); + protected Connection c; + protected PreparedStatement ps; + protected ResultSet rs; + protected abstract T run(U u) throws Exception; + public T protect(ConnectionFactory cf, U u) { + try { + try { + return(attempt(cf, u, false)); + } catch (SQLException sqle) { + logger.error("Error", sqle); + return(attempt(cf, u, true)); + } + } catch (RuntimeException rte) { + throw rte; + } catch (Exception e) { + throw new DBException(e); + } + } + private T attempt(ConnectionFactory cf, U u, boolean fresh) throws Exception { + c = null; + ps = null; + rs = null; + try { + c = cf.get(fresh); + T ret = run(u); + cf.release(c); + c = null; + return(ret); + } finally { + if (rs != null) { + try { + rs.close(); + } catch (Exception e) { + logger.error("Error", e); + }} + rs = null; + if (ps != null) { + try { + ps.close(); + } catch (Exception e) { + logger.error("Error", e); + }} + ps = null; + if (c != null) { + try { + c.close(); + } catch (Exception e) { + logger.error("Error", e); + }} + c = null; + } + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/ConnectionFactory.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/ConnectionFactory.java new file mode 100644 index 0000000..6004d9b --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/ConnectionFactory.java @@ -0,0 +1,117 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.database; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.util.Properties; +import java.util.concurrent.TimeUnit; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class ConnectionFactory extends BaseLoggingClass { + + static final int PREPARE_PSQL_CONNECTION_ATTEMPTS = 5; + + static { + try { + Class.forName("org.postgresql.Driver"); + } catch (Exception e) { + errorLogger.error("Unable to load postgres driver " + e, e); + } + } + private static ConnectionFactory instance = new ConnectionFactory(); + private String host; + private String dbname; + private String dbuser; + private String dbcr; + private String schema; + + public ConnectionFactory() { + Properties p = DmaapConfig.getConfig(); + host = p.getProperty("DB.host", "dcae-pstg-write-ftl.domain.notset.com"); + dbname = p.getProperty("DB.name", "dmaap"); + dbuser = getValue(p, "DB.user", "dmaap_admin"); + dbcr = getValue(p, "DB.cred", "test234-ftl"); + schema = p.getProperty("DB.schema", "dmaap_admin"); + } + + private static String getValue(final Properties props, final String value, final String defaultValue) { + String prop = props.getProperty(value, defaultValue); + if (prop != null && prop.matches("[$][{].*[}]$")) { + return System.getenv(prop.substring(2, prop.length() - 1)); + } + return prop; + } + + public static ConnectionFactory getDefaultInstance() { + return(instance); + } + private Connection[] pool = new Connection[5]; + private int cur; + public Connection get(boolean fresh) throws SQLException { + if (!fresh) { + synchronized(this) { + if (cur > 0) { + return(pool[--cur]); + } + } + } + Properties p = new Properties(); + p.put("user", dbuser); + p.put("password", dbcr); + for (int i=1; i<PREPARE_PSQL_CONNECTION_ATTEMPTS; i++){ + try{ + return(DriverManager.getConnection("jdbc:postgresql://" + host + "/" + dbname, p)); + }catch(SQLException e){ + errorLogger.error("Unable to connect to the postgres server. " + i + "attempt failed. ", e); + waitFor(1); + } + } + return(DriverManager.getConnection("jdbc:postgresql://" + host + "/" + dbname, p)); + } + public String getSchema() { + return(schema); + } + public void release(Connection c) { + synchronized(this) { + if (cur < pool.length) { + pool[cur++] = c; + return; + } + } + try { + c.close(); + } catch (Exception e) { + errorLogger.error("Error", e); + } + } + private void waitFor(long seconds){ + try { + TimeUnit.SECONDS.sleep(seconds); + } catch (InterruptedException e) { + debugLogger.debug("Waiting interrupted. ", e); + Thread.currentThread().interrupt(); + } + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DBException.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DBException.java new file mode 100644 index 0000000..6538167 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DBException.java @@ -0,0 +1,34 @@ +/*- + * ============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.database; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; + +public class DBException extends RuntimeException { + static final EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger(); + public DBException(Exception e) { + super(e); + errorLogger.error(DmaapbcLogMessageEnum.DB_ACCESS_ERROR, e.getMessage()); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DBFieldHandler.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DBFieldHandler.java new file mode 100644 index 0000000..618932e --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DBFieldHandler.java @@ -0,0 +1,205 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.database; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.lang.reflect.Method; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.util.HashMap; +import java.util.Map; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; + + +public class DBFieldHandler { + static final EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger(); + + public DBFieldHandler(Class<?> c, String fieldname, int fieldnum) throws Exception { + this(c, fieldname, fieldnum, null); + } + public DBFieldHandler(Class<?> c, String fieldname, int fieldnum, SqlOp op) throws Exception { + this.fieldnum = fieldnum; + StringBuilder sb = new StringBuilder(); + for (String s: fieldname.split("_")) { + sb.append(s.substring(0, 1).toUpperCase()).append(s.substring(1)); + } + String camelcase = sb.toString(); + try { + objget = c.getMethod("is" + camelcase); + } catch (Exception e) { + errorLogger.warn("No 'is' method for " + c.getName() + " so trying 'get' method"); + objget = c.getMethod("get" + camelcase); + } + objset = c.getMethod("set" + camelcase, objget.getReturnType()); + sqlop = op; + if (sqlop != null) { + return; + } + Class<?> x = objget.getReturnType(); + if (x.isEnum()) { + sqlop = new EnumSql(x); + return; + } + sqlop = sqltypes.get(x.getName()); + if (sqlop != null) { + return; + } + errorLogger.error(DmaapbcLogMessageEnum.DB_NO_FIELD_HANDLER, c.getName(), fieldname, Integer.toString(fieldnum), x.getName()); + } + + public static interface SqlOp { + public Object get(ResultSet rs, int index) throws Exception; + public void set(PreparedStatement ps, int index, Object value) throws Exception; + } + private static class AofString implements SqlOp { + public Object get(ResultSet rs, int index) throws Exception { + String val = rs.getString(index); + if (val == null) { + return(null); + } + String[] ret = val.split(","); + for (int i = 0; i < ret.length; i++) { + ret[i] = funesc(ret[i]); + } + return(ret); + } + public void set(PreparedStatement ps, int index, Object x) throws Exception { + String[] val = (String[])x; + if (val == null) { + ps.setString(index, null); + return; + } + StringBuilder sb = new StringBuilder(); + String sep = ""; + for (String s: val) { + sb.append(sep).append(fesc(s)); + sep = ","; + } + ps.setString(index, sb.toString()); + } + } + private static class EnumSql implements SqlOp { + private Class enclass; + public EnumSql(Class enclass) { + this.enclass = enclass; + } + @SuppressWarnings("unchecked") + public Object get(ResultSet rs, int index) throws Exception { + String val = rs.getString(index); + if (val == null) { + return(null); + } else { + return(Enum.valueOf(enclass, val)); + } + } + public void set(PreparedStatement ps, int index, Object value) throws Exception { + if (value == null) { + ps.setString(index, null); + } else { + ps.setString(index, value.toString()); + } + } + } + private static class SqlDate implements SqlOp { + public Object get(ResultSet rs, int index) throws Exception { + return(rs.getTimestamp(index)); + } + public void set(PreparedStatement ps, int index, Object val) throws Exception { + if (val instanceof java.util.Date && !(val instanceof java.sql.Timestamp)) { + val = new java.sql.Timestamp(((java.util.Date)val).getTime()); + } + ps.setTimestamp(index, (java.sql.Timestamp)val); + } + } + private static class SqlType implements SqlOp { + private Method sqlget; + private Method sqlset; + private SqlType(String tag) throws Exception { + sqlget = ResultSet.class.getMethod("get" + tag, Integer.TYPE); + sqlset = PreparedStatement.class.getMethod("set" + tag, Integer.TYPE, sqlget.getReturnType()); + sqltypes.put(sqlget.getReturnType().getName(), this); + } + public Object get(ResultSet rs, int index) throws Exception { + return(sqlget.invoke(rs, index)); + } + public void set(PreparedStatement ps, int index, Object val) throws Exception { + try { + sqlset.invoke(ps, index, val); + } catch (Exception e) { + errorLogger.error(DmaapbcLogMessageEnum.DB_FIELD_INIT_ERROR, Integer.toString(index), val.toString(), ps.toString()); + throw e; + } + } + } + private static Map<String, SqlOp> sqltypes; + static { + sqltypes = new HashMap<>(); + sqltypes.put("[Ljava.lang.String;", new AofString()); + sqltypes.put("java.util.Date", new SqlDate()); + try { + new SqlType("Boolean"); + new SqlType("Timestamp"); + new SqlType("Double"); + new SqlType("Float"); + new SqlType("Int"); + new SqlType("Long"); + new SqlType("Short"); + new SqlType("String"); + } catch (Exception e) { + errorLogger.error("Error", e); + errorLogger.error(DmaapbcLogMessageEnum.DB_ACCESS_INIT_ERROR, e.getMessage() ); + } + } + private Method objget; + private Method objset; + private SqlOp sqlop; + private int fieldnum; + public void copy(Object from, Object to) throws Exception { + objset.invoke(to, objget.invoke(from)); + } + public void setKey(Object o, String key) throws Exception { + objset.invoke(o, key); + } + public String getKey(Object o) throws Exception { + return((String)objget.invoke(o)); + } + public void toSQL(Object o, PreparedStatement ps) throws Exception { + sqlop.set(ps, fieldnum, objget.invoke(o)); + } + public void fromSQL(ResultSet r, Object o) throws Exception { + objset.invoke(o, sqlop.get(r, fieldnum)); + } + public static String fesc(String s) { + if (s == null) { + return(s); + } + return(s.replaceAll("@", "@a").replaceAll(";", "@s").replaceAll(",", "@c")); + } + public static String funesc(String s) { + if (s == null) { + return(s); + } + return(s.replaceAll("@c", ",").replaceAll("@s", ";").replaceAll("@a", "@")); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DBMap.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DBMap.java new file mode 100644 index 0000000..b3282ed --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DBMap.java @@ -0,0 +1,137 @@ +/*- + * ============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.database; + +import java.sql.*; +import java.util.*; + +public class DBMap<C> extends TableHandler<C> implements Map<String, C> { + public DBMap(Class<C> cls, String tabname, String keyfield) throws Exception { + this(ConnectionFactory.getDefaultInstance(), cls, tabname, keyfield); + } + public DBMap(ConnectionFactory cf, Class<C> cls, String tabname, String keyfield) throws Exception { + super(cf, cls, tabname, keyfield); + } + public void clear() { + throw new UnsupportedOperationException(); + } + public boolean containsKey(Object key) { + return(get(key) != null); + } + public boolean containsValue(Object value) { + throw new UnsupportedOperationException(); + } + public boolean isEmpty() { + return(false); + } + public Set<Map.Entry<String, C>> entrySet() { + return(list()); + } + public Set<String> keySet() { + Set<String> ret = new HashSet<>(); + for (Map.Entry<String, C> x: list()) { + ret.add(x.getKey()); + } + return(ret); + } + public void putAll(Map<? extends String, ? extends C> m) { + throw new UnsupportedOperationException(); + } + public int size() { + return(2); + } + public Collection<C> values() { + Collection<C> ret = new ArrayList<>(); + for (Map.Entry<String, C> x: list()) { + ret.add(x.getValue()); + } + return(ret); + } + public C get(Object key) { + if (!(key instanceof String)) { + return(null); + } + return((new ConnWrapper<C, String>() { + protected C run(String key) throws Exception { + ps = c.prepareStatement(getstmt); + ps.setString(1, (String)key); + rs = ps.executeQuery(); + if (!rs.next()) { + return(null); + } + C ret = cls.newInstance(); + for (DBFieldHandler f: fields) { + f.fromSQL(rs, ret); + } + return(ret); + } + }).protect(cf, (String)key)); + } + public Set<Map.Entry<String, C>> list() { + return((new ConnWrapper<Set<Map.Entry<String, C>>, Object>() { + protected Set<Map.Entry<String, C>> run(Object junk) throws Exception { + DBFieldHandler keyfield = fields[fields.length - 1]; + ps = c.prepareStatement(liststmt); + rs = ps.executeQuery(); + Set<Map.Entry<String, C>> ret = new HashSet<>(); + while (rs.next()) { + C val = cls.newInstance(); + for (DBFieldHandler f: fields) { + f.fromSQL(rs, val); + } + String key = keyfield.getKey(val); + ret.add(new AbstractMap.SimpleEntry<String, C>(key, val)); + } + return(ret); + } + }).protect(cf, null)); + } + public C put(String key, C val) { + try { + fields[fields.length - 1].setKey(val, key); + } catch (Exception e) { + throw new DBException(e); + } + return((new ConnWrapper<C, C>() { + protected C run(C val) throws Exception { + ps = c.prepareStatement(insorreplstmt); + for (DBFieldHandler f: fields) { + f.toSQL(val, ps); + } + ps.executeUpdate(); + return(null); + } + }).protect(cf, val)); + } + public C remove(Object key) { + if (!(key instanceof String)) { + return(null); + } + return((new ConnWrapper<C, String>() { + protected C run(String key) throws Exception { + ps = c.prepareStatement(delstmt); + ps.setString(1, key); + ps.executeUpdate(); + return(null); + } + }).protect(cf, (String)key)); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DBSingleton.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DBSingleton.java new file mode 100644 index 0000000..2633d70 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DBSingleton.java @@ -0,0 +1,98 @@ +/*- + * ============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.database; + +import java.sql.*; +import java.util.*; + +import org.onap.dmaap.dbcapi.util.Singleton; + +public class DBSingleton<C> extends TableHandler<C> implements Singleton<C> { + private C singleton; + public DBSingleton(Class<C> cls, String tabname) throws Exception { + this(ConnectionFactory.getDefaultInstance(), cls, tabname); + } + public DBSingleton(ConnectionFactory cf, Class<C> cls, String tabname) throws Exception { + super(cf, cls, tabname, null); + singleton = cls.newInstance(); + } + public C get() { + return((new ConnWrapper<C, Object>() { + protected C run(Object junk) throws Exception { + ps = c.prepareStatement(getstmt); + rs = ps.executeQuery(); + if (!rs.next()) { + return(null); + } + for (DBFieldHandler f: fields) { + f.fromSQL(rs, singleton); + } + return(singleton); + } + }).protect(cf, null)); + } + public void init(C val) { + if (get() != null) { + return; + } + (new ConnWrapper<Void, C>() { + protected Void run(C val) throws Exception { + ps = c.prepareStatement(initstmt); + for (DBFieldHandler f: fields) { + f.toSQL(val, ps); + } + ps.executeUpdate(); + if (val != singleton) { + for (DBFieldHandler f: fields) { + f.copy(val, singleton); + } + } + return(null); + } + }).protect(cf, val); + } + public void update(C val) { + (new ConnWrapper<Void, C>() { + protected Void run(C val) throws Exception { + ps = c.prepareStatement(insorreplstmt); + for (DBFieldHandler f: fields) { + f.toSQL(val, ps); + } + ps.executeUpdate(); + if (val != singleton) { + for (DBFieldHandler f: fields) { + f.copy(val, singleton); + } + } + return(null); + } + }).protect(cf, val); + } + public void remove() throws DBException { + (new ConnWrapper<Void, Object>() { + protected Void run(Object junk) throws Exception { + ps = c.prepareStatement(delstmt); + ps.executeUpdate(); + return(null); + } + }).protect(cf, null); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DatabaseClass.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DatabaseClass.java new file mode 100644 index 0000000..c82e964 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/DatabaseClass.java @@ -0,0 +1,286 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.database; + +import java.util.*; +import java.sql.*; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.Singleton; + + +public class DatabaseClass extends BaseLoggingClass { + + private static Singleton<Dmaap> dmaap; + private static Map<String, DcaeLocation> dcaeLocations; + private static Map<String, DR_Node> dr_nodes; + private static Map<String, DR_Pub> dr_pubs; + private static Map<String, DR_Sub> dr_subs; + private static Map<String, MR_Client> mr_clients; + private static Map<String, MR_Cluster> mr_clusters; + private static Map<String, Feed> feeds; + private static Map<String, Topic> topics; + private static Map<String, MirrorMaker> mirrors; + + private static long lastTime = 0L; + private static DBType databaseType; + + private enum DBType { + PGSQL, MEMORY + } + + public static Singleton<Dmaap> getDmaap() { + return dmaap; + } + + + public static Map<String, DcaeLocation> getDcaeLocations() { + return dcaeLocations; + } + + public static Map<String, DR_Node> getDr_nodes() { + return dr_nodes; + } + + public static Map<String, DR_Sub> getDr_subs() { + return dr_subs; + } + + public static Map<String, DR_Pub> getDr_pubs() { + return dr_pubs; + } + + public static Map<String, MR_Client> getMr_clients() { + return mr_clients; + } + + + public static Map<String, MR_Cluster> getMr_clusters() { + return mr_clusters; + } + + public static Map<String, Feed> getFeeds() { + return feeds; + } + + public static Map<String, Topic> getTopics() { + return topics; + } + + public static Map<String, MirrorMaker> getMirrorMakers() { + return mirrors; + } + + static { + try { + appLogger.info("begin static initialization"); + appLogger.info("initializing dmaap"); + determineDatabaseType(); + + switch (databaseType) { + case PGSQL: + databaseResourceInit(); + break; + case MEMORY: + inMemoryResourceInit(); + break; + } + + dmaap.init(new Dmaap.DmaapBuilder().setVer("0").setTnr("").setDn("").setDpu("").setLu("").setBat("").setNk("").setAko("").createDmaap()); + // force initial read from DB, if it exists + @SuppressWarnings("unused") + Dmaap dmx = dmaap.get(); + + // old code in this spot would read from properties file as part of init. + // but all those properties are now set via /dmaap API + + } catch (Exception e) { + errorLogger.error("Error", e); + errorLogger.error(DmaapbcLogMessageEnum.DB_UPDATE_ERROR, e.getMessage()); + } + + } + + public static synchronized String getNextClientId() { + + long id = System.currentTimeMillis(); + if (id <= lastTime) { + id = lastTime + 1; + } + lastTime = id; + return Long.toString(id); + } + + public static synchronized void clearDatabase() { + switch (databaseType) { + case PGSQL: + try { + initDatabase(); + } catch (Exception e) { + errorLogger.error("Error initializing database access " + e, e); + } + break; + case MEMORY: + initMemoryDatabase(); + break; + } + } + + private static void inMemoryResourceInit() { + appLogger.info("Data from memory"); + dmaap = new Singleton<Dmaap>() { + private Dmaap dmaap; + + public void remove() { + dmaap = null; + } + + public void init(Dmaap val) { + if (dmaap == null) { + dmaap = val; + } else { + update(val); + } + } + + public Dmaap get() { + return (dmaap); + } + + public void update(Dmaap nd) { + dmaap.setVersion(nd.getVersion()); + dmaap.setTopicNsRoot(nd.getTopicNsRoot()); + dmaap.setDmaapName(nd.getDmaapName()); + dmaap.setDrProvUrl(nd.getDrProvUrl()); + dmaap.setBridgeAdminTopic(nd.getBridgeAdminTopic()); + dmaap.setLoggingUrl(nd.getLoggingUrl()); + dmaap.setNodeKey(nd.getNodeKey()); + dmaap.setAccessKeyOwner(nd.getAccessKeyOwner()); + } + }; + initMemoryDatabase(); + } + + private static void databaseResourceInit() { + appLogger.info("Data from database"); + try { + LoadSchema.loadSchema(); + } catch (Exception e) { + appLogger.warn("Problem updating DB schema", e); + } + try { + Thread.sleep(5000); + dmaap = new DBSingleton<>(Dmaap.class, "dmaap"); + TableHandler.setSpecialCase("topic", "replication_case", new TopicReplicationTypeHandler()); + TableHandler.setSpecialCase("mirror_maker", "topics", new MirrorTopicsHandler()); + initDatabase(); + } catch (Exception e) { + errorLogger.error("Error initializing database access " + e, e); + System.exit(1); + } + } + + private static class MirrorTopicsHandler implements DBFieldHandler.SqlOp { + + public Object get(ResultSet rs, int index) throws Exception { + String val = rs.getString(index); + if (val == null) { + return (null); + } + List<String> rv = new ArrayList<>(); + for (String s : val.split(",")) { + rv.add(new String(s)); + } + return (rv); + } + + public void set(PreparedStatement ps, int index, Object val) throws Exception { + if (val == null) { + ps.setString(index, null); + return; + } + @SuppressWarnings("unchecked") + List<String> xv = (List<String>) val; + StringBuilder sb = new StringBuilder(); + String sep = ""; + for (Object o : xv) { + String rv = (String) o; + sb.append(sep).append(DBFieldHandler.fesc(rv)); + sep = ","; + } + ps.setString(index, sb.toString()); + } + } + + private static class TopicReplicationTypeHandler implements DBFieldHandler.SqlOp { + + public Object get(ResultSet rs, int index) throws Exception { + int val = rs.getInt(index); + + return (ReplicationType.valueOf(val)); + } + + public void set(PreparedStatement ps, int index, Object val) throws Exception { + if (val == null) { + ps.setInt(index, 0); + return; + } + @SuppressWarnings("unchecked") + ReplicationType rep = (ReplicationType) val; + ps.setInt(index, rep.getValue()); + } + } + + private static void initMemoryDatabase() { + dcaeLocations = new HashMap<>(); + dr_nodes = new HashMap<>(); + dr_pubs = new HashMap<>(); + dr_subs = new HashMap<>(); + mr_clients = new HashMap<>(); + mr_clusters = new HashMap<>(); + feeds = new HashMap<>(); + topics = new HashMap<>(); + mirrors = new HashMap<>(); + } + + private static void initDatabase() throws Exception { + dcaeLocations = new DBMap<>(DcaeLocation.class, "dcae_location", "dcae_location_name"); + dr_nodes = new DBMap<>(DR_Node.class, "dr_node", "fqdn"); + dr_pubs = new DBMap<>(DR_Pub.class, "dr_pub", "pub_id"); + dr_subs = new DBMap<>(DR_Sub.class, "dr_sub", "sub_id"); + mr_clients = new DBMap<>(MR_Client.class, "mr_client", "mr_client_id"); + mr_clusters = new DBMap<>(MR_Cluster.class, "mr_cluster", "dcae_location_name"); + feeds = new DBMap<>(Feed.class, "feed", "feed_id"); + topics = new DBMap<>(Topic.class, "topic", "fqtn"); + mirrors = new DBMap<>(MirrorMaker.class, "mirror_maker", "mm_name"); + } + + private static void determineDatabaseType() { + DmaapConfig dmaapConfig = (DmaapConfig) DmaapConfig.getConfig(); + String isPgSQLset = dmaapConfig.getProperty("UsePGSQL", "false"); + databaseType = isPgSQLset.equalsIgnoreCase("true") ? DBType.PGSQL : DBType.MEMORY; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/LoadSchema.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/LoadSchema.java new file mode 100644 index 0000000..97bea4d --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/LoadSchema.java @@ -0,0 +1,57 @@ +/*- + * ============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.database; + +import java.io.FileReader; +import java.io.LineNumberReader; +import java.sql.Connection; +import java.sql.Statement; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; + +public class LoadSchema extends BaseLoggingClass { + + private LoadSchema(){} + + static void loadSchema() { + ConnectionFactory cf = ConnectionFactory.getDefaultInstance(); + try (LineNumberReader lineReader = new LineNumberReader(new FileReader("/opt/app/dmaapbc/misc/schema_all.sql")); + Connection c = cf.get(true); + Statement stmt = c.createStatement()) { + StringBuilder strBuilder = new StringBuilder(); + String line; + while ((line = lineReader.readLine()) != null) { + if (!line.startsWith("--")) { + line = line.trim(); + strBuilder.append(line); + if (line.endsWith(";")) { + String sql = strBuilder.toString(); + strBuilder.setLength(0); + stmt.execute(sql); + appLogger.debug("SQL EXECUTE SUCCESS: " + sql); + } + } + } + strBuilder.setLength(0); + } catch (Exception e) { + errorLogger.error("Error when initializing table: " + e.getMessage(), e); + } + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/TableHandler.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/TableHandler.java new file mode 100644 index 0000000..a85bdae --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/database/TableHandler.java @@ -0,0 +1,126 @@ +/*- + * ============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.database; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; +import java.util.Vector; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; + +class TableHandler<C> extends BaseLoggingClass { + protected ConnectionFactory cf; + protected boolean haskey; + protected String delstmt; + protected String insorreplstmt; + protected String getstmt; + protected String liststmt; + protected String initstmt; + protected Class<C> cls; + protected DBFieldHandler[] fields; + private static Map<String, Map<String, DBFieldHandler.SqlOp>> exceptions = new HashMap<>(); + private String select = "SELECT "; + private String from = " FROM "; + + protected TableHandler(Class<C> cls, String tabname, String keyname) throws Exception { + this(ConnectionFactory.getDefaultInstance(), cls, tabname, keyname); + } + protected TableHandler(ConnectionFactory cf, Class<C> cls, String tabname, String keyname) throws Exception { + this.cf = cf; + Connection c = null; + try { + c = cf.get(false); + setup(c.getMetaData(), cls, tabname, keyname); + } finally { + if (c != null) { + cf.release(c); + } + } + } + + public static void setSpecialCase(String dbtabname, String dbfldname, DBFieldHandler.SqlOp handler) { + Map<String, DBFieldHandler.SqlOp> m = exceptions.get(dbtabname); + if (m == null) { + m = new HashMap<>(); + exceptions.put(dbtabname, m); + } + m.put(dbfldname, handler); + } + public static DBFieldHandler.SqlOp getSpecialCase(String dbtabname, String dbfldname) { + Map<String, DBFieldHandler.SqlOp> m = exceptions.get(dbtabname); + if (m != null) { + return(m.get(dbfldname)); + } + return(null); + } + + private void setup(DatabaseMetaData dmd, Class<C> cls, String tabname, String keyname) throws Exception { + this.cls = cls; + Vector<DBFieldHandler> h = new Vector<>(); + String qualifiedTableName = String.format( "%s.%s", cf.getSchema(), tabname ); + ResultSet rs = dmd.getColumns("", cf.getSchema(), tabname, null); + StringBuilder sb1 = new StringBuilder(); + StringBuilder sb2 = new StringBuilder(); + StringBuilder sb3 = new StringBuilder(); + int count = 0; + while (rs.next()) { + if (!rs.getString(3).equals(tabname)) { + continue; + } + String cname = rs.getString(4); + if (cname.equals(keyname)) { + haskey = true; + continue; + } + sb1.append(", ").append(cname); + sb2.append(", ?"); + sb3.append(", EXCLUDED.").append(cname); + count++; + h.add(new DBFieldHandler(cls, cname, count, getSpecialCase(tabname, cname))); + } + if (count == 0) { + throw new SQLException("Table " + tabname + " not found"); + } + String clist = sb1.substring(2); + String qlist = sb2.substring(2); + String elist = sb3.substring(2); + if (keyname != null && !haskey) { + throw new SQLException("Table " + tabname + " does not have key column " + keyname + " not found"); + } + if (haskey) { + count++; + h.add(new DBFieldHandler(cls, keyname, count, getSpecialCase(tabname, keyname))); + delstmt = "DELETE FROM " + qualifiedTableName + " WHERE " + keyname + " = ?"; + insorreplstmt = "INSERT INTO " + qualifiedTableName + " (" + clist + ", " + keyname + ") VALUES (" + qlist + ", ?) ON CONFLICT(" + keyname + ") DO UPDATE SET (" + clist + ") = (" + elist + ")"; + getstmt = select + clist + ", " + keyname + from + qualifiedTableName + " WHERE " + keyname + " = ?"; + liststmt = select + clist + ", " + keyname + from + qualifiedTableName; + } else { + delstmt = "DELETE FROM " + qualifiedTableName; + initstmt = "INSERT INTO " + qualifiedTableName + " (" + clist + ") VALUES (" + qlist + ")"; + insorreplstmt = "UPDATE " + qualifiedTableName + " SET (" + clist + ") = (" + qlist + ")"; + getstmt = select + clist + ", " + keyname + from + qualifiedTableName; + } + fields = h.toArray(new DBFieldHandler[h.size()]); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/logging/BaseLoggingClass.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/logging/BaseLoggingClass.java new file mode 100644 index 0000000..4bde17a --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/logging/BaseLoggingClass.java @@ -0,0 +1,36 @@ +/*- + * ============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.logging; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; + +public abstract class BaseLoggingClass { + protected EELFLogger logger = EELFManager.getInstance().getLogger( super.getClass()); + protected static final EELFLogger appLogger = EELFManager.getInstance().getApplicationLogger(); + protected static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger(); + protected static final EELFLogger debugLogger = EELFManager.getInstance().getDebugLogger(); + protected static final EELFLogger errorLogger = EELFManager.getInstance().getErrorLogger(); + protected static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger(); + protected static final EELFLogger serverLogger = EELFManager.getInstance().getServerLogger(); + + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/logging/DmaapbcLogMessageEnum.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/logging/DmaapbcLogMessageEnum.java new file mode 100644 index 0000000..86c5fe0 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/logging/DmaapbcLogMessageEnum.java @@ -0,0 +1,81 @@ +/*- + * ============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.logging; + +import com.att.eelf.i18n.EELFResourceManager; +import com.att.eelf.i18n.EELFResolvableErrorEnum; + +public enum DmaapbcLogMessageEnum implements EELFResolvableErrorEnum { +//0xx sample stock messages + MESSAGE_SAMPLE_NOARGS, + MESSAGE_SAMPLE_ONE_ARG, + MESSAGE_SAMPLE_TWO_ARGS, + +// 1xx Permission Errors + AAF_CREDENTIAL_ERROR, + CODEC_CREDENTIAL_ERROR, + PE_AUTHENTICATION_ERROR, + DR_PROV_AUTHORIZATION, + +// 2xx Availability Errors/Timeouts + DRIVER_UNAVAILABLE, + HTTP_CONNECTION_ERROR, + HTTP_CONNECTION_EXCEPTION, + UNKNOWN_HOST_EXCEPTION, + + +// 3xx Data Errors + IO_EXCEPTION, + SSL_HANDSHAKE_ERROR, + AAF_UNEXPECTED_RESPONSE, + PE_EXCEPTION, + SOCKET_EXCEPTION, + JSON_PARSING_ERROR, + DECRYPT_IO_ERROR, + +//4xx Schema Errors + DB_UPGRADE_ERROR, + DB_INIT_ERROR, + DB_UPDATE_ERROR, + DB_ACCESS_ERROR, + DB_FIELD_INIT_ERROR, + DB_ACCESS_INIT_ERROR, + DB_NO_FIELD_HANDLER, + + +// 5xx Business Process Errors + PREREQ_DMAAP_OBJECT, + PROV_OUT_OF_SYNC, + MM_CIRCULAR_REF, + TOPIC_CREATE_ERROR, + INGRESS_CREATE_ERROR, + FEED_PUB_PROV_ERROR, + FEED_SUB_PROV_ERROR, + MM_PUBLISH_ERROR, + EGRESS_CREATE_ERROR, + +// 900 Unknown Errors + UNEXPECTED_CONDITION; + + static { + EELFResourceManager.loadMessageBundle("logmsg"); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/logging/logmsg.properties b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/logging/logmsg.properties new file mode 100644 index 0000000..6548433 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/logging/logmsg.properties @@ -0,0 +1,240 @@ +### +# ============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========================================================= +### + +# 0xx sample stock messages +MESSAGE_SAMPLE_NOARGS=\ + 01|\ + Ignore: demo msg with no arg|\ + No resolution|\ + An example of a message with no args + +MESSAGE_SAMPLE_ONE_ARG=\ + 02|\ + Ignore: demo msg with 1 arg {0}|\ + No resolution|\ + An example of a message with 1 arg + +MESSAGE_SAMPLE_TWO_ARGS=\ + 03|\ + Ignore: demo msg with arg1 {0} and arg2 {1}|\ + No resolution|\ + An example of a message with 2 args + + + +# 1xx Permission Errors +AAF_CREDENTIAL_ERROR=\ + 101|\ + Service credentials ({0}) are not valid for AAF connection|\ + Check credentials are valid in appropriate AAF environment.|\ + Connection to AAF was not allowed for the specified credentials. + +CODEC_CREDENTIAL_ERROR=\ + 102|\ + Failed to read CredentialCodecKeyfile {0} with error {1}|\ + Check if CredentialCodecKeyfile has been corrupted.|\ + CredentialCodecKeyfile is not in sync with application + +PE_AUTHENTICATION_ERROR=\ + 103|\ + User {0} perms {1} caught PolicyEngineException {1}|\ + User needs to be granted perm before access.|\ + Identified user was not authorized for the specific perm. + +DR_PROV_AUTHORIZATION=\ + 104|\ + Not authorized for API {0}|\ + Bus Controller host needs to be provisioned as a Node and an AUTHORIZED_HOST.|\ + DR Prov indicates that Bus Controller host is not authorized for the specified API. + +# 2xx Availability Errors/Timeouts +DRIVER_UNAVAILABLE=\ + 201|\ + Unable to load driver {0}. Error {1}|\ + Check that specified driver is installed and accessible to application.|\ + The software attempted to load a driver and was not successful. + +HTTP_CONNECTION_ERROR=\ + 202|\ + Exception during openConnection to {0} failed with {1}|\ + Confirm syntax of URL is correct and network access from this host is allowed.|\ + An attempt to URL.openConnection failed + +HTTP_CONNECTION_EXCEPTION=\ + 203|\ + Connection to {0} refused because {1}|\ + Check if this is the proper server.|\ + Application caught a ConnectionException + +UNKNOWN_HOST_EXCEPTION=\ + 204|\ + Caught exception {0} attempting to access {1}|\ + Confirm that host is in DNS|\ + Caught UnknownHostException when connecting to the designated host name. + +# 3xx Data Errors +IO_EXCEPTION=\ + 301|\ + IOexception {0}|\ + No resolution.|\ + Generic IO Exception condition + +SSL_HANDSHAKE_ERROR=\ + 302|\ + SSLHandshakeException from URL {0}|\ + Confirm that target host has proper SSL certificate for DNS value used to access it.|\ + SSLHandshake exception thrown on HttpsURLConnection method + +AAF_UNEXPECTED_RESPONSE=\ + 303|\ + rc= {0} :unable to {1} for {2}|\ + Check configuration for this AAF instance.|\ + Unexpected response from AAF for the intended action + +PE_EXCEPTION=\ + 304|\ + Trying to read {0} and caught PolicyEngineException {1}|\ + Check config file exists and has proper settings.|\ + An unexpected exception from PE was caught. + +SOCKET_EXCEPTION=\ + 305|\ + Caught exception {0} while {1}|\ + No comment.|\ + An unexpected socket exception was caught while performing the specified action. + +JSON_PARSING_ERROR=\ + 306|\ + ParsingException for object {0} using data:{1}|\ + No comment.|\ + The JSON data provided to the object was not in the expected format + + DECRYPT_IO_ERROR=\ + 307|\ + IO Error attempting using {0} to decrypt value {1}|\ + Check permissions of file set for property CredentialCodecKeyfile.|\ + Error using codec file for decryption. + +# 4xx Schema Errors + +DB_UPGRADE_ERROR=\ + 401|\ + Problem updating DB schema. {0}|\ + Examine stack trace for clues.|\ + The software was not able to process the sql file resources in the jar file. + +DB_INIT_ERROR=\ + 402|\ + Error initializing database access: {0}|\ + Correct configuration based on detail.|\ + The software was not able initialize objects from the DB. + +DB_UPDATE_ERROR=\ + 403|\ + Error while updating DB: {0}|\ + Correct configuration based on detail.|\ + The software was not able to update record(s) in the DB. + +DB_ACCESS_ERROR=\ + 404|\ + Database access problem: {0}|\ + Correct configuration based on detail.|\ + An exception related to DB access was caught and logged. + +DB_FIELD_INIT_ERROR=\ + 405|\ + Problem setting field {0} to {1} statement is {2}|\ + DB schema may be out of sync with code.|\ + SQLDate.set() failed to set field value. + +DB_ACCESS_INIT_ERROR=\ + 406|\ + Problem initializing sql access methods {0} |\ + No comment.|\ + Error encountered while initializing basic field types. + +DB_NO_FIELD_HANDLER=\ + 407|\ + No field handler for class {0} field {1} index {2} type {3}|\ + No comment.|\ + Missing field handler for specified code. + + +# 5xx Business Process Errors +PREREQ_DMAAP_OBJECT=\ + 501|\ + Attempt to access {0} before dmaap object resource is available.|\ + No remediation.|\ + The dmaap object needs to be defined before attempting the desired access + +PROV_OUT_OF_SYNC=\ + 502|\ + Resource {0} with id {1} was not in sync with DR Prov.\ + May need manual sync steps.\ + The Bus Controller view of a resource does not match what was found on DR Prov + +MM_CIRCULAR_REF=\ + 503|\ + Trying to add edge from source {0} into Map belonging to {1}|\ + May indicate a provisioning error.|\ + Some error in logic is attempting to add an edge to a Map that is an edge. + +TOPIC_CREATE_ERROR=\ + 504|\ + Unable to create topic for {0} err={1} fields={2} msg={3}|\ + No comment.|\ + Reporting an error caught while creating a topic + +INGRESS_CREATE_ERROR=\ + 505|\ + rc={0} unable to create ingress rule for {1} on feed {2} to {3}|\ + No comment.|\ + Unexpected response while creating ingress rule + +FEED_PUB_PROV_ERROR=\ + 506|\ + For feed {0} resulting set of publishers do not match requested set of publishers {1} vs {2}|\ + No comment.|\ + The number of publishers on a feed do not match after provisioning request. + +FEED_SUB_PROV_ERROR=\ + 507|\ + For feed {0} i={1} url={2} err={3}|\ + No comment.|\ + An error occurred when provisioning subs on a feed. + +MM_PUBLISH_ERROR=\ + 508|\ + Unable to publish {0} provisioning message. rc={1} msg={2}|\ + No comment.|\ + An error occurred when publishing a message to MM + +EGRESS_CREATE_ERROR=\ + 509|\ + rc={0} unable to create egress rule for {1} on feed {2} to {3}|\ + No comment.|\ + Unexpected response while creating egress rule + +# 900 Unknown Errors +UNEXPECTED_CONDITION=\ + 901|\ + Unexpected exception encountered {0}|\ + No resolution|\ + An error to catch unexpected conditions. Hopefully a clue in the stack trace. diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/ApiError.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/ApiError.java new file mode 100644 index 0000000..c67e55b --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/ApiError.java @@ -0,0 +1,92 @@ +/*- + * ============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 javax.xml.bind.annotation.XmlRootElement; +import java.io.Serializable; +import java.util.Objects; + +@XmlRootElement +public class ApiError implements Serializable { + private int code; + private String message; + private String fields; + + public ApiError() { + this(0, null, null); + } + + public ApiError(int code, String message) { + this(code, message, null); + } + + public ApiError(int code, String message, String fields) { + this.code = code; + this.message = message; + this.fields = fields; + } + + public int getCode() { + return code; + } + public void setCode(int rc) { + this.code = rc; + } + public String getMessage() { + return message; + } + public void setMessage(String message) { + this.message = message; + } + public String getFields() { + return fields; + } + public void setFields(String fields) { + this.fields = fields; + } + public String toString() { + return String.format( "code=%d msg=%s fields=%s", this.code, this.message, this.fields ); + } + public boolean is2xx() { + + return code >= 200 && code < 300; + } + public void reset() { + code = 0; + message = null; + fields = null; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ApiError apiError = (ApiError) o; + return code == apiError.code && + Objects.equals(message, apiError.message) && + Objects.equals(fields, apiError.fields); + } + + @Override + public int hashCode() { + return Objects.hash(code, message, fields); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/BrTopic.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/BrTopic.java new file mode 100644 index 0000000..ba050c3 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/BrTopic.java @@ -0,0 +1,71 @@ +/*- + * ============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 javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class BrTopic { + + private String brSource; + private String brTarget; + private String mmAgentName; + private int topicCount; + + // no-op constructor used by framework + public BrTopic() { + } + + public String getBrSource() { + return brSource; + } + + public void setBrSource(String brSource) { + this.brSource = brSource; + } + + public String getBrTarget() { + return brTarget; + } + + public void setBrTarget(String brTarget) { + this.brTarget = brTarget; + } + + public int getTopicCount() { + return topicCount; + } + + public void setTopicCount(int topicCount) { + this.topicCount = topicCount; + } + + public String getMmAgentName() { + return mmAgentName; + } + + public void setMmAgentName(String mmAgentName) { + this.mmAgentName = mmAgentName; + } + + + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DR_Node.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DR_Node.java new file mode 100644 index 0000000..4b2ef90 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DR_Node.java @@ -0,0 +1,94 @@ +/*- + * ============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 javax.xml.bind.annotation.XmlRootElement; +import java.util.Objects; + +@XmlRootElement +public class DR_Node extends DmaapObject { + private String fqdn; + private String dcaeLocationName; + private String hostName; + private String version; + + public DR_Node() { + + } + + public DR_Node( String f, + String dLN, + String hN, + String v ) { + this.fqdn = f; + this.dcaeLocationName = dLN; + this.hostName = hN; + this.version = v; + } + + public String getFqdn() { + return fqdn; + } + + public void setFqdn(String fqdn) { + this.fqdn = fqdn; + } + + public String getDcaeLocationName() { + return dcaeLocationName; + } + + public void setDcaeLocationName(String dcaeLocationName) { + this.dcaeLocationName = dcaeLocationName; + } + + public String getHostName() { + return hostName; + } + + public void setHostName(String hostName) { + this.hostName = hostName; + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DR_Node dr_node = (DR_Node) o; + return Objects.equals(fqdn, dr_node.fqdn) && + Objects.equals(dcaeLocationName, dr_node.dcaeLocationName) && + Objects.equals(hostName, dr_node.hostName) && + Objects.equals(version, dr_node.version); + } + + @Override + public int hashCode() { + return Objects.hash(fqdn, dcaeLocationName, hostName, version); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DR_Pub.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DR_Pub.java new file mode 100644 index 0000000..4e64089 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DR_Pub.java @@ -0,0 +1,187 @@ +/*- + * ============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 javax.xml.bind.annotation.XmlRootElement; + +import org.onap.dmaap.dbcapi.util.RandomString; + +import java.util.Objects; + +@XmlRootElement +public class DR_Pub extends DmaapObject { + + private String dcaeLocationName; + private String username; + private String userpwd; + private String feedId; + private String pubId; + + // NOTE: the following fields are optional in the API but not stored in the DB + private String feedName; + private String feedVersion; + + + public DR_Pub() { + status = DmaapObject_Status.EMPTY; + + } + + public DR_Pub( String dLN ) { + this.dcaeLocationName = dLN; + this.status = DmaapObject_Status.STAGED; + } + + public DR_Pub( String dLN, + String uN, + String uP, + String fI, + String pI ) { + this.dcaeLocationName = dLN; + this.username = uN; + this.userpwd = uP; + this.feedId = fI; + this.pubId = pI; + this.status = DmaapObject_Status.VALID; + } + + + public DR_Pub( String dLN, + String uN, + String uP, + String fI ) { + this.dcaeLocationName = dLN; + this.username = uN; + this.userpwd = uP; + this.feedId = fI; + this.pubId = fI + "." + DR_Pub.nextKey(); + this.status = DmaapObject_Status.VALID; + } + + + public String getDcaeLocationName() { + return dcaeLocationName; + } + + public void setDcaeLocationName(String dcaeLocationName) { + this.dcaeLocationName = dcaeLocationName; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getUserpwd() { + return userpwd; + } + + public void setUserpwd(String userpwd) { + this.userpwd = userpwd; + } + + public String getFeedId() { + return feedId; + } + + public void setFeedId(String feedId) { + this.feedId = feedId; + } + + public String getPubId() { + return pubId; + } + + public void setPubId(String pubId) { + this.pubId = pubId; + } + + public void setNextPubId() { + this.pubId = this.feedId + "." + DR_Pub.nextKey(); + } + + public String getFeedName() { + return feedName; + } + + public void setFeedName(String feedName) { + this.feedName = feedName; + } + + public String getFeedVersion() { + return feedVersion; + } + + public void setFeedVersion(String feedVersion) { + this.feedVersion = feedVersion; + } + + public DR_Pub setRandomUserName() { + RandomString r = new RandomString(15); + this.username = "tmp_" + r.nextString(); + return this; + } + public DR_Pub setRandomPassword() { + RandomString r = new RandomString(15); + this.userpwd = r.nextString(); + return this; + } + + public static String nextKey() { + RandomString ri = new RandomString(5); + return ri.nextString(); + + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DR_Pub dr_pub = (DR_Pub) o; + return Objects.equals(dcaeLocationName, dr_pub.dcaeLocationName) && + Objects.equals(username, dr_pub.username) && + Objects.equals(userpwd, dr_pub.userpwd) && + Objects.equals(feedId, dr_pub.feedId) && + Objects.equals(pubId, dr_pub.pubId); + } + + @Override + public int hashCode() { + + return Objects.hash(dcaeLocationName, username, userpwd, feedId, pubId); + } + + @Override + public String toString() { + return "DR_Pub{" + + "dcaeLocationName='" + dcaeLocationName + '\'' + + ", username='" + username + '\'' + + ", userpwd='" + userpwd + '\'' + + ", feedId='" + feedId + '\'' + + ", pubId='" + pubId + '\'' + + ", feedName='" + feedName + '\'' + + ", feedVersion='" + feedVersion + '\'' + + '}'; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DR_Sub.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DR_Sub.java new file mode 100644 index 0000000..90da956 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DR_Sub.java @@ -0,0 +1,391 @@ +/*- + * ============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.nio.charset.StandardCharsets; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; + +@XmlRootElement +public class DR_Sub extends DmaapObject { + + private String dcaeLocationName; + private String username; + private String userpwd; + private String feedId; + private String deliveryURL; + private String logURL; + private String subId; + private boolean use100; + private boolean suspended; + private String owner; + private boolean guaranteedDelivery; + private boolean guaranteedSequence; + private boolean privilegedSubscriber; + private boolean decompress; + + // NOTE: the following fields are optional in the API but not stored in the DB + + private String feedName; + private String feedVersion; + public DR_Sub() { + + } + + public DR_Sub( String dLN, + String uN, + String uP, + String fI, + String dU, + String lU, + boolean u100 ) { + this.dcaeLocationName = dLN; + this.username = uN; + this.userpwd = uP; + this.feedId = fI; + this.deliveryURL = dU; + this.logURL = lU; + this.use100 = u100; + this.setStatus( DmaapObject_Status.NEW ); + this.subId = "0"; + } + + public DR_Sub ( String json ) { + logger.info( "DR_Sub:" + json ); + JSONParser parser = new JSONParser(); + JSONObject jsonObj; + + try { + jsonObj = (JSONObject) parser.parse( json ); + } catch ( ParseException pe ) { + errorLogger.error( DmaapbcLogMessageEnum.JSON_PARSING_ERROR, "DR_Sub", json ); + this.setStatus( DmaapObject_Status.INVALID ); + return; + } + + this.setOwner( (String) jsonObj.get("subscriber")); + this.setSuspended( (boolean) jsonObj.get("suspend")); + + try { + JSONObject links = (JSONObject) jsonObj.get("links"); + String url = (String) links.get("feed"); + this.setFeedId( url.substring( url.lastIndexOf('/')+1, url.length() )); + url = (String) links.get("self"); + this.setSubId( url.substring( url.lastIndexOf('/')+1, url.length() )); + logger.info( "feedid="+ this.getFeedId() ); + this.setLogURL( (String) links.get("log") ); + } catch (NullPointerException npe ) { + + } + try { + this.setGuaranteedDelivery( (boolean) jsonObj.get("guaranteed_delivery")); + } catch( NullPointerException npe ) { + this.setGuaranteedDelivery(false); + } + try { + this.setGuaranteedSequence( (boolean) jsonObj.get("guaranteed_sequence")); + } catch( NullPointerException npe ) { + this.setGuaranteedSequence(false); + } + try { + this.setPrivilegedSubscriber((boolean) jsonObj.get("privilegedSubscriber")); + } catch( NullPointerException npe ) { + this.setPrivilegedSubscriber(false); + } + try { + this.setDecompress((boolean) jsonObj.get("decompress")); + } catch( NullPointerException npe ) { + this.setDecompress(false); + } + + JSONObject del = (JSONObject) jsonObj.get("delivery"); + this.setDeliveryURL( (String) del.get("url") ); + this.setUsername( (String) del.get("user")); + this.setUserpwd( (String) del.get( "password")); + this.setUse100((boolean) del.get( "use100")); + + this.setStatus( DmaapObject_Status.VALID ); + + logger.info( "new DR_Sub returning"); + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public boolean isSuspended() { + return suspended; + } + + public void setSuspended(boolean suspended) { + this.suspended = suspended; + } + + + + public boolean isUse100() { + return use100; + } + + public void setUse100(boolean use100) { + this.use100 = use100; + } + + public String getDcaeLocationName() { + return dcaeLocationName; + } + + public void setDcaeLocationName(String dcaeLocationName) { + this.dcaeLocationName = dcaeLocationName; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getUserpwd() { + return userpwd; + } + + public void setUserpwd(String userpwd) { + this.userpwd = userpwd; + } + + public String getFeedId() { + return feedId; + } + + public void setFeedId(String feedId) { + this.feedId = feedId; + } + + public String getDeliveryURL() { + return deliveryURL; + } + + public void setDeliveryURL(String deliveryURL) { + this.deliveryURL = deliveryURL; + } + + public String getLogURL() { + return logURL; + } + + public void setLogURL(String logURL) { + this.logURL = logURL; + } + + public String getSubId() { + return subId; + } + + public void setSubId(String subId) { + this.subId = subId; + } + + + public boolean isGuaranteedDelivery() { + return guaranteedDelivery; + } + + public void setGuaranteedDelivery(boolean guaranteedDelivery) { + this.guaranteedDelivery = guaranteedDelivery; + } + + public boolean isGuaranteedSequence() { + return guaranteedSequence; + } + + public void setGuaranteedSequence(boolean guaranteedSequence) { + this.guaranteedSequence = guaranteedSequence; + } + + public boolean isPrivilegedSubscriber() { + return privilegedSubscriber; + } + + public void setPrivilegedSubscriber(boolean privilegedSubscriber) { + this.privilegedSubscriber = privilegedSubscriber; + } + + public boolean isDecompress() { + return decompress; + } + + public void setDecompress(boolean decompressData) { + this.decompress = decompressData; + } + + public String getFeedName() { + return feedName; + } + + public void setFeedName(String feedName) { + this.feedName = feedName; + } + + public String getFeedVersion() { + return feedVersion; + } + + public void setFeedVersion(String feedVersion) { + this.feedVersion = feedVersion; + } + + public byte[] getBytes(String provApi) { + if ( "AT&T".equals(provApi)) { + return toProvJSONforATT().getBytes(StandardCharsets.UTF_8); + } + return toProvJSON().getBytes(StandardCharsets.UTF_8); + } + // returns the DR_Sub object in JSON that conforms to ONAP DR Prov Server expectations + public String toProvJSON() { + // this is the original DR API that was contributed to ONAP + String postJSON = String.format("{\"suspend\": %s, \"delivery\":" + + "{\"url\": \"%s\", \"user\": \"%s\", \"password\": \"%s\", \"use100\": %s }" + + ", \"metadataOnly\": %s, \"groupid\": \"%s\", \"follow_redirect\": %s " + + ", \"privilegedSubscriber\": %s, \"decompress\": %s " + + "}" + ,this.suspended + ,this.getDeliveryURL() + ,this.getUsername() + ,this.getUserpwd() + ,this.isUse100() + ,"false" + ,"0" + ,"true" + ,this.isPrivilegedSubscriber() + ,this.isDecompress() + ); + + logger.info( postJSON ); + return postJSON; + } + // returns the DR_Sub object in JSON that conforms to AT&T DR Prov Server expectations + // In Jan, 2019, the DR API used internally at AT&T diverged, so this function can be used in + // that runtime environment + public String toProvJSONforATT() { + // in DR 3.0, API v2.1 a new groupid field is added. We are not using this required field so just set it to 0. + // we send this regardless of DR Release because older versions of DR seem to safely ignore it + // and soon those versions won't be around anyway... + // Similarly, in the 1704 Release, a new subscriber attribute "follow_redirect" was introduced. + // We are setting it to "true" because that is the general behavior desired in OpenDCAE. + // But it is really a no-op for OpenDCAE because we've deployed DR with the SYSTEM-level parameter for FOLLOW_REDIRECTS set to true. + // In the event we abandon that, then setting the sub attribute to true will be a good thing. + // Update Jan, 2019: added guaranteed_delivery and guaranteed_sequence with value false for + // backwards compatibility + // TODO: + // - introduce Bus Controller API support for these attributes + // - store the default values in the DB + String postJSON = String.format("{\"suspend\": %s, \"delivery\":" + + "{\"url\": \"%s\", \"user\": \"%s\", \"password\": \"%s\", \"use100\": %s}" + + ", \"metadataOnly\": %s, \"groupid\": \"%s\", \"follow_redirect\": %s " + + ", \"guaranteed_delivery\": %s, \"guaranteed_sequence\": %s" + + "}" + ,this.suspended + ,this.getDeliveryURL() + ,this.getUsername() + ,this.getUserpwd() + ,this.isUse100() + ,"false" + ,"0" + ,"true" + ,this.isGuaranteedDelivery() + ,this.isGuaranteedSequence() + ); + + logger.info( postJSON ); + return postJSON; + } + + @Override + public String toString() { + return String.format ( "DR_Sub: {dcaeLocationName=%s username=%s userpwd=%s feedId=%s deliveryURL=%s logURL=%s subid=%s use100=%s suspended=%s owner=%s}", + dcaeLocationName, + username, + userpwd, + feedId, + deliveryURL, + logURL, + subId, + use100, + suspended, + owner + ); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + + DR_Sub drSub = (DR_Sub) o; + + if (use100 != drSub.use100) { + return false; + } + if (suspended != drSub.suspended) { + return false; + } + if (!dcaeLocationName.equals(drSub.dcaeLocationName)) { + return false; + } + if (!username.equals(drSub.username)) { + return false; + } + if (!userpwd.equals(drSub.userpwd)) { + return false; + } + if (!feedId.equals(drSub.feedId)) { + return false; + } + return subId.equals(drSub.subId); + } + + @Override + public int hashCode() { + int result = dcaeLocationName.hashCode(); + result = 31 * result + username.hashCode(); + result = 31 * result + userpwd.hashCode(); + result = 31 * result + feedId.hashCode(); + result = 31 * result + subId.hashCode(); + result = 31 * result + (use100 ? 1 : 0); + result = 31 * result + (suspended ? 1 : 0); + return result; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DcaeLocation.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DcaeLocation.java new file mode 100644 index 0000000..f459c6c --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DcaeLocation.java @@ -0,0 +1,119 @@ +/*- + * ============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 javax.xml.bind.annotation.XmlRootElement; + +import java.util.Objects; + +@XmlRootElement +public class DcaeLocation extends DmaapObject { + private String clli; + private String dcaeLayer; + private String dcaeLocationName; + private String openStackAvailabilityZone; + private String subnet; + + + + public DcaeLocation() { + + } + + public DcaeLocation( String c, + String dL, + String dLN, + String oSAZ, + String s ) { + + this.clli = c; + this.dcaeLayer = dL; + this.dcaeLocationName = dLN; + this.openStackAvailabilityZone = oSAZ; + this.subnet = s; + } + + public String getClli() { + return clli; + } + + public void setClli(String clli) { + this.clli = clli; + } + + public String getDcaeLayer() { + return dcaeLayer; + } + + public void setDcaeLayer(String dcaeLayer) { + this.dcaeLayer = dcaeLayer; + } + public boolean isCentral() { + return dcaeLayer != null && dcaeLayer.contains("central"); + } + public boolean isLocal() { + return dcaeLayer != null && dcaeLayer.contains("local"); + } + + public String getDcaeLocationName() { + return dcaeLocationName; + } + + public void setDcaeLocationName(String dcaeLocationName) { + this.dcaeLocationName = dcaeLocationName; + } + + + + public String getOpenStackAvailabilityZone() { + return openStackAvailabilityZone; + } + + public void setOpenStackAvailabilityZone(String openStackAvailabilityZone) { + this.openStackAvailabilityZone = openStackAvailabilityZone; + } + + public String getSubnet() { + return subnet; + } + + public void setSubnet(String subnet) { + this.subnet = subnet; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DcaeLocation that = (DcaeLocation) o; + return Objects.equals(clli, that.clli) && + Objects.equals(dcaeLayer, that.dcaeLayer) && + Objects.equals(dcaeLocationName, that.dcaeLocationName) && + Objects.equals(openStackAvailabilityZone, that.openStackAvailabilityZone) && + Objects.equals(subnet, that.subnet); + } + + @Override + public int hashCode() { + + return Objects.hash(clli, dcaeLayer, dcaeLocationName, openStackAvailabilityZone, subnet); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/Dmaap.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/Dmaap.java new file mode 100644 index 0000000..96248f3 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/Dmaap.java @@ -0,0 +1,177 @@ +/*- + * ============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 javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class Dmaap extends DmaapObject { + + private String version; + private String topicNsRoot; + private String dmaapName; + private String drProvUrl; + private String bridgeAdminTopic; + private String loggingUrl; + private String nodeKey; + private String accessKeyOwner; + + + // no-op constructor used by framework + public Dmaap() { + + } + + public Dmaap( DmaapBuilder builder ) { + this.version = builder.ver; + this.topicNsRoot = builder.tnr; + this.dmaapName = builder.dn; + this.drProvUrl = builder.dpu; + this.bridgeAdminTopic = builder.bat; + this.loggingUrl = builder.lu; + this.nodeKey = builder.nk; + this.accessKeyOwner = builder.ako; + this.setStatus( DmaapObject_Status.NEW ); + + } + + public static class DmaapBuilder { + private String ver; + private String tnr; + private String dn; + private String dpu; + private String lu; + private String bat; + private String nk; + private String ako; + + public DmaapBuilder setVer(String ver) { + this.ver = ver; + return this; + } + + public DmaapBuilder setTnr(String tnr) { + this.tnr = tnr; + return this; + } + + public DmaapBuilder setDn(String dn) { + this.dn = dn; + return this; + } + + public DmaapBuilder setDpu(String dpu) { + this.dpu = dpu; + return this; + } + + public DmaapBuilder setLu(String lu) { + this.lu = lu; + return this; + } + + public DmaapBuilder setBat(String bat) { + this.bat = bat; + return this; + } + + public DmaapBuilder setNk(String nk) { + this.nk = nk; + return this; + } + + public DmaapBuilder setAko(String ako) { + this.ako = ako; + return this; + } + + public Dmaap createDmaap() { + return new Dmaap(this); + } + } + + public String getVersion() { + return version; + } + + public void setVersion(String version) { + this.version = version; + } + + public String getTopicNsRoot() { + return topicNsRoot; + } + + public void setTopicNsRoot(String topicNsRoot) { + this.topicNsRoot = topicNsRoot; + } + + public String getDmaapName() { + return dmaapName; + } + + public void setDmaapName(String dmaapName) { + this.dmaapName = dmaapName; + } + + public String getDrProvUrl() { + return drProvUrl; + } + + public void setDrProvUrl(String drProvUrl) { + this.drProvUrl = drProvUrl; + } + + + public String getNodeKey() { + return nodeKey; + } + + public void setNodeKey(String nodeKey) { + this.nodeKey = nodeKey; + } + + public String getAccessKeyOwner() { + return accessKeyOwner; + } + + public void setAccessKeyOwner(String accessKeyOwner) { + this.accessKeyOwner = accessKeyOwner; + } + + + public String getBridgeAdminTopic() { + return bridgeAdminTopic; + } + + public void setBridgeAdminTopic(String bridgeAdminTopic) { + this.bridgeAdminTopic = bridgeAdminTopic; + } + + public String getLoggingUrl() { + return loggingUrl; + } + + public void setLoggingUrl(String loggingUrl) { + this.loggingUrl = loggingUrl; + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DmaapObject.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DmaapObject.java new file mode 100644 index 0000000..4ff2eec --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/DmaapObject.java @@ -0,0 +1,144 @@ +/*- + * ============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 io.swagger.annotations.ApiModelProperty; +import java.util.Calendar; +import java.util.Date; +import java.util.TimeZone; +import javax.xml.bind.annotation.XmlRootElement; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; + +@XmlRootElement +public abstract class DmaapObject extends BaseLoggingClass { + @ApiModelProperty( value = "datestamp for last update to this object") + protected Date lastMod; + protected DmaapObject_Status status; + + public Date getLastMod() { + return lastMod; + } + + public void setLastMod(Date lastMod) { + this.lastMod = lastMod; + } + + public void setLastMod() { + this.lastMod = Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTime(); + } + + public enum DmaapObject_Status { + EMPTY, + NEW, + STAGED, + VALID, + INVALID, + DELETED + } + public DmaapObject_Status getStatus() { + return status; + } + + public void setStatus(DmaapObject_Status status) { + this.status = status; + } + + public void setStatus( String val ) { + if ( val == null || val.isEmpty() ) { + this.status = DmaapObject_Status.EMPTY; + } else if (val.compareToIgnoreCase("new") == 0 ) { + this.status = DmaapObject_Status.NEW; + } else if ( val.compareToIgnoreCase("staged" ) == 0) { + this.status = DmaapObject_Status.STAGED; + } else if ( val.compareToIgnoreCase("valid") == 0) { + this.status = DmaapObject_Status.VALID; + } else if ( val.compareToIgnoreCase("invalid") == 0) { + this.status = DmaapObject_Status.INVALID; + } else if ( val.compareToIgnoreCase("deleted") == 0) { + this.status = DmaapObject_Status.DELETED; + } else { + this.status = DmaapObject_Status.INVALID; + } + } + + @ApiModelProperty( hidden=true ) + public boolean isStatusValid() { + if ( this.status == DmaapObject_Status.VALID ) { + return true; + } + return false; + } + + /* + * TODO: get this working so arrays and sub-class within an Object can be logged + * + public String toString() { + return classToString( this ); + } + + private String classToString( Object obj ) { + Field[] fields = obj.getClass().getDeclaredFields(); + StringBuilder res = new StringBuilder( "{"); + boolean first = true; + for ( Field field: fields ) { + logger.info( field.getName() + " toString=" + field.toString() + " toGenericString=" + field.toGenericString()); + if ( first ) { + first = false; + } else { + res.append( ", "); + } + + + field.setAccessible(true); // avoid IllegalAccessException + + + Class<?> t = field.getType(); + + if ( t == String.class ) { + res.append( "\"" ).append( field.getName() ).append( "\": \""); + + try { + res.append(field.get(this)); + } catch ( IllegalAccessException iae) { + res.append( "UNK(iae)"); + } catch (IllegalArgumentException iae2 ) { + res.append( "UNK(iae2)"); + } catch ( NullPointerException npe ) { + res.append( "UNK(npe)"); + } catch ( ExceptionInInitializerError eie ) { + res.append( "UNK(eie)"); + } + res.append( "\""); + } else if ( t == ArrayList.class ){ + res.append( "["); + res.append( classToString( field )); + res.append( "]"); + + } + } + res.append( "}"); + return( res.toString()); + + + } + */ + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/Feed.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/Feed.java new file mode 100644 index 0000000..b3c7332 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/Feed.java @@ -0,0 +1,294 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.nio.charset.StandardCharsets; +import java.util.ArrayList; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.json.simple.*; +import org.json.simple.parser.*; +import org.onap.dmaap.dbcapi.service.DmaapService; + +@XmlRootElement +public class Feed extends DmaapObject { + + private String feedId; + + private String feedName; + private String feedVersion; + private String feedDescription; + private String owner; + private String asprClassification; + private String publishURL; + private String subscribeURL; + private boolean suspended; + private String logURL; + private String formatUuid; + + private ArrayList<DR_Pub> pubs; + private ArrayList<DR_Sub> subs; + + + public Feed() { + this.pubs = new ArrayList<>(); + this.subs = new ArrayList<>(); + this.setStatus( DmaapObject_Status.EMPTY ); + + } + + public Feed( String name, + String version, + String description, + String owner, + String aspr) { + this.feedName = name; + this.feedVersion = version; + this.feedDescription = description; + this.owner = owner; + this.asprClassification = aspr; + this.pubs = new ArrayList<>(); + this.subs = new ArrayList<>(); + this.setStatus( DmaapObject_Status.NEW ); + + } + + // expects a String in JSON format, with known fields to populate Feed object + public Feed ( String json ) { + JSONParser parser = new JSONParser(); + JSONObject jsonObj; + try { + jsonObj = (JSONObject) parser.parse( json ); + } catch ( ParseException pe ) { + logger.error( "Error parsing provisioning data: " + json ); + this.setStatus( DmaapObject_Status.INVALID ); + return; + } + this.setFeedName( (String) jsonObj.get("name")); + + this.setFeedVersion( (String) jsonObj.get("version")); + this.setFeedDescription( (String) jsonObj.get("description")); + this.setOwner( (String) jsonObj.get("publisher")); + + this.setSuspended( (boolean) jsonObj.get("suspend")); + JSONObject links = (JSONObject) jsonObj.get("links"); + String url = (String) links.get("publish"); + this.setPublishURL( url ); + this.setFeedId( url.substring( url.lastIndexOf('/')+1, url.length() )); + logger.info( "feedid="+ this.getFeedId() ); + this.setSubscribeURL( (String) links.get("subscribe") ); + this.setLogURL( (String) links.get("log") ); + JSONObject auth = (JSONObject) jsonObj.get("authorization"); + this.setAsprClassification( (String) auth.get("classification")); + JSONArray pubs = (JSONArray) auth.get( "endpoint_ids"); + int i; + ArrayList<DR_Pub> dr_pub = new ArrayList<>(); + this.subs = new ArrayList<>(); + + for( i = 0; i < pubs.size(); i++ ) { + JSONObject entry = (JSONObject) pubs.get(i); + dr_pub.add( new DR_Pub( "someLocation", + (String) entry.get("id"), + (String) entry.get("password"), + this.getFeedId(), + this.getFeedId() + "." + DR_Pub.nextKey() )); + + } + this.setPubs( dr_pub ); + + this.setStatus( DmaapObject_Status.VALID ); + + } + + + + public boolean isSuspended() { + return suspended; + } + + public void setSuspended(boolean suspended) { + this.suspended = suspended; + } + + public String getSubscribeURL() { + return subscribeURL; + } + + public void setSubscribeURL(String subscribeURL) { + this.subscribeURL = subscribeURL; + } + + public String getFeedId() { + return feedId; + } + + public void setFeedId(String feedId) { + this.feedId = feedId; + } + + public String getFeedName() { + return feedName; + } + + public void setFeedName(String feedName) { + this.feedName = feedName; + } + + public String getFeedVersion() { + return feedVersion; + } + + public void setFeedVersion(String feedVersion) { + this.feedVersion = feedVersion; + } + + public String getFeedDescription() { + return feedDescription; + } + + public void setFeedDescription(String feedDescription) { + this.feedDescription = feedDescription; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public String getAsprClassification() { + return asprClassification; + } + + public void setAsprClassification(String asprClassification) { + this.asprClassification = asprClassification; + } + + public String getPublishURL() { + return publishURL; + } + + public void setPublishURL(String publishURL) { + this.publishURL = publishURL; + } + + public String getLogURL() { + return logURL; + } + + public void setLogURL(String logURL) { + this.logURL = logURL; + } + + + + public String getFormatUuid() { + return formatUuid; + } + + public void setFormatUuid(String formatUuid) { + this.formatUuid = formatUuid; + } + + // returns the Feed object in JSON that conforms to DR Prov Server expectations + public String toProvJSON() { + + String postJSON = String.format("{\"name\": \"%s\", \"version\": \"%s\", \"description\": \"%s\", \"suspend\": %s, \"authorization\": { \"classification\": \"%s\", ", + this.getFeedName(), + this.getFeedVersion(), + this.getFeedDescription(), + this.isSuspended() , + this.getAsprClassification() + ); + int i; + postJSON += "\"endpoint_addrs\": [],\"endpoint_ids\": ["; + String comma = ""; + for( i = 0 ; i < pubs.size(); i++) { + postJSON += String.format(" %s{\"id\": \"%s\",\"password\": \"%s\"}", + comma, + pubs.get(i).getUsername(), + pubs.get(i).getUserpwd() + ) ; + comma = ","; + } + postJSON += "]}}"; + + logger.info( "postJSON=" + postJSON); + return postJSON; + } + + public ArrayList<DR_Pub> getPubs() { + return pubs; + } + + public void setPubs( ArrayList<DR_Pub> pubs) { + this.pubs = pubs; + } + + public ArrayList<DR_Sub> getSubs() { + return subs; + } + + public void setSubs( ArrayList<DR_Sub> subs) { + this.subs = subs; + } + + public byte[] getBytes() { + return toProvJSON().getBytes(StandardCharsets.UTF_8); + } + + public static String getSubProvURL( String feedId ) { + return new DmaapService().getDmaap().getDrProvUrl() + "/subscribe/" + feedId; + } + + @Override + public String toString() { + String rc = String.format ( "Feed: {feedId=%s feedName=%s feedVersion=%s feedDescription=%s owner=%s asprClassification=%s publishURL=%s subscriberURL=%s suspended=%s logURL=%s formatUuid=%s}", + feedId, + feedName, + feedVersion, + feedDescription, + owner, + asprClassification, + publishURL, + subscribeURL, + suspended, + logURL, + formatUuid + + + ); + + for( DR_Pub pub: pubs) { + rc += "\n" + pub.toString(); + } + + for( DR_Sub sub: subs ) { + rc += "\n" + sub.toString(); + } + return rc; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/FqtnType.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/FqtnType.java new file mode 100644 index 0000000..697e9b8 --- /dev/null +++ b/dmaap-bc/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/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/MR_Client.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/MR_Client.java new file mode 100644 index 0000000..0631f07 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/MR_Client.java @@ -0,0 +1,162 @@ +/*- + * ============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.Date; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.onap.dmaap.dbcapi.database.DatabaseClass; + +import io.swagger.annotations.ApiModelProperty; + +@XmlRootElement +public class MR_Client extends DmaapObject { + + @ApiModelProperty( value="a tag indicating a logical deployment site") + private String dcaeLocationName; + @ApiModelProperty( value="the URL for a MR instance - typically in the same dcaeLocation - that this client should use to access the topic") + private String topicURL; + @ApiModelProperty( value="Fully Qualified Topic Name constructed by dbcapi") + private String fqtn; + @ApiModelProperty( value="an AAF Role to be granted an appropriate Permission. If specified, takes precedence over clientIdentity, for backwards compatibility.") + private String clientRole; + @ApiModelProperty( value="one or more actions from the set (\"pub\", \"sub\", \"view\") for which this client needs Permission") + private String[] action; + @ApiModelProperty( value="a unique identifier generated by dbcapi for this client") + private String mrClientId; + @ApiModelProperty( value="an AAF identity to be associated to an appropriate topic Role") + private String clientIdentity; + + + public MR_Client() { + this.mrClientId = DatabaseClass.getNextClientId(); + this.lastMod = new Date(); + this.setLastMod(); + debugLogger.debug( "MR_Client constructor " + this.lastMod ); + + } + + public MR_Client( String dLN, + String f, + String cR, + String[] a ) { + this.dcaeLocationName = dLN; + this.fqtn = f; + this.clientRole = cR; + int i = 0; + + if (a != null) { + this.action = new String[a.length]; + for (String aa : a) { + this.action[i++] = new String(aa); + } + } + this.setStatus( DmaapObject_Status.NEW ); + this.mrClientId = DatabaseClass.getNextClientId(); + this.setLastMod(); + debugLogger.debug( "MR_Client constructor w initialization " + this.lastMod ); + } + + public String getDcaeLocationName() { + return dcaeLocationName; + } + + public void setDcaeLocationName(String dcaeLocationName) { + this.dcaeLocationName = dcaeLocationName; + } + + public String getFqtn() { + return fqtn; + } + + public void setFqtn(String fqtn) { + this.fqtn = fqtn; + } + + public String getClientRole() { + return clientRole; + } + + public void setClientRole(String clientRole) { + this.clientRole = clientRole; + } + + public String[] getAction() { + return action; + } + + public void setAction(String[] action) { + this.action = action; + } + + @ApiModelProperty( hidden=true ) + public boolean isPublisher() { + return hasAction( "pub"); + } + @ApiModelProperty( hidden=true ) + public boolean isSubscriber() { + return hasAction( "sub"); + } + + public boolean hasAction( String val ) { + for (String s: this.action) { + if ( s!= null && s.equals(val)) { + return true; + } + } + return false; + } + public String getMrClientId() { + return mrClientId; + } + + public void setMrClientId(String mrClientId) { + this.mrClientId = mrClientId; + } + + + + public String getTopicURL() { + return topicURL; + } + + public void setTopicURL(String topicURL) { + this.topicURL = topicURL; + } + + public String getClientIdentity() { + return clientIdentity; + } + + public void setClientIdentity(String clientIdentity) { + this.clientIdentity = clientIdentity; + } + public boolean hasClientIdentity() { + if ( this.clientIdentity == null || this.clientIdentity.isEmpty() ) { + return false; + } else { + return true; + } + } + + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/MR_Cluster.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/MR_Cluster.java new file mode 100644 index 0000000..06b6194 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/MR_Cluster.java @@ -0,0 +1,235 @@ +/*- + * ============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 javax.xml.bind.annotation.XmlRootElement; + +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.DmaapTimestamp; + + + +@XmlRootElement +public class MR_Cluster extends DmaapObject { + + private String dcaeLocationName; + private String fqdn; + private DmaapTimestamp lastMod; + private String topicProtocol; + private String topicPort; + private String replicationGroup; + private String sourceReplicationPort; + private String targetReplicationPort; + + + // TODO: make this a system property + private static String defaultTopicProtocol; + private static String defaultTopicPort; + private static String defaultReplicationGroup; + private static String defaultSourceReplicationPort; + private static String defaultTargetReplicationPort; + + private static void setDefaults() { + /* boolean been_here = false; + if ( been_here ) { + return; + } */ + DmaapConfig dc = (DmaapConfig)DmaapConfig.getConfig(); + defaultTopicProtocol = dc.getProperty("MR.TopicProtocol", "https"); + defaultTopicPort = dc.getProperty( "MR.TopicPort", "3905"); + defaultReplicationGroup = dc.getProperty( "MR.ReplicationGroup", "" ); + defaultSourceReplicationPort = dc.getProperty( "MR.SourceReplicationPort", "2181"); + defaultTargetReplicationPort = dc.getProperty( "MR.TargetReplicationPort", "9092"); + // been_here = true; + } + + + public MR_Cluster() { + setDefaults(); + this.topicProtocol = defaultTopicProtocol; + this.topicPort = defaultTopicPort; + this.replicationGroup = null; + this.sourceReplicationPort = defaultSourceReplicationPort; + this.targetReplicationPort = defaultTargetReplicationPort; + this.lastMod = new DmaapTimestamp(); + this.lastMod.mark(); + + debugLogger.debug( "MR_Cluster constructor " + this.lastMod ); + + } + + // new style constructor + public MR_Cluster( String dLN, + String f, + String prot, + String port) { + setDefaults(); + this.dcaeLocationName = dLN; + this.fqdn = f; + + if ( prot == null || prot.isEmpty() ) { + this.topicProtocol = defaultTopicProtocol; + } else { + this.topicProtocol = prot; + } + if ( port == null || port.isEmpty() ) { + this.topicPort = defaultTopicPort; + } else { + this.topicPort = port; + } + + this.replicationGroup = defaultReplicationGroup; + this.sourceReplicationPort = defaultSourceReplicationPort; + this.targetReplicationPort = defaultTargetReplicationPort; + + this.lastMod = new DmaapTimestamp(); + this.lastMod.mark(); + + debugLogger.debug( "MR_Cluster constructor w initialization complete" + this.lastMod.getVal() ); + } + + public MR_Cluster( String dLN, + String f, + String prot, + String port, + String repGroup, + String sourceRepPort, + String targetRepPort ) { + setDefaults(); + this.dcaeLocationName = dLN; + this.fqdn = f; + + if ( prot == null || prot.isEmpty() ) { + this.topicProtocol = defaultTopicProtocol; + } else { + this.topicProtocol = prot; + } + if ( port == null || port.isEmpty() ) { + this.topicPort = defaultTopicPort; + } else { + this.topicPort = port; + } + if ( repGroup == null || repGroup.isEmpty() ) { + this.replicationGroup = defaultReplicationGroup; + } else { + this.replicationGroup = repGroup; + } + if ( sourceRepPort == null || sourceRepPort.isEmpty()) { + this.sourceReplicationPort = defaultSourceReplicationPort; + } else { + this.sourceReplicationPort = sourceRepPort; + } + if ( targetRepPort == null || targetRepPort.isEmpty()) { + this.targetReplicationPort = defaultTargetReplicationPort; + } else { + this.targetReplicationPort = targetRepPort; + } + + this.lastMod = new DmaapTimestamp(); + this.lastMod.mark(); + + debugLogger.debug( "MR_Cluster constructor w initialization complete" + this.lastMod.getVal() ); + } + public String getDcaeLocationName() { + return dcaeLocationName; + } + + public void setDcaeLocationName(String dcaeLocationName) { + this.dcaeLocationName = dcaeLocationName; + } + + public String getFqdn() { + return fqdn; + } + + public void setFqdn(String fqdn) { + this.fqdn = fqdn; + } + + + public String getTopicProtocol() { + return topicProtocol; + } + + public void setTopicProtocol(String topicProtocol) { + this.topicProtocol = topicProtocol; + } + + public String getTopicPort() { + return topicPort; + } + + public void setTopicPort(String topicPort) { + this.topicPort = topicPort; + } + + public String getReplicationGroup() { + return replicationGroup; + } + + public void setReplicationGroup(String replicationGroup) { + this.replicationGroup = replicationGroup; + } + + + + + public String getSourceReplicationPort() { + return sourceReplicationPort; + } + + + + public void setSourceReplicationPort(String sourceReplicationPort) { + this.sourceReplicationPort = sourceReplicationPort; + } + + + + public String getTargetReplicationPort() { + return targetReplicationPort; + } + + + + public void setTargetReplicationPort(String targetReplicationPort) { + this.targetReplicationPort = targetReplicationPort; + } + + + + public String genTopicURL(String overideFqdn, String topic) { + + StringBuilder str = new StringBuilder( topicProtocol ); + str.append("://") + .append( overideFqdn != null ? overideFqdn : fqdn) + .append(":") + .append(topicPort) + .append("/events/") + .append(topic); + + return str.toString(); + + + } + + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/MirrorMaker.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/MirrorMaker.java new file mode 100644 index 0000000..098524c --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/MirrorMaker.java @@ -0,0 +1,165 @@ +/*- + * ============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 org.onap.dmaap.dbcapi.service.MirrorMakerService; + +import java.util.ArrayList; + +public class MirrorMaker extends DmaapObject { + + private String sourceCluster; + private String targetCluster; + private String mmName; + private ArrayList<String> topics; //re-using this var name for backwards DB compatibility + + public MirrorMaker(){ + + } + + public MirrorMaker(String source, String target, int i) { + initMM( source, target ); + // original mm names did not have any index, so leave off index 0 for + // backwards compatibility + if ( i != 0 ) { + String n = this.getMmName() + "_" + i; + this.setMmName(n); + } + } + + public MirrorMaker(String source, String target) { + initMM( source, target ); + } + + private void initMM(String source, String target) { + sourceCluster = source; + targetCluster = target; + mmName = genKey(source, target); + topics = new ArrayList<>(); + + } + + public String getMmName() { + return mmName; + } + + public void setMmName(String mmName) { + this.mmName = mmName; + } + + // returns the JSON for MM message containing which Topics to replicate + /* + * example: + * + { + "messageID":"12349", + "updateWhiteList": + { + "name":"Global1ToGlobal3", + "whitelist":"org.openecomp.dcae.topic1,org.openecomp.dcae.topic2" + } + } + */ + public String getWhitelistUpdateJSON() { + StringBuilder str = new StringBuilder( "{ \"messageID\": \"" + MirrorMakerService.genTransactionId() + "\", \"updateWhiteList\": {" ); + str.append( " \"name\": \"" + this.getMmName() + "\", \"whitelist\": \"" ); + int numTargets = 0; + + for (String rv: topics) { + if ( numTargets > 0 ) { + str.append( ","); + } + str.append( rv ); + numTargets++; + } + str.append( "\" } }" ); + + return str.toString(); + } + + // returns the JSON for MM message indicating that a MM agent is needed between two clusters + // example: + /* + * + { + "messageID":"12345" + "createMirrorMaker": + { + "name":"Global1ToGlobal2", + "consumer":"192.168.0.1:2181", + "producer":"192.168.0.2:9092" + } + } + */ + public String createMirrorMaker( String consumerPort, String producerPort ) { + StringBuilder str = new StringBuilder( "{ \"messageID\": \"" + MirrorMakerService.genTransactionId() + "\", \"createMirrorMaker\": {" ); + str.append( " \"name\": \"" + this.getMmName() + "\", " ); + str.append( " \"consumer\": \"" + this.sourceCluster + ":" + consumerPort + "\", " ); + str.append( " \"producer\": \"" + this.targetCluster + ":" + producerPort + "\", "); + + str.append( " \"numStreams\": \"10\" } }" ); + + return str.toString(); + } + + public String getSourceCluster() { + return sourceCluster; + } + + public void setSourceCluster(String sourceCluster) { + this.sourceCluster = sourceCluster; + } + + public String getTargetCluster() { + return targetCluster; + } + + public void setTargetCluster(String targetCluster) { + this.targetCluster = targetCluster; + } + + public ArrayList<String> getTopics() { + return topics; + } + + public void setTopics(ArrayList<String> topics) { + this.topics = topics; + } + + public static String genKey( String s, String t) { + StringBuilder str = new StringBuilder(); + str.append(s); + str.append("-To-"); + str.append(t); + return str.toString(); + } + + public void addTopic( String topic ) { + if ( ! topics.contains(topic)) { + topics.add(topic); + } + logger.info( "Mirrormaker.addTopic: topic=" + topic + " . Now have " + topics.size() + " topics" ); + } + + public int getTopicCount() { + return topics.size(); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/ReplicationType.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/ReplicationType.java new file mode 100644 index 0000000..5d5b6c6 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/ReplicationType.java @@ -0,0 +1,109 @@ +/*- + * ============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 ReplicationType { + REPLICATION_NOT_SPECIFIED(0), + REPLICATION_NONE(1), + REPLICATION_EDGE_TO_CENTRAL(10), + REPLICATION_EDGE_TO_CENTRAL_TO_GLOBAL(110), + REPLICATION_CENTRAL_TO_EDGE(20), + REPLICATION_CENTRAL_TO_GLOBAL(21), + REPLICATION_GLOBAL_TO_CENTRAL(30), + REPLICATION_GLOBAL_TO_CENTRAL_TO_EDGE(120), + REPLICATION_EDGE_TO_FQDN(40), + REPLICATION_FQDN_TO_EDGE(41), + REPLICATION_FQDN_TO_GLOBAL(50), + REPLICATION_GLOBAL_TO_FQDN(51), + REPLICATION_EDGE_TO_FQDN_TO_GLOBAL(130), + REPLICATION_GLOBAL_TO_FQDN_TO_EDGE (140); + + private int value; + private static Map map = new HashMap<>(); + + private ReplicationType(int value) { + this.value = value; + } + + static { + for (ReplicationType repType : ReplicationType.values()) { + map.put(repType.value, repType); + } + } + + public static ReplicationType valueOf(int repType) { + return (ReplicationType) map.get(repType); + } + + public int getValue() { + return value; + } + + static public ReplicationType Validator( String input ){ + + ReplicationType t; + try { + t = ReplicationType.valueOf( input ); + } catch ( IllegalArgumentException e ) { + t = REPLICATION_NOT_SPECIFIED; + } + return t; + } + + public boolean involvesGlobal() { + + + if ( ( this.compareTo(REPLICATION_CENTRAL_TO_GLOBAL) == 0 ) || + ( this.compareTo(REPLICATION_GLOBAL_TO_CENTRAL) == 0 ) || + ( this.compareTo(REPLICATION_EDGE_TO_CENTRAL_TO_GLOBAL) == 0 ) || + ( this.compareTo(REPLICATION_GLOBAL_TO_CENTRAL_TO_EDGE) == 0 ) || + ( this.compareTo(REPLICATION_EDGE_TO_FQDN_TO_GLOBAL) == 0 ) || + ( this.compareTo(REPLICATION_GLOBAL_TO_FQDN_TO_EDGE) == 0 ) || + ( this.compareTo(REPLICATION_FQDN_TO_GLOBAL) == 0 ) || + ( this.compareTo(REPLICATION_GLOBAL_TO_FQDN) == 0 ) ) { + return true; + } + return false; + } + + public boolean involvesFQDN() { + if ( + ( this.compareTo(REPLICATION_EDGE_TO_FQDN) == 0 ) || + ( this.compareTo(REPLICATION_EDGE_TO_FQDN_TO_GLOBAL) == 0 ) || + ( this.compareTo(REPLICATION_GLOBAL_TO_FQDN_TO_EDGE) == 0 ) || + ( this.compareTo(REPLICATION_FQDN_TO_GLOBAL) == 0 ) || + ( this.compareTo(REPLICATION_GLOBAL_TO_FQDN) == 0 ) || + ( this.compareTo(REPLICATION_FQDN_TO_EDGE) == 0 ) + ) { + return true; + } + return false; + } + + + +}
\ No newline at end of file diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java new file mode 100644 index 0000000..d2a9077 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/model/Topic.java @@ -0,0 +1,352 @@ +/*- + * ============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 com.google.common.base.Objects; +import io.swagger.annotations.ApiModelProperty; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import javax.xml.bind.annotation.XmlRootElement; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.onap.dmaap.dbcapi.service.DmaapService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + + +@XmlRootElement +public class Topic extends DmaapObject { + + @ApiModelProperty( value="Fully Qualified Topic Name constructed by dbcapi, following the rules for `fqtnStyle`") + private String fqtn; + @ApiModelProperty( value="the short name used by humans, and utilized to construct the `FQTN`") + private String topicName; + @ApiModelProperty( value="a description of what this Topic is used for") + private String topicDescription; + private String tnxEnabled; + @ApiModelProperty( value="a label used to identify who requested this `Topic` to be provisioned. In the future this " + + "may be an AAF Identity.") + private String owner; + @ApiModelProperty( value="a reference to an identifier that describes a data format used for this `Topic`") + private String formatUuid; + @ApiModelProperty( value="An indicator for how this `Topic` should be replicated when there are more than one `MR_Cluster` instances") + private ReplicationType replicationCase; + @ApiModelProperty( value="the URL of an outside MR instance") + private String globalMrURL; // optional: URL of global MR to replicate to/from + @ApiModelProperty( value="the construction rule for the `fqtn` field") + private FqtnType fqtnStyle; + @ApiModelProperty( value="a hook for any versioning needed for managing a `Topic` over time") + private String version; + @ApiModelProperty( value="the kafka attribute for specifying the number of partitions") + private String partitionCount; + @ApiModelProperty( value="the kafka attribute for specifying replication within an `MR_Cluster` instance") + private String replicationCount; + @ApiModelProperty( value="a value generated by dbcapi, this AAF Role has permission to publish to this `Topic`") + private String publisherRole; + @ApiModelProperty( value="a value generated by dbcapi, this AAF Role has permission to subscribe to this `Topic`") + private String subscriberRole; + + @ApiModelProperty( value="an array of `MR_Client` objects associated to this `Topic`") + private List<MR_Client> clients; + + + + private static Dmaap dmaap = new DmaapService().getDmaap(); + + private static String defaultPartitionCount; + private static String defaultReplicationCount; + + // 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 String genFqtn( ) { + DmaapConfig dc = (DmaapConfig)DmaapConfig.getConfig(); + String projectId = dc.getProperty("MR.projectID", "99999"); + CharSequence signal = "."; + String ret; + if ( this.getTopicName().contains( signal )) { + // presence of a dot indicates the name is already fully qualified + ret = this.getTopicName(); + } else { + // 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; + } + + + + public Topic() { + super(); + this.clients = new ArrayList<>(); + this.lastMod = new Date(); + this.replicationCase = ReplicationType.Validator("none"); + this.setLastMod(); + logger.debug( "Topic constructor " + this.lastMod ); + } + public Topic(String fqtn, String topicName, String topicDescription, + String tnxEnabled, String owner) { + super(); + this.fqtn = fqtn; + this.topicName = topicName; + this.topicDescription = topicDescription; + this.tnxEnabled = tnxEnabled; + this.owner = owner; + this.init(); + this.setLastMod(); + logger.debug( "Topic constructor w args " + this.getLastMod() ); + } + + public Topic init() { + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + + defaultPartitionCount = p.getProperty( "MR.partitionCount", "2"); + defaultReplicationCount = p.getProperty( "MR.replicationCount", "1"); + + this.setStatus( DmaapObject_Status.NEW ); + this.replicationCase = ReplicationType.Validator("none"); + this.fqtnStyle = FqtnType.Validator("none"); + this.setPartitionCount( defaultPartitionCount ); + this.setReplicationCount( defaultReplicationCount ); + + return this; + } + + // expects a String in JSON format, with known fields to populate Topic object + public Topic ( String json ) { + JSONParser parser = new JSONParser(); + JSONObject jsonObj; + try { + jsonObj = (JSONObject) parser.parse( json ); + } catch ( ParseException pe ) { + logger.error( "Error parsing provisioning data: " + json ); + this.setStatus( DmaapObject_Status.INVALID ); + return; + } + this.setFqtn( (String) jsonObj.get( "fqtn" ) ); + this.setTopicName( (String) jsonObj.get( "topicName" ) ); + this.setTopicDescription( (String) jsonObj.get( "topicDescription" )); + this.setOwner( (String) jsonObj.get( "owner" ) ); + this.setStatus( (String) jsonObj.get( "status" ) ); + this.setReplicationCase( ReplicationType.Validator( (String) jsonObj.get( "replicationCase" ) )); + this.setFqtnStyle( FqtnType.Validator( (String) jsonObj.get( "fqtnStyle" ) ) ); + this.setPartitionCount( (String) jsonObj.get("partitionCount")); + + } + public String getFqtn() { + return fqtn; + } + public void setFqtn(String fqtn) { + this.fqtn = fqtn; + } + public String getTopicName() { + return topicName; + } + public void setTopicName(String topicName) { + this.topicName = topicName; + } + public String getTopicDescription() { + return topicDescription; + } + public void setTopicDescription(String topicDescription) { + this.topicDescription = topicDescription; + } + + public String getTnxEnabled() { + return tnxEnabled; + } + public void setTnxEnabled(String tnxEnabled) { + this.tnxEnabled = tnxEnabled; + } + public String getOwner() { + return owner; + } + public void setOwner(String owner) { + this.owner = owner; + } + public String getPartitionCount() { + return partitionCount; + } + public void setPartitionCount(String partitions) { + this.partitionCount = partitions; + } + public String getReplicationCount() { + return replicationCount; + } + public void setReplicationCount(String replicationCount) { + this.replicationCount = replicationCount; + } + + + public void setClients(List<MR_Client> clients) { + this.clients = clients; + } + + public List<MR_Client> getClients() { + return clients; + } + + @ApiModelProperty( hidden=true ) + public int getNumClients() { + if ( this.clients == null ) { + return 0; + } + return this.clients.size(); + } + + + + + public String getFormatUuid() { + return formatUuid; + } + + + + public void setFormatUuid(String formatUuid) { + this.formatUuid = formatUuid; + } + + + public ReplicationType getReplicationCase() { + return replicationCase; + } + + + 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; + } + + + + public void setGlobalMrURL(String globalMrURL) { + this.globalMrURL = globalMrURL; + } + + + + public String getVersion() { + return version; + } + + + + public void setVersion(String version) { + this.version = version; + } + + + + public String getPublisherRole() { + return publisherRole; + } + public void setPublisherRole(String publisherRole) { + this.publisherRole = publisherRole; + } + public String getSubscriberRole() { + return subscriberRole; + } + public void setSubscriberRole(String subscriberRole) { + this.subscriberRole = subscriberRole; + } + public String toProvJSON() { + StringBuilder str = new StringBuilder(); + str.append("{ \"topicName\": \""); + str.append( this.getFqtn() ); + str.append( "\", \"topicDescription\": \""); + str.append( this.getTopicDescription()); + str.append( "\", \"partitionCount\": \""); + str.append( this.getPartitionCount()); + str.append( "\", \"replicationCount\": \""); + str.append( this.getReplicationCount()); + str.append( "\" } "); + + logger.info( str.toString() ); + return str.toString(); + } + @ApiModelProperty( hidden=true ) + public byte[] getBytes() { + return toProvJSON().getBytes(StandardCharsets.UTF_8); + } + + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + Topic topic = (Topic) o; + return Objects.equal(fqtn, topic.fqtn) && + Objects.equal(topicName, topic.topicName) && + Objects.equal(tnxEnabled, topic.tnxEnabled) && + Objects.equal(owner, topic.owner); + } + + @Override + public int hashCode() { + return Objects.hashCode(fqtn, topicName, tnxEnabled, owner); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/AAFAuthenticationFilter.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/AAFAuthenticationFilter.java new file mode 100644 index 0000000..d8a7302 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/AAFAuthenticationFilter.java @@ -0,0 +1,141 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.resources; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpStatus; +import org.onap.aaf.cadi.PropAccess; +import org.onap.aaf.cadi.filter.CadiFilter; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class AAFAuthenticationFilter extends BaseLoggingClass implements Filter{ + + static final String CADI_PROPERTIES = "cadi.properties"; + static final String CADI_AUTHN_FLAG = "enableCADI"; + + private boolean isCadiEnabled; + private CadiFilter cadiFilter; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + DmaapConfig dmaapConfig = getConfig(); + String flag = dmaapConfig.getProperty(CADI_AUTHN_FLAG, "false"); + isCadiEnabled = "true".equalsIgnoreCase(flag); + initCadi(dmaapConfig); + } + + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + + if(isCadiEnabled) { + cadiFilter.doFilter(servletRequest, servletResponse, filterChain); + updateResponseBody((HttpServletResponse)servletResponse); + } else { + filterChain.doFilter(servletRequest, servletResponse); + } + } + + private void updateResponseBody(HttpServletResponse httpResponse) + throws IOException { + if(httpResponse.getStatus() == 401) { + String errorMsg = "invalid or no credentials provided"; + errorLogger.error(errorMsg); + httpResponse.setContentType("application/json"); + httpResponse.setCharacterEncoding("UTF-8"); + httpResponse.getWriter().print(buildErrorResponse(errorMsg)); + httpResponse.getWriter().flush(); + } + } + + private String buildErrorResponse(String msg) { + try { + return new ObjectMapper().writeValueAsString(new ApiError(HttpStatus.UNAUTHORIZED_401, msg, "Authentication")); + } catch (JsonProcessingException e) { + logger.warn("Could not serialize response entity: " + e.getMessage()); + return ""; + } + } + + + @Override + public void destroy() { + //nothing to cleanup + } + + private void initCadi(DmaapConfig dmaapConfig) throws ServletException { + if(isCadiEnabled) { + try { + String cadiPropertiesFile = dmaapConfig.getProperty(CADI_PROPERTIES); + if(cadiPropertiesFile != null && !cadiPropertiesFile.isEmpty()) { + cadiFilter = new CadiFilter(loadCadiProperties(cadiPropertiesFile)); + } else { + throw new ServletException("Cannot initialize CADI filter.CADI properties not available."); + } + } catch (ServletException e) { + errorLogger.error("CADI init error :" + e.getMessage()); + throw e; + } + } + } + + private PropAccess loadCadiProperties(String propertiesFilePath) throws ServletException { + try { + Properties props = new Properties(); + props.load(new FileInputStream(propertiesFilePath)); + return new PropAccess(props); + } catch (IOException e) { + String msg = "Could not load CADI properties file: " + propertiesFilePath; + errorLogger.error(msg, e); + throw new ServletException(msg); + } + } + + DmaapConfig getConfig() { + return (DmaapConfig) DmaapConfig.getConfig(); + } + + //tests only + CadiFilter getCadiFilter() { + return cadiFilter; + } + + void setCadiFilter(CadiFilter cadiFilter) { + this.cadiFilter = cadiFilter; + } + + boolean isCadiEnabled() { + return isCadiEnabled; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/AAFAuthorizationFilter.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/AAFAuthorizationFilter.java new file mode 100644 index 0000000..779f71b --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/AAFAuthorizationFilter.java @@ -0,0 +1,115 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.resources; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.IOException; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.eclipse.jetty.http.HttpStatus; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.service.DmaapService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.PermissionBuilder; + +public class AAFAuthorizationFilter extends BaseLoggingClass implements Filter { + + static final String CADI_AUTHZ_FLAG = "enableCADI"; + private boolean isCadiEnabled = false; + + private PermissionBuilder permissionBuilder; + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + DmaapConfig dmaapConfig = getConfig(); + isCadiEnabled = "true".equalsIgnoreCase(dmaapConfig.getProperty(CADI_AUTHZ_FLAG, "false")); + if(isCadiEnabled) { + permissionBuilder = new PermissionBuilder(dmaapConfig, getDmaapService()); + } + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) + throws IOException, ServletException { + + if(isCadiEnabled) { + HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; + permissionBuilder.updateDmaapInstance(); + String permission = permissionBuilder.buildPermission(httpRequest); + + if (httpRequest.isUserInRole(permission)) { + logger.info("User " + httpRequest.getUserPrincipal().getName() + " has permission " + permission); + filterChain.doFilter(servletRequest, servletResponse); + } else { + String msg = "User " + httpRequest.getUserPrincipal().getName() + " does not have permission " + permission; + errorLogger.error(msg); + ((HttpServletResponse) servletResponse).setStatus(HttpStatus.FORBIDDEN_403); + servletResponse.setContentType("application/json"); + servletResponse.setCharacterEncoding("UTF-8"); + servletResponse.getWriter().print(buildErrorResponse(msg)); + servletResponse.getWriter().flush(); + } + } else { + filterChain.doFilter(servletRequest, servletResponse); + } + } + + @Override + public void destroy() { + //nothing to cleanup + } + + DmaapConfig getConfig() { + return (DmaapConfig) DmaapConfig.getConfig(); + } + + DmaapService getDmaapService() { + return new DmaapService(); + } + + private String buildErrorResponse(String msg) { + try { + return new ObjectMapper().writeValueAsString(new ApiError(HttpStatus.FORBIDDEN_403, msg, "Authorization")); + } catch (JsonProcessingException e) { + logger.warn("Could not serialize response entity: " + e.getMessage()); + return ""; + } + } + + PermissionBuilder getPermissionBuilder() { + return permissionBuilder; + } + + void setPermissionBuilder(PermissionBuilder permissionBuilder) { + this.permissionBuilder = permissionBuilder; + } + + void setCadiEnabled(boolean cadiEnabled) { + isCadiEnabled = cadiEnabled; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/Authorization.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/Authorization.java new file mode 100644 index 0000000..e8b05c6 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/Authorization.java @@ -0,0 +1,35 @@ +/*- + * ============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.resources; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.annotation.ElementType; + +import javax.ws.rs.NameBinding; + +// @Authorization annotation +@NameBinding +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.METHOD, ElementType.TYPE}) +public @interface Authorization { + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/AuthorizationFilter.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/AuthorizationFilter.java new file mode 100644 index 0000000..32e8845 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/AuthorizationFilter.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.resources; + +import javax.ws.rs.container.ContainerRequestContext; +import javax.ws.rs.container.ContainerRequestFilter; + +import org.onap.dmaap.dbcapi.authentication.AuthenticationErrorException; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.service.ApiService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + + +@Authorization +public class AuthorizationFilter extends BaseLoggingClass implements ContainerRequestFilter { + + private static final String AAF_CADI_FLAG = "enableCADI"; + private final ResponseBuilder responseBuilder = new ResponseBuilder(); + private final boolean isCadiEnabled; + + + public AuthorizationFilter() { + DmaapConfig dmaapConfig = (DmaapConfig) DmaapConfig.getConfig(); + String flag = dmaapConfig.getProperty(AAF_CADI_FLAG, "false"); + isCadiEnabled = "true".equalsIgnoreCase(flag); + } + + @Override + public void filter(ContainerRequestContext requestContext) { + + if(!isCadiEnabled) { + ApiService apiResp = new ApiService() + .setAuth(requestContext.getHeaderString("Authorization")) + .setUriPath(requestContext.getUriInfo().getPath()) + .setHttpMethod(requestContext.getMethod()) + .setRequestId(requestContext.getHeaderString("X-ECOMP-RequestID")); + + try { + apiResp.checkAuthorization(); + } catch (AuthenticationErrorException ae) { + errorLogger.error("Error", ae); + requestContext.abortWith(responseBuilder.unauthorized(apiResp.getErr().getMessage())); + } catch (Exception e) { + errorLogger.error("Error", e); + requestContext.abortWith(responseBuilder.unavailable()); + } + } + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java new file mode 100644 index 0000000..299c48f --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/BridgeResource.java @@ -0,0 +1,191 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright (C) 2018 IBM. + * ================================================================================ + * 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.resources; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.BrTopic; +import org.onap.dmaap.dbcapi.model.MirrorMaker; +import org.onap.dmaap.dbcapi.service.MirrorMakerService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; + +@Path("/bridge") +@Api( value= "bridge", description = "Endpoint for retreiving MR Bridge metrics" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class BridgeResource extends BaseLoggingClass { + + private MirrorMakerService mmService = new MirrorMakerService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + + @GET + @ApiOperation( value = "return BrTopic details", + 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 = BrTopic.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) +}) + public Response getBridgedTopics(@QueryParam("mmagent") String mmagent, + @QueryParam("detail") Boolean detailFlag ){ + + if ( mmagent == null ) { + return responseBuilder.success(getMMcounts(Boolean.TRUE.equals(detailFlag))); + + } + logger.info( "getBridgeTopics():" + " mmagent=" + mmagent); + + if ( ! Boolean.TRUE.equals(detailFlag)) { + BrTopic brTopic = new BrTopic(); + + // get topics between 2 bridged locations + + MirrorMaker mm = mmService.getMirrorMaker(mmagent); + if ( mm == null ) { + return responseBuilder.notFound(); + } + + brTopic.setTopicCount( mm.getTopicCount() ); + brTopic.setBrSource( mm.getSourceCluster()); + brTopic.setBrTarget( mm.getTargetCluster()); + brTopic.setMmAgentName(mm.getMmName()); + + logger.info( "topicCount [2 locations]: " + brTopic.getTopicCount() ); + + return responseBuilder.success(brTopic); + } else { + logger.info( "getBridgeTopics() detail:" + " mmagent=" + mmagent); + // get topics between 2 bridged locations + MirrorMaker mm = mmService.getMirrorMaker(mmagent); + if ( mm == null ) { + return responseBuilder.notFound(); + } + + return responseBuilder.success(mm); + } + } + + private BrTopic[] getMMcounts( Boolean showDetail ) { + + List<String> mmList = mmService.getAllMirrorMakers(); + int s = 1; + if ( showDetail ) { + s = mmList.size() + 1; + } + BrTopic[] brTopic = new BrTopic[s]; + + int totCnt = 0; + s = 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; + if (showDetail && mm!=null) { + brTopic[s] = new BrTopic(); + brTopic[s].setBrSource( mm.getSourceCluster()); + brTopic[s].setBrTarget(mm.getTargetCluster()); + brTopic[s].setMmAgentName(mm.getMmName()); + brTopic[s].setTopicCount(mm.getTopicCount()); + s++; + } + } + + logger.info( "topicCount [all locations]: " + totCnt ); + brTopic[s] = new BrTopic(); + brTopic[s].setBrSource("all"); + brTopic[s].setBrTarget("all"); + brTopic[s].setMmAgentName("n/a"); + brTopic[s].setTopicCount(totCnt); + return brTopic; + } + + @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." + + "If split param is true, spread whitelist over smaller mmagents.", + response = MirrorMaker.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = BrTopic.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response putBridgedTopics(@QueryParam("mmagent") String mmagent, + @QueryParam("refresh") Boolean refreshFlag, + @QueryParam("split") Boolean splitFlag, + MirrorMaker newBridge ){ + logger.info( "putBridgeTopics() mmagent:" + mmagent ); + + if ( mmagent != null ) { // put topics between 2 bridged locations + + MirrorMaker mm = mmService.getMirrorMaker(mmagent); + if ( mm == null ) { + return responseBuilder.notFound(); + } + + if ( splitFlag != null && splitFlag == true ) { + mm = mmService.splitMM( mm ); + } else if ( refreshFlag == null || refreshFlag == false ) { + logger.info( "setting whitelist from message body containing mmName=" + newBridge.getMmName()); + if ( ! mmagent.equals(newBridge.getMmName()) ){ + logger.error( "mmagent query param does not match mmName in body"); + return responseBuilder.error(new ApiError(BAD_REQUEST.getStatusCode(), + "mmagent query param does not match mmName in body")); + } + mm.setTopics( newBridge.getTopics() ); + } else { + logger.info( "refreshing whitelist from memory"); + } + mmService.updateMirrorMaker(mm); + return responseBuilder.success(mm); + } + + else { + logger.error( "mmagent is required for PUT"); + return responseBuilder.error(new ApiError(BAD_REQUEST.getStatusCode(), "mmagent is required for PUT")); + } + + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DR_NodeResource.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DR_NodeResource.java new file mode 100644 index 0000000..f001136 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DR_NodeResource.java @@ -0,0 +1,172 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcae + * ================================================================================ + * 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.resources; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DR_Node; +import org.onap.dmaap.dbcapi.service.DR_NodeService; + +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static javax.ws.rs.core.Response.Status.NO_CONTENT; + +@Path("/dr_nodes") +@Api( value= "dr_nodes", description = "Endpoint for a Data Router Node server" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class DR_NodeResource extends BaseLoggingClass { + + private DR_NodeService dr_nodeService = new DR_NodeService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); + + @GET + @ApiOperation( value = "return DR_Node details", + notes = "Returns array of `DR_Node` object array. Need to add filter by dcaeLocation.", + response = DR_Node.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Node.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response getDr_Nodes() { + List<DR_Node> nodes = dr_nodeService.getAllDr_Nodes(); + + GenericEntity<List<DR_Node>> list = new GenericEntity<List<DR_Node>>(nodes) { + }; + return responseBuilder.success(list); + } + + @POST + @ApiOperation( value = "return DR_Node details", + notes = "create a `DR_Node` in a *dcaeLocation*. Note that multiple `DR_Node`s may exist in the same `dcaeLocation`.", + response = DR_Node.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Node.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addDr_Node(DR_Node node) { + + ApiError apiError = new ApiError(); + + try { + checker.required( "dcaeLocation", node.getDcaeLocationName()); + checker.required( "fqdn", node.getFqdn()); + } catch ( RequiredFieldException rfe ) { + return responseBuilder.error(new ApiError(BAD_REQUEST.getStatusCode(), + "missing required field", "dcaeLocation, fqdn")); + } + DR_Node nNode = dr_nodeService.addDr_Node(node, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(nNode); + } + return responseBuilder.error(apiError); + } + + @PUT + @ApiOperation( value = "return DR_Node details", + notes = "Update a single `DR_Node` object.", + response = DR_Node.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Node.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{fqdn}") + public Response updateDr_Node(@PathParam("fqdn") String name, DR_Node node) { + + ApiError apiError = new ApiError(); + + try { + checker.required( "dcaeLocation", node.getDcaeLocationName()); + checker.required( "fqdn", node.getFqdn()); + } catch ( RequiredFieldException rfe ) { + return responseBuilder.error(new ApiError(BAD_REQUEST.getStatusCode(), + "missing required field", "dcaeLocation, fqdn")); + } + node.setFqdn(name); + DR_Node nNode = dr_nodeService.updateDr_Node(node, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(nNode); + } + return responseBuilder.error(apiError); + } + + @DELETE + @ApiOperation( value = "No Content", + notes = "Delete a single `DR_Node` object.", + response = DR_Node.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = DR_Node.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{fqdn}") + public Response deleteDr_Node( + @PathParam("fqdn") String name){ + + + ApiError apiError = new ApiError(); + + dr_nodeService.removeDr_Node(name, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(NO_CONTENT.getStatusCode(), null); + } + return responseBuilder.error(apiError); + } + + @GET + @ApiOperation( value = "return DR_Node details", + notes = "Retrieve a single `DR_Node` object.", + response = DR_Node.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Node.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{fqdn}") + public Response get(@PathParam("fqdn") String name) { + + ApiError apiError = new ApiError(); + + DR_Node nNode = dr_nodeService.getDr_Node( name, apiError ); + if (apiError.is2xx()) { + return responseBuilder.success(nNode); + } + return responseBuilder.error(apiError); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DR_PubResource.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DR_PubResource.java new file mode 100644 index 0000000..f512124 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DR_PubResource.java @@ -0,0 +1,252 @@ +/*- + * ============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.resources; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +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.Feed; +import org.onap.dmaap.dbcapi.service.DR_PubService; +import org.onap.dmaap.dbcapi.service.FeedService; + + +@Path("/dr_pubs") +@Api( value= "dr_pubs", description = "Endpoint for a Data Router client that implements a Publisher" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class DR_PubResource extends BaseLoggingClass { + + private DR_PubService dr_pubService = new DR_PubService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); + + @GET + @ApiOperation( value = "return DR_Pub details", + notes = "Returns array of `DR_Pub` objects. Add filter for feedId.", + response = DR_Pub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response getDr_Pubs() { + logger.info( "Entry: GET /dr_pubs"); + List<DR_Pub> pubs = dr_pubService.getAllDr_Pubs(); + + GenericEntity<List<DR_Pub>> list = new GenericEntity<List<DR_Pub>>(pubs) { + }; + return responseBuilder.success(list); + } + + + @POST + @ApiOperation( value = "return DR_Pub details", + notes = "create a DR Publisher in the specified environment.", + response = DR_Pub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addDr_Pub(DR_Pub pub) { + ApiError apiError = new ApiError(); + FeedService feeds = new FeedService(); + Feed fnew = null; + + logger.info( "Entry: POST /dr_pubs"); + + try { + checker.required( "feedId", pub.getFeedId()); + } catch ( RequiredFieldException rfe ) { + try { + checker.required( "feedName", pub.getFeedName()); + }catch ( RequiredFieldException rfe2 ) { + logger.debug( rfe2.getApiError().toString() ); + return responseBuilder.error(rfe2.getApiError()); + } + // if we found a FeedName instead of a FeedId then try to look it up. + List<Feed> nfeeds = feeds.getAllFeeds( pub.getFeedName(), pub.getFeedVersion(), "equals"); + if ( nfeeds.isEmpty() ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields("feedName"); + return responseBuilder.error(apiError); + } + fnew = nfeeds.get(0); + } + try { + checker.required( "dcaeLocationName", pub.getDcaeLocationName()); + } catch ( RequiredFieldException rfe ) { + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); + } + + + // we may have fnew already if located by FeedName + if ( fnew == null ) { + fnew = feeds.getFeed(pub.getFeedId(), apiError); + } + if ( fnew == null ) { + logger.info( "Specified feed " + pub.getFeedId() + " or " + pub.getFeedName() + " not known to Bus Controller"); + return responseBuilder.error(apiError); + } + + ArrayList<DR_Pub> pubs = fnew.getPubs(); + logger.info( "num existing pubs before = " + pubs.size() ); + + logger.info( "update feed"); + pub.setNextPubId(); + if ( pub.getUsername() == null ) { + pub.setRandomUserName(); + } + if ( pub.getUserpwd() == null ) { + pub.setRandomPassword(); + } + pubs.add( pub ); + fnew.setPubs(pubs); + fnew = feeds.updateFeed(fnew, apiError); + + if (!apiError.is2xx()) { + return responseBuilder.error(apiError); + } + pubs = fnew.getPubs(); + logger.info( "num existing pubs after = " + pubs.size() ); + + DR_Pub pnew = dr_pubService.getDr_Pub(pub.getPubId(), apiError); + return responseBuilder.success(Status.CREATED.getStatusCode(), pnew); + } + + @PUT + @ApiOperation( value = "return DR_Pub details", + notes = "update a DR Publisher in the specified environment. Update a `DR_Pub` object by pubId", + response = DR_Pub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{pubId}") + public Response updateDr_Pub(@PathParam("pubId") String name, DR_Pub pub) { + logger.info( "Entry: PUT /dr_pubs"); + pub.setPubId(name); + DR_Pub res = dr_pubService.updateDr_Pub(pub); + return responseBuilder.success(res); + } + + @DELETE + @ApiOperation( value = "return DR_Pub details", + notes = "delete a DR Publisher in the specified environment. Delete a `DR_Pub` object by pubId", + response = DR_Pub.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{pubId}") + public Response deleteDr_Pub(@PathParam("pubId") String id){ + + ApiError apiError = new ApiError(); + + try { + checker.required( "pubId", id); + } catch ( RequiredFieldException rfe ) { + return responseBuilder.error(rfe.getApiError()); + } + + DR_Pub pub = dr_pubService.getDr_Pub(id, apiError); + if ( !apiError.is2xx()) { + return responseBuilder.error(apiError); + } + FeedService feeds = new FeedService(); + Feed fnew = feeds.getFeed(pub.getFeedId(), apiError); + if ( fnew == null ) { + logger.info( "Specified feed " + pub.getFeedId() + " not known to Bus Controller"); + return responseBuilder.error(apiError); + } + ArrayList<DR_Pub> pubs = fnew.getPubs(); + if ( pubs.size() == 1 ) { + apiError.setCode(Status.BAD_REQUEST.getStatusCode()); + apiError.setMessage( "Can't delete the last publisher of a feed"); + return responseBuilder.error(apiError); + } + + for( Iterator<DR_Pub> i = pubs.iterator(); i.hasNext(); ) { + DR_Pub listItem = i.next(); + if ( listItem.getPubId().equals(id)) { + i.remove(); + } + } + fnew.setPubs(pubs); + fnew = feeds.updateFeed(fnew,apiError); + if (!apiError.is2xx()) { + return responseBuilder.error(apiError); + } + + dr_pubService.removeDr_Pub(id, apiError); + if (!apiError.is2xx()) { + return responseBuilder.error(apiError); + } + return responseBuilder.success(Status.NO_CONTENT.getStatusCode(), null); + } + + @GET + @ApiOperation( value = "return DR_Pub details", + notes = "returns a DR Publisher in the specified environment. Gets a `DR_Pub` object by pubId", + response = DR_Pub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{pubId}") + public Response get(@PathParam("pubId") String id) { + ApiError apiError = new ApiError(); + + try { + checker.required( "feedId", id); + } catch ( RequiredFieldException rfe ) { + return responseBuilder.error(rfe.getApiError()); + } + + DR_Pub pub = dr_pubService.getDr_Pub(id, apiError); + if (!apiError.is2xx()) { + return responseBuilder.error(apiError); + } + return responseBuilder.success(Status.OK.getStatusCode(), pub); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DR_SubResource.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DR_SubResource.java new file mode 100644 index 0000000..2fa6ccd --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DR_SubResource.java @@ -0,0 +1,243 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.resources; + +import com.google.common.collect.Iterables; +import java.util.ArrayList; +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DR_Sub; +import org.onap.dmaap.dbcapi.model.Feed; +import org.onap.dmaap.dbcapi.service.DR_SubService; +import org.onap.dmaap.dbcapi.service.FeedService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import static javax.ws.rs.core.Response.Status.CREATED; + + +@Path("/dr_subs") +@Api( value= "dr_subs", description = "Endpoint for a Data Router client that implements a Subscriber" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class DR_SubResource extends BaseLoggingClass { + + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); + + @GET + @ApiOperation( value = "return DR_Sub details", + notes = "Returns array of `DR_Sub` objects. Add filter for feedId.", + response = DR_Sub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Sub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response getDr_Subs() { + DR_SubService dr_subService = new DR_SubService(); + List<DR_Sub> subs = dr_subService.getAllDr_Subs(); + + GenericEntity<List<DR_Sub>> list = new GenericEntity<List<DR_Sub>>(subs) { + }; + return responseBuilder.success(list); + } + + @POST + @ApiOperation( value = "return DR_Sub details", + notes = "Create a `DR_Sub` object. ", + response = DR_Sub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Sub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addDr_Sub(DR_Sub sub) { + + ApiError apiError = new ApiError(); + FeedService feeds = new FeedService(); + Feed fnew = null; + try { + checker.required( "feedId", sub.getFeedId()); + } catch ( RequiredFieldException rfe ) { + try { + checker.required( "feedName", sub.getFeedName()); + }catch ( RequiredFieldException rfe2 ) { + logger.debug( rfe2.getApiError().toString() ); + return responseBuilder.error(rfe2.getApiError()); + } + // if we found a FeedName instead of a FeedId then try to look it up. + List<Feed> nfeeds = feeds.getAllFeeds( sub.getFeedName(), sub.getFeedVersion(), "equals"); + if ( nfeeds.isEmpty() ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields("feedName"); + return responseBuilder.error(apiError); + } else if (nfeeds.size() > 1) { + logger.debug( "Attempt to match "+ sub.getFeedName() + " ver="+sub.getFeedVersion() + " matched " + nfeeds.size() ); + apiError.setCode(Status.CONFLICT.getStatusCode()); + apiError.setFields("feedName"); + return responseBuilder.error(apiError); + } + fnew = Iterables.getOnlyElement(nfeeds); + } + + try { + checker.required( "dcaeLocationName", sub.getDcaeLocationName()); + } catch ( RequiredFieldException rfe ) { + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); + } + // we may have fnew already if located by FeedName + if ( fnew == null ) { + fnew = feeds.getFeed( sub.getFeedId(), apiError); + } + if ( fnew == null ) { + logger.warn( "Specified feed " + sub.getFeedId() + " or " + sub.getFeedName() + " not known to Bus Controller"); + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + return responseBuilder.error(apiError); + } + DR_SubService dr_subService = new DR_SubService( fnew.getSubscribeURL()); + ArrayList<DR_Sub> subs = fnew.getSubs(); + logger.info( "num existing subs before = " + subs.size() ); + DR_Sub snew = dr_subService.addDr_Sub(sub, apiError); + if (!apiError.is2xx()) { + return responseBuilder.error(apiError); + } + subs.add( snew ); + logger.info( "num existing subs after = " + subs.size() ); + + fnew.setSubs(subs); + logger.info( "update feed"); + return responseBuilder.success(CREATED.getStatusCode(), snew); + + } + + @PUT + @ApiOperation( value = "return DR_Sub details", + notes = "Update a `DR_Sub` object, selected by subId", + response = DR_Sub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Sub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{subId}") + public Response updateDr_Sub(@PathParam("subId") String name, DR_Sub sub) { + + ApiError apiError = new ApiError(); + + try { + checker.required( "subId", name); + checker.required( "feedId", sub.getFeedId()); + checker.required( "dcaeLocationName", sub.getDcaeLocationName()); + + } catch ( RequiredFieldException rfe ) { + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); + } + FeedService feeds = new FeedService(); + Feed fnew = feeds.getFeed(sub.getFeedId(), apiError); + if ( fnew == null ) { + logger.warn( "Specified feed " + sub.getFeedId() + " not known to Bus Controller"); + return responseBuilder.error(apiError); + } + + DR_SubService dr_subService = new DR_SubService(); + sub.setSubId(name); + DR_Sub nsub = dr_subService.updateDr_Sub(sub, apiError); + if ( nsub != null && nsub.isStatusValid() ) { + return responseBuilder.success(nsub); + } + return responseBuilder.error(apiError); + } + + @DELETE + @ApiOperation( value = "return DR_Sub details", + notes = "Delete a `DR_Sub` object, selected by subId", + response = DR_Sub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Sub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{subId}") + public Response deleteDr_Sub(@PathParam("subId") String id){ + + ApiError apiError = new ApiError(); + + try { + checker.required( "subId", id); + } catch ( RequiredFieldException rfe ) { + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); + } + DR_SubService dr_subService = new DR_SubService(); + dr_subService.removeDr_Sub(id, apiError); + if (!apiError.is2xx() ) { + return responseBuilder.error(apiError); + } + return responseBuilder.success(Status.NO_CONTENT.getStatusCode(), null ); + } + + @GET + @ApiOperation( value = "return DR_Sub details", + notes = "Retrieve a `DR_Sub` object, selected by subId", + response = DR_Sub.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Sub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{subId}") + public Response get(@PathParam("subId") String id) { + + ApiError apiError = new ApiError(); + + try { + checker.required( "subId", id); + } catch ( RequiredFieldException rfe ) { + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); + } + DR_SubService dr_subService = new DR_SubService(); + DR_Sub sub = dr_subService.getDr_Sub(id, apiError); + if ( sub != null && sub.isStatusValid() ) { + return responseBuilder.success(sub); + } + return responseBuilder.error(apiError); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DcaeLocationResource.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DcaeLocationResource.java new file mode 100644 index 0000000..89c9b49 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DcaeLocationResource.java @@ -0,0 +1,153 @@ +/*- + * ============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.resources; + + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.service.DcaeLocationService; + +import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static javax.ws.rs.core.Response.Status.NO_CONTENT; + + +@Path("/dcaeLocations") +@Api( value= "dcaeLocations", description = "an OpenStack tenant purposed for OpenDCAE (i.e. where OpenDCAE components might be deployed)" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class DcaeLocationResource extends BaseLoggingClass { + private DcaeLocationService locationService = new DcaeLocationService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + + @GET + @ApiOperation( value = "return dcaeLocation details", + notes = "Returns array of `dcaeLocation` objects. All objects managed by DMaaP are deployed in some `dcaeLocation` which is a unique identifier for an *OpenStack* tenant purposed for a *dcaeLayer* (ecomp or edge).", + response = DcaeLocation.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DcaeLocation.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response getDcaeLocations() { + List<DcaeLocation> locs = locationService.getAllDcaeLocations(); + + GenericEntity<List<DcaeLocation>> list = new GenericEntity<List<DcaeLocation>>(locs) {}; + return responseBuilder.success(list); + } + + @POST + @ApiOperation( value = "return dcaeLocation details", + notes = "Create some `dcaeLocation` which is a unique identifier for an *OpenStack* tenant purposed for a *dcaeLayer* (ecomp or edge).", + response = DcaeLocation.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DcaeLocation.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addDcaeLocation(DcaeLocation location) { + + if ( locationService.getDcaeLocation(location.getDcaeLocationName()) != null ) { + return responseBuilder.error(new ApiError(Status.CONFLICT.getStatusCode(), + "dcaeLocation already exists", "dcaeLocation")); + } + DcaeLocation loc = locationService.addDcaeLocation(location); + return responseBuilder.success(Status.CREATED.getStatusCode(), loc); + } + + @PUT + @ApiOperation( value = "return dcaeLocation details", + notes = "update the openStackAvailabilityZone of a dcaeLocation", + response = DcaeLocation.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DcaeLocation.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{locationName}") + public Response updateDcaeLocation( + @PathParam("locationName") String name, DcaeLocation location) { + + location.setDcaeLocationName(name); + if ( locationService.getDcaeLocation(location.getDcaeLocationName()) == null ) { + return responseBuilder.notFound(); + + } + DcaeLocation loc = locationService.updateDcaeLocation(location); + return responseBuilder.success(Status.CREATED.getStatusCode(), loc ); + } + + @DELETE + @ApiOperation( value = "return dcaeLocation details", notes = "delete a dcaeLocation", response = DcaeLocation.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = DcaeLocation.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{locationName}") + public Response deleteDcaeLocation( + @PathParam("locationName") String name + ){ + locationService.removeDcaeLocation(name); + return responseBuilder.success(NO_CONTENT.getStatusCode(), null); + } + + @GET + @ApiOperation( value = "return dcaeLocation details", notes = "Returns a specific `dcaeLocation` object with specified tag", response = DcaeLocation.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DcaeLocation.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{locationName}") + public Response getDcaeLocation( + @PathParam("locationName") String name) { + + DcaeLocation loc = locationService.getDcaeLocation( name ); + if ( loc == null ) { + ApiError err = new ApiError(); + + err.setCode(NOT_FOUND.getStatusCode()); + err.setMessage("dcaeLocation does not exist"); + err.setFields("dcaeLocation"); + + return responseBuilder.error(err); + } + + return responseBuilder.success(loc); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DmaapResource.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DmaapResource.java new file mode 100644 index 0000000..955cab7 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/DmaapResource.java @@ -0,0 +1,123 @@ +/*- + * ============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 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.DmaapService; + +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; + + +@Path("/dmaap") +@Api( value= "dmaap", description = "Endpoint for this instance of DMaaP object containing values for this OpenDCAE deployment" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class DmaapResource extends BaseLoggingClass { + + + private DmaapService dmaapService = new DmaapService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); + + @GET + @ApiOperation( value = "return dmaap details", notes = "returns the `dmaap` object, which contains system wide configuration settings", response = Dmaap.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Dmaap.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + + public Response getDmaap(@Context UriInfo uriInfo) { + Dmaap d = dmaapService.getDmaap(); + return responseBuilder.success(d); + } + + @POST + @ApiOperation( value = "return dmaap details", notes = "Create a new DMaaP set system wide configuration settings for the *dcaeEnvironment*. Deprecated with introduction of persistence in 1610.", response = Dmaap.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Dmaap.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addDmaap( Dmaap obj ) { + + try { + validateRequiredFields(obj); + } catch( RequiredFieldException rfe ) { + return responseBuilder.error(rfe.getApiError()); + } + + Dmaap d = dmaapService.addDmaap(obj); + if ( d == null ) { + return responseBuilder.notFound(); + + } + + return responseBuilder.success(d); + } + + @PUT + @ApiOperation( value = "return dmaap details", notes = "Update system settings for *dcaeEnvironment*.", response = Dmaap.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Dmaap.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response updateDmaap( Dmaap obj ) { + + try { + validateRequiredFields(obj); + } catch( RequiredFieldException rfe ) { + return responseBuilder.error(rfe.getApiError()); + } + + Dmaap d = dmaapService.updateDmaap(obj); + if ( d != null ) { + return responseBuilder.success(d); + } else { + return responseBuilder.notFound(); + } + } + + private void validateRequiredFields(Dmaap obj) throws RequiredFieldException { + checker.required( "dmaapName", obj.getDmaapName(), "^\\S+$" ); //no white space allowed in dmaapName + checker.required( "dmaapProvUrl", obj.getDrProvUrl()); + checker.required( "topicNsRoot", obj.getTopicNsRoot()); + checker.required( "bridgeAdminTopic", obj.getBridgeAdminTopic()); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java new file mode 100644 index 0000000..28bdb00 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/FeedResource.java @@ -0,0 +1,259 @@ +/*- + * ============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.resources; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +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.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +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.Feed; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.service.FeedService; + + +@Path("/feeds") +@Api( value= "Feeds", description = "Endpoint for a Data Router Feed" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class FeedResource extends BaseLoggingClass { + + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); + + @GET + @ApiOperation( value = "return Feed details", + notes = "Returns array of `Feed` objects.", + response = Feed.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Feed.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response getFeeds( + @QueryParam("feedName") String feedName, + @QueryParam("version") String version, + @QueryParam("match") String match) { + + FeedService feedService = new FeedService(); + List<Feed> nfeeds = feedService.getAllFeeds( feedName, version, match ); + GenericEntity<List<Feed>> list = new GenericEntity<List<Feed>>(nfeeds) { + }; + return responseBuilder.success(list); + } + + + + @POST + @ApiOperation( value = "return Feed details", + notes = "Create a of `Feed` object.", + response = Feed.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Feed.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addFeed( + Feed feed, + @QueryParam("useExisting") String useExisting) { + + ApiError apiError = new ApiError(); + + try { + checker.required( "feedName", feed.getFeedName()); + checker.required( "feedVersion", feed.getFeedVersion()); + checker.required( "owner", feed.getOwner()); + checker.required( "asprClassification", feed.getAsprClassification()); + } catch ( RequiredFieldException rfe ) { + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); + } + + + FeedService feedService = new FeedService(); + Feed nfeed = feedService.getFeedByName( feed.getFeedName(), feed.getFeedVersion(), apiError); + if ( nfeed == null ) { + nfeed = feedService.addFeed(feed, apiError); + if ( nfeed != null ) { + return responseBuilder.success(nfeed); + } else { + logger.error( "Unable to create: " + feed.getFeedName() + ":" + feed.getFeedVersion()); + + return responseBuilder.error(apiError); + } + } else if ( nfeed.getStatus() == DmaapObject_Status.DELETED ) { + feed.setFeedId( nfeed.getFeedId()); + nfeed = feedService.updateFeed(feed, apiError); + if ( nfeed != null ) { + return responseBuilder.success(nfeed); + } else { + logger.info( "Unable to update: " + feed.getFeedName() + ":" + feed.getFeedVersion()); + + return responseBuilder.error(apiError); + } + } else if ( (useExisting != null) && ("true".compareToIgnoreCase( useExisting ) == 0)) { + return responseBuilder.success(nfeed); + } + + apiError.setCode(Status.CONFLICT.getStatusCode()); + return responseBuilder.error(apiError); + } + + @PUT + @ApiOperation( value = "return Feed details", + notes = "Update a `Feed` object, specified by id.", + response = Feed.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Feed.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{id}") + public Response updateFeed( + @PathParam("id") String id, + Feed feed) { + + FeedService feedService = new FeedService(); + ApiError apiError = new ApiError(); + + try { + checker.required( "feedId", id); + } catch ( RequiredFieldException rfe ) { + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); + } + + Feed nfeed = feedService.getFeed(id, apiError); + if ( nfeed == null || nfeed.getStatus() == DmaapObject_Status.DELETED ) { + return responseBuilder.notFound(); + } + + // we assume there is no updates allowed for pubs and subs objects via this api... + // need to update any fields supported by PUT but preserve original field values. + nfeed.setSuspended(feed.isSuspended()); + nfeed.setFeedDescription(feed.getFeedDescription()); + nfeed.setFormatUuid(feed.getFormatUuid()); + + nfeed = feedService.updateFeed(nfeed, apiError); + if ( nfeed != null ) { + return responseBuilder.success(nfeed); + } else { + logger.info( "Unable to update: " + feed.getFeedName() + ":" + feed.getFeedVersion()); + + return responseBuilder.error(apiError); + } + } + + @DELETE + @ApiOperation( value = "return Feed details", + notes = "Delete a `Feed` object, specified by id.", + response = Feed.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = Feed.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{id}") + public Response deleteFeed(@PathParam("id") String id){ + ApiError apiError = new ApiError(); + + logger.debug( "Entry: DELETE " + id); + FeedService feedService = new FeedService(); + Feed nfeed = feedService.getFeed(id, apiError); + if ( nfeed == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + return responseBuilder.error(apiError); + } + nfeed = feedService.removeFeed(nfeed, apiError); + if ( nfeed == null || nfeed.getStatus() == DmaapObject_Status.DELETED ) { + return responseBuilder.success(Status.NO_CONTENT.getStatusCode(), null); + } + logger.info( "Unable to delete: " + id + ":" + nfeed.getFeedVersion()); + + return responseBuilder.error(apiError); + } + + @GET + @ApiOperation( value = "return Feed details", + notes = "Retrieve a `Feed` object, specified by id.", + response = Feed.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = DR_Pub.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{id}") + public Response getFeed(@PathParam("id") String id) { + ApiError apiError = new ApiError(); + + FeedService feedService = new FeedService(); + Feed nfeed = feedService.getFeed(id, apiError); + if ( nfeed == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + return responseBuilder.error(apiError); + } + return responseBuilder.success(nfeed); + } + + @PUT + @ApiOperation( value = "sync feeds to existing DR", + notes = "When Bus Controller is deployed after DR, then it is possible" + + "that DR has previous provisioning data that needs to be imported" + + "into Bus Controller.", + response = Feed.class ) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Feed.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path( "/sync") + public Response syncFeeds (@QueryParam("hard") String hardParam) { + ApiError error = new ApiError(); + + FeedService feedService = new FeedService(); + boolean hard = false; + if ( hardParam != null && hardParam.equalsIgnoreCase("true")) { + hard = true; + } + feedService.sync( hard, error ); + if ( error.is2xx()) { + List<Feed> nfeeds = feedService.getAllFeeds(); + GenericEntity<List<Feed>> list = new GenericEntity<List<Feed>>(nfeeds) { + }; + return responseBuilder.success(list); + } + return responseBuilder.error(error); + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/InfoResource.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/InfoResource.java new file mode 100644 index 0000000..bcb7ed2 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/InfoResource.java @@ -0,0 +1,72 @@ +/*- + * ============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.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; + + + +@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 { + + + private ResponseBuilder responseBuilder = new ResponseBuilder(); + + @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) { + return responseBuilder.success(204, null); + } + + + + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClientResource.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClientResource.java new file mode 100644 index 0000000..80ee0a6 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClientResource.java @@ -0,0 +1,208 @@ +/*- + * ============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.resources; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.MR_Client; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.service.MR_ClientService; +import org.onap.dmaap.dbcapi.service.MR_ClusterService; +import org.onap.dmaap.dbcapi.service.TopicService; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import java.util.List; + +import static javax.ws.rs.core.Response.Status.NO_CONTENT; + + +@Path("/mr_clients") +@Api( value= "MR_Clients", description = "Endpoint for a Message Router Client that implements a Publisher or a Subscriber" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class MR_ClientResource extends BaseLoggingClass { + + private MR_ClientService mr_clientService = new MR_ClientService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); + + @GET + @ApiOperation( value = "return MR_Client details", + notes = "Returns array of `MR_Client` objects.", + response = MR_Client.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = MR_Client.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response getMr_Clients() { + List<MR_Client> clients = mr_clientService.getAllMr_Clients(); + + GenericEntity<List<MR_Client>> list = new GenericEntity<List<MR_Client>>(clients) { + }; + return responseBuilder.success(list); + } + + @POST + @ApiOperation( value = "Associate an MR_Client object to a Topic", + notes = "Create a `MR_Client` object." + + "The `dcaeLocation` attribute is used to match an `MR_Cluster` object with the same value, with the intent of localizing message traffic." + + " In legacy implementation, the `clientRole` is granted appropriate permission in AAF." + + " Newer implementions may instead specify an AAF Identity, which will be added to the appropriate `Topic` role.", + response = MR_Client.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = MR_Client.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addMr_Client(MR_Client client) { + ApiError apiError = new ApiError(); + + try { + checker.required( "fqtn", client.getFqtn()); + checker.required( "dcaeLocationName", client.getDcaeLocationName()); + String s = client.getClientRole(); + if ( s == null ) { + s = client.getClientIdentity(); + } + checker.required( "clientRole or clientIdentity", s); + checker.required( "action", client.getAction()); + + } catch ( RequiredFieldException rfe ) { + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); + } + MR_ClusterService clusters = new MR_ClusterService(); + + MR_Cluster cluster = clusters.getMr_Cluster(client.getDcaeLocationName(), apiError); + if ( cluster == null ) { + + apiError.setCode(Status.BAD_REQUEST.getStatusCode()); + apiError.setMessage( "MR_Cluster alias not found for dcaeLocation: " + client.getDcaeLocationName()); + apiError.setFields("dcaeLocationName"); + logger.warn(apiError.toString()); + return responseBuilder.error(apiError); + } + + TopicService topics = new TopicService(); + + Topic t = topics.getTopic(client.getFqtn(), apiError); + if ( t == null ) { + return responseBuilder.error(apiError); + } + MR_Client nClient = mr_clientService.addMr_Client(client, t, apiError); + if (apiError.is2xx()) { + t = topics.getTopic(client.getFqtn(), apiError); + topics.checkForBridge(t, apiError); + return responseBuilder.success(nClient); + } + else { + return responseBuilder.error(apiError); + } + } + + @PUT + @ApiOperation( value = "Update an MR_Client object", + notes = "Update a `MR_Client` object, specified by clientId", + response = MR_Client.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = MR_Client.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{clientId}") + public Response updateMr_Client(@PathParam("clientId") String clientId, MR_Client client) { + ApiError apiError = new ApiError(); + + try { + checker.required( "fqtn", client.getFqtn()); + checker.required( "dcaeLocationName", client.getDcaeLocationName()); + checker.required( "clientRole", client.getClientRole()); + checker.required( "action", client.getAction()); + + } catch ( RequiredFieldException rfe ) { + logger.debug( rfe.getApiError().toString() ); + return responseBuilder.error(rfe.getApiError()); + } + client.setMrClientId(clientId); + MR_Client nClient = mr_clientService.updateMr_Client(client, apiError); + if (apiError.is2xx()) { + return Response.ok(nClient) + .build(); + } + return Response.status(apiError.getCode()) + .entity(apiError) + .build(); + } + + @DELETE + @ApiOperation( value = "Delete an MR_Client object", + notes = "Delete a `MR_Client` object, specified by clientId", + response = MR_Client.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = MR_Client.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{subId}") + public Response deleteMr_Client(@PathParam("subId") String id){ + ApiError apiError = new ApiError(); + + mr_clientService.removeMr_Client(id, true, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(NO_CONTENT.getStatusCode(), null); + } + + return responseBuilder.error(apiError); + } + + @GET + @ApiOperation( value = "return MR_Client details", + notes = "Retrieve a `MR_Client` object, specified by clientId", + response = MR_Client.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = MR_Client.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{subId}") + public Response getMr_Client(@PathParam("subId") String id) { + ApiError apiError = new ApiError(); + + MR_Client nClient = mr_clientService.getMr_Client(id, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(nClient); + } + return responseBuilder.error(apiError); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResource.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResource.java new file mode 100644 index 0000000..0a361ff --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResource.java @@ -0,0 +1,174 @@ +/*- + * ============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.resources; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.service.MR_ClusterService; + + +@Path("/mr_clusters") +@Api( value= "MR_Clusters", description = "Endpoint for a Message Router servers in a Cluster configuration" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class MR_ClusterResource extends BaseLoggingClass { + + private MR_ClusterService mr_clusterService = new MR_ClusterService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); + + @GET + @ApiOperation( value = "return MR_Cluster details", + notes = "Returns array of `MR_Cluster` objects.", + response = MR_Cluster.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = MR_Cluster.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response getMr_Clusters() { + List<MR_Cluster> clusters = mr_clusterService.getAllMr_Clusters(); + + GenericEntity<List<MR_Cluster>> list = new GenericEntity<List<MR_Cluster>>(clusters) { + }; + return responseBuilder.success(list); + } + + @POST + @ApiOperation( value = "return MR_Cluster details", + notes = "Create an `MR_Cluster` object.", + response = MR_Cluster.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = MR_Cluster.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addMr_Cluster(MR_Cluster cluster) { + ApiError apiError = new ApiError(); + + try { + checker.required( "dcaeLocationName", cluster.getDcaeLocationName()); + checker.required( "fqdn", cluster.getFqdn()); + } catch( RequiredFieldException rfe ) { + return responseBuilder.error(rfe.getApiError()); + } + MR_Cluster mrc = mr_clusterService.addMr_Cluster(cluster, apiError); + if ( mrc != null && mrc.isStatusValid() ) { + return responseBuilder.success(Status.CREATED.getStatusCode(), mrc); + } + return responseBuilder.error(apiError); + + } + + @PUT + @ApiOperation( value = "return MR_Cluster details", + notes = "Update an `MR_Cluster` object, specified by clusterId.", + response = MR_Cluster.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = MR_Cluster.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{clusterId}") + public Response updateMr_Cluster(@PathParam("clusterId") String clusterId, MR_Cluster cluster) { + ApiError apiError = new ApiError(); + + try { + checker.required( "fqdn", clusterId); + checker.required( "dcaeLocationName", cluster.getDcaeLocationName()); + } catch( RequiredFieldException rfe ) { + return responseBuilder.error(rfe.getApiError()); + } + cluster.setDcaeLocationName(clusterId); + MR_Cluster mrc = mr_clusterService.updateMr_Cluster(cluster, apiError); + if ( mrc != null && mrc.isStatusValid() ) { + return responseBuilder.success(Status.CREATED.getStatusCode(), mrc); + } + return responseBuilder.error(apiError); + } + + @DELETE + @ApiOperation( value = "return MR_Cluster details", + notes = "Delete an `MR_Cluster` object, specified by clusterId.", + response = MR_Cluster.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = MR_Cluster.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{clusterId}") + public Response deleteMr_Cluster(@PathParam("clusterId") String id){ + ApiError apiError = new ApiError(); + + try { + checker.required( "fqdn", id); + } catch( RequiredFieldException rfe ) { + return responseBuilder.error(rfe.getApiError()); + } + mr_clusterService.removeMr_Cluster(id, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(Status.NO_CONTENT.getStatusCode(), null); + } + return responseBuilder.error(apiError); + } + + @GET + @ApiOperation( value = "return MR_Cluster details", + notes = "Retrieve an `MR_Cluster` object, specified by clusterId.", + response = MR_Cluster.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = MR_Cluster.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{clusterId}") + public Response getMR_Cluster(@PathParam("clusterId") String id) { + ApiError apiError = new ApiError(); + + try { + checker.required( "dcaeLocationName", id); + } catch( RequiredFieldException rfe ) { + return responseBuilder.error(rfe.getApiError()); + } + MR_Cluster mrc = mr_clusterService.getMr_Cluster(id, apiError); + if ( mrc != null && mrc.isStatusValid() ) { + return responseBuilder.success(Status.CREATED.getStatusCode(), mrc); + } + return responseBuilder.error(apiError); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/RequestTimeLogFilter.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/RequestTimeLogFilter.java new file mode 100644 index 0000000..b2b98b6 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/RequestTimeLogFilter.java @@ -0,0 +1,55 @@ +/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dmaap
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.resources;
+
+import com.att.eelf.configuration.EELFLogger;
+import java.time.Clock;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerRequestFilter;
+import javax.ws.rs.container.ContainerResponseContext;
+import javax.ws.rs.container.ContainerResponseFilter;
+import org.onap.dmaap.dbcapi.logging.BaseLoggingClass;
+
+public class RequestTimeLogFilter extends BaseLoggingClass implements ContainerRequestFilter, ContainerResponseFilter {
+
+ private final EELFLogger log;
+ private Clock clock;
+
+ public RequestTimeLogFilter() {
+ this(auditLogger, Clock.systemDefaultZone());
+ }
+
+ RequestTimeLogFilter(EELFLogger logger, Clock clock) {
+ this.log = logger;
+ this.clock = clock;
+ }
+
+ @Override
+ public void filter(ContainerRequestContext requestContext) {
+ requestContext.setProperty("start", clock.millis());
+ }
+
+ @Override
+ public void filter(ContainerRequestContext requestContext, ContainerResponseContext containerResponseContext) {
+ long startTime = (long) requestContext.getProperty("start");
+ long elapsedTime = clock.millis() - startTime;
+ log.info("Request took {} ms", elapsedTime);
+ }
+}
diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredChecker.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredChecker.java new file mode 100644 index 0000000..52646aa --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredChecker.java @@ -0,0 +1,52 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA 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.resources; + +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.onap.dmaap.dbcapi.model.ApiError; + +public class RequiredChecker { + + public void required(String name, Object val) throws RequiredFieldException { + if (val == null) { + throw new RequiredFieldException(new ApiError(BAD_REQUEST.getStatusCode(), + "missing required field", name)); + } + } + + public void required(String name, String val, String expr) throws RequiredFieldException { + + required(name, val); + + if (expr != null && !expr.isEmpty()) { + Pattern pattern = Pattern.compile(expr); + Matcher matcher = pattern.matcher(val); + if (!matcher.find()) { + throw new RequiredFieldException(new ApiError(BAD_REQUEST.getStatusCode(), + "value '" + val + "' violates regexp check '" + expr + "'", name)); + } + } + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredFieldException.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredFieldException.java new file mode 100644 index 0000000..2968d18 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/RequiredFieldException.java @@ -0,0 +1,46 @@ +/*- + * ============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.resources; + +import org.onap.dmaap.dbcapi.model.ApiError; + +public class RequiredFieldException extends Exception { + + private static final long serialVersionUID = 2L; + + private final ApiError apiError; + + public RequiredFieldException(ApiError apiError) { + super(); + this.apiError = apiError; + } + + public ApiError getApiError() { + return apiError; + } + + @Override + public String toString() { + return "RequiredFieldException{" + + "apiError=" + apiError + + '}'; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/ResponseBuilder.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/ResponseBuilder.java new file mode 100644 index 0000000..044e7c4 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/ResponseBuilder.java @@ -0,0 +1,84 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA 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.resources; + +import static com.att.eelf.configuration.Configuration.MDC_RESPONSE_CODE; +import static com.att.eelf.configuration.Configuration.MDC_RESPONSE_DESC; +import static com.att.eelf.configuration.Configuration.MDC_STATUS_CODE; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; +import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; + +import javax.ws.rs.core.Response; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.slf4j.MDC; + +public class ResponseBuilder extends BaseLoggingClass { + + Response success(Object d) { + return buildSuccessResponse(d, Response.Status.OK.getStatusCode()); + } + + Response success(int code, Object d) { + return buildSuccessResponse(d, code); + } + + Response error(ApiError err) { + return buildErrResponse(err); + } + + Response unauthorized(String msg) { + return buildErrResponse(new ApiError(UNAUTHORIZED.getStatusCode(), msg, "Authorization")); + } + + Response unavailable() { + return buildErrResponse(new ApiError(SERVICE_UNAVAILABLE.getStatusCode(), + "Request is unavailable due to unexpected condition")); + } + + Response notFound() { + return buildErrResponse(new ApiError(NOT_FOUND.getStatusCode(),"Requested object not found")); + } + + private Response buildSuccessResponse(Object d, int code) { + MDC.put(MDC_STATUS_CODE, "COMPLETE"); + MDC.put(MDC_RESPONSE_DESC, ""); + return buildResponse(d, code); + } + + private Response buildErrResponse(ApiError err) { + MDC.put(MDC_STATUS_CODE, "ERROR"); + MDC.put(MDC_RESPONSE_DESC, err.getMessage()); + + return buildResponse(err, err.getCode()); + } + + private Response buildResponse(Object obj, int code) { + MDC.put(MDC_RESPONSE_CODE, String.valueOf(code)); + + auditLogger.auditEvent(""); + return Response.status(code) + .entity(obj) + .build(); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java new file mode 100644 index 0000000..01926b7 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/resources/TopicResource.java @@ -0,0 +1,218 @@ +/*- + * ============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.resources; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; + +import java.util.List; + +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +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.GenericEntity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +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.TopicService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +import static javax.ws.rs.core.Response.Status.CREATED; + +@Path("/topics") +@Api( value= "topics", description = "Endpoint for retreiving MR Topics" ) +@Consumes(MediaType.APPLICATION_JSON) +@Produces(MediaType.APPLICATION_JSON) +@Authorization +public class TopicResource extends BaseLoggingClass { + private static FqtnType defaultTopicStyle; + private static String defaultPartitionCount; + private static String defaultReplicationCount; + private TopicService mr_topicService = new TopicService(); + private ResponseBuilder responseBuilder = new ResponseBuilder(); + private RequiredChecker checker = new RequiredChecker(); + static final String UNSUPPORTED_PUT_MSG = "Method /PUT not supported for /topics"; + + public TopicResource() { + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + defaultTopicStyle = FqtnType.Validator( p.getProperty("MR.topicStyle", "FQTN_LEGACY_FORMAT")); + defaultPartitionCount = p.getProperty( "MR.partitionCount", "2"); + defaultReplicationCount = p.getProperty( "MR.replicationCount", "1"); + + logger.info( "Setting defaultTopicStyle=" + defaultTopicStyle ); + } + + @GET + @ApiOperation( value = "return Topic details", + notes = "Returns array of `Topic` objects.", + response = Topic.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Topic.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response getTopics() { + List<Topic> allTopics = mr_topicService.getAllTopics(); + + GenericEntity<List<Topic>> list = new GenericEntity<List<Topic>>(allTopics) { + }; + return responseBuilder.success(list); + + } + + @POST + @ApiOperation( value = "Create a Topic object", + notes = "Create `Topic` object." + + "For convenience, the message body may populate the `clients` array, in which case each entry will be added as an `MR_Client`." + + " Beginning in ONAP Dublin Release, dbcapi will create two AAF Roles by default, one each for the publisher and subscriber per topic." + + " MR_Clients can then specify an AAF Identity to be added to the appropriate default Role, avoiding the need to create Role(s) in advance.", + response = Topic.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Topic.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + public Response addTopic(Topic topic, @QueryParam("useExisting") String useExisting) { + logger.info( "addTopic request: " + topic + " useExisting=" + useExisting ); + ApiError apiError = new ApiError(); + + try { + checker.required( "topicName", topic.getTopicName(), "^\\S+$" ); //no white space allowed in topicName + checker.required( "topicDescription", topic.getTopicDescription()); + checker.required( "owner", topic.getOwner()); + } catch( RequiredFieldException rfe ) { + logger.error("Error", rfe.getApiError()); + return responseBuilder.error(rfe.getApiError()); + } + + ReplicationType t = topic.getReplicationCase(); + 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 ); + } + String pc = topic.getPartitionCount(); + if ( pc == null ) { + topic.setPartitionCount(defaultPartitionCount); + } + String rc = topic.getReplicationCount(); + if ( rc == null ) { + topic.setReplicationCount(defaultReplicationCount); + } + topic.setLastMod(); + Boolean flag = false; + if (useExisting != null) { + flag = "true".compareToIgnoreCase( useExisting ) == 0; + } + + Topic mrc = mr_topicService.addTopic(topic, apiError, flag); + if ( mrc != null && apiError.is2xx() ) { + return responseBuilder.success(CREATED.getStatusCode(), mrc); + } + return responseBuilder.error(apiError); + } + + @PUT + @ApiOperation( value = "return Topic details", + notes = "Update a `Topic` object, identified by topicId", + response = Topic.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Topic.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{topicId}") + public Response updateTopic(@PathParam("topicId") String topicId) { + ApiError apiError = new ApiError(); + + apiError.setCode(Status.BAD_REQUEST.getStatusCode()); + apiError.setMessage(UNSUPPORTED_PUT_MSG); + + return responseBuilder.error(apiError); + } + + @DELETE + @ApiOperation( value = "return Topic details", + notes = "Delete a `Topic` object, identified by topicId", + response = Topic.class) + @ApiResponses( value = { + @ApiResponse( code = 204, message = "Success", response = Topic.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{topicId}") + public Response deleteTopic(@PathParam("topicId") String id){ + ApiError apiError = new ApiError(); + + try { + checker.required( "fqtn", id); + } catch( RequiredFieldException rfe ) { + logger.error("Error", rfe.getApiError()); + return responseBuilder.error(rfe.getApiError()); + } + + mr_topicService.removeTopic(id, apiError); + if (apiError.is2xx()) { + return responseBuilder.success(Status.NO_CONTENT.getStatusCode(), null); + } + return responseBuilder.error(apiError); + } + + + @GET + @ApiOperation( value = "return Topic details", + notes = "Retrieve a `Topic` object, identified by topicId", + response = Topic.class) + @ApiResponses( value = { + @ApiResponse( code = 200, message = "Success", response = Topic.class), + @ApiResponse( code = 400, message = "Error", response = ApiError.class ) + }) + @Path("/{topicId}") + public Response getTopic(@PathParam("topicId") String id) { + logger.info("Entry: /GET " + id); + ApiError apiError = new ApiError(); + + try { + checker.required( "topicName", id, "^\\S+$" ); //no white space allowed in topicName + } catch( RequiredFieldException rfe ) { + logger.error("Error", rfe.getApiError()); + return responseBuilder.error(rfe.getApiError()); + } + Topic mrc = mr_topicService.getTopic(id, apiError); + if ( mrc == null ) { + return responseBuilder.error(apiError); + } + return responseBuilder.success(mrc); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/ApplicationConfig.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/ApplicationConfig.java new file mode 100644 index 0000000..2244b73 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/ApplicationConfig.java @@ -0,0 +1,37 @@ +/*- + * ============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.server; + +import org.glassfish.jersey.server.ResourceConfig; +import org.onap.dmaap.dbcapi.resources.RequestTimeLogFilter; +import org.onap.dmaap.dbcapi.resources.AuthorizationFilter; + +public class ApplicationConfig extends ResourceConfig { + + /* + * Register JAX-RS application components + */ + public ApplicationConfig() { + + register(AuthorizationFilter.class). + register(RequestTimeLogFilter.class); + + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/CadiCertificateManager.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/CadiCertificateManager.java new file mode 100644 index 0000000..1da2bc4 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/CadiCertificateManager.java @@ -0,0 +1,61 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2020 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.server; + +import java.io.FileInputStream; +import java.io.IOException; +import java.util.Properties; + +import org.onap.aaf.cadi.PropAccess; + +public class CadiCertificateManager extends CertificateManager { + private PropAccess propAccess; + + CadiCertificateManager( Properties properties ) { + String cadiPropsFile = properties.getProperty("cadi.properties", "etc/org.onap.dmaa-bc.props"); + logger.info( "using cadi properties in ", cadiPropsFile); + + propAccess = new PropAccess(); + ready = true; + try { + propAccess.load( new FileInputStream( cadiPropsFile )); + } catch ( IOException e ) { + logger.error( "Failed to load props file: " + cadiPropsFile + "\n" + e.getMessage()); + ready = false; + } + setKeyStoreType( "jks"); + setKeyStoreFile( propAccess.getProperty("cadi_keystore") ); + setKeyStorePassword( decryptPass( propAccess.getProperty("cadi_keystore_password_jks" ) )); + + setTrustStoreType( "jks"); + setTrustStoreFile( propAccess.getProperty("cadi_truststore" ) ); + setTrustStorePassword( decryptPass( propAccess.getProperty("cadi_truststore_password" ) )); + } + + private String decryptPass( String password ) { + String clear = null; + try { + clear = propAccess.decrypt(password, false ); + } catch (IOException e) { + logger.error( "Failed to decrypt " + password + ": " + e.getMessage() ); + } + return clear; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/CertficateManagerFactory.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/CertficateManagerFactory.java new file mode 100644 index 0000000..0bffd84 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/CertficateManagerFactory.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2020 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.server; + + +import java.util.Properties; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class CertficateManagerFactory extends BaseLoggingClass { + private final Properties dmaapConfig; + + public CertficateManagerFactory() { + this((DmaapConfig) DmaapConfig.getConfig()); + } + + CertficateManagerFactory(Properties params) { + this.dmaapConfig = params; + } + + public CertificateManager initCertificateManager() { + boolean useCadi = "cadi".equalsIgnoreCase(dmaapConfig.getProperty("CertificateManagement", "legacy")); + logger.info("CertificateManagerFactory: useCadi=" + useCadi); + + if ( useCadi ) { + return new CadiCertificateManager( dmaapConfig ); + } + return new LegacyCertificateManager( dmaapConfig ); + } + + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/CertificateManager.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/CertificateManager.java new file mode 100644 index 0000000..2772b92 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/CertificateManager.java @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2020 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.server; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; + +public abstract class CertificateManager extends BaseLoggingClass{ + + class cmAttribute { + private String type; + private String file; + private String password; + + private String getType() { + return type; + } + private void setType(String certificateType) { + this.type = certificateType; + } + private String getFile() { + return file; + } + private void setFile(String keyStoreFile) { + this.file = keyStoreFile; + } + private void setPassword( String pwd ) { + this.password = pwd; + } + private String getPassword() { + return password; + } + } + + private cmAttribute keyStore; + private cmAttribute trustStore; + protected boolean ready; + + CertificateManager() { + keyStore = new cmAttribute(); + trustStore = new cmAttribute(); + ready = false; + } + + public boolean isReady() { + return ready; + } + + public String getKeyStoreType() { + return keyStore.getType(); + } + public void setKeyStoreType(String certificateType) { + this.keyStore.setType( certificateType) ; + } + public String getKeyStoreFile() { + return keyStore.getFile(); + } + public void setKeyStoreFile(String keyStoreFile) { + this.keyStore.setFile(keyStoreFile); + } + + public String getKeyStorePassword() { + return keyStore.getPassword(); + } + public void setKeyStorePassword(String keyStorePassword) { + this.keyStore.setPassword(keyStorePassword); + } + public String getTrustStoreType() { + return trustStore.getType(); + } + public void setTrustStoreType( String type ) { + this.trustStore.setType(type); + } + public String getTrustStoreFile() { + return trustStore.getFile(); + } + public void setTrustStoreFile(String trustStoreFile) { + this.trustStore.setFile(trustStoreFile); + } + public String getTrustStorePassword() { + return trustStore.getPassword(); + } + public void setTrustStorePassword(String trustStorePassword) { + this.trustStore.setPassword(trustStorePassword); + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/JettyServer.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/JettyServer.java new file mode 100644 index 0000000..52d7570 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/JettyServer.java @@ -0,0 +1,174 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.server; + +import com.google.common.collect.Sets; +import java.util.Properties; +import javax.servlet.DispatcherType; +import org.eclipse.jetty.http.HttpVersion; +import org.eclipse.jetty.server.HttpConfiguration; +import org.eclipse.jetty.server.HttpConnectionFactory; +import org.eclipse.jetty.server.SecureRequestCustomizer; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.ServerConnector; +import org.eclipse.jetty.server.SslConnectionFactory; +import org.eclipse.jetty.servlet.DefaultServlet; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +/** + * A Jetty server which supports: + * - http and https (simultaneously for dev env) + * - REST API context + * - static html pages (for documentation). + */ +public class JettyServer extends BaseLoggingClass { + + private static final CertificateManager certificateManager = + new CertficateManagerFactory(DmaapConfig.getConfig()).initCertificateManager(); + private final Server server; + + + public Server getServer() { + return server; + } + + public static CertificateManager getCertificateManager() { + return certificateManager; + } + + public JettyServer(Properties params) { + + server = new Server(); + int httpPort = Integer.parseInt(params.getProperty("IntHttpPort", "80")); + int sslPort = Integer.parseInt(params.getProperty("IntHttpsPort", "443")); + boolean allowHttp = Boolean.parseBoolean(params.getProperty("HttpAllowed", "false")); + serverLogger.info("port params: http=" + httpPort + " https=" + sslPort); + serverLogger.info("allowHttp=" + allowHttp); + + // HTTP Server + HttpConfiguration httpConfig = new HttpConfiguration(); + httpConfig.setSecureScheme("https"); + httpConfig.setSecurePort(sslPort); + httpConfig.setOutputBufferSize(32768); + + try (ServerConnector httpConnector = new ServerConnector(server, new HttpConnectionFactory(httpConfig))) { + httpConnector.setPort(httpPort); + httpConnector.setIdleTimeout(30000); + + // HTTPS Server + HttpConfiguration httpsConfig = new HttpConfiguration(httpConfig); + httpsConfig.addCustomizer(new SecureRequestCustomizer()); + SslContextFactory sslContextFactory = new SslContextFactory.Server(); + sslContextFactory.setWantClientAuth(true); + + if ( ! certificateManager.isReady()) { + serverLogger.error("CertificateManager is not ready. NOT starting https!"); + } else { + setUpKeystore(sslContextFactory); + setUpTrustStore(sslContextFactory); + + + if (sslPort != 0) { + try (ServerConnector sslConnector = new ServerConnector(server, + new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()), + new HttpConnectionFactory(httpsConfig))) { + sslConnector.setPort(sslPort); + server.addConnector(sslConnector); + serverLogger.info("Starting sslConnector on port " + sslPort + " for https"); + } + } else { + serverLogger.info("NOT starting sslConnector because InHttpsPort param is " + sslPort ); + } + } + if (allowHttp) { + serverLogger.info("Starting httpConnector on port " + httpPort); + server.addConnector(httpConnector); + } else { + serverLogger.info("NOT starting httpConnector because HttpAllowed param is " + allowHttp); + } + } + + // Set context for servlet. This is shared for http and https + ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); + context.setContextPath("/"); + server.setHandler(context); + + ServletHolder jerseyServlet = context + .addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/webapi/*"); + jerseyServlet.setInitOrder(1); + jerseyServlet.setInitParameter("jersey.config.server.provider.packages", "org.onap.dmaap.dbcapi.resources"); + jerseyServlet.setInitParameter("javax.ws.rs.Application", "org.onap.dmaap.dbcapi.server.ApplicationConfig"); + + // also serve up some static pages... + ServletHolder staticServlet = context.addServlet(DefaultServlet.class, "/*"); + staticServlet.setInitParameter("resourceBase", "www"); + staticServlet.setInitParameter("pathInfoOnly", "true"); + + registerAuthFilters(context); + + try { + + serverLogger.info("Starting jetty server"); + String unitTest = params.getProperty("UnitTest", "No"); + serverLogger.info("UnitTest=" + unitTest); + if (unitTest.equals("No")) { + server.start(); + server.dumpStdErr(); + server.join(); + } + } catch (Exception e) { + errorLogger.error("Exception " + e); + } finally { + server.destroy(); + } + + } + + private void registerAuthFilters(ServletContextHandler context) { + context.addFilter("org.onap.dmaap.dbcapi.resources.AAFAuthenticationFilter", "/webapi/*", + Sets.newEnumSet(Sets.newHashSet(DispatcherType.FORWARD, DispatcherType.REQUEST), DispatcherType.class)); + context.addFilter("org.onap.dmaap.dbcapi.resources.AAFAuthorizationFilter", "/webapi/*", + Sets.newEnumSet(Sets.newHashSet(DispatcherType.FORWARD, DispatcherType.REQUEST), DispatcherType.class)); + } + + private void setUpKeystore(SslContextFactory sslContextFactory) { + String keystore = JettyServer.certificateManager.getKeyStoreFile(); + logger.info("https Server using keystore at " + keystore); + sslContextFactory.setKeyStorePath(keystore); + sslContextFactory.setKeyStoreType(JettyServer.certificateManager.getKeyStoreType()); + sslContextFactory.setKeyStorePassword(JettyServer.certificateManager.getKeyStorePassword()); + sslContextFactory.setKeyManagerPassword(JettyServer.certificateManager.getKeyStorePassword()); + } + + private void setUpTrustStore(SslContextFactory sslContextFactory) { + String truststore = JettyServer.certificateManager.getTrustStoreFile(); + logger.info("https Server using truststore at " + truststore); + sslContextFactory.setTrustStorePath(truststore); + sslContextFactory.setTrustStoreType(JettyServer.certificateManager.getTrustStoreType()); + sslContextFactory.setTrustStorePassword(JettyServer.certificateManager.getTrustStorePassword()); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/LegacyCertificateManager.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/LegacyCertificateManager.java new file mode 100644 index 0000000..bd54003 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/LegacyCertificateManager.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2020 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.server; + +import java.util.Properties; + +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class LegacyCertificateManager extends CertificateManager { + + public LegacyCertificateManager(Properties properties ) { + setKeyStoreType( properties.getProperty("KeyStoreType", "jks") ); + setKeyStoreFile( properties.getProperty("KeyStoreFile", "etc/keystore") ); + setKeyStorePassword( properties.getProperty("KeyStorePassword", "changeit") ); + + setTrustStoreFile( properties.getProperty("TrustStoreFile", "etc/org.onap.dmaap-bc.trust.jks") ); + setTrustStoreType( properties.getProperty("TrustStoreType", "jks") ); + setTrustStorePassword( properties.getProperty("TrustStorePassword", "changeit") ); + ready = true; + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/Main.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/Main.java new file mode 100644 index 0000000..942fe6c --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/server/Main.java @@ -0,0 +1,93 @@ +/*- + * ============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.server; +import static com.att.eelf.configuration.Configuration.MDC_ALERT_SEVERITY; +import static com.att.eelf.configuration.Configuration.MDC_INSTANCE_UUID; +import static com.att.eelf.configuration.Configuration.MDC_SERVER_FQDN; +import static com.att.eelf.configuration.Configuration.MDC_SERVER_IP_ADDRESS; +import static com.att.eelf.configuration.Configuration.MDC_SERVICE_INSTANCE_ID; +import static com.att.eelf.configuration.Configuration.MDC_TARGET_ENTITY; + +import java.net.InetAddress; +import java.util.Properties; +import java.util.UUID; +import org.onap.dmaap.dbcapi.authentication.ApiPerms; +import org.onap.dmaap.dbcapi.authentication.ApiPolicy; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.Singleton; +import org.slf4j.MDC; + +public class Main extends BaseLoggingClass { + + private static String provFQDN; + public static String getProvFQDN() { + return provFQDN; + } + public void setProvFQDN(String provFQDN) { + Main.provFQDN = provFQDN; + } + private Main() { + } + public static void main(String[] args) { + (new Main()).main(); + } + + private void main() { + + MDC.clear(); + + MDC.put(MDC_SERVICE_INSTANCE_ID, ""); + try { + MDC.put(MDC_SERVER_FQDN, InetAddress.getLocalHost().getHostName()); + MDC.put(MDC_SERVER_IP_ADDRESS, InetAddress.getLocalHost().getHostAddress()); + } catch (Exception e) { + errorLogger.error("Error while getting hostname or address", e); + } + MDC.put(MDC_INSTANCE_UUID, UUID.randomUUID().toString()); + MDC.put(MDC_ALERT_SEVERITY, "0"); + MDC.put(MDC_TARGET_ENTITY, "DCAE"); + + appLogger.info("Started."); + Properties parameters = DmaapConfig.getConfig(); + setProvFQDN( parameters.getProperty("ProvFQDN", "ProvFQDN.notset.com")); + + // for fresh installs, we may come up with no dmaap name so need to have a way for Controller to talk to us + Singleton<Dmaap> dmaapholder = DatabaseClass.getDmaap(); + String name = dmaapholder.get().getDmaapName(); + ApiPolicy apiPolicy = new ApiPolicy(); + if ( apiPolicy.isPermissionClassSet() && (name == null || name.isEmpty())) { + ApiPerms p = new ApiPerms(); + p.setBootMap(); + } + + try { + new JettyServer(parameters); + } catch (Exception e) { + errorLogger.error("Unable to start Jetty " + DmaapConfig.getConfigFileName(), e); + System.exit(1); + } + + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/AafPermissionService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/AafPermissionService.java new file mode 100644 index 0000000..1997633 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/AafPermissionService.java @@ -0,0 +1,122 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.service; + +import org.onap.dmaap.dbcapi.aaf.AafService; +import org.onap.dmaap.dbcapi.aaf.AafUserRole; +import org.onap.dmaap.dbcapi.aaf.DmaapGrant; +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.model.MR_Client; + +import static java.lang.String.format; + +class AafPermissionService extends BaseLoggingClass { + + private static final String INSTANCE_PREFIX = ":topic."; + private final AafService aafService; + private final DmaapService dmaapService; + + AafPermissionService(AafService aafService, DmaapService dmaapService) { + this.aafService = aafService; + this.dmaapService = dmaapService; + } + + ApiError assignClientToRole(MR_Client client, String role) { + AafUserRole ur = new AafUserRole(client.getClientIdentity(), role); + int rc = aafService.addUserRole(ur); + if (rc != 201 && rc != 409) { + return handleErrorStatus(rc, client, + format("Failed to add user %s to role %s", client.getClientIdentity(), role)); + } + return handleOkStatus(client); + } + + ApiError grantClientRolePerms(MR_Client client) { + return forEachClientAction(client, this::grantPermForClientRole); + } + + private ApiError forEachClientAction(MR_Client client, PermissionUpdate permissionUpdate) { + try { + String instance = INSTANCE_PREFIX + client.getFqtn(); + + for (String action : client.getAction()) { + permissionUpdate.execute(client.getClientRole(), instance, action); + } + + } catch (PermissionServiceException e) { + return handleErrorStatus(e.getCode(), client, e.getMessage()); + } + return handleOkStatus(client); + } + + private void grantPermForClientRole(String clientRole, String instance, String action) throws PermissionServiceException { + if (clientRole != null) { + DmaapPerm perm = new DmaapPerm(dmaapService.getTopicPerm(), instance, action); + DmaapGrant g = new DmaapGrant(perm, clientRole); + int code = aafService.addGrant(g); + if (code != 201 && code != 409) { + throw new PermissionServiceException(code, format("Grant of %s|%s|%s failed for %s", + dmaapService.getTopicPerm(), instance, action, clientRole)); + } + } else { + logger.warn("No Grant of {}|{}|{} because role is null ", dmaapService.getTopicPerm(), instance, action); + } + } + + private ApiError handleErrorStatus(int code, MR_Client client, String message) { + ApiError apiError = new ApiError(code, message); + client.setStatus(DmaapObject_Status.INVALID); + logger.warn(apiError.getMessage()); + return apiError; + } + + private ApiError handleOkStatus(MR_Client client) { + client.setStatus(DmaapObject_Status.VALID); + return new ApiError(200, "OK"); + } + + private class PermissionServiceException extends Exception { + private final int code; + private final String message; + + PermissionServiceException(int code, String message) { + this.code = code; + this.message = message; + } + + public int getCode() { + return code; + } + + @Override + public String getMessage() { + return message; + } + } + + @FunctionalInterface + interface PermissionUpdate { + void execute(String clientRole, String instance, String action) throws PermissionServiceException; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/AafTopicSetupService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/AafTopicSetupService.java new file mode 100644 index 0000000..16ffa08 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/AafTopicSetupService.java @@ -0,0 +1,218 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.service; + +import org.onap.dmaap.dbcapi.aaf.AafNamespace; +import org.onap.dmaap.dbcapi.aaf.AafRole; +import org.onap.dmaap.dbcapi.aaf.AafService; +import org.onap.dmaap.dbcapi.aaf.DmaapGrant; +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +import static java.lang.String.format; +import static org.apache.commons.lang3.StringUtils.isNumeric; + +class AafTopicSetupService extends BaseLoggingClass { + + private final AafService aafService; + private final DmaapService dmaapService; + private final DmaapConfig dmaapConfig; + + AafTopicSetupService(AafService aafService, DmaapService dmaapService, DmaapConfig dmaapConfig) { + this.aafService = aafService; + this.dmaapService = dmaapService; + this.dmaapConfig = dmaapConfig; + } + + ApiError aafTopicSetup(Topic topic) { + + try { + String instance = ":topic." + topic.getFqtn(); + String topicPerm = dmaapService.getTopicPerm(); + DmaapPerm pubPerm = createPermission(topicPerm, instance, "pub"); + DmaapPerm subPerm = createPermission(topicPerm, instance, "sub"); + DmaapPerm viewPerm = createPermission(topicPerm, instance, "view"); + + // creating Topic Roles was not an original feature. + // For backwards compatibility, only do this if the feature is enabled. + // Also, if the namespace of the topic is a foreign namespace, (i.e. not the same as our root ns) + // then we likely don't have permission to create sub-ns and Roles so don't try. + if (createTopicRoles() && topic.getFqtn().startsWith(getTopicsNsRoot())) { + createNamespace(topic); + + AafRole pubRole = createRole(topic, "publisher"); + topic.setPublisherRole(pubRole.getFullyQualifiedRole()); + + AafRole subRole = createRole(topic, "subscriber"); + topic.setSubscriberRole(subRole.getFullyQualifiedRole()); + + grantPermToRole(pubRole, pubPerm); + grantPermToRole(pubRole, viewPerm); + + grantPermToRole(subRole, subPerm); + grantPermToRole(subRole, viewPerm); + } + + } catch (TopicSetupException ex) { + logger.error("Exception in topic setup {}", ex.getMessage()); + return new ApiError(ex.getCode(), ex.getMessage(), ex.getFields()); + } + return okStatus(); + } + + ApiError aafTopicCleanup(Topic topic) { + try { + if (performCleanup()) { + String instance = ":topic." + topic.getFqtn(); + String topicPerm = dmaapService.getTopicPerm(); + removePermission(topicPerm, instance, "pub"); + removePermission(topicPerm, instance, "sub"); + removePermission(topicPerm, instance, "view"); + + if (createTopicRoles() && topic.getFqtn().startsWith(getTopicsNsRoot())) { + removeNamespace(topic); + } + } + } catch (TopicSetupException ex) { + return new ApiError(ex.getCode(), ex.getMessage(), ex.getFields()); + } + return okStatus(); + } + + private String getTopicsNsRoot() throws TopicSetupException { + String nsr = dmaapService.getDmaap().getTopicNsRoot(); + if (nsr == null) { + throw new TopicSetupException(500, + "Unable to establish AAF namespace root: (check /dmaap object)", "topicNsRoot"); + } + return nsr; + } + + private DmaapPerm createPermission(String permission, String instance, String action) throws TopicSetupException { + DmaapPerm perm = new DmaapPerm(permission, instance, action); + int rc = aafService.addPerm(perm); + if (rc != 201 && rc != 409) { + throw new TopicSetupException(500, + format("Unexpected response from AAF: %d permission=%s instance=%s action=%s", + rc, perm, instance, action)); + } + return perm; + } + + private void grantPermToRole(AafRole aafRole, DmaapPerm perm) throws TopicSetupException { + DmaapGrant g = new DmaapGrant(perm, aafRole.getFullyQualifiedRole()); + int rc = aafService.addGrant(g); + if (rc != 201 && rc != 409) { + String message = format("Grant of %s failed for %s", perm.toString(), aafRole.getFullyQualifiedRole()); + logger.warn(message); + throw new TopicSetupException(rc, message); + } + } + + private void createNamespace(Topic topic) throws TopicSetupException { + AafNamespace ns = new AafNamespace(topic.getFqtn(), aafService.getIdentity()); + int rc = aafService.addNamespace(ns); + if (rc != 201 && rc != 409) { + throw new TopicSetupException(500, + format("Unexpected response from AAF: %d namespace=%s identity=%s", + rc, topic.getFqtn(), aafService.getIdentity())); + } + } + + private AafRole createRole(Topic topic, String roleName) throws TopicSetupException { + AafRole role = new AafRole(topic.getFqtn(), roleName); + int rc = aafService.addRole(role); + if (rc != 201 && rc != 409) { + throw new TopicSetupException(500, + format("Unexpected response from AAF: %d topic=%s role=%s", + rc, topic.getFqtn(), roleName)); + } + return role; + } + + private void removePermission(String permission, String instance, String action) throws TopicSetupException { + DmaapPerm perm = new DmaapPerm(permission, instance, action); + int rc = aafService.delPerm(perm, true); + if (rc != 200 && rc != 404) { + throw new TopicSetupException(500, + format("Unexpected response from AAF: %d permission=%s instance=%s action=%s", + rc, perm, instance, action)); + } + } + + private void removeNamespace(Topic topic) throws TopicSetupException { + AafNamespace ns = new AafNamespace(topic.getFqtn(), aafService.getIdentity()); + int rc = aafService.delNamespace(ns, true); + if (rc != 200 && rc != 404) { + throw new TopicSetupException(500, + format("Unexpected response from AAF: %d namespace=%s identity=%s", + rc, topic.getFqtn(), aafService.getIdentity())); + } + } + + private ApiError okStatus() { + return new ApiError(200, "OK"); + } + + private boolean createTopicRoles() { + return "true".equalsIgnoreCase(dmaapConfig.getProperty("aaf.CreateTopicRoles", "true")); + } + + private boolean performCleanup() { + String deleteLevel = dmaapConfig.getProperty("MR.ClientDeleteLevel", "0"); + if (!isNumeric(deleteLevel)) { + return false; + } + return Integer.valueOf(deleteLevel) >= 2; + } + + private class TopicSetupException extends Exception { + + private final int code; + private final String message; + private final String fields; + + TopicSetupException(int code, String message) { + this(code, message, ""); + } + + TopicSetupException(int code, String message, String fields) { + this.code = code; + this.message = message; + this.fields = fields; + } + + public int getCode() { + return code; + } + + @Override + public String getMessage() { + return message; + } + + public String getFields() { + return fields; + } + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/ApiService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/ApiService.java new file mode 100644 index 0000000..ef1e6f4 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/ApiService.java @@ -0,0 +1,159 @@ +/*- + * ============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.service; + +import static com.att.eelf.configuration.Configuration.MDC_KEY_REQUEST_ID; +import static com.att.eelf.configuration.Configuration.MDC_SERVICE_NAME; + +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.authentication.ApiPolicy; +import org.onap.dmaap.dbcapi.authentication.AuthenticationErrorException; +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.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.RandomString; +import org.slf4j.MDC; + +public class ApiService extends BaseLoggingClass { + + private String apiNamespace; + private String uri; + private String uriPath; + private String method; + private String authorization; + private String requestId; + private ApiError err; + private ApiPolicy apiPolicy; + private CredentialsParser credentialsParser = new CredentialsParser(); + + public ApiService() { + + err = new ApiError(); + requestId = (new RandomString(10)).nextString(); + + if (apiNamespace == null) { + DmaapConfig p = (DmaapConfig) DmaapConfig.getConfig(); + apiNamespace = p.getProperty("ApiNamespace", "org.openecomp.dmaapBC.api"); + logger.info("config param usePE has been deprecated. Use ApiPermission.Class property instead."); + } + apiPolicy = new ApiPolicy(); + + logger.info("apiNamespace=" + apiNamespace); + } + + public ApiService setAuth(String auth) { + this.authorization = auth; + logger.info("setAuth: authorization={} ", authorization); + return this; + } + + private void setServiceName() { + String svcRequest = new String(this.method + " " + this.uriPath); + MDC.put(MDC_SERVICE_NAME, svcRequest); + } + + public ApiService setHttpMethod(String httpMethod) { + this.method = httpMethod; + logger.info("setHttpMethod: method={} ", method); + setServiceName(); + return this; + } + + public ApiService setUriPath(String uriPath) { + this.uriPath = uriPath; + this.uri = setUriFromPath(uriPath); + logger.info("setUriPath: uriPath={} uri={}", uriPath, uri); + setServiceName(); + return this; + } + + private String setUriFromPath(String uriPath) { + int ch = uriPath.indexOf("/"); + if (ch > 0) { + return ((String) uriPath.subSequence(0, ch)); + } else { + return uriPath; + } + } + + public ApiError getErr() { + return err; + } + + public void checkAuthorization() throws Exception { + + MDC.put(MDC_KEY_REQUEST_ID, requestId); + + logger.info("request: uri={} method={} auth={}", uri, method, authorization); + + if (uri == null || uri.isEmpty()) { + String errmsg = "No URI value provided "; + err.setMessage(errmsg); + logger.info(errmsg); + throw new AuthenticationErrorException(); + } + if (method == null || method.isEmpty()) { + String errmsg = "No method value provided "; + err.setMessage(errmsg); + logger.info(errmsg); + throw new AuthenticationErrorException(); + } + DmaapService dmaapService = new DmaapService(); + Dmaap dmaap = dmaapService.getDmaap(); + String env = dmaap.getDmaapName(); + + // special case during bootstrap of app when DMaaP environment may not be set. + // this allows us to authorize certain APIs used for initialization during this window. + if (env == null || env.isEmpty()) { + env = "boot"; + } + if (!apiPolicy.isPermissionClassSet()) { + return; // skip authorization if not enabled + } + + Credentials credentials = credentialsParser.parse(authorization); + try { + DmaapPerm p = new DmaapPerm(apiNamespace + "." + uri, env, method); + apiPolicy.check(credentials.getId(), credentials.getPwd(), p); + } catch (AuthenticationErrorException ae) { + String errmsg = + "User " + credentials.getId() + " failed authentication/authorization for " + apiNamespace + "." + uriPath + " " + env + + " " + method; + logger.info(errmsg); + err.setMessage(errmsg); + throw ae; + + } + } + + public ApiService setRequestId(String requestId) { + if (requestId == null || requestId.isEmpty()) { + this.requestId = (new RandomString(10)).nextString(); + logger.warn("X-ECOMP-RequestID not set in HTTP Header. Setting RequestId value to: " + this.requestId); + } else { + this.requestId = requestId; + } + MDC.put(MDC_KEY_REQUEST_ID, this.requestId); + return this; + } +} + diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/Credentials.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/Credentials.java new file mode 100644 index 0000000..aee9b4f --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/Credentials.java @@ -0,0 +1,44 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.service; + +public class Credentials { + + private final String id; + private final String pwd; + + Credentials(String id, String pwd) { + this.id = id; + this.pwd = pwd; + } + + static Credentials empty() { + return new Credentials("", ""); + } + + public String getId() { + return id; + } + + public String getPwd() { + return pwd; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/CredentialsParser.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/CredentialsParser.java new file mode 100644 index 0000000..4156d1b --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/CredentialsParser.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.service; + +import javax.xml.bind.DatatypeConverter; + +class CredentialsParser { + + Credentials parse(String authorizationHeader) { + if (authorizationHeader == null || authorizationHeader.isEmpty()) { + return Credentials.empty(); + } + + String credentials = authorizationHeader.substring("Basic".length()).trim(); + byte[] decoded = DatatypeConverter.parseBase64Binary(credentials); + String decodedString = new String(decoded); + String[] actualCredentials = decodedString.split(":"); + return new Credentials(actualCredentials[0], actualCredentials[1]); + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DR_NodeService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DR_NodeService.java new file mode 100644 index 0000000..b29beb9 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DR_NodeService.java @@ -0,0 +1,273 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dcae + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.Response.Status; +import org.onap.dmaap.dbcapi.client.DrProvConnection; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DR_Node; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + + +public class DR_NodeService extends BaseLoggingClass { + private class DrProv { + String currentNodes; + String currentStaticNodes; + + private String getX( String X, ApiError apiError ) { + + logger.info( "templog:getX at" + " 12.10.10" ); + DrProvConnection prov = new DrProvConnection(); + logger.info( "templog:getX at" + " 12.10.12" ); + prov.makeNodesConnection( X ); + logger.info( "templog:getX at" + " 12.10.14" ); + String resp = prov.doGetNodes( apiError ); + logger.info( "templog:getX at" + " 12.10.16" ); + logger.info( "rc=" + apiError.getCode() ); + logger.info( "templog:getX at" + " 12.10.18" ); + return resp; + } + + private void setX( String X, String list, ApiError apiError ) { + DrProvConnection prov = new DrProvConnection(); + prov.makeNodesConnection( X, list ); + prov.doPutNodes( apiError ); + } + + private String removeFromList( String aNode, String aList ) { + String[] nodeList = aList.split("\\|"); + StringBuilder res = new StringBuilder(); + for ( String n: nodeList ) { + logger.info( "compare existing node " + n + " vs " + aNode ); + if ( ! n.equals(aNode)) { + if (res.length() > 0 ) { + res.append( "|" ); + } + res.append(n); + } + } + logger.info( "result=" + res.toString() ); + return res.toString(); + } + + boolean containsNode( String aNode , ApiError apiError ){ + + logger.info( "templog:containsNode at" + " 12.10" ); + //DrProvConnection prov = new DrProvConnection(); + //prov.makeNodesConnection(); + currentNodes = getX( "NODES", apiError ); + logger.info( "templog:containsNode at" + " 12.12" ); + if ( ! apiError.is2xx() || currentNodes == null ) { + logger.info( "templog:containsNode at" + " 12.14" ); + return false; + } + logger.info( "templog:containsNode at" + " 12.16" ); + logger.info( "NODES now=" + currentNodes ); + String[] nodeList = currentNodes.split("\\|"); + logger.info( "templog:containsNode at" + " 12.17" ); + for( String n: nodeList ) { + logger.info( "templog:containsNode at" + " 12.18" ); + logger.info( "compare existing node " + n + " vs " + aNode ); + if ( n.equals(aNode) ) { + return true; + } + } + return false; + } + + void addNode( String aNode, ApiError apiError ) { + + currentNodes = currentNodes + "|" + aNode; + setX( "NODES", currentNodes, apiError ); + + + } + void removeNode( String aNode, ApiError apiError ) { + currentNodes = removeFromList( aNode, currentNodes ); + setX( "NODES", currentNodes, apiError ); + } + + public boolean containsStaticNode(String aNode, ApiError apiError) { + + //DrProvConnection prov = new DrProvConnection(); + //prov.makeNodesConnection(); + currentStaticNodes = getX( "STATIC_ROUTING_NODES", apiError ); + if (! apiError.is2xx() || currentStaticNodes == null ) { + return false; + } + logger.info( "STATIC_ROUTING_NODES now=" + currentNodes ); + String[] nodeList = currentStaticNodes.split("\\|"); + for( String n: nodeList ) { + logger.info( "compare existing node " + n + " vs " + aNode ); + if ( n.equals(aNode) ) { + return true; + } + } + return false; + } + + + public void addStaticNode(String aNode, ApiError apiError) { + currentStaticNodes = currentStaticNodes + "|" + aNode; + setX( "STATIC_ROUTING_NODES", currentStaticNodes, apiError ); + } + void removeStaticNode( String aNode, ApiError apiError ) { + currentStaticNodes = removeFromList( aNode, currentStaticNodes ); + setX( "STATIC_ROUTING_NODES", currentStaticNodes, apiError ); + } + } + + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + String unit_test = p.getProperty( "UnitTest", "No" ); + + private Map<String, DR_Node> dr_nodes = DatabaseClass.getDr_nodes(); + + public Map<String, DR_Node> getDr_Nodes() { + return dr_nodes; + } + + public List<DR_Node> getAllDr_Nodes() { + return new ArrayList<DR_Node>(dr_nodes.values()); + } + + public DR_Node getDr_Node( String fqdn, ApiError apiError ) { + DR_Node old = dr_nodes.get( fqdn ); + if ( old == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "fqdn"); + apiError.setMessage( "Node " + fqdn + " does not exist"); + return null; + } + apiError.setCode(200); + return old; + } + + public DR_Node addDr_Node( DR_Node node, ApiError apiError ) { + String fqdn = node.getFqdn(); + DR_Node old = dr_nodes.get( fqdn ); + if ( old != null ) { + apiError.setCode(Status.CONFLICT.getStatusCode()); + apiError.setFields( "fqdn"); + apiError.setMessage( "Node " + fqdn + " already exists"); + return null; + } + logger.info( "templog:addDr_Node at" + " 10" ); + + DrProv drProv = new DrProv(); + logger.info( "templog:addDr_Node at" + " 12" ); + + if ( ! drProv.containsNode( node.getFqdn(), apiError ) && apiError.is2xx() ) { + logger.info( "templog:addDr_Node at" + " 15" ); + drProv.addNode( node.getFqdn(), apiError ); + } + logger.info( "templog:addDr_Node at" + " 20" ); + if ( ! apiError.is2xx() && ! unit_test.equals( "Yes" ) ) { + return null; + } + logger.info( "templog:addDr_Node at" + " 30" ); + DcaeLocationService locService = new DcaeLocationService(); + if ( locService.isEdgeLocation( node.getDcaeLocationName()) && ! drProv.containsStaticNode( node.getFqdn(), apiError ) ) { + if ( apiError.is2xx() ) { + drProv.addStaticNode( node.getFqdn(), apiError ); + } + } + logger.info( "templog:addDr_Node at" + " 40" ); + if ( ! apiError.is2xx() && ! unit_test.equals("Yes") ) { + return null; + } + + logger.info( "templog:addDr_Node at" + " 50" ); + node.setLastMod(); + node.setStatus(DmaapObject_Status.VALID); + dr_nodes.put( node.getFqdn(), node ); + logger.info( "templog:addDr_Node at" + " 60" ); + apiError.setCode(200); + return node; + } + + public DR_Node updateDr_Node( DR_Node node, ApiError apiError ) { + DR_Node old = dr_nodes.get( node.getFqdn() ); + if ( old == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "fqdn"); + apiError.setMessage( "Node " + node.getFqdn() + " does not exist"); + return null; + } + node.setLastMod(); + dr_nodes.put( node.getFqdn(), node ); + apiError.setCode(200); + return node; + } + + public DR_Node removeDr_Node( String nodeName, ApiError apiError ) { + DR_Node old = dr_nodes.get( nodeName ); + if ( old == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "fqdn"); + apiError.setMessage( "Node " + nodeName + " does not exist"); + return null; + } + + DrProv drProv = new DrProv(); + if ( drProv.containsNode( old.getFqdn(), apiError ) && apiError.is2xx() ) { + drProv.removeNode( old.getFqdn(), apiError ); + } + DcaeLocationService locService = new DcaeLocationService(); + if ( locService.isEdgeLocation( old.getDcaeLocationName()) && drProv.containsStaticNode( old.getFqdn(), apiError ) ) { + if ( apiError.is2xx()) { + drProv.removeStaticNode( old.getFqdn(), apiError ); + } + + } + + apiError.setCode(200); + return dr_nodes.remove(nodeName); + } + + public String getNodePatternAtLocation( String loc, boolean allowMult ) { + logger.info( "loc=" + loc ); + if ( loc == null ) { + return null; + } + StringBuilder str = new StringBuilder(); + for( DR_Node node : dr_nodes.values() ) { + if ( loc.equals( node.getDcaeLocationName()) ) { + if ( str.length() > 0 ) { + str.append( ","); + } + str.append( node.getFqdn()); + if ( ! allowMult ) { + break; + } + } + } + logger.info( "returning " + str.toString() ); + return str.toString(); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DR_PubService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DR_PubService.java new file mode 100644 index 0000000..352330a --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DR_PubService.java @@ -0,0 +1,147 @@ +/*- + * ============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.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.Response.Status; +import org.onap.dmaap.dbcapi.client.DrProvConnection; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DR_Pub; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; + +public class DR_PubService extends BaseLoggingClass{ + + private Map<String, DR_Pub> dr_pubs = DatabaseClass.getDr_pubs(); + private DR_NodeService nodeService = new DR_NodeService(); + private static DrProvConnection prov; + + public DR_PubService() { + super(); + prov = new DrProvConnection(); + } + + public Map<String, DR_Pub> getDr_Pubs() { + return dr_pubs; + } + + public List<DR_Pub> getAllDr_Pubs() { + return new ArrayList<DR_Pub>(dr_pubs.values()); + } + + public ArrayList<DR_Pub> getDr_PubsByFeedId( String feedId ) { + ArrayList<DR_Pub> somePubs = new ArrayList<DR_Pub>(); + for( DR_Pub pub : dr_pubs.values() ) { + if ( feedId.equals( pub.getFeedId() )) { + somePubs.add( pub ); + } + } + + return somePubs; + } + + public DR_Pub getDr_Pub( String key, ApiError err ) { + DR_Pub pub = dr_pubs.get( key ); + if ( pub == null ) { + err.setCode(Status.NOT_FOUND.getStatusCode()); + err.setFields( "pubId"); + err.setMessage("DR_Pub with pubId = " + key + " not found"); + } else { + err.setCode(Status.OK.getStatusCode()); + } + return pub; + } + + private void addIngressRoute( DR_Pub pub, ApiError err ) { + + String nodePattern = nodeService.getNodePatternAtLocation( pub.getDcaeLocationName(), true ); + if ( nodePattern != null && nodePattern.length() > 0 ) { + logger.info( "creating ingress rule: pub " + pub.getPubId() + " on feed " + pub.getFeedId() + " to " + nodePattern); + prov.makeIngressConnection( pub.getFeedId(), pub.getUsername(), "-", nodePattern); + int rc = prov.doXgressPost(err); + logger.info( "rc=" + rc + " error code=" + err.getCode() ); + + if ( rc != 200 ) { + switch( rc ) { + case 403: + logger.error( "Not authorized for DR ingress API"); + err.setCode(500); + err.setMessage("API deployment/configuration error - contact support"); + err.setFields( "PROV_AUTH_ADDRESSES"); + break; + + default: + logger.info( DmaapbcLogMessageEnum.INGRESS_CREATE_ERROR, Integer.toString(rc), pub.getPubId(), pub.getFeedId(), nodePattern); + } + } + + } + } + + public DR_Pub addDr_Pub( DR_Pub pub ) { + ApiError err = new ApiError(); + if ( pub.getPubId() != null && ! pub.getPubId().isEmpty() ) { + addIngressRoute( pub, err); + if ( err.getCode() > 0 ) { + pub.setStatus(DmaapObject_Status.INVALID); + } + pub.setLastMod(); + dr_pubs.put( pub.getPubId(), pub ); + return pub; + } + else { + return null; + } + } + + public DR_Pub updateDr_Pub( DR_Pub pub ) { + if ( pub.getPubId().isEmpty()) { + return null; + } + pub.setLastMod(); + dr_pubs.put( pub.getPubId(), pub ); + return pub; + } + + public DR_Pub removeDr_Pub( String pubId, ApiError err ) { + return removeDr_Pub( pubId, err, true ); + } + + + public DR_Pub removeDr_Pub( String pubId, ApiError err, boolean hitDR ) { + DR_Pub pub = dr_pubs.get( pubId ); + if ( pub == null ) { + err.setCode(Status.NOT_FOUND.getStatusCode()); + err.setFields( "pubId"); + err.setMessage( "pubId " + pubId + " not found"); + } else { + dr_pubs.remove(pubId); + err.setCode(Status.OK.getStatusCode()); + } + return pub; + + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DR_SubService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DR_SubService.java new file mode 100644 index 0000000..0a583a0 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DR_SubService.java @@ -0,0 +1,228 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.Response.Status; + +import org.onap.dmaap.dbcapi.client.DrProvConnection; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DR_Sub; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.RandomInteger; + +public class DR_SubService extends BaseLoggingClass { + + private Map<String, DR_Sub> dr_subs = DatabaseClass.getDr_subs(); + private DR_NodeService nodeService = new DR_NodeService(); + private String provURL; + private static DrProvConnection prov; + + private String unit_test; + + + public DR_SubService( ) { + logger.debug( "Entry: DR_SubService (with no args)" ); + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + unit_test = p.getProperty( "UnitTest", "No" ); + } + public DR_SubService( String subURL ) { + logger.debug( "Entry: DR_SubService " + subURL ); + provURL = subURL; + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + unit_test = p.getProperty( "UnitTest", "No" ); + } + public Map<String, DR_Sub> getDR_Subs() { + logger.debug( "enter getDR_Subs()"); + return dr_subs; + } + + public List<DR_Sub> getAllDr_Subs() { + logger.debug( "enter getAllDR_Subs()"); + return new ArrayList<>(dr_subs.values()); + } + + public ArrayList<DR_Sub> getDr_SubsByFeedId( String pubId ) { + ArrayList<DR_Sub> someSubs = new ArrayList<>(); + for( DR_Sub sub : dr_subs.values() ) { + if ( pubId.equals( sub.getFeedId() )) { + someSubs.add( sub ); + } + } + + return someSubs; + } + public DR_Sub getDr_Sub( String key, ApiError apiError ) { + logger.debug( "enter getDR_Sub()"); + DR_Sub sub = dr_subs.get( key ); + if ( sub == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "subId"); + apiError.setMessage("subId " + key + " not found"); + } else { + apiError.setCode(200); + } + return sub; + } + + public DR_Sub addDr_Sub( DR_Sub sub, ApiError apiError ) { + logger.debug( "enter addDR_Subs()"); + prov = new DrProvConnection(); + prov.makeSubPostConnection( provURL ); + String resp = prov.doPostDr_Sub( sub, apiError ); + if ( "Yes".equals(unit_test) ) { + resp = simulateResp( sub, "POST" ); + apiError.setCode(201); + } + logger.debug( "addDr_Sub resp=" + resp ); + + DR_Sub snew = null; + + if ( resp != null ) { + snew = new DR_Sub( resp ); + snew.setDcaeLocationName(sub.getDcaeLocationName()); + snew.setLastMod(); + addEgressRoute( snew, apiError ); + dr_subs.put( snew.getSubId(), snew ); + apiError.setCode(201); + } else { + apiError.setCode(400); + } + + return snew; + } + + private void addEgressRoute( DR_Sub sub, ApiError err ) { + + String nodePattern = nodeService.getNodePatternAtLocation( sub.getDcaeLocationName(), false ); + if ( nodePattern != null && nodePattern.length() > 0 ) { + logger.info( "creating egress rule: sub " + sub.getSubId() + " on feed " + sub.getFeedId() + " to " + nodePattern); + prov.makeEgressConnection( sub.getSubId(), nodePattern); + int rc = prov.doXgressPost(err); + logger.info( "rc=" + rc + " error code=" + err.getCode() ); + + if ( rc != 200 ) { + switch( rc ) { + case 403: + logger.error( "Not authorized for DR egress API"); + err.setCode(500); + err.setMessage("API deployment/configuration error - contact support"); + err.setFields( "PROV_AUTH_ADDRESSES"); + break; + + default: + logger.info( DmaapbcLogMessageEnum.EGRESS_CREATE_ERROR, Integer.toString(rc), sub.getSubId(), sub.getFeedId(), nodePattern); + } + } + + } + } + + public DR_Sub updateDr_Sub( DR_Sub obj, ApiError apiError ) { + logger.debug( "enter updateDR_Subs()"); + + DrProvConnection prov = new DrProvConnection(); + prov.makeSubPutConnection( obj.getSubId() ); + String resp = prov.doPutDr_Sub( obj, apiError ); + if ( unit_test.equals( "Yes" ) ) { + resp = simulateResp( obj, "PUT" ); + apiError.setCode(200); + } + logger.debug( "resp=" + resp ); + + DR_Sub snew = null; + + if ( resp != null ) { + snew = new DR_Sub( resp ); + snew.setDcaeLocationName(obj.getDcaeLocationName()); + snew.setLastMod(); + dr_subs.put( snew.getSubId(), snew ); + apiError.setCode(200); + } else if ( apiError.is2xx()) { + apiError.setCode(400); + apiError.setMessage("unexpected empty response from DR Prov"); + } + + return snew; + } + + public void removeDr_Sub( String key, ApiError apiError ) { + removeDr_Sub( key, apiError, true ); + return; + } + + public void removeDr_Sub( String key, ApiError apiError, boolean hitDR ) { + logger.debug( "enter removeDR_Subs()"); + + DR_Sub sub = dr_subs.get( key ); + if ( sub == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "subId"); + apiError.setMessage("subId " + key + " not found"); + } else { + if ( hitDR ) { + DrProvConnection prov = new DrProvConnection(); + prov.makeSubPutConnection( key ); + String resp = prov.doDeleteDr_Sub( sub, apiError ); + logger.debug( "resp=" + resp ); + } else { + apiError.setCode(200); + } + + if ( apiError.is2xx() || unit_test.equals( "Yes" ) ) { + dr_subs.remove(key); + } + } + + return; + } + + private String simulateResp( DR_Sub sub, String action ){ + String server = "subscriber.onap.org"; + String subid; + if ( action.equals( "POST" ) ) { + RandomInteger ran = new RandomInteger(10000); + subid = Integer.toString( ran.next() ); + } else if ( action.equals( "PUT" ) ) { + subid = sub.getSubId(); + } else { + subid = "99"; + } + String ret = String.format("{\"suspend\": false, \"delivery\": {\"url\": \"https://%s/delivery/%s\", \"user\": \"%s\", \"password\": \"%s\", \"use100\": true}, \"metadataOnly\": false, \"groupid\": \"0\" , \"follow_redirect\": true, ", + server, subid, sub.getUsername(), sub.getUserpwd()); + String links = String.format( "\"links\": {\"feed\": \"https://dr-prov/feedlog/%s\", \"self\": \"https://dr-prov/sub/%s\", \"log\": \"https://dr-prov/sublog/%s\" }", + sub.getFeedId(), + subid, + subid ); + ret += links + "}"; + logger.info( "DR_SubService:simulateResp=" + ret); + + return ret; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DcaeLocationService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DcaeLocationService.java new file mode 100644 index 0000000..ad6c993 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DcaeLocationService.java @@ -0,0 +1,85 @@ +/*- + * ============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.service; + +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class DcaeLocationService { + + private static final String DEFAULT_CENTRAL_LOCATION = "aCentralLocation"; // default value that is obvious to see is wrong + private final Map<String, DcaeLocation> dcaeLocations; + + public DcaeLocationService() { + this(DatabaseClass.getDcaeLocations()); + } + + DcaeLocationService(Map<String, DcaeLocation> dcaeLocations) { + this.dcaeLocations = dcaeLocations; + } + + public List<DcaeLocation> getAllDcaeLocations() { + return new ArrayList<>(dcaeLocations.values()); + } + + public DcaeLocation getDcaeLocation(String name) { + return dcaeLocations.get(name); + } + + public DcaeLocation addDcaeLocation(DcaeLocation location) { + location.setLastMod(); + location.setStatus(DmaapObject_Status.VALID); + dcaeLocations.put(location.getDcaeLocationName(), location); + return location; + } + + public DcaeLocation updateDcaeLocation(DcaeLocation location) { + if (location.getDcaeLocationName().isEmpty()) { + return null; + } + location.setLastMod(); + dcaeLocations.put(location.getDcaeLocationName(), location); + return location; + } + + public DcaeLocation removeDcaeLocation(String locationName) { + return dcaeLocations.remove(locationName); + } + + String getCentralLocation() { + + Optional<DcaeLocation> firstCentralLocation = + dcaeLocations.values().stream().filter(DcaeLocation::isCentral).findFirst(); + + return firstCentralLocation.isPresent() ? firstCentralLocation.get().getDcaeLocationName() : DEFAULT_CENTRAL_LOCATION; + } + + boolean isEdgeLocation(String aName) { + return dcaeLocations.get(aName) != null && !dcaeLocations.get(aName).isCentral(); + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DmaapService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DmaapService.java new file mode 100644 index 0000000..8789ac4 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/DmaapService.java @@ -0,0 +1,310 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.service; + +import java.util.ArrayList; +import org.onap.dmaap.dbcapi.aaf.AafService; +import org.onap.dmaap.dbcapi.aaf.AafServiceFactory; +import org.onap.dmaap.dbcapi.aaf.DmaapGrant; +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType; +import org.onap.dmaap.dbcapi.authentication.ApiPerms; +import org.onap.dmaap.dbcapi.authentication.ApiPolicy; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.model.MR_Client; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.Singleton; + +public class DmaapService extends BaseLoggingClass { + + + private Singleton<Dmaap> dmaapholder = DatabaseClass.getDmaap(); + private static String noEnvironmentPrefix; + + + String topicFactory; // = "org.openecomp.dcae.dmaap.topicFactory"; + String topicMgrRole; // = "org.openecomp.dmaapBC.TopicMgr"; + + private boolean multiSite; + + + public DmaapService() { + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + topicFactory = p.getProperty("MR.TopicFactoryNS", "MR.topicFactoryNS.not.set"); + topicMgrRole = p.getProperty("MR.TopicMgrRole", "MR.TopicMgrRole.not.set" ); + + multiSite = "true".equalsIgnoreCase(p.getProperty("MR.multisite", "true")); + noEnvironmentPrefix = p.getProperty( "AAF.NoEnvironmentPrefix", "org.onap"); + + logger.info( "DmaapService settings: " + + " topicFactory=" + topicFactory + + " topicMgrRole=" + topicMgrRole + + + " multisite=" + multiSite + + " noEnvironmentPrefix=" + noEnvironmentPrefix + ); + + Dmaap dmaap = dmaapholder.get(); + logger.info( "DmaapService object values: " + + " dmaapName=" + dmaap.getDmaapName() + + " drProvURL=" + dmaap.getDrProvUrl() + + " version="+ dmaap.getVersion() + ); + + } + + public Dmaap getDmaap() { + logger.info( "entering getDmaap()" ); + return(dmaapholder.get()); + } + + public Dmaap addDmaap( Dmaap nd ) { + + logger.info( "entering addDmaap()" ); + Dmaap dmaap = dmaapholder.get(); + if ( dmaap.getVersion().equals( "0")) { + + nd.setLastMod(); + dmaapholder.update(nd); + + AafService aaf = new AafServiceFactory().initAafService(ServiceType.AAF_Admin); + ApiPolicy apiPolicy = new ApiPolicy(); + if ( apiPolicy.isPermissionClassSet() ) { + ApiPerms p = new ApiPerms(); + p.setEnvMap(); + } + boolean anythingWrong = false; + + if ( multiSite ) { + anythingWrong = setTopicMgtPerms( nd, aaf ) || createMmaTopic(); + } + + if ( anythingWrong ) { + dmaap.setStatus(DmaapObject_Status.INVALID); + } + else { + dmaap.setStatus(DmaapObject_Status.VALID); + } + dmaap.setLastMod(); + dmaapholder.update(dmaap); + + return dmaap; + + } + else { + return dmaap; + } + } + + public Dmaap updateDmaap( Dmaap nd ) { + logger.info( "entering updateDmaap()" ); + + boolean anythingWrong = false; + + Dmaap dmaap = dmaapholder.get(); + + // some triggers for when we attempt to reprovision perms and MMA topic: + // - if the DMaaP Name changes + // - if the version is 0 (this is a handy test to force this processing by updating the DB) + // - if the object is invalid, reprocessing might fix it. + if ( ! dmaap.isStatusValid() || ! nd.getDmaapName().equals(dmaap.getDmaapName()) || dmaap.getVersion().equals( "0") ) { + nd.setLastMod(); + dmaapholder.update(nd); //need to set this so the following perms will pick up any new vals. + //dcaeTopicNs = dmaapholder.get().getTopicNsRoot(); + ApiPolicy apiPolicy = new ApiPolicy(); + if ( apiPolicy.isPermissionClassSet()) { + ApiPerms p = new ApiPerms(); + p.setEnvMap(); + } + AafService aaf = new AafServiceFactory().initAafService(ServiceType.AAF_Admin); + if ( multiSite ) { + anythingWrong = setTopicMgtPerms( nd, aaf ) || createMmaTopic(); + } + } + + if ( anythingWrong ) { + nd.setStatus(DmaapObject_Status.INVALID); + } + else { + nd.setStatus(DmaapObject_Status.VALID); + } + nd.setLastMod(); + dmaapholder.update(nd); // may need to update status... + return(dmaapholder.get()); + + } + + public String getTopicPerm(){ + Dmaap dmaap = dmaapholder.get(); + return getTopicPerm( dmaap.getDmaapName() ); + } + public String getTopicPerm( String val ) { + Dmaap dmaap = dmaapholder.get(); + String nsRoot = dmaap.getTopicNsRoot(); + if ( nsRoot == null ) { return null; } + + String t; + // in ONAP Casablanca, we assume no distinction of environments reflected in topic namespace + if ( nsRoot.startsWith(noEnvironmentPrefix) ) { + t = nsRoot + ".mr.topic"; + } else { + t = nsRoot + "." + val + ".mr.topic"; + } + return t; + } + + public String getBridgeAdminFqtn(){ + Dmaap dmaap = dmaapholder.get(); + String topic = dmaap.getBridgeAdminTopic(); + + // check if this is already an fqtn (contains a dot) + // otherwise build it + if ( topic.indexOf('.') < 0 ) { + topic = dmaap.getTopicNsRoot() + "." + dmaap.getDmaapName() + "." + dmaap.getBridgeAdminTopic(); + } + return( topic ); + } + + private boolean setTopicMgtPerms( Dmaap nd, AafService aaf ){ + String[] actions = { "create", "destroy" }; + String instance = ":" + nd.getTopicNsRoot() + "." + nd.getDmaapName() + ".mr.topic:" + nd.getTopicNsRoot() + "." + nd.getDmaapName(); + + for( String action : actions ) { + + DmaapPerm perm = new DmaapPerm( topicFactory, instance, action ); + + int rc = aaf.addPerm( perm ); + if ( rc != 201 && rc != 409 ) { + logger.error( "unable to add perm for "+ topicFactory + "|" + instance + "|" + action ); + return true; + } + + DmaapGrant grant = new DmaapGrant( perm, topicMgrRole ); + rc = aaf.addGrant( grant ); + if ( rc != 201 && rc != 409 ) { + logger.error( "unable to grant to " + topicMgrRole + " perm for "+ topicFactory + "|" + instance + "|" + action ); + return true; + } + } + + String t = nd.getTopicNsRoot() +"." + nd.getDmaapName() + ".mr.topic"; + String[] s = { "view", "pub", "sub" }; + actions = s; + instance = "*"; + + for( String action : actions ) { + + DmaapPerm perm = new DmaapPerm( t, instance, action ); + + int rc = aaf.addPerm( perm ); + if ( rc != 201 && rc != 409 ) { + errorLogger.error( DmaapbcLogMessageEnum.AAF_UNEXPECTED_RESPONSE, Integer.toString(rc), "add perm", t + "|" + instance + "|" + action ); + return true; + } + + DmaapGrant grant = new DmaapGrant( perm, topicMgrRole ); + rc = aaf.addGrant( grant ); + if ( rc != 201 && rc != 409 ) { + errorLogger.error( DmaapbcLogMessageEnum.AAF_UNEXPECTED_RESPONSE, Integer.toString(rc), "grant to " + topicMgrRole + " perm ", topicFactory + "|" + instance + "|" + action ); + return true; + } + + } + return false; + } + + public boolean testCreateMmaTopic() { + + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + String unit_test = p.getProperty( "UnitTest", "No" ); + if ( unit_test.equals( "Yes" ) ) { + return createMmaTopic(); + } + return false; + } + + // create the special topic for MMA provisioning. + // return true indicating a problem in topic creation, + // else false means it was ok (created or previously existed) + private boolean createMmaTopic() { + boolean rc = true; + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + Dmaap dmaap = dmaapholder.get(); + + ArrayList<MR_Client> clients = new ArrayList<MR_Client>(); + String[] actions = { "pub", "sub", "view" }; + String centralMR = new DcaeLocationService().getCentralLocation(); + if ( centralMR == null ) { + return rc; + } + logger.info( "Location for " + dmaap.getBridgeAdminTopic() + " is " + centralMR ); + + // first client is the Role used by Bus Controller to send messages to MMA + String provRole = p.getProperty("MM.ProvRole"); + MR_Client nClient = new MR_Client(); + nClient.setAction(actions); + nClient.setClientRole(provRole); + nClient.setDcaeLocationName(centralMR); + clients.add( nClient ); + + // second client is the Role used by MMA to listen to messages from Bus Controller + String agentRole = p.getProperty("MM.AgentRole"); + nClient = new MR_Client(); + nClient.setAction(actions); + nClient.setClientRole(agentRole); + nClient.setDcaeLocationName(centralMR); + clients.add( nClient ); + + // initialize Topic + Topic mmaTopic = new Topic().init(); + mmaTopic.setTopicName(dmaap.getBridgeAdminTopic()); + mmaTopic.setClients(clients); + mmaTopic.setOwner("BusController"); + mmaTopic.setTopicDescription("topic reserved for MirrorMaker Administration"); + mmaTopic.setTnxEnabled("false"); + mmaTopic.setPartitionCount("1"); // a single partition should guarantee message order + + + ApiError err = new ApiError(); + TopicService svc = new TopicService(); + try { + @SuppressWarnings("unused") + Topic nTopic = svc.addTopic(mmaTopic, err, true); + if ( err.is2xx() || err.getCode() == 409 ) { + return false; + } + } catch ( Exception e) { + errorLogger.error( DmaapbcLogMessageEnum.UNEXPECTED_CONDITION, " while adding Topic: " + e.getMessage()); + } + errorLogger.error( DmaapbcLogMessageEnum.TOPIC_CREATE_ERROR, dmaap.getBridgeAdminTopic(), err.getFields(), err.getFields(), err.getMessage()); + + return rc; + + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java new file mode 100644 index 0000000..19b0267 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/FeedService.java @@ -0,0 +1,572 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.service; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import javax.ws.rs.core.Response.Status; +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; +import org.onap.dmaap.dbcapi.client.DrProvConnection; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +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.DR_Sub; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.model.Feed; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.RandomInteger; + +public class FeedService extends BaseLoggingClass { + + private Map<String, Feed> feeds = DatabaseClass.getFeeds(); + private Map<String, DR_Sub> dr_subs = DatabaseClass.getDr_subs(); + private DR_PubService pubService = new DR_PubService(); + private DR_SubService subService = new DR_SubService(); + private DcaeLocationService dcaeLocations = new DcaeLocationService(); + private String deleteHandling; + private String unit_test; + + public FeedService() { + logger.info( "new FeedService"); + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + deleteHandling = p.getProperty("Feed.deleteHandling", "DeleteOnDR"); + unit_test = p.getProperty( "UnitTest", "No" ); + + } + + public Map<String, Feed> getFeeds() { + return feeds; + } + + private void getSubObjects( Feed f ) { + ArrayList<DR_Pub> pubs = pubService.getDr_PubsByFeedId( f.getFeedId() ); + f.setPubs(pubs); + ArrayList<DR_Sub> subs = subService.getDr_SubsByFeedId( f.getFeedId() ); + f.setSubs(subs); + } + + public List<Feed> getAllFeeds(){ + return getAllFeeds(null, null, null); + } + + 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() ) { + boolean keep = true; + if ( name != null ) { + if ( match != null && "startsWith".equals(match) ) { + 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; + } + + + private Feed _getFeed( String key, ApiError err, boolean flag ) { + Feed f = feeds.get( key ); + if ( f != null && ( flag || f.getStatus() != DmaapObject_Status.DELETED ) ) { + getSubObjects( f ); + } else { + err.setCode(Status.NOT_FOUND.getStatusCode()); + err.setMessage("feed not found"); + err.setFields("feedId=" + key ); + return null; + } + err.setCode(200); + return f; + } + public Feed getFeed( String key, ApiError err ) { + return _getFeed( key, err, false ); + } + public Feed getFeedPure( String key, ApiError err ) { + return _getFeed( key, err, true ); + } + + public Feed getFeedByName( String name, String ver, ApiError err ) { + for( Feed f: feeds.values() ) { + if ( f.getFeedName().equals( name ) && f.getFeedVersion().equals(ver) ) { + getSubObjects(f); + return f; + } + + } + err.setCode(Status.NOT_FOUND.getStatusCode()); + err.setMessage("feed not found"); + err.setFields("feedName=" + name + " and ver=" + ver ); + return null; + + } + + private boolean savePubs( Feed f ) { + return savePubs( f, f ); + } + // need to save the Pub objects independently and copy pubId from original request + private boolean savePubs( Feed fnew, Feed req ) { + // save any pubs + DR_PubService pubSvc = new DR_PubService(); + ArrayList<DR_Pub> reqPubs = req.getPubs(); + ArrayList<DR_Pub> newPubs = fnew.getPubs(); + + + + int nSize = newPubs.size(); + int rSize = reqPubs.size(); + logger.info( "reqPubs size=" + rSize + " newPubs size=" + nSize ); + if ( nSize != rSize ) { + errorLogger.error( "Resulting set of publishers do not match requested set of publishers " + nSize + " vs " + rSize ); + fnew.setStatus( DmaapObject_Status.INVALID); + return false; + } + // NOTE: when i > 1 newPubs are in reverse order from reqPubs + for( int i = 0; i < reqPubs.size(); i++ ) { + DR_Pub reqPub = reqPubs.get(i); + ApiError err = new ApiError(); + if ( pubSvc.getDr_Pub( reqPub.getPubId(), err ) == null ) { + DR_Pub newPub = newPubs.get(nSize - i - 1); + reqPub.setPubId(newPub.getPubId()); + reqPub.setFeedId(newPub.getFeedId()); + reqPub.setStatus(DmaapObject_Status.VALID); + if ( reqPub.getDcaeLocationName() == null ) { + reqPub.setDcaeLocationName("notSpecified"); + } + pubSvc.addDr_Pub( reqPub ); + } + + } + + fnew.setPubs(reqPubs); + fnew.setStatus(DmaapObject_Status.VALID); + return true; + + } + + private boolean saveSubs( Feed f ) { + return saveSubs( f, f ); + } + // need to save the Sub objects independently + private boolean saveSubs( Feed fnew, Feed req ) { + ArrayList<DR_Sub> subs = req.getSubs(); + if ( subs == null || subs.size() == 0 ) { + logger.info( "No subs specified"); + } else { + DR_SubService subSvc = new DR_SubService( fnew.getSubscribeURL() ); + ApiError err = new ApiError(); + for( int i = 0; i < subs.size(); i++ ) { + DR_Sub sub = subs.get(i); + if ( subSvc.getDr_Sub( sub.getSubId(), err) == null ) { + subs.set( i, subSvc.addDr_Sub(sub, err)); + if ( ! err.is2xx()) { + logger.error( "i=" + i + " url=" + sub.getDeliveryURL() + " err=" + err.getCode() ); + return false; + } + } + + } + fnew.setSubs(subs); + } + + + fnew.setStatus(DmaapObject_Status.VALID); + return true; + + } + + public Feed addFeed( Feed req, ApiError err ) { + + // at least 1 pub is required by DR, so create a default pub if none is specified + if ( req.getPubs().size() == 0 ) { + logger.info( "No pubs specified - creating tmp pub"); + ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>(); + pubs.add( new DR_Pub( dcaeLocations.getCentralLocation()) + .setRandomUserName() + .setRandomPassword()); + req.setPubs(pubs); + } + + + DrProvConnection prov = new DrProvConnection(); + prov.makeFeedConnection(); + String resp = prov.doPostFeed( req, err ); + if ( unit_test.equals( "Yes" ) ) { + // assume resp is null, so need to simulate it + resp = simulateResp( req, "POST" ); + } + logger.info( "resp=" + resp ); + if ( resp == null ) { + switch( err.getCode() ) { + case 400: + err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() ); + break; + case 403: + err.setCode(500); + err.setMessage("API deployment/configuration error - contact support"); + err.setFields( "PROV_AUTH_ADDRESSES"); + logger.error( "Prov response: 403. " + err.getMessage() + " regarding " + err.getFields() ); + break; + default: + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + } + return null; + + } + + + Feed fnew = new Feed( resp ); + logger.info( "fnew status is:" + fnew.getStatus() ); + if ( ! fnew.isStatusValid()) { + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + return null; + } + + //saveChildren( fnew, req ); + if ( ! savePubs( fnew, req ) || ! saveSubs( fnew, req ) ) { + err.setCode(Status.BAD_REQUEST.getStatusCode()); + err.setMessage("Unable to save Pub or Sub objects"); + return null; + } + fnew.setFormatUuid(req.getFormatUuid()); + fnew.setLastMod(); + feeds.put( fnew.getFeedId(), fnew ); + return fnew; + } + + public Feed updateFeed( Feed req, ApiError err ) { + + // at least 1 pub is required by DR, so create a default pub if none is specified + if ( req.getPubs().size() == 0 ) { + logger.info( "No pubs specified - creating tmp pub"); + ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>(); + pubs.add( new DR_Pub( dcaeLocations.getCentralLocation()) + .setRandomUserName() + .setRandomPassword()); + req.setPubs(pubs); + } + + DrProvConnection prov = new DrProvConnection(); + prov.makeFeedConnection( req.getFeedId() ); + String resp = prov.doPutFeed( req, err ); + if ( unit_test.equals( "Yes" ) ) { + // assume resp is null, so need to simulate it + resp = simulateResp( req, "PUT" ); + err.setCode(200); + } + logger.info( "resp=" + resp ); + if ( resp == null ) { + switch( err.getCode() ) { + case 400: + err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() ); + break; + case 403: + err.setCode(500); + err.setMessage("API deployment/configuration error - contact support"); + err.setFields( "PROV_AUTH_ADDRESSES"); + break; + default: + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + } + return null; + } + + + Feed fnew = new Feed( resp ); + logger.info( "fnew status is:" + fnew.getStatus() ); + if ( ! fnew.isStatusValid()) { + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + return null; + } + + if ( ! savePubs( fnew, req ) || ! saveSubs( fnew, req ) ) { + err.setCode(Status.BAD_REQUEST.getStatusCode()); + err.setMessage("Unable to save Pub or Sub objects"); + return null; + } + fnew.setFormatUuid(req.getFormatUuid()); + fnew.setLastMod(); + feeds.put( fnew.getFeedId(), fnew ); + return fnew; + } + + + // + // DR does not actually delete a feed, so we provide two behaviors: + // 1) clean up the feed by removing all subs and pubs, mark it here as DELETED. + // then client can add it back if desired. + // 2) Call the DR Delete function. Feed with the same name and version can never be added again + // + public Feed removeFeed( Feed req, ApiError err ) { + return removeFeed( req, err, true ); + } + + public Feed removeFeed( Feed req, ApiError err, boolean hitDR ) { + + // strip pubs and subs from feed first no matter what + ArrayList<DR_Pub> pubs = pubService.getDr_PubsByFeedId( req.getFeedId() ); + for( DR_Pub pub: pubs ) { + pubService.removeDr_Pub(pub.getPubId(), err, hitDR); + if ( ! err.is2xx()) { + return req; + } + } + ArrayList<DR_Sub> subs = subService.getDr_SubsByFeedId( req.getFeedId() ); + for ( DR_Sub sub: subs ) { + subService.removeDr_Sub(sub.getSubId(), err, hitDR); + if ( ! err.is2xx()) { + return req; + } + } + + if ( ! hitDR ) { + return feeds.remove(req.getFeedId()); + } + + if ( deleteHandling.equalsIgnoreCase("DeleteOnDR")) { + DrProvConnection prov = new DrProvConnection(); + prov.makeFeedConnection( req.getFeedId() ); + String resp = prov.doDeleteFeed( req, err ); + if ( unit_test.equals( "Yes" ) ) { + // assume resp is null, so need to simulate it + resp = simulateDelResp( req ); + } + logger.info( "resp=" + resp ); + if ( resp == null ) { + switch( err.getCode() ) { + case 400: + err.setFields( "feedName=" + req.getFeedName() + " + feedVersion=" + req.getFeedVersion() ); + break; + case 403: + err.setCode(500); + err.setMessage("API deployment/configuration error - contact support"); + err.setFields( "PROV_AUTH_ADDRESSES"); + break; + default: + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + } + return req; // return back the requested feed - implies it wasn't removed + } + return feeds.remove(req.getFeedId()); + } else { + + logger.info( "Disable pubs for deleted feed - creating tmp pub"); + ArrayList<DR_Pub> tmppub = new ArrayList<DR_Pub>(); + tmppub.add( new DR_Pub( dcaeLocations.getCentralLocation()) + .setRandomUserName() + .setRandomPassword()); + req.setPubs(tmppub); + req.setSubs(null); + Feed fnew = updateFeed( req, err ); + if ( ! err.is2xx()) { + return req; + } + fnew.setStatus(DmaapObject_Status.DELETED); + feeds.put( fnew.getFeedId(), fnew ); + return null; + } + + + } + + + /* + * sync will retrieve current config from DR and add it to the DB + * when hard = true, then first git rid of current DR provisioning data (from the DB) + */ + public void sync( boolean hard, ApiError err ) { + + if ( hard ) { + + ArrayList<Feed> flist = new ArrayList<Feed>(this.getAllFeeds()); + for ( Iterator<Feed> it = flist.iterator(); it.hasNext(); ) { + Feed f = it.next(); + + @SuppressWarnings("unused") + Feed old = removeFeed( f, err, false ); + if (! err.is2xx()) { + return; + } + } + } + + DrProvConnection prov = new DrProvConnection(); + prov.makeDumpConnection(); + String resp = prov.doGetDump( err ); + if (! err.is2xx()) { + return; + } + logger.debug("sync: resp from DR is: " + resp); + + JSONParser parser = new JSONParser(); + JSONObject jsonObj; + try { + jsonObj = (JSONObject) parser.parse( resp ); + } catch ( ParseException pe ) { + logger.error( "Error parsing provisioning data: " + resp ); + err.setCode(500); + return; + } + + int i; + + JSONArray feedsArray = (JSONArray) jsonObj.get( "feeds"); + for( i = 0; i < feedsArray.size(); i++ ) { + JSONObject entry = (JSONObject) feedsArray.get(i); + Feed fnew = new Feed( entry.toJSONString() ); + + logger.info( "fnew status is:" + fnew.getStatus() ); + if ( ! fnew.isStatusValid()) { + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + return; + } + + if ( ! savePubs( fnew ) ) { + err.setCode(Status.BAD_REQUEST.getStatusCode()); + err.setMessage("Unable to save Pub or Sub objects"); + return; + } + fnew.setFormatUuid(fnew.getFormatUuid()); + fnew.setLastMod(); + feeds.put( fnew.getFeedId(), fnew ); + + } + + JSONArray subArray = (JSONArray) jsonObj.get( "subscriptions"); + for( i = 0; i < subArray.size(); i++ ) { + JSONObject entry = (JSONObject) subArray.get(i); + DR_Sub snew = new DR_Sub( entry.toJSONString() ); + + logger.info( "snew status is:" + snew.getStatus() ); + if ( ! snew.isStatusValid()) { + err.setCode(500); + err.setMessage( "Unexpected response from DR backend" ); + err.setFields("response"); + return; + } + + dr_subs.put( snew.getSubId(), snew ); + + } + err.setCode(200); + return; + + } + + private String simulateResp( Feed f, String action ){ + String server = "localhost"; + String feedid; + if ( action.equals( "POST" ) ) { + RandomInteger ran = new RandomInteger(10000); + feedid = Integer.toString( ran.next() ); + } else if ( action.equals( "PUT" ) ) { + feedid = f.getFeedId(); + } else { + feedid = "99"; + } + String ret = String.format( +"{\"suspend\":false,\"groupid\":0,\"description\":\"%s\",\"version\":\"1.0\",\"authorization\":", + f.getFeedDescription() ); + + String endpoints = "{\"endpoint_addrs\":[],\"classification\":\"unclassified\",\"endpoint_ids\":["; + String sep = ""; + for( DR_Pub pub: f.getPubs()) { + endpoints += String.format( "%s{\"password\":\"%s\",\"id\":\"%s\"}", + sep, pub.getUserpwd(), pub.getUsername() ); + sep = ","; + + } + endpoints += "]},"; + ret += endpoints; + + ret += String.format( + "\"name\":\"%s\",\"business_description\":\"\",\"publisher\":\"sim\",\"links\":{\"subscribe\":\"https://%s/subscribe/%s\",\"log\":\"https://%s/feedlog/%s\",\"publish\":\"https://%s/publish/%s\",\"self\":\"https://%s/feed/%s\"}}", + + f.getFeedName(), + server, feedid, + server, feedid, + server, feedid, + server, feedid + ); + logger.info( "simulateResp ret=" + ret ); + return ret; + } + private String simulateDelResp( Feed f ){ + String server = "localhost"; + String feedid = f.getFeedId(); + String ret = String.format( +"{\"suspend\":true,\"groupid\":0,\"description\":\"%s\",\"version\":\"1.0\",\"authorization\":{\"endpoint_addrs\":[],\"classification\":\"unclassified\",\"endpoint_ids\":[{\"password\":\"topSecret123\",\"id\":\"sim\"}]},\"name\":\"%s\",\"business_description\":\"\",\"publisher\":\"sim\",\"links\":{\"subscribe\":\"https://%s/subscribe/%s\",\"log\":\"https://%s/feedlog/%s\",\"publish\":\"https://%s/publish/%s\",\"self\":\"https://%s/feed/%s\"}}", + f.getFeedDescription(), + f.getFeedName(), + server, feedid, + server, feedid, + server, feedid, + server, feedid + + ); + return ret; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/MR_ClientService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/MR_ClientService.java new file mode 100644 index 0000000..bcf5408 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/MR_ClientService.java @@ -0,0 +1,234 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.service; + +import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType; +import org.onap.dmaap.dbcapi.aaf.AafServiceFactory; +import org.onap.dmaap.dbcapi.client.MrProvConnection; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.model.MR_Client; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +import javax.ws.rs.core.Response.Status; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +public class MR_ClientService extends BaseLoggingClass { + + private static final String MR_CLIENT_ID = "mrClientId"; + private int deleteLevel; + private Map<String, MR_Client> mr_clients = DatabaseClass.getMr_clients(); + private Map<String, MR_Cluster> clusters = DatabaseClass.getMr_clusters(); + private Map<String, DcaeLocation> locations = DatabaseClass.getDcaeLocations(); + private DmaapService dmaap = new DmaapService(); + private AafPermissionService aafPermissionService = + new AafPermissionService(new AafServiceFactory().initAafService(ServiceType.AAF_TopicMgr), dmaap); + private String centralCname; + + public MR_ClientService() { + DmaapConfig p = (DmaapConfig) DmaapConfig.getConfig(); + + centralCname = p.getProperty("MR.CentralCname", "MRcname.not.set"); + deleteLevel = Integer.valueOf(p.getProperty("MR.ClientDeleteLevel", "0")); + } + + public List<MR_Client> getAllMr_Clients() { + return new ArrayList<>(mr_clients.values()); + } + + List<MR_Client> getAllMrClients(String fqtn) { + ArrayList<MR_Client> results = new ArrayList<>(); + for (Map.Entry<String, MR_Client> entry : mr_clients.entrySet()) { + MR_Client client = entry.getValue(); + if (fqtn.equals(client.getFqtn())) { + results.add(client); + } + } + return results; + } + + List<MR_Client> getClientsByLocation(String location) { + List<MR_Client> results = new ArrayList<>(); + for (Map.Entry<String, MR_Client> entry : mr_clients.entrySet()) { + MR_Client client = entry.getValue(); + if (location.equals(client.getDcaeLocationName())) { + results.add(client); + } + } + return results; + } + + public MR_Client getMr_Client(String key, ApiError apiError) { + MR_Client c = mr_clients.get(key); + if (c == null) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields(MR_CLIENT_ID); + apiError.setMessage(MR_CLIENT_ID + " " + key + " not found"); + } else { + apiError.setCode(200); + } + return c; + } + + public MR_Client addMr_Client(MR_Client client, Topic topic, ApiError err) { + if (client.getDcaeLocationName().isEmpty()) { + logger.info("Client dcaeLocation that doesn't exist or not specified"); + return null; + } + // original style: clients specified Role. This has precedence for backwards + // compatibility. + // ONAP style: clients specify Identity to be assigned to generated Role + String role = client.getClientRole(); + if (role != null) { + updateApiError(err, aafPermissionService.grantClientRolePerms(client)); + } else if (client.hasClientIdentity()) { + if (client.isSubscriber()) { + role = topic.getSubscriberRole(); + updateApiError(err, aafPermissionService.assignClientToRole(client, role)); + } + if (client.isPublisher()) { + role = topic.getPublisherRole(); + updateApiError(err, aafPermissionService.assignClientToRole(client, role)); + } + } + if (!client.isStatusValid()) { + return null; + } + String centralFqdn = null; + DcaeLocation candidate = locations.get(client.getDcaeLocationName()); + + MR_Cluster cluster = clusters.get(client.getDcaeLocationName()); + if (cluster != null && candidate != null) { + if (candidate.isCentral() && !topic.getReplicationCase().involvesFQDN()) { + centralFqdn = centralCname; + } + client.setTopicURL(cluster.genTopicURL(centralFqdn, client.getFqtn())); + if (centralFqdn == null) { + client.setStatus(addTopicToCluster(cluster, topic, err)); + if (!err.is2xx() && err.getCode() != 409) { + topic.setFqtn(err.getMessage()); + return null; + } + + } else { + MR_ClusterService clusters = new MR_ClusterService(); + // MM should only exist for edge-to-central + // we use a cname for the central target (default resiliency with no replicationGroup set) + // but still need to provision topics on all central MRs + for (MR_Cluster central : clusters.getCentralClusters()) { + client.setStatus(addTopicToCluster(central, topic, err)); + if (!err.is2xx() && err.getCode() != 409) { + topic.setFqtn(err.getMessage()); + return null; + } + } + } + + } else { + logger.warn("Client references a dcaeLocation that doesn't exist:" + client.getDcaeLocationName()); + client.setStatus(DmaapObject_Status.STAGED); + } + + mr_clients.put(client.getMrClientId(), client); + + err.setCode(200); + + return client; + } + + private DmaapObject_Status addTopicToCluster(MR_Cluster cluster, Topic topic, ApiError err) { + + MrProvConnection prov = new MrProvConnection(); + logger.info("POST topic " + topic.getFqtn() + " to cluster " + cluster.getFqdn() + " in loc " + cluster.getDcaeLocationName()); + if (prov.makeTopicConnection(cluster)) { + prov.doPostTopic(topic, err); + logger.info("response code: " + err.getCode()); + if (err.is2xx() || err.getCode() == 409) { + return DmaapObject_Status.VALID; + } + } + return DmaapObject_Status.INVALID; + } + + public MR_Client updateMr_Client(MR_Client client, ApiError apiError) { + MR_Client c = mr_clients.get(client.getMrClientId()); + if (c == null) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields(MR_CLIENT_ID); + apiError.setMessage("mrClientId " + client.getMrClientId() + " not found"); + } else { + apiError.setCode(200); + } + mr_clients.put(client.getMrClientId(), client); + return client; + } + + public void removeMr_Client(String key, boolean updateTopicView, ApiError apiError) { + MR_Client client = mr_clients.get(key); + if (client == null) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields(MR_CLIENT_ID); + apiError.setMessage("mrClientId " + key + " not found"); + return; + } else { + apiError.setCode(200); + } + + if (updateTopicView) { + + TopicService topics = new TopicService(); + + Topic t = topics.getTopic(client.getFqtn(), apiError); + if (t != null) { + List<MR_Client> tc = t.getClients(); + for (MR_Client c : tc) { + if (c.getMrClientId().equals(client.getMrClientId())) { + tc.remove(c); + break; + } + } + t.setClients(tc); + topics.updateTopic(t, apiError); + } + + } + + // remove from DB + if (deleteLevel >= 1) { + mr_clients.remove(key); + } + } + + private void updateApiError(ApiError err, ApiError permissionServiceError) { + err.setCode(permissionServiceError.getCode()); + err.setMessage(permissionServiceError.getMessage()); + err.setFields(permissionServiceError.getFields()); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/MR_ClusterService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/MR_ClusterService.java new file mode 100644 index 0000000..db6389e --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/MR_ClusterService.java @@ -0,0 +1,205 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.service; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.ws.rs.core.Response.Status; + +import org.onap.dmaap.dbcapi.client.MrProvConnection; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.service.DcaeLocationService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +public class MR_ClusterService extends BaseLoggingClass { + + private Map<String, MR_Cluster> mr_clusters = DatabaseClass.getMr_clusters(); + private boolean multiSite; + + public MR_ClusterService() { + logger.info( "new ClusterService"); + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + multiSite = "true".equalsIgnoreCase(p.getProperty("MR.multisite", "true")); + + } + + public Map<String, MR_Cluster> getMR_Clusters() { + return mr_clusters; + } + + public List<MR_Cluster> getAllMr_Clusters() { + return new ArrayList<MR_Cluster>(mr_clusters.values()); + } + + public MR_Cluster getMr_Cluster( String key, ApiError apiError ) { + MR_Cluster mrc = mr_clusters.get( key ); + if ( mrc == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "dcaeLocationName"); + apiError.setMessage( "Cluster with dcaeLocationName " + key + " not found"); + } + apiError.setCode(200); + return mrc; + } + public MR_Cluster getMr_ClusterByFQDN( String key ) { + for( MR_Cluster cluster: mr_clusters.values() ) { + if ( key.equals( cluster.getFqdn() ) ) { + return cluster; + } + } + return null; + } + + public MR_Cluster getMr_ClusterByLoc( String loc ) { + return mr_clusters.get( loc ); + } + + public List<MR_Cluster> getCentralClusters() { + DcaeLocationService locations = new DcaeLocationService(); + List<MR_Cluster> result = new ArrayList<MR_Cluster>(); + for( MR_Cluster c: mr_clusters.values() ) { + try { + if ( locations.getDcaeLocation(c.getDcaeLocationName()).isCentral() ) { + result.add(c); + } + } catch ( NullPointerException npe ) { + logger.warn( "Failed test isCentral for location:" + c.getDcaeLocationName() ); + } + } + return result; + } + + // builds the set of unique cluster groups + public Set<String> getGroups() { + Set<String> result = new HashSet<String>(); + for( MR_Cluster c: mr_clusters.values() ) { + try { + result.add(c.getReplicationGroup()); + } catch ( NullPointerException npe ) { + logger.warn( "Failed to add Group for cluster:" + c.getDcaeLocationName() ); + } + } + return result; + } + + + public MR_Cluster addMr_Cluster( MR_Cluster cluster, ApiError apiError ) { + logger.info( "Entry: addMr_Cluster"); + MR_Cluster mrc = mr_clusters.get( cluster.getDcaeLocationName() ); + if ( mrc != null ) { + apiError.setCode(Status.CONFLICT.getStatusCode()); + apiError.setFields( "dcaeLocationName"); + apiError.setMessage( "Cluster with dcaeLocationName " + cluster.getDcaeLocationName() + " already exists"); + return null; + } + cluster.setLastMod(); + cluster.setStatus( addTopicsToCluster( cluster, apiError ) ); + mr_clusters.put( cluster.getDcaeLocationName(), cluster ); + DcaeLocationService svc = new DcaeLocationService(); + DcaeLocation loc = svc.getDcaeLocation( cluster.getDcaeLocationName() ); + if ( loc != null && loc.isCentral() && multiSite ) { + ApiError resp = TopicService.setBridgeClientPerms( cluster ); + if ( ! resp.is2xx() ) { + logger.error( "Unable to provision Bridge to " + cluster.getDcaeLocationName() ); + cluster.setLastMod(); + cluster.setStatus(DmaapObject_Status.INVALID); + mr_clusters.put( cluster.getDcaeLocationName(), cluster ); + } + } + apiError.setCode(200); + return cluster; + } + + public MR_Cluster updateMr_Cluster( MR_Cluster cluster, ApiError apiError ) { + MR_Cluster mrc = mr_clusters.get( cluster.getDcaeLocationName() ); + if ( mrc == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "dcaeLocationName"); + apiError.setMessage( "Cluster with dcaeLocationName " + cluster.getDcaeLocationName() + " not found"); + return null; + } + cluster.setLastMod(); + cluster.setStatus( addTopicsToCluster( cluster, apiError ) ); + mr_clusters.put( cluster.getDcaeLocationName(), cluster ); + DcaeLocationService svc = new DcaeLocationService(); + DcaeLocation loc = svc.getDcaeLocation( cluster.getDcaeLocationName() ); + if ( loc == null ) { + logger.error( "DcaeLocation not found for cluster in " + cluster.getDcaeLocationName() ); + cluster.setLastMod(); + cluster.setStatus(DmaapObject_Status.INVALID); + mr_clusters.put( cluster.getDcaeLocationName(), cluster ); + } else if ( loc.isCentral() && multiSite ) { + ApiError resp = TopicService.setBridgeClientPerms( cluster ); + if ( ! resp.is2xx() ) { + logger.error( "Unable to provision Bridge to " + cluster.getDcaeLocationName() ); + cluster.setLastMod(); + cluster.setStatus(DmaapObject_Status.INVALID); + mr_clusters.put( cluster.getDcaeLocationName(), cluster ); + } + } + + apiError.setCode(200); + return cluster; + } + + public MR_Cluster removeMr_Cluster( String key, ApiError apiError ) { + MR_Cluster mrc = mr_clusters.get( key ); + if ( mrc == null ) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields( "dcaeLocationName"); + apiError.setMessage( "Cluster with dcaeLocationName " + key + " not found"); + return null; + } + apiError.setCode(200); + return mr_clusters.remove(key); + } + + private DmaapObject_Status addTopicsToCluster( MR_Cluster cluster, ApiError err ){ + + TopicService ts = new TopicService(); + MrProvConnection prov = new MrProvConnection(); + List<Topic> topics = ts.getAllTopicsWithoutClients(); + for( Topic topic: topics ) { + logger.info( "POST topic " + topic.getFqtn() + " to cluster " + cluster.getFqdn() + " in loc " + cluster.getDcaeLocationName()); + if ( prov.makeTopicConnection(cluster)) { + String resp = prov.doPostTopic(topic, err); + logger.info( "response code: " + err.getCode() ); + if ( ! err.is2xx() && ! (err.getCode() == 409) ) { + return DmaapObject_Status.INVALID; + } + } + } + + return DmaapObject_Status.VALID; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/MirrorMakerService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/MirrorMakerService.java new file mode 100644 index 0000000..7c4b2ce --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/MirrorMakerService.java @@ -0,0 +1,255 @@ +/*- + * ============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.service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + + + + + + + + + +//import org.openecomp.dmaapbc.aaf.AndrewDecryptor; +import org.onap.dmaap.dbcapi.aaf.AafDecrypt; +import org.onap.dmaap.dbcapi.client.MrTopicConnection; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.model.MirrorMaker; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.RandomInteger; + +public class MirrorMakerService extends BaseLoggingClass { + + private Map<String, MirrorMaker> mirrors = DatabaseClass.getMirrorMakers(); + private static MrTopicConnection prov; + private static AafDecrypt decryptor; + + static final String PROV_USER_PROPERTY = "MM.ProvUserMechId"; + static final String PROV_PWD_PROPERTY = "MM.ProvUserPwd"; + static final String PROV_PWD_DEFAULT = "pwdNotSet"; + static final String SOURCE_REPLICATION_PORT_PROPERTY = "MR.SourceReplicationPort"; + static final String SOURCE_REPLICATION_PORT_DEFAULT = "9092"; + static final String TARGET_REPLICATION_PORT_PROPERTY = "MR.TargetReplicationPort"; + static final String TARGET_REPLICATION_PORT_DEFAULT = "2181"; + + private static String provUser; + private static String provUserPwd; + private static String defaultProducerPort; + private static String defaultConsumerPort; + private static String centralFqdn; + private int maxTopicsPerMM; + private boolean mmPerMR; + + public MirrorMakerService() { + super(); + decryptor = new AafDecrypt(); + DmaapConfig p = (DmaapConfig)DmaapConfig.getConfig(); + provUser = p.getProperty(PROV_USER_PROPERTY); + provUserPwd = decryptor.decrypt(p.getProperty( PROV_PWD_PROPERTY, PROV_PWD_DEFAULT )); + defaultProducerPort = p.getProperty( SOURCE_REPLICATION_PORT_PROPERTY, SOURCE_REPLICATION_PORT_DEFAULT ); + defaultConsumerPort = p.getProperty( TARGET_REPLICATION_PORT_PROPERTY, TARGET_REPLICATION_PORT_DEFAULT ); + centralFqdn = p.getProperty("MR.CentralCname", "notSet"); + maxTopicsPerMM = Integer.valueOf( p.getProperty( "MaxTopicsPerMM", "5")); + mmPerMR = "true".equalsIgnoreCase(p.getProperty("MirrorMakerPerMR", "true")); + } + + // will create a MM on MMagent if needed + // will update the MMagent whitelist with all topics for this MM + public MirrorMaker updateMirrorMaker( MirrorMaker mm ) { + logger.info( "updateMirrorMaker"); + + prov = new MrTopicConnection( provUser, provUserPwd ); + + DmaapService dmaap = new DmaapService(); + MR_ClusterService clusters = new MR_ClusterService(); + MR_Cluster target_cluster = null; + String override = null; + + if ( ! mmPerMR ) { + // in ECOMP, MM Agent is only deployed at central, so this case is needed for backwards compatibility + // we use a cname for the central MR cluster that is active, and provision on agent topic on that target + // but only send 1 message so MM Agents can read it relying on kafka delivery + for( MR_Cluster cluster: clusters.getCentralClusters() ) { + + target_cluster = cluster; + override = centralFqdn; + // we only want to send one message even if there are multiple central clusters + break; + + } + } else { + // In ONAP deployment architecture, the MM Agent is deployed with each target MR + target_cluster = clusters.getMr_ClusterByFQDN(mm.getTargetCluster()); + override = null; + } + + prov.makeTopicConnection(target_cluster, dmaap.getBridgeAdminFqtn(), override ); + ApiError resp = prov.doPostMessage(mm.createMirrorMaker( defaultConsumerPort, defaultProducerPort )); + if ( ! resp.is2xx() ) { + + errorLogger.error( DmaapbcLogMessageEnum.MM_PUBLISH_ERROR, "create MM", Integer.toString(resp.getCode()), resp.getMessage()); + mm.setStatus(DmaapObject_Status.INVALID); + } else { + prov.makeTopicConnection(target_cluster, dmaap.getBridgeAdminFqtn(), override ); + resp = prov.doPostMessage(mm.getWhitelistUpdateJSON()); + if ( ! resp.is2xx()) { + errorLogger.error( DmaapbcLogMessageEnum.MM_PUBLISH_ERROR,"MR Bridge", Integer.toString(resp.getCode()), resp.getMessage()); + mm.setStatus(DmaapObject_Status.INVALID); + } else { + mm.setStatus(DmaapObject_Status.VALID); + } + } + + mm.setLastMod(); + return mirrors.put( mm.getMmName(), mm); + } + public MirrorMaker getMirrorMaker( String part1, String part2, int index ) { + String targetPart; + + // original mm names did not have any index, so leave off index 0 for + // backwards compatibility + if ( index == 0 ) { + targetPart = part2; + } else { + targetPart = part2 + "_" + index; + } + logger.info( "getMirrorMaker using " + part1 + " and " + targetPart ); + return mirrors.get(MirrorMaker.genKey(part1, targetPart)); + } + public MirrorMaker getMirrorMaker( String part1, String part2 ) { + logger.info( "getMirrorMaker using " + part1 + " and " + part2 ); + return mirrors.get(MirrorMaker.genKey(part1, part2)); + } + public MirrorMaker getMirrorMaker( String key ) { + logger.info( "getMirrorMaker using " + key); + return mirrors.get(key); + } + + + public void delMirrorMaker( MirrorMaker mm ) { + logger.info( "delMirrorMaker"); + mirrors.remove(mm.getMmName()); + } + + // TODO: this should probably return sequential values or get replaced by the MM client API + // but it should be sufficient for initial 1610 development + public static String genTransactionId() { + RandomInteger ri = new RandomInteger(100000); + int randomInt = ri.next(); + return Integer.toString(randomInt); + } + public List<String> getAllMirrorMakers() { + List<String> ret = new ArrayList<String>(); + for( String key: mirrors.keySet()) { + ret.add( key ); + } + + return ret; + } + + public MirrorMaker findNextMM( String source, String target, String fqtn ) { + int i = 0; + MirrorMaker mm = null; + while( mm == null ) { + + mm = this.getMirrorMaker( source, target, i); + if ( mm == null ) { + mm = new MirrorMaker(source, target, i); + } + if ( mm.getTopics().contains(fqtn) ) { + break; + } + if ( mm.getTopicCount() >= maxTopicsPerMM ) { + logger.info( "getNextMM: MM " + mm.getMmName() + " has " + mm.getTopicCount() + " topics. Moving to next MM"); + i++; + mm = null; + } + } + + + return mm; + } + + public MirrorMaker splitMM( MirrorMaker orig ) { + + String source = orig.getSourceCluster(); + String target = orig.getTargetCluster(); + + + ArrayList<String> whitelist = orig.getTopics(); + while( whitelist.size() > maxTopicsPerMM ) { + + int last = whitelist.size() - 1; + String topic = whitelist.get(last); + whitelist.remove(last); + MirrorMaker mm = this.findNextMM( source, target, "aValueThatShouldNotMatchAnything" ); + mm.addTopic(topic); + this.updateMirrorMaker(mm); + } + + orig.setTopics(whitelist); + + return orig; + + } + + public static String getProvUser() { + return provUser; + } + + public static void setProvUser(String provUser) { + MirrorMakerService.provUser = provUser; + } + + public static String getProvUserPwd() { + return provUserPwd; + } + + public static void setProvUserPwd(String provUserPwd) { + MirrorMakerService.provUserPwd = provUserPwd; + } + + public static String getDefaultProducerPort() { + return defaultProducerPort; + } + + public static void setDefaultProducerPort(String defaultProducerPort) { + MirrorMakerService.defaultProducerPort = defaultProducerPort; + } + + public static String getDefaultConsumerPort() { + return defaultConsumerPort; + } + + public static void setDefaultConsumerPort(String defaultConsumerPort) { + MirrorMakerService.defaultConsumerPort = defaultConsumerPort; + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java new file mode 100644 index 0000000..009b745 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/service/TopicService.java @@ -0,0 +1,526 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.service; + +import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType; +import org.onap.dmaap.dbcapi.aaf.AafServiceFactory; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.logging.DmaapbcLogMessageEnum; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.model.MR_Client; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.model.MirrorMaker; +import org.onap.dmaap.dbcapi.model.ReplicationType; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.Fqdn; +import org.onap.dmaap.dbcapi.util.Graph; + +import javax.ws.rs.core.Response.Status; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +public class TopicService extends BaseLoggingClass { + + + // REF: https://wiki.web.att.com/pages/viewpage.action?pageId=519703122 + private static String defaultGlobalMrHost; + + private Map<String, Topic> mr_topics; + + private static DmaapService dmaapSvc = new DmaapService(); + private MR_ClientService clientService; + private MR_ClusterService clusters; + private DcaeLocationService locations; + private MirrorMakerService bridge; + private AafTopicSetupService aafTopicSetupService; + + private static String centralCname; + private boolean strictGraph = true; + private boolean mmPerMR; + + + public TopicService() { + this(DatabaseClass.getTopics(), new MR_ClientService(), (DmaapConfig) DmaapConfig.getConfig(), + new MR_ClusterService(), new DcaeLocationService(), new MirrorMakerService(), + new AafTopicSetupService( + new AafServiceFactory().initAafService(ServiceType.AAF_TopicMgr), + dmaapSvc, (DmaapConfig) DmaapConfig.getConfig())); + } + + TopicService(Map<String, Topic> mr_topics, MR_ClientService clientService, DmaapConfig p, + MR_ClusterService clusters, DcaeLocationService locations, MirrorMakerService bridge, AafTopicSetupService aafTopicSetupService) { + this.mr_topics = mr_topics; + this.clientService = clientService; + defaultGlobalMrHost = p.getProperty("MR.globalHost", "global.host.not.set"); + centralCname = p.getProperty("MR.CentralCname"); + String unit_test = p.getProperty("UnitTest", "No"); + if ("Yes".equals(unit_test)) { + strictGraph = false; + } + mmPerMR = "true".equalsIgnoreCase(p.getProperty("MirrorMakerPerMR", "true")); + logger.info("TopicService properties: CentralCname=" + centralCname + + " defaultGlobarlMrHost=" + defaultGlobalMrHost + + " mmPerMR=" + mmPerMR); + this.clusters = clusters; + this.locations = locations; + this.bridge = bridge; + this.aafTopicSetupService = aafTopicSetupService; + } + + public Map<String, Topic> getTopics() { + return mr_topics; + } + + public List<Topic> getAllTopics() { + return getAllTopics(true); + } + + public List<Topic> getAllTopicsWithoutClients() { + return getAllTopics(false); + } + + private List<Topic> getAllTopics(Boolean withClients) { + ArrayList<Topic> topics = new ArrayList<>(mr_topics.values()); + if (withClients) { + for (Topic topic : topics) { + topic.setClients(clientService.getAllMrClients(topic.getFqtn())); + } + } + return topics; + } + + public Topic getTopic(String key, ApiError apiError) { + logger.info("getTopic: key=" + key); + Topic t = mr_topics.get(key); + if (t == null) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setFields("fqtn"); + apiError.setMessage("topic with fqtn " + key + " not found"); + return null; + } + t.setClients(clientService.getAllMrClients(key)); + apiError.setCode(Status.OK.getStatusCode()); + return t; + } + + public Topic addTopic(Topic topic, ApiError err, Boolean useExisting) { + logger.info("Entry: addTopic"); + logger.info("Topic name=" + topic.getTopicName() + " fqtnStyle=" + topic.getFqtnStyle()); + String nFqtn = topic.genFqtn(); + logger.info("FQTN=" + nFqtn); + Topic pTopic = getTopic(nFqtn, err); + if (pTopic != null) { + String t = "topic already exists: " + nFqtn; + logger.info(t); + if (useExisting) { + err.setCode(Status.OK.getStatusCode()); + return pTopic; + } + err.setMessage(t); + err.setFields("fqtn"); + err.setCode(Status.CONFLICT.getStatusCode()); + return null; + } + err.reset(); // err filled with NOT_FOUND is expected case, but don't want to litter... + + topic.setFqtn(nFqtn); + + ApiError topicSetupError = aafTopicSetupService.aafTopicSetup(topic); + updateApiError(err, topicSetupError); + if (err.getCode() >= 400) { + return null; + } + + if (topic.getReplicationCase().involvesGlobal()) { + if (topic.getGlobalMrURL() == null) { + topic.setGlobalMrURL(defaultGlobalMrHost); + } + if (!Fqdn.isValid(topic.getGlobalMrURL())) { + logger.error("GlobalMR FQDN not valid: " + topic.getGlobalMrURL()); + topic.setStatus(DmaapObject_Status.INVALID); + err.setCode(500); + err.setMessage("Value is not a valid FQDN:" + topic.getGlobalMrURL()); + err.setFields("globalMrURL"); + + return null; + } + } + + + if (topic.getNumClients() > 0) { + ArrayList<MR_Client> clients = new ArrayList<MR_Client>(topic.getClients()); + + + ArrayList<MR_Client> clients2 = new ArrayList<MR_Client>(); + for (Iterator<MR_Client> it = clients.iterator(); it.hasNext(); ) { + MR_Client c = it.next(); + + logger.info("c fqtn=" + c.getFqtn() + " ID=" + c.getMrClientId() + " url=" + c.getTopicURL()); + MR_Client nc = new MR_Client(c.getDcaeLocationName(), topic.getFqtn(), c.getClientRole(), c.getAction()); + nc.setFqtn(topic.getFqtn()); + nc.setClientIdentity(c.getClientIdentity()); + logger.info("nc fqtn=" + nc.getFqtn() + " ID=" + nc.getMrClientId() + " url=" + nc.getTopicURL()); + clients2.add(clientService.addMr_Client(nc, topic, err)); + if (!err.is2xx()) { + return null; + } + } + + topic.setClients(clients2); + } + + Topic ntopic = checkForBridge(topic, err); + if (ntopic == null) { + topic.setStatus(DmaapObject_Status.INVALID); + if (!err.is2xx()) { + return null; + } + } + + + mr_topics.put(nFqtn, ntopic); + + err.setCode(Status.OK.getStatusCode()); + return ntopic; + } + + + public Topic updateTopic(Topic topic, ApiError err) { + logger.info("updateTopic: entry"); + logger.info("updateTopic: topic=" + topic); + logger.info("updateTopic: fqtn=" + topic.getFqtn()); + if (topic.getFqtn().isEmpty()) { + return null; + } + logger.info("updateTopic: call checkForBridge"); + Topic ntopic = checkForBridge(topic, err); + if (ntopic == null) { + topic.setStatus(DmaapObject_Status.INVALID); + if (!err.is2xx()) { + return null; + } + } + if (ntopic != null) { + logger.info("updateTopic: call put"); + mr_topics.put(ntopic.getFqtn(), ntopic); + } + err.setCode(Status.OK.getStatusCode()); + return ntopic; + } + + public Topic removeTopic(String pubId, ApiError apiError) { + Topic topic = mr_topics.get(pubId); + if (topic == null) { + apiError.setCode(Status.NOT_FOUND.getStatusCode()); + apiError.setMessage("Topic " + pubId + " does not exist"); + apiError.setFields("fqtn"); + return null; + } + + ApiError topicSetupError = aafTopicSetupService.aafTopicCleanup(topic); + updateApiError(apiError, topicSetupError); + if (apiError.getCode() >= 400) { + return null; + } + + ArrayList<MR_Client> clients = new ArrayList<MR_Client>(clientService.getAllMrClients(pubId)); + for (Iterator<MR_Client> it = clients.iterator(); it.hasNext(); ) { + MR_Client c = it.next(); + clientService.removeMr_Client(c.getMrClientId(), false, apiError); + if (!apiError.is2xx()) { + return null; + } + } + apiError.setCode(Status.OK.getStatusCode()); + return mr_topics.remove(pubId); + } + + public static ApiError setBridgeClientPerms(MR_Cluster node) { + DmaapConfig p = (DmaapConfig) DmaapConfig.getConfig(); + String mmProvRole = p.getProperty("MM.ProvRole"); + String mmAgentRole = p.getProperty("MM.AgentRole"); + String[] Roles = {mmProvRole, mmAgentRole}; + String[] actions = {"view", "pub", "sub"}; + Topic bridgeAdminTopic = new Topic().init(); + bridgeAdminTopic.setTopicName(dmaapSvc.getBridgeAdminFqtn()); + bridgeAdminTopic.setTopicDescription("RESERVED topic for MirroMaker Provisioning"); + bridgeAdminTopic.setOwner("DBC"); + + ArrayList<MR_Client> clients = new ArrayList<MR_Client>(); + for (String role : Roles) { + MR_Client client = new MR_Client(); + client.setAction(actions); + client.setClientRole(role); + client.setDcaeLocationName(node.getDcaeLocationName()); + clients.add(client); + } + bridgeAdminTopic.setClients(clients); + + TopicService ts = new TopicService(); + ApiError err = new ApiError(); + ts.addTopic(bridgeAdminTopic, err, true); + + if (err.is2xx() || err.getCode() == 409) { + err.setCode(200); + return err; + } + + errorLogger.error(DmaapbcLogMessageEnum.TOPIC_CREATE_ERROR, bridgeAdminTopic.getFqtn(), Integer.toString(err.getCode()), err.getFields(), err.getMessage()); + return err; + } + + + public Topic checkForBridge(Topic topic, ApiError err) { + logger.info("checkForBridge: entry"); + logger.info("fqtn=" + topic.getFqtn() + " replicatonType=" + topic.getReplicationCase()); + if (topic.getReplicationCase() == ReplicationType.REPLICATION_NONE) { + topic.setStatus(DmaapObject_Status.VALID); + return topic; + } + + boolean anythingWrong = false; + + Set<String> groups = clusters.getGroups(); + for (String g : groups) { + logger.info("buildBridge for " + topic.getFqtn() + " on group" + g); + anythingWrong |= buildBridge(topic, err, g); + } + if (anythingWrong) { + topic.setStatus(DmaapObject_Status.INVALID); + if (!err.is2xx()) { + return null; + } + } else { + topic.setStatus(DmaapObject_Status.VALID); + } + return topic; + } + + private boolean buildBridge(Topic topic, ApiError err, String group) { + logger.info("buildBridge: entry"); + boolean anythingWrong = false; + Graph graph; + logger.info("buildBridge: strictGraph=" + strictGraph); + if (group == null || group.isEmpty()) { + graph = new Graph(topic.getClients(), strictGraph); + } else { + graph = new Graph(topic.getClients(), strictGraph, group); + } + logger.info("buildBridge: graph=" + graph); + MR_Cluster groupCentralCluster = null; + + + if (graph.isEmpty()) { + logger.info("buildBridge: graph is empty. return false"); + return false; + } else if (group == null && topic.getReplicationCase().involvesFQDN()) { + logger.info("buildBridge: group is null and replicationCaseInvolvesFQDN. return false"); + return false; + } else if (!graph.hasCentral()) { + logger.warn("Topic " + topic.getFqtn() + " wants to be " + topic.getReplicationCase() + " but has no central clients"); + return true; + } else { + groupCentralCluster = clusters.getMr_ClusterByLoc(graph.getCentralLoc()); + } + Collection<String> clientLocations = graph.getKeys(); + for (String loc : clientLocations) { + logger.info("loc=" + loc); + DcaeLocation location = locations.getDcaeLocation(loc); + MR_Cluster cluster = clusters.getMr_ClusterByLoc(loc); + logger.info("cluster=" + cluster + " at " + cluster.getDcaeLocationName()); + logger.info("location.isCentral()=" + location.isCentral() + " getCentralLoc()=" + graph.getCentralLoc()); + + + String source = null; + String target = null; + + /* + * Provision Edge to Central bridges... + */ + if (!location.isCentral() && !graph.getCentralLoc().equals(cluster.getDcaeLocationName())) { + switch (topic.getReplicationCase()) { + case REPLICATION_EDGE_TO_CENTRAL: + case REPLICATION_EDGE_TO_CENTRAL_TO_GLOBAL: // NOTE: this is for E2C portion only + source = cluster.getFqdn(); + target = (mmPerMR) ? groupCentralCluster.getFqdn() : centralCname; + logger.info("REPLICATION_EDGE_TO_CENTRAL: source=" + source + " target=" + target); + break; + case REPLICATION_CENTRAL_TO_EDGE: + case REPLICATION_GLOBAL_TO_CENTRAL_TO_EDGE: // NOTE: this is for C2E portion only + source = (mmPerMR) ? groupCentralCluster.getFqdn() : centralCname; + target = cluster.getFqdn(); + break; + case REPLICATION_CENTRAL_TO_GLOBAL: + case REPLICATION_GLOBAL_TO_CENTRAL: + case REPLICATION_FQDN_TO_GLOBAL: + case REPLICATION_GLOBAL_TO_FQDN: + break; + + case REPLICATION_EDGE_TO_FQDN: + case REPLICATION_EDGE_TO_FQDN_TO_GLOBAL: // NOTE: this is for E2C portion only + source = cluster.getFqdn(); + target = groupCentralCluster.getFqdn(); + break; + case REPLICATION_FQDN_TO_EDGE: + case REPLICATION_GLOBAL_TO_FQDN_TO_EDGE: // NOTE: this is for F2E portion only + source = groupCentralCluster.getFqdn(); + target = cluster.getFqdn(); + break; + + default: + logger.error("Unexpected value for ReplicationType (" + topic.getReplicationCase() + ") for topic " + topic.getFqtn()); + anythingWrong = true; + err.setCode(400); + err.setFields("topic=" + topic.genFqtn() + " replicationCase=" + + topic.getReplicationCase()); + err.setMessage("Unexpected value for ReplicationType"); + continue; + } + + } else if (location.isCentral() && graph.getCentralLoc().equals(cluster.getDcaeLocationName())) { + /* + * Provision Central to Global bridges + */ + switch (topic.getReplicationCase()) { + + case REPLICATION_CENTRAL_TO_GLOBAL: + case REPLICATION_EDGE_TO_CENTRAL_TO_GLOBAL: + source = centralCname; + target = topic.getGlobalMrURL(); + break; + case REPLICATION_GLOBAL_TO_CENTRAL: + case REPLICATION_GLOBAL_TO_CENTRAL_TO_EDGE: // NOTE: this is for G2C portion only + source = topic.getGlobalMrURL(); + target = centralCname; + break; + + case REPLICATION_EDGE_TO_FQDN_TO_GLOBAL: // NOTE: this is for E2F portion only + source = groupCentralCluster.getFqdn(); + target = topic.getGlobalMrURL(); + break; + + case REPLICATION_FQDN_TO_GLOBAL: + source = groupCentralCluster.getFqdn(); + target = topic.getGlobalMrURL(); + break; + + case REPLICATION_GLOBAL_TO_FQDN: + case REPLICATION_GLOBAL_TO_FQDN_TO_EDGE: // NOTE: this is for G2F portion only + source = topic.getGlobalMrURL(); + target = groupCentralCluster.getFqdn(); + break; + + case REPLICATION_FQDN_TO_EDGE: + case REPLICATION_EDGE_TO_FQDN: + case REPLICATION_EDGE_TO_CENTRAL: + case REPLICATION_CENTRAL_TO_EDGE: + break; + default: + logger.error("Unexpected value for ReplicationType (" + topic.getReplicationCase() + ") for topic " + topic.getFqtn()); + anythingWrong = true; + err.setCode(400); + err.setFields("topic=" + topic.genFqtn() + " replicationCase=" + + topic.getReplicationCase()); + err.setMessage("Unexpected value for ReplicationType"); + continue; + } + } else { + logger.warn("dcaeLocation " + loc + " is neither Edge nor Central so no mmagent provisioning was done"); + anythingWrong = true; + continue; + } + if (source != null && target != null) { + try { + logger.info("Create a MM from " + source + " to " + target); + MirrorMaker mm = bridge.findNextMM(source, target, topic.getFqtn()); + mm.addTopic(topic.getFqtn()); + bridge.updateMirrorMaker(mm); + } catch (Exception ex) { + err.setCode(500); + err.setFields("mirror_maker.topic"); + err.setMessage("Unexpected condition: " + ex); + anythingWrong = true; + break; + } + } + + + } + return anythingWrong; + + } + + + /* + * Prior to 1707, we only supported EDGE_TO_CENTRAL replication. + * This was determined automatically based on presence of edge publishers and central subscribers. + * The following method is a modification of that original logic, to preserve some backwards compatibility, + * i.e. to be used when no ReplicationType is specified. + */ + + public ReplicationType reviewTopic(Topic topic) { + + + if (topic.getNumClients() > 1) { + Graph graph = new Graph(topic.getClients(), false); + + String centralFqdn = new String(); + if (graph.hasCentral()) { + DmaapConfig p = (DmaapConfig) DmaapConfig.getConfig(); + centralFqdn = p.getProperty("MR.CentralCname"); + } + + Collection<String> locations = graph.getKeys(); + for (String loc : locations) { + logger.info("loc=" + loc); + MR_Cluster cluster = clusters.getMr_ClusterByLoc(loc); + if (cluster == null) { + logger.info("No MR cluster for location " + loc); + continue; + } + if (graph.hasCentral() && !graph.getCentralLoc().equals(cluster.getDcaeLocationName())) { + logger.info("Detected case for EDGE_TO_CENTRAL from " + cluster.getFqdn() + " to " + centralFqdn); + return ReplicationType.REPLICATION_EDGE_TO_CENTRAL; + + } + + } + } + + return ReplicationType.REPLICATION_NONE; + } + + private void updateApiError(ApiError err, ApiError topicSetupError) { + err.setCode(topicSetupError.getCode()); + err.setMessage(topicSetupError.getMessage()); + err.setFields(topicSetupError.getFields()); + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/DmaapConfig.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/DmaapConfig.java new file mode 100644 index 0000000..e95ebab --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/DmaapConfig.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========================================================= + */ + +package org.onap.dmaap.dbcapi.util; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import java.io.*; +import java.security.KeyStore; +import java.util.*; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import org.onap.dmaap.dbcapi.server.CertificateManager; +import org.onap.dmaap.dbcapi.server.JettyServer; + +public class DmaapConfig extends Properties { + + private static final EELFLogger logger = EELFManager.getInstance().getLogger(DmaapConfig.class); + private static final long serialVersionUID = 1L; + private static final String CONFIG_FILE_NAME = System.getProperty("ConfigFile", "/opt/app/config/conf/dmaapbc.properties"); + private static final Properties config = new DmaapConfig(); + + public static Properties getConfig() { + return(config); + } + public static String getConfigFileName() { + return(CONFIG_FILE_NAME); + } + private DmaapConfig() { + try (InputStream is = new FileInputStream(CONFIG_FILE_NAME)){ + load(is); + } catch (Exception e) { + logger.error("Unable to load configuration file " + CONFIG_FILE_NAME); + System.exit(1); + } + } + + public static SSLSocketFactory getSSLSocketFactory() { + SSLSocketFactory factory = null; + try { + CertificateManager cm = JettyServer.getCertificateManager(); + String truststore = cm.getTrustStoreFile(); + KeyStore ts = KeyStore.getInstance(cm.getTrustStoreType()); + try (InputStream in = new FileInputStream(truststore)) { + ts.load(in, cm.getTrustStorePassword().toCharArray()); + } + TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + tmf.init(ts); + TrustManager[] tm = tmf.getTrustManagers(); + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, tm, null); + factory = sslContext.getSocketFactory(); + } catch (Exception e) { + logger.error("Exception thrown trying to get SSLSocketFactory: ", e); + } + return factory; + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/DmaapTimestamp.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/DmaapTimestamp.java new file mode 100644 index 0000000..f36df1c --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/DmaapTimestamp.java @@ -0,0 +1,46 @@ +/*- + * ============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.util; + +import javax.xml.bind.annotation.XmlRootElement; +import java.util.Date; + +@XmlRootElement +public class DmaapTimestamp { + private Date stamp; + + public DmaapTimestamp() { + this(new Date()); + } + + DmaapTimestamp(Date stamp) { + this.stamp = new Date(stamp.getTime()); + } + + public void mark() { + stamp = new Date(); + } + + public Date getVal() { + return new Date(stamp.getTime()); + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/Fqdn.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/Fqdn.java new file mode 100644 index 0000000..37715d3 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/Fqdn.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.util; + +import java.util.regex.Pattern; + +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; + +public class Fqdn extends BaseLoggingClass { + // regexp value sourced from https://www.regextester.com/23 + static String regexp = "^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$"; + + + public static boolean isValid( String s ) { + appLogger.info( "Fqdn testing: " + s ); + boolean b = false; + if ( s != null ) { + b = Pattern.matches( regexp, s); + } + appLogger.info( "Fqdn isValid=" + b ); + return b; + } + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/Graph.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/Graph.java new file mode 100644 index 0000000..ab40765 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/Graph.java @@ -0,0 +1,132 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. + * + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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.util; + +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.MR_Client; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.service.MR_ClusterService; + +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + + +public class Graph { + private HashMap<String, String> graph; + private boolean hasCentral; + + private Map<String, DcaeLocation> locations = DatabaseClass.getDcaeLocations(); + + //TODO add to properties file + private static String centralDcaeLayerName = "central"; + + + public Graph(HashMap<String, String> graph) { + super(); + this.graph = graph; + } + + public Graph( List<MR_Client> clients, boolean strict ) { + if ( clients == null ) + return; + initGraph( clients, strict, "" ); + + } + public Graph( List<MR_Client> clients, boolean strict, String group ) { + if ( clients == null ) + return; + initGraph( clients, strict, group ); + } + + private void initGraph(List<MR_Client> clients, boolean strict, String group ) { + MR_ClusterService clusters = new MR_ClusterService(); + this.graph = new HashMap<>(); + this.hasCentral = false; + for( MR_Client client: clients ) { + if ( ! strict || client.isStatusValid()) { + String loc = client.getDcaeLocationName(); + DcaeLocation dcaeLoc = locations.get(loc); + if ( dcaeLoc == null ) continue; + MR_Cluster c = clusters.getMr_ClusterByLoc(loc); + if ( group != null && ! group.isEmpty() && ! group.equals(c.getReplicationGroup())) continue; + + for( String action : client.getAction() ){ + if ( ! action.equals("view") && dcaeLoc != null ) { + String layer = dcaeLoc.getDcaeLayer(); + if ( layer != null && layer.contains(centralDcaeLayerName) ) { + this.hasCentral = true; + } + graph.put(loc, layer); + } + } + + } + } + } + + public HashMap<String, String> getGraph() { + return graph; + } + + public void setGraph(HashMap<String, String> graph) { + this.graph = graph; + } + + public String put( String key, String val ) { + return graph.put(key, val); + } + + public String get( String key ) { + return graph.get(key); + } + + public Collection<String> getKeys() { + return graph.keySet(); + } + public boolean hasCentral() { + return hasCentral; + } + public void setHasCentral(boolean hasCentral) { + this.hasCentral = hasCentral; + } + + public String getCentralLoc() { + if ( ! hasCentral ) { + return null; + } + for( String loc : graph.keySet()) { + if ( graph.get(loc).contains(centralDcaeLayerName)) { + return loc; + } + } + return null; + } + public boolean isEmpty() { + return graph.isEmpty(); + } + + +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/PermissionBuilder.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/PermissionBuilder.java new file mode 100644 index 0000000..d1f6b2b --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/PermissionBuilder.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.util; + +import javax.servlet.http.HttpServletRequest; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.service.DmaapService; + +public class PermissionBuilder { + + static final String API_NS_PROP = "ApiNamespace"; + static final String DEFAULT_API_NS = "org.onap.dmaap-bc.api"; + static final String BOOT_INSTANCE = "boot"; + private static final String PERM_SEPARATOR = "|"; + private static final String NS_SEPARATOR = "."; + private DmaapConfig dmaapConfig; + private DmaapService dmaapService; + private String instance; + private String apiNamespace; + + public PermissionBuilder(DmaapConfig dmaapConfig, DmaapService dmaapService) { + this.dmaapConfig = dmaapConfig; + this.dmaapService = dmaapService; + initFields(); + } + + public synchronized void updateDmaapInstance() { + if(instance == null || instance.isEmpty() || instance.equalsIgnoreCase(BOOT_INSTANCE)) { + String dmaapName = getDmaapName(); + instance = (dmaapName == null || dmaapName.isEmpty()) ? BOOT_INSTANCE : dmaapName; + } + } + + public String buildPermission(HttpServletRequest httpRequest) { + + StringBuilder sb = new StringBuilder(apiNamespace); + sb.append(NS_SEPARATOR) + .append(getPermissionType(httpRequest.getPathInfo())) + .append(PERM_SEPARATOR) + .append(instance) + .append(PERM_SEPARATOR) + .append(httpRequest.getMethod()); + return sb.toString(); + } + + + private void initFields() { + apiNamespace = dmaapConfig.getProperty(API_NS_PROP, DEFAULT_API_NS); + updateDmaapInstance(); + } + + private String getDmaapName() { + Dmaap dmaap = dmaapService.getDmaap(); + return ( dmaap != null ) ? dmaap.getDmaapName() : BOOT_INSTANCE; + } + + private String getPermissionType(String pathInfo) { + char pathSeparator = '/'; + String[] pathSlices = pathInfo.split(String.valueOf(pathSeparator)); + return pathSlices[1]; + } + + String getInstance() { + return instance; + } +} diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/RandomInteger.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/RandomInteger.java new file mode 100644 index 0000000..1c9bc11 --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/RandomInteger.java @@ -0,0 +1,43 @@ +/*- + * ============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.util; + +import java.util.Date; +// source: http://www.javapractices.com/topic/TopicAction.do?Id=62 +// with some modifications +import java.util.Random; + +public final class RandomInteger { + private static Random randomGenerator; + private int range; + + public RandomInteger( int r ) { + randomGenerator = new Random(); + randomGenerator.setSeed((new Date()).getTime()); + range = r; + } + + public int next(){ + return randomGenerator.nextInt(range); + } + +} + diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/RandomString.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/RandomString.java new file mode 100644 index 0000000..b889c1c --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/RandomString.java @@ -0,0 +1,55 @@ +/*- + * ============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.util; + +import java.util.Random; + +// source: http://stackoverflow.com/questions/41107/how-to-generate-a-random-alpha-numeric-string + +public class RandomString { + + private static final char[] symbols; + + static { + StringBuilder tmp = new StringBuilder(); + for (char ch = '0'; ch <= '9'; ++ch) + tmp.append(ch); + for (char ch = 'a'; ch <= 'z'; ++ch) + tmp.append(ch); + symbols = tmp.toString().toCharArray(); + } + + private final Random random = new Random(); + + private final char[] buf; + + public RandomString(int length) { + if (length < 1) + throw new IllegalArgumentException("length < 1: " + length); + buf = new char[length]; + } + + public String nextString() { + for (int idx = 0; idx < buf.length; ++idx) + buf[idx] = symbols[random.nextInt(symbols.length)]; + return new String(buf); + } + } diff --git a/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/Singleton.java b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/Singleton.java new file mode 100644 index 0000000..3ef6a3d --- /dev/null +++ b/dmaap-bc/src/main/java/org/onap/dmaap/dbcapi/util/Singleton.java @@ -0,0 +1,28 @@ +/*- + * ============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.util; + +public interface Singleton<T> { + public T get(); + public void init(T val); + public void update(T val); + public void remove(); +} diff --git a/dmaap-bc/src/main/resources/docker-compose.yml b/dmaap-bc/src/main/resources/docker-compose.yml deleted file mode 100644 index 41bc473..0000000 --- a/dmaap-bc/src/main/resources/docker-compose.yml +++ /dev/null @@ -1,25 +0,0 @@ -version: '2' -services: - dbc-pg-primary: - image: crunchydata/crunchy-postgres:centos7-10.4-2.0.0 - ports: - - "5432:5432" - environment: - - PG_MODE=master - - PG_PRIMARY_USER="dmaap_admin" - - PG_PRIMARY_PASSWORD=onapdemodb - - PG_USER="dmaap_admin" - - PG_PASSWORD=onapdemodb - - PG_ROOT_PASSWORD=onapdemodb - - PG_DATABASE="dmaap" - - PG_PRIMARY_PORT=5432 - - dmaap-bc: - image: nexus3.onap.org:10001/onap/dmaap/buscontroller:latest - ports: - - "30241:8080" - - "30242:8443" - volumes: - - /var/tmp/docker-databus-controller.conf:/opt/app/config/conf - depends_on: - - dbc-pg-primary diff --git a/dmaap-bc/src/main/resources/docker-databus-controller.conf b/dmaap-bc/src/main/resources/docker-databus-controller.conf deleted file mode 100644 index 7214adf..0000000 --- a/dmaap-bc/src/main/resources/docker-databus-controller.conf +++ /dev/null @@ -1,12 +0,0 @@ -DMAAPBC_WAIT_TO_EXIT=Y -DMAAPBC_PG_ENABLED=true -DMAAPBC_PGHOST=dbc-pg-primary -DMAAPBC_PGDBNAME=dmaap -DMAAPBC_PGCRED=onapdemodb -DMAAPBC_PGUSER=dmaap_admin -DMAAPBC_MR_CNAME=message-router -DMAAPBC_AAF_URL=https://aaf-authz/ -DMAAPBC_TOPICMGR_USER=m23456@dmaapbc.onap.org -DMAAPBC_TOPICMGR_PWD=onapdemo -DMAAPBC_ADMIN_USER=m12345@dmaapbc.onap.org -DMAAPBC_ADMIN_PWD=onapdemo
\ No newline at end of file diff --git a/dmaap-bc/src/main/resources/Dockerfile b/dmaap-bc/src/main/resources/docker/Dockerfile index 0f9e6a6..a801896 100644 --- a/dmaap-bc/src/main/resources/Dockerfile +++ b/dmaap-bc/src/main/resources/docker/Dockerfile @@ -4,6 +4,7 @@ # =========================================================================== # Copyright © 2017 AT&T Intellectual Property. All rights reserved. # Modifications Copyright (C) 2018 Nokia. All rights reserved. +# Modifications Copyright (C) 2021 Nordix Foundation. # =========================================================================== # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,40 +18,24 @@ # See the License for the specific language governing permissions and # limitations under the License. # ============LICENSE_END==================================================== -# -FROM library/maven:3.6-jdk-11 -MAINTAINER DMAAP Team +FROM nexus3.onap.org:10001/onap/integration-java11:8.0.0 -COPY /opt /opt +MAINTAINER DMAAP Team WORKDIR /opt/app/dmaapbc -RUN apt-get update && \ - apt-get install -y \ - curl \ - jq \ - openssl \ - net-tools \ - wget \ - procps \ - bash - -#prepare certificate location for cadi -RUN mkdir -p /opt/app/osaaf +COPY /opt /opt +USER root +RUN apk add --no-cache curl jq net-tools wget procps \ -RUN chmod +x bin/* && \ +&& mkdir -p /opt/app/osaaf && \ + chmod +x bin/* && \ mkdir logs && \ - mkdir www && \ mkdir doc && \ - mkdir config - -VOLUME /opt/app/dmaapbc/log - -RUN addgroup --system -gid 1001 onap \ - && adduser --ingroup onap --system --disabled-password --no-create-home --uid 1000 dbc \ - && chown -R dbc:onap /opt/ + mkdir config && \ + chown -R onap:onap /opt/ -USER dbc +USER onap -ENTRYPOINT ["sh", "./bin/dmaapbc", "deploy"] +ENTRYPOINT ["sh", "bin/dmaapbc", "deploy"] diff --git a/dmaap-bc/src/main/resources/misc/LocalKey b/dmaap-bc/src/main/resources/misc/LocalKey new file mode 100644 index 0000000..38ede55 --- /dev/null +++ b/dmaap-bc/src/main/resources/misc/LocalKey @@ -0,0 +1,27 @@ +7ntUvubggJ1h6AXwQENQScrnlqmLMno_583XufLsguAT11bnBk0DVLE2GtCZ0pNQzlR8I3PJ1_nZ +UEVQs1G_qZzV-MHQZvz54solEp8dNUVji4JUzP7WiPuJdvCX8vvGLc8-jOVzEJ2DAGmV3gNp60_F +jrKx7F7Dz-h94jWZ45rNn7-Re_BneSto6HiSj0DN_SKSNhE5z9Qf3tFyFLGIYmlQoxzbTYC38uN0 +FjAYuKz6W_pTLzyOjHNAagYwEjTUUU-ei-QA5pL20-oG3jSYGnj_V94kd8X5ncB1-nybUsy5OOvZ +huCxf9hSetn2fpIszkRcuFxaxiwubpmEWp2L_zovhcRI1OMFPIIK0IckRHD1a5CpFVzR7P5L7LQk +FErATsQkHsPS9BJN5wlj1EoIhA2uaELjXjmOqPQg76eyQqXXcMHRJTA6czbXPYfTQMQx1r2USC9o +HdoLT4-so7zARZidmYmvPPT9qvNisK6BF4M32K-_s6YyJspSEB1MscNPujsD7zczIsBct7BTRoeZ +CbtkskT_yFhQzdzdSMzFN_NJ7Yb9p3d1G4gSkj2rbA-BDybHHPij8k6-k-ipvi_T_LW9B_J8Jf5f +aRclZqVgwwSG-mUKUyk9bI3cVc-1P2ICUmr59EjuauDAtlMQL-hnTJUs1rUerh4Q7d4XgrNLjLHY +Oue8MEj24VSMl-f28DDIV1N6ODiBKDHUmdENsmlbqeNpzQxu7FoSbLu6gN6zDP8Jw4ck1NHEIv8H +ecUf-hBGdB0HINClaV9X2ycafWcmRY-NCzX65cp7a1Rpl1kCEW5u79LLN28aJeTzmriewhy87hJf +rAah8z3dHteIN1fuvRoGsFwZ4jKo6olFxcBOlpHQIW5JJ1roO1vQ2Dx_l-Foo7wV_AD127zCu7ci +lYodnAOocKbhAub4sf90P3D2NMKb20e5CQrBSchtIEaD3G7J-vL5xYydLuLu5WipOdZuq3VhSSZm +TZIR3Ya2QiZVokxKgH-N0gPDz-TimNV_MkUSCNsv2NxjBM7oPF3dzEHbHS5eue41_R4vqxFdTdva +o0ASTFkARmmnMFBx1a73jmcoBBx-i4el8Rce7RvFWn1PALOnRsIQPy_Pgx0OE9_6eHfOSvyxbyMM +0FwE5f77gO967tgc4LwqB1pzz2Uk7hfizLKNc6nrrgDxSb_9rDWwiE4rWw7WYcRKvRQ270lCH4FQ +ezrPacnnK3cKM5L6brOyhbhiL4MnNX714L0K8C6TQnIVisQCLHwif40G_DSEWxICQ5V2DMzFn3JT +PefaubHlqxRZVikNH71b_2ZRLEi84m5iUuy8Ir1s3W6xuyIdt-yKLnjgnLjOPPxTDC5G_xaXAAuM +SkSOjvPzOArMUUnwYk68jAxXS2tBT8JN6OnglN8dHC-P24tYzfs4B4tMYJ1ibz6BUsQ6nYxsRUak +4ZjRmo3UG0OFJbOY-f0ja6Q4pISe1IXmlM4Ly9QdCfeHyDV-7Fiud9V_zo92lpQwttwSpBvFoDYQ +oePdA0zmCx6GIX_8L9e8a03hUx4aUtZ8C3Kf0PzOWTcjrV7nGb99ctjmRtfGw5GPWudH6CI3WFK2 +5wFDhrQSbRhzV4iQalYVPJQ7LO4WEi4EsBTRSiz074UpvkMV3UfMGDlpXAAq5rEjj-d5WbHhzbs8 +MGKzZLTfUz9lP4CME9AOwto_ey1ly3H-yaEgCpnshm-CZoSqVDmuFYM0QR_NcrqmSQ9ZKJEF_wTa +TEAXNJ99CYE0ZLvU9FjgCqH1-q1zL7z3NLX1uFYazEZWGMZFPVD5XOcCtUlVyUz9KuAO9ARVyu5C +7kzo_AFePtnsA_JUvvkauo6RwO6qhLJjZuSjvmiSdOAohiXUalDFjWVW8CMfgLF4PbRDklsAcsiT +P0xUdyWJ5slu87f9PunXDwQZWNv6haTIhVX7bilCDpRPbTbmimmE_C2J7tgV2EvazD7o8V_jeu0g +cnIpzRnaPG9l-uy2UKoxOXI4CSymcJoyV2xxC0SF7Q5quAhf3UGAdQUeFtHwxZtYiAMXLs06
\ No newline at end of file diff --git a/dmaap-bc/src/main/resources/misc/PolicyEngineApi.properties.tmpl b/dmaap-bc/src/main/resources/misc/PolicyEngineApi.properties.tmpl new file mode 100644 index 0000000..248b288 --- /dev/null +++ b/dmaap-bc/src/main/resources/misc/PolicyEngineApi.properties.tmpl @@ -0,0 +1,36 @@ +# +# ============LICENSE_START========================================== +# org.onap.dmaap +# =================================================================== +# Copyright © 2018 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============================================ +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# +# + +cat <<!EOF +#PDP URLs to which will be used by the Policy Engine API to take Decisions. There are multiple to support redundancy. +#Format: PDP_URL{PriorityNumber} = URL, id, password. +PDP_URL1 = ${DMAAPBC_PDP1_URL:-https://host1.domain.notset.com:8081/pdp/} , ${DMAAPBC_PDP1_USER:-testpdp} , ${DMAAPBC_PDP1_PWD:-alpha123} +PDP_URL2 = ${DMAAPBC_PDP2_URL:-https://host2.domain.notset.com:8082/pdp/} , ${DMAAPBC_PDP2_USER:-testpdp} , ${DMAAPBC_PDP2_PWD:-alpha456} +PAP_URL = ${DMAAPBC_PAP_URL:-https://host3.domain.notset.com:9091/pap/} , ${DMAAPBC_PAP_USER:-testpap} , ${DMAAPBC_PAP_PWD:-alpha123} + + + +CLIENT_ID=${DMAAPBC_TOPICMGR_USER:-mechIdNotSet@namespaceNotSet} +ENVIRONMENT=${DMAAPBC_PE_AAF_ENV:-DEVL} + + +!EOF diff --git a/dmaap-bc/misc/dmaapbc b/dmaap-bc/src/main/resources/misc/dmaapbc index 15f2fd2..963d2d1 100644 --- a/dmaap-bc/misc/dmaapbc +++ b/dmaap-bc/src/main/resources/misc/dmaapbc @@ -4,6 +4,7 @@ # org.onap.dmaap # =================================================================== # Copyright © 2018 AT&T Intellectual Property. All rights reserved. +# Modifications copyright (C) 2021 Nordix Foundation. # =================================================================== # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,24 +20,23 @@ # ============LICENSE_END============================================ # ECOMP is a trademark and service mark of AT&T Intellectual Property. # -# umask 0022 TZ=GMT0 COMPONENT=dmaapbc APP_ROOT=/opt/app/$COMPONENT -USER=dbc +USER=onap GROUP=onap export TZ -PATH=/usr/local/openjdk-11/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin +PATH=/opt/java/openjdk/bin:/usr/sbin:/usr/bin:/sbin:/bin export PATH -CLASSPATH=`echo $APP_ROOT/etc $APP_ROOT/lib/*.jar | tr ' ' ':'` +CLASSPATH=`echo $APP_ROOT/etc $APP_ROOT/lib/*.jar | tr ' ' ':'` export CLASSPATH CONFIGMAP_ROOT=${CONFIGMAP_ROOT:-/opt/app/config} CONFIGMAP_PROPS=${CONFIGMAP_PROPS:-$CONFIGMAP_ROOT/conf/dmaapbc.properties} CONTAINER_CONFIG=$CONFIGMAP_ROOT/conf/buscontroller.env -MAIN=org.onap.dmaap.dbcapi.server.Main +MAIN=org.onap.dmaap.dbcapi.server.Main authcheck() { set -x @@ -75,8 +75,8 @@ config() { then echo "WARNING: Expected env file $CONTAINER_CONFIG not found. Default behaviors in effect" find $CONTAINER_ROOT -type f - else - . $CONTAINER_CONFIG + else + . $CONTAINER_CONFIG fi if [ "$DMAAPBC_WAIT_TO_EXIT" != "Y" ] @@ -85,27 +85,8 @@ config() { > $APP_ROOT/ok_to_exit else echo "Not creating $APP_ROOT/ok_to_exit" - fi - - #. misc/havecert.tmpl > etc/havecert - #chmod +x etc/havecert - echo Check for certificate - TZ=GMT0 - cd /opt/app/dmaapbc; - KEYSTORE=${DMAAPBC_KSTOREFILE:-etc/keystore} - echo "KEYSTORE=$KEYSTORE" - d=`dirname $KEYSTORE` - ls -l $d - if [ -f ${KEYSTORE} ] - then - echo "Goodness: Found ${KEYSTORE}" - else - EMSG="`date '+%F %T,000'` WARN Certificate file $KEYSTORE is missing" - echo $EMSG - echo $EMSG >>${DMAAPBC_LOGS:-logs}/dmaapbc.log fi - # These files might be better provided in kubernetes configmaps # so if they are there, use them if [ -f $CONFIGMAP_PROPS ] @@ -117,7 +98,7 @@ config() { fi if [ ! -f config/PolicyEngineApi.properties ] then - . misc/PolicyEngineApi.properties.tmpl > config/PolicyEngineApi.properties + . misc/PolicyEngineApi.properties.tmpl > config/PolicyEngineApi.properties fi set +x } @@ -129,13 +110,6 @@ start() { cd $APP_ROOT pwd - if [ -f "$KEYSTORE" ] - then - echo >/dev/null - else - echo No certificate file available. Cannot start - exit 0 - fi PIDS=`pids` if [ "$PIDS" != "" ] then @@ -144,11 +118,11 @@ start() { fi rm -f $APP_ROOT/etc/SHUTDOWN + java -classpath $CLASSPATH $MAIN + dmaapjar="$APP_ROOT/lib/dmaap-bc.jar" # JVM flags -#old line from Dockerfile...keep for reference only - FLAGS="-cp etc:lib/* -Dlog4j.configuration=etc/log4j.properties -DConfigFile=$PROPS -Dlogback.configurationFile=etc/logback.xml -Dhttps.protocols=TLSv1.2 -Dhttps.cipherSuites=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" - #nohup java $FLAGS $MAIN </dev/null >/dev/null 2>&1 & - nohup java $FLAGS $MAIN </dev/null & + FLAGS="-cp etc:lib/* -DConfigFile=$PROPS -Dlogback.configurationFile=etc/logback.xml -Dhttps.protocols=TLSv1.2 -Dhttps.cipherSuites=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256" + nohup java $FLAGS -jar $dmaapjar </dev/null & sleep 5 PIDS=`pids` set +x @@ -181,46 +155,11 @@ status() { fi } -init() { - echo "ENTER init" - if [ ! -d $CONFIGMAP_ROOT ] - then - echo $CONFIGMAP_ROOT does not exist - return - fi - - #loop on get /dmaap until we get a good response to indicate other provisioning can continue - rc=999 - while [ $rc != "200" ] - do - sleep 10 - rc=`curl -s -o /dev/null -I -w "%{http_code}" -X GET -H "Content-Type: application/json" http://dmaap-bc:8080/webapi/dmaap` - echo "get dmaap response=${rc}" - done - - cd $CONFIGMAP_ROOT - pwd - # order is important in this next list - for uri in dmaap dcaeLocations mr_clusters topics feeds - do - if [ -d ${uri} ] - then - for j in `ls ${uri}/*.json` - do - echo "POST $j to $uri" - rc=`curl -v -X POST -w "%{http_code}" -H "Content-Type: application/json" -d @${j} http://dmaap-bc:8080/webapi/${uri}` - echo "response=$rc" - done - fi - done -} - set -x case "$1" in 'deploy') config start - #init wait ;; 'start') @@ -244,11 +183,11 @@ case "$1" in esac ls -l $APP_ROOT/logs/ONAP echo "------------ tail -100 error.log ---------------" - tail -100 $APP_ROOT/logs/ONAP/error.log + tail -n 1000 $APP_ROOT/logs/ONAP/error.log echo "------------ tail -100 server.log ---------------" - tail -100 $APP_ROOT/logs/ONAP/server.log + tail -n 1000 $APP_ROOT/logs/ONAP/server.log echo "------------ tail -100 application.log ---------------" - tail -100 $APP_ROOT/logs/ONAP/application.log + tail -n 1000 $APP_ROOT/logs/ONAP/application.log echo "Check $APP_ROOT/ok_to_exit" while [ ! -f $APP_ROOT/ok_to_exit ] diff --git a/dmaap-bc/src/main/resources/misc/dmaapbc.properties.tmpl b/dmaap-bc/src/main/resources/misc/dmaapbc.properties.tmpl new file mode 100755 index 0000000..d013ca3 --- /dev/null +++ b/dmaap-bc/src/main/resources/misc/dmaapbc.properties.tmpl @@ -0,0 +1,222 @@ +cat <<!EOF +# +# ============LICENSE_START========================================== +# org.onap.dmaap +# =================================================================== +# Copyright © 2018 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============================================ +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# +# +# +# Configuration parameters fixed at startup for the DMaaP Bus Controller +# +# CSIT TESTING +csit: ${DMAAPBC_CSIT:-No} + +# +# URI to retrieve dynamic DR configuration +# +ProvisioningURI: ${DMAAPBC_INTURI:-/internal/prov} +# +# Allow http access to API +# +HttpAllowed: ${DMAAPBC_HTTPALLOWED:-true} +# +# The port number for http as seen within the server +# +IntHttpPort: ${DMAAPBC_INT_HTTP_PORT:-8080} +# +# The port number for https as seen within the server +# Set to 0 if no certificate is available yet... +# +IntHttpsPort: ${DMAAPBC_INT_HTTPS_PORT:-8443} +# +# The external port number for https taking port mapping into account +# +ExtHttpsPort: ${DMAAPBC_EXT_HTTPS_PORT:-443} +# +# The type of keystore for https +# +KeyStoreType: jks +# +# The path to the keystore for https +# +KeyStoreFile: ${DMAAPBC_KSTOREFILE:-etc/keystore} +# +# The password for the https keystore (remember to put password in "" and escape $ characters) +# +KeyStorePassword: ${DMAAPBC_KSTOREPASS:-"Y@Y5f&gm?PAz,CVQL,lk[VAF"} +# +# The password for the private key in the https keystore (remember to put password in "" and escape $ characters) +# +KeyPassword: ${DMAAPBC_PVTKEYPASS:-"Y@Y5f&gm?PAz,CVQL,lk[VAF"} +# +# The type of truststore for https +# +TrustStoreType: jks +# +# The path to the truststore for https +# +TrustStoreFile: ${DMAAPBC_TSTOREFILE:-etc/org.onap.dmaap-bc.trust.jks} +# +# The password for the https truststore (remember to put password in "" and escape $ characters) +# +TrustStorePassword: ${DMAAPBC_TSTOREPASS:-"8b&R5%l\$l:@jSWz@FCs;rhY*"} +# +# The path to the file used to trigger an orderly shutdown +# +QuiesceFile: etc/SHUTDOWN +# +# Enable postgress +# +UsePGSQL: ${DMAAPBC_PG_ENABLED:-false} +# +# The host for postgres access +# +DB.host: ${DMAAPBC_PGHOST:-HostNotSet} +# +# For postgres access +# +DB.cred: ${DMAAPBC_PGCRED:-ValueNotSet} +# +# Name of this environment +# +DmaapName: ${DMAAPBC_INSTANCE_NAME:-demo} +# +# Name of DR prov server +# +DR.provhost: ${DMAAPBC_DRPROV_FQDN:-dcae-drps.domain.notset.com} +# +# handling of feed delete +# DeleteOnDR - means use the DR API to DELETE a feed. (default for backwards compatibility) +# SimulateDelete - means preserve the feed on DR (after cleaning it up), and mark as DELETED in DBCL. Better for cfy environments +Feed.deleteHandling: ${DMAAPBC_FEED_DELETE:-DeleteOnDR} + +################################################################################ +# MR Related Properties: +# +# ONAP Beijing and Casablanca are a single site deployment. +MR.multisite: false +# +# Value of the CNAME DNS entry which resolves to the primary central MR cluster (when there are more than one central clusters). +# if there is only one MR cluster in an environment, set this to the DNS name for that cluster +# +MR.CentralCname: ${DMAAPBC_MR_CNAME:-message-router} +# +# MR Client Delete Level thoroughness: +# 0 = don't delete +# 1 = delete from persistent store +# 2 = delete from persistent store (DB) and authorization store (AAF) +MR.ClientDeleteLevel: 1 +# +# MR Topic Factory Namespace +# +MR.TopicFactoryNS: org.onap.dcae.dmaap.topicFactory +# +# MR TopicMgr Role +MR.TopicMgrRole: org.onap.dmaap-bc-topic-mgr.client + +# MR topic name style +MR.topicStyle: FQTN_LEGACY_FORMAT + +# MR topic ProjectID +MR.projectID: 23456 +# +# end of MR Related Properties +################################################################################ + +# +# The Role and credentials of the MirrorMaker Provisioner. This is used by DMaaP Bus Controller to pub to the provisioning topic +# Not part of 1701 +# +MM.ProvRole: ${DMAAPBC_MMPROV_ROLE:-org.onap.dmaap-bc-mm-prov.prov} +MM.ProvUserMechId: ${DMAAPBC_MMPROV_ID:-dmaap-bc-mm-prov@dmaap-bc-mm-prov.onap.org} +MM.ProvUserPwd: ${DMAAPBC_MMPROV_PWD:-demo123456!} +# +# The Role of the MirrorMaker Agent. This is used by MM to sub to provisioning topic +# +MM.AgentRole: ${DMAAPBC_MMAGENT_ROLE:-org.onap.dmaap-bc-mm-prov.agent} +################# +# +# CADI settings +# +# flag indication if CADI filtering is used +enableCADI: ${DMAAPBC_ENABLE_CADI:-false} +# +# path to CADI properties +cadi.properties: /opt/app/osaaf/local/org.onap.dmaap-bc.props + +################# +# AAF Properties: +UseAAF: ${DMAAPBC_USEAAF:-false} +# +# regarding password encryption: +# In the dependencies that Maven retrieves (e.g., under dcae_dmaapbc/target/deps/ is a jar file cadi-core-version.jar. Generate the key file with: +# +# java \u2013jar wherever/cadi-core-*.jar keygen keyfilename +# chmod 400 keyfilename +# +# To encrypt a key: +# +# java \u2013jar wherever/cadi-core-*.jar digest password-to-encrypt keyfilename +# +# This will generate a string. Put \u201Cenc:\u201D on the front of the string, and put the result in this properties file. +# +# Location of the Codec Keyfile which is used to decrypt passwords in this properties file before they are passed to AAF +# +# REF: https://wiki.domain.notset.com/display/cadi/CADI+Deployment +# +CredentialCodecKeyfile: ${DMAAPBC_CODEC_KEYFILE:-etc/LocalKey} +# +# This overrides the Class used for Decryption. +# This allows for a plugin encryption/decryption method if needed. +# Call this Class for decryption at runtime. +#AafDecryption.Class: com.company.proprietaryDecryptor + +# +# This overrides the Class used for API Permission check. +# This allows for a plugin policy check, if needed +ApiPermission.Class: org.onap.dmaap.dbcapi.authentication.AllowAll + +# Namespace for URI values for API used to create AAF permissions +# e.g. if ApiNamespace is X.Y..dmaapBC.api then for URI /topics we create an AAF perm X.Y..dmaapBC.api.topics +ApiNamespace: ${DMAAPBC_API_NAMESPACE:-org.onap.dmaap-bc.api} +# +# URL of AAF environment to use. +# +aaf.URL: ${DMAAPBC_AAF_URL:-https://aaf-onap-test.osaaf.org:8100} +# +# TopicMgr mechid@namespace +# +aaf.TopicMgrUser: ${DMAAPBC_TOPICMGR_USER:-dmaap-bc-topic-mgr@dmaap-bc-topic-mgr.onap.org} +# +# TopicMgr password +# +aaf.TopicMgrPassword: ${DMAAPBC_TOPICMGR_PWD:-enc:l0ScEojNQiiKbbkuM6U1mtnrme69q960} +# +# Bus Controller Namespace Admin mechid@namespace +# +aaf.AdminUser: ${DMAAPBC_ADMIN_USER:-aaf_admin@people.osaag.org} +# +# Bus Controller Namespace Admin password +# +aaf.AdminPassword: ${DMAAPBC_ADMIN_PWD:-demo123456!} + + +# +# endof AAF Properties +################# +!EOF diff --git a/dmaap-bc/misc/log4j.properties.tmpl b/dmaap-bc/src/main/resources/misc/havecert.tmpl index 2a30bf5..3d23c7b 100644 --- a/dmaap-bc/misc/log4j.properties.tmpl +++ b/dmaap-bc/src/main/resources/misc/havecert.tmpl @@ -1,3 +1,4 @@ +#!/bin/bash # # ============LICENSE_START========================================== # org.onap.dmaap @@ -20,13 +21,20 @@ # # cat <<!EOF -log4j.debug=FALSE -log4j.rootLogger=INFO,Root - -log4j.appender.Root=org.apache.log4j.DailyRollingFileAppender -log4j.appender.Root.file=${DMAAPBC_LOGS:-logs}/buscontroller.log -log4j.appender.Root.datePattern='.'yyyyMMdd -log4j.appender.Root.append=true -log4j.appender.Root.layout=org.apache.log4j.PatternLayout -log4j.appender.Root.layout.ConversionPattern=%d %p %F %L %t %m%n +echo Check for certificate +TZ=GMT0 +cd /opt/app/dmaapbc; +KEYSTORE=${DMAAPBC_KSTOREFILE:-etc/keystore} +echo "KEYSTORE=$KEYSTORE" +d=`dirname $KEYSTORE` +ls -l $d +if [ -f ${KEYSTORE} ] +then + echo "Goodness: Found ${KEYSTORE}" + exit 0 +fi +EMSG="`date '+%F %T,000'` WARN Certificate file $KEYSTORE is missing" +echo $EMSG +echo $EMSG >>${DMAAPBC_LOGS:-logs}/dmaapbc.log +exit 1 !EOF diff --git a/dmaap-bc/misc/logback.xml b/dmaap-bc/src/main/resources/misc/logback.xml index 2af00f1..37a3af8 100644 --- a/dmaap-bc/misc/logback.xml +++ b/dmaap-bc/src/main/resources/misc/logback.xml @@ -19,19 +19,13 @@ ============LICENSE_END============================================ ECOMP is a trademark and service mark of AT&T Intellectual Property. --> - - + <configuration scan="true" scanPeriod="3 seconds"> <!--<jmxConfigurator /> --> <!-- directory path for all other type logs --> <property name="logDir" value="logs" /> - - <!-- directory path for debugging type logs --> - <property name="debugDir" value="logs" /> - - <!-- specify the component name - <ECOMP-component-name>::= "MSO" | "DCAE" | "ASDC " | "AAI" |"Policy" | "SDNC" | "AC" --> - <property name="componentName" value="ONAP"></property> + <!-- specify the component name --> + <property name="componentName" value="ONAP"/> <!-- log file names --> <property name="generalLogName" value="application" /> @@ -52,8 +46,6 @@ <property name="debugLoggerPattern" value="%date{ISO8601,UTC}|%X{RequestId}|%thread|%msg%n" /> <property name="logDirectory" value="${logDir}/${componentName}" /> - <property name="debugLogDirectory" value="${debugDir}/${componentName}" /> - <!-- Example evaluator filter applied against console appender --> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> @@ -287,10 +279,10 @@ <appender name="EELFDebug" class="ch.qos.logback.core.rolling.RollingFileAppender"> - <file>${debugLogDirectory}/${debugLogName}.log</file> + <file>${logDirectory}/${debugLogName}.log</file> <rollingPolicy class="ch.qos.logback.core.rolling.FixedWindowRollingPolicy"> - <fileNamePattern>${debugLogDirectory}/${debugLogName}.%i.log.zip + <fileNamePattern>${logDirectory}/${debugLogName}.%i.log.zip </fileNamePattern> <minIndex>1</minIndex> <maxIndex>9</maxIndex> @@ -337,8 +329,8 @@ <logger name="com.att.eelf.metrics" level="info" additivity="false"> <appender-ref ref="asyncEELFMetrics" /> </logger> - - + + <logger name="com.att.eelf.error" level="error" additivity="false"> <appender-ref ref="asyncEELFError" /> </logger> @@ -346,11 +338,9 @@ <logger name="com.att.eelf.debug" level="debug" additivity="false"> <appender-ref ref="asyncEELFDebug" /> </logger> - - - - <root level="INFO"> + + <root level="TRACE"> <appender-ref ref="asyncEELF" /> </root> diff --git a/dmaap-bc/src/main/resources/misc/schema_all.sql b/dmaap-bc/src/main/resources/misc/schema_all.sql new file mode 100644 index 0000000..c294b09 --- /dev/null +++ b/dmaap-bc/src/main/resources/misc/schema_all.sql @@ -0,0 +1,144 @@ +--- +-- ============LICENSE_START======================================================= +-- OpenECOMP - org.openecomp.dmaapbc +-- ================================================================================ +-- 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========================================================= +--- + +CREATE TABLE IF NOT EXISTS dcae_location ( + dcae_location_name VARCHAR(100), + clli VARCHAR(100), + dcae_layer VARCHAR(100), + open_stack_availability_zone VARCHAR(100), + last_mod TIMESTAMP, + subnet VARCHAR(100), + status VARCHAR(100), + PRIMARY KEY(dcae_location_name) +); +CREATE TABLE IF NOT EXISTS dmaap ( + version VARCHAR(100), + topic_ns_root VARCHAR(100), + dmaap_name VARCHAR(100), + dr_prov_url VARCHAR(200), + node_key VARCHAR(100), + access_key_owner VARCHAR(100), + last_mod TIMESTAMP, + status VARCHAR(100), + bridge_admin_topic VARCHAR(100), + logging_url VARCHAR(200) +); +CREATE TABLE IF NOT EXISTS dr_node ( + fqdn VARCHAR(100), + dcae_location_name VARCHAR(100), + host_name VARCHAR(100), + version VARCHAR(100), + last_mod TIMESTAMP, + status VARCHAR(100), + PRIMARY KEY(fqdn) +); +CREATE TABLE IF NOT EXISTS dr_pub ( + dcae_location_name VARCHAR(100), + username VARCHAR(100), + userpwd VARCHAR(100), + feed_id VARCHAR(100), + pub_id VARCHAR(100), + status VARCHAR(100), + last_mod TIMESTAMP, + PRIMARY KEY(pub_id) +); +CREATE TABLE IF NOT EXISTS dr_sub ( + owner VARCHAR(100), + suspended BOOLEAN, + status VARCHAR(100), + use100 BOOLEAN, + dcae_location_name VARCHAR(100), + username VARCHAR(100), + userpwd VARCHAR(100), + feed_id VARCHAR(100), + delivery_u_r_l VARCHAR(200), + log_u_r_l VARCHAR(200), + sub_id VARCHAR(100), + last_mod TIMESTAMP, + guaranteed_delivery BOOLEAN, + guaranteed_sequence BOOLEAN, + privileged_subscriber BOOLEAN, + decompress BOOLEAN, + PRIMARY KEY(sub_id) +); +CREATE TABLE IF NOT EXISTS mr_client ( + dcae_location_name VARCHAR(100), + fqtn VARCHAR(100), + client_role VARCHAR(100), + action VARCHAR(300), + mr_client_id VARCHAR(100), + status VARCHAR(100), + topic_u_r_l VARCHAR(200), + last_mod TIMESTAMP, + client_identity varchar(100), + PRIMARY KEY(mr_client_id) +); +CREATE TABLE IF NOT EXISTS mr_cluster ( + last_mod TIMESTAMP, + dcae_location_name VARCHAR(100), + fqdn VARCHAR(100), + topic_protocol VARCHAR(100), + topic_port VARCHAR(100), + status VARCHAR(100), + replication_group VARCHAR(100), + PRIMARY KEY(dcae_location_name) +); +CREATE TABLE IF NOT EXISTS feed ( + suspended BOOLEAN, + subscribe_u_r_l VARCHAR(200), + feed_id VARCHAR(100), + feed_name VARCHAR(100), + feed_version VARCHAR(100), + feed_description VARCHAR(1000), + owner VARCHAR(100), + aspr_classification VARCHAR(100), + publish_u_r_l VARCHAR(200), + log_u_r_l VARCHAR(200), + status VARCHAR(100), + last_mod TIMESTAMP, + format_uuid VARCHAR(100), + PRIMARY KEY(feed_id) +); +CREATE TABLE IF NOT EXISTS topic ( + last_mod TIMESTAMP, + fqtn VARCHAR(100), + topic_name VARCHAR(100), + topic_description VARCHAR(1000), + tnx_enabled VARCHAR(100), + owner VARCHAR(100), + status VARCHAR(100), + format_uuid VARCHAR(100), + replication_case INT, + global_mr_u_r_l VARCHAR(200), + partition_count VARCHAR(10) DEFAULT 2, + replication_count VARCHAR(10) DEFAULT 1, + publisher_role VARCHAR(100), + subscriber_role VARCHAR(100), + PRIMARY KEY(fqtn) +); +CREATE TABLE IF NOT EXISTS mirror_maker ( + mm_name VARCHAR(100), + source_cluster VARCHAR(100), + target_cluster VARCHAR(100), + last_mod TIMESTAMP, + status VARCHAR(100), + topics TEXT, + PRIMARY KEY(mm_name) +); diff --git a/dmaap-bc/src/main/webapp/HelloJetty.html b/dmaap-bc/src/main/webapp/HelloJetty.html deleted file mode 100644 index 4d61636..0000000 --- a/dmaap-bc/src/main/webapp/HelloJetty.html +++ /dev/null @@ -1,30 +0,0 @@ -<!DOCTYPE html> -<!-- - ============LICENSE_START======================================================= - OpenECOMP - org.openecomp.dmaapbc - ================================================================================ - 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========================================================= - --> - -<html> -<head> -<meta charset="ISO-8859-1"> -<title>Index</title> -</head> -<body> -Hello Jetty! -</body> -</html> diff --git a/dmaap-bc/src/main/webapp/WEB-INF/log4j2.xml b/dmaap-bc/src/main/webapp/WEB-INF/log4j2.xml deleted file mode 100644 index bd7e9c5..0000000 --- a/dmaap-bc/src/main/webapp/WEB-INF/log4j2.xml +++ /dev/null @@ -1,50 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ============LICENSE_START======================================================= - Copyright (C) 2021 Nordix Foundation. - ================================================================================ - 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========================================================= - --> - -<Configuration status="WARN"> - <Appenders> - <!-- Console Appender --> - <Console name="STDOUT" target="SYSTEM_OUT"> - <PatternLayout pattern="%d %-5r %-5p [%c] (%t:%x) %m%n"/> - </Console> - - <!-- Rolling File Appender --> - <RollingFile name="rollingFile"> - <FileName>dmaapBC.log</FileName> - <FilePattern>${date:yyyy-MM}/dmaapBC-%d{yyyy-MM-dd}-%i.log.gz</FilePattern> - <PatternLayout> - <Pattern>[%d{HH:mm:ss:SSS}] - %-6p - %c.%M() - %m%n</Pattern> - </PatternLayout> - <Policies> - <SizeBasedTriggeringPolicy size="1000 KB"/> - </Policies> - <DefaultRolloverStrategy max="3"/> - </RollingFile> - </Appenders> - <Loggers> - <Logger name="org.openecomp.dcae.dmaapBC" level="debug" additivity="false"> - <AppenderRef ref="rollingFile"/> - </Logger> - <Root level="ALL"> - <AppenderRef ref="STDOUT"/> - </Root> - </Loggers> -</Configuration>
\ No newline at end of file diff --git a/dmaap-bc/src/main/webapp/WEB-INF/web.xml b/dmaap-bc/src/main/webapp/WEB-INF/web.xml deleted file mode 100644 index 055fbf0..0000000 --- a/dmaap-bc/src/main/webapp/WEB-INF/web.xml +++ /dev/null @@ -1,38 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- - ============LICENSE_START======================================================= - OpenECOMP - org.openecomp.dmaapbc - ================================================================================ - 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========================================================= - --> - -<!-- This web.xml file is not required when using Servlet 3.0 container, - see implementation details http://jersey.java.net/nonav/documentation/latest/jax-rs.html --> -<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> - <servlet> - <servlet-name>Jersey Web Application</servlet-name> - <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class> - <init-param> - <param-name>jersey.config.server.provider.packages</param-name> - <param-value>org.openecomp.dmaapBC</param-value> - </init-param> - <load-on-startup>1</load-on-startup> - </servlet> - <servlet-mapping> - <servlet-name>Jersey Web Application</servlet-name> - <url-pattern>/webapi/*</url-pattern> - </servlet-mapping> -</web-app> diff --git a/dmaap-bc/src/main/webapp/index.jsp b/dmaap-bc/src/main/webapp/index.jsp deleted file mode 100644 index 3c20e06..0000000 --- a/dmaap-bc/src/main/webapp/index.jsp +++ /dev/null @@ -1,28 +0,0 @@ -<%-- - ============LICENSE_START======================================================= - org.onap.dcae - ================================================================================ - 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========================================================= - --%> - -<html> -<body> - <h2>Jersey RESTful Web Application!</h2> - <p><a href="webapi/dmaap">Jersey resource</a> - <p>Visit <a href="http://jersey.java.net">Project Jersey website</a> - for more information on Jersey! -</body> -</html> diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/aaf/AafRoleTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/aaf/AafRoleTest.java new file mode 100644 index 0000000..c53d8c6 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/aaf/AafRoleTest.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright 2019 IBM + * ================================================================================ + * 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.aaf; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import org.junit.Before; +import org.junit.Test; + +public class AafRoleTest { + + AafRole aafRole; + + @Before + public void setUp() { + aafRole = new AafRole("testNs", "testRole"); + } + + @Test + public void testAafRole() { + aafRole.setNamespace("namespace"); + aafRole.setRole("role"); + assertEquals("namespace", aafRole.getNamespace()); + assertEquals("role", aafRole.getRole()); + assertEquals("namespace.role", aafRole.getFullyQualifiedRole()); + assertNotNull(aafRole.toJSON()); + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/aaf/AafServiceFactoryTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/aaf/AafServiceFactoryTest.java new file mode 100644 index 0000000..45ff2b1 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/aaf/AafServiceFactoryTest.java @@ -0,0 +1,103 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.aaf; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.dmaap.dbcapi.aaf.AafService.ServiceType; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.BDDMockito.given; + +@RunWith(MockitoJUnitRunner.class) +public class AafServiceFactoryTest { + + private static final String USE_AAF = "true"; + private static final String AAF_URL = "https://aaf.url/api"; + private static final String ADMIN_USER = "admin_user"; + private static final String TOPIC_MANAGER = "topic_manager"; + private static final String ADMIN_PASS = "admin_pass"; + private static final String MANAGER_PASS = "manager_pass"; + @Mock + private DmaapConfig dmaapConfig; + private AafServiceFactory aafServiceFactory; + + @Before + public void setUp() throws Exception { + aafServiceFactory = new AafServiceFactory(dmaapConfig); + } + + @Test + public void shouldBuildAafServiceForAafAdmin() { + givenDmaapConfig(); + + AafServiceImpl aafService = (AafServiceImpl) aafServiceFactory.initAafService(ServiceType.AAF_Admin); + + assertEquals(ADMIN_USER, aafService.getIdentity()); + assertEquals(AAF_URL, aafService.getAafUrl()); + assertTrue(aafService.isUseAAF()); + } + + @Test + public void shouldBuildAafServiceForTopicManager() { + givenDmaapConfig(); + + AafServiceImpl aafService = (AafServiceImpl) aafServiceFactory.initAafService(ServiceType.AAF_TopicMgr); + + assertEquals(TOPIC_MANAGER, aafService.getIdentity()); + assertEquals(AAF_URL, aafService.getAafUrl()); + assertTrue(aafService.isUseAAF()); + } + + @Test + public void shouldCorrectlyCreateCredentialsForAafAdmin() { + givenDmaapConfig(); + + AafServiceFactory.AafCred cred = aafServiceFactory.getCred(ServiceType.AAF_Admin); + + assertEquals(ADMIN_USER, cred.getIdentity()); + assertEquals(ADMIN_USER + ":" + new AafDecrypt().decrypt(ADMIN_PASS), cred.toString()); + } + + @Test + public void shouldCorrectlyCreateCredentialsForTopicManager() { + givenDmaapConfig(); + + AafServiceFactory.AafCred cred = aafServiceFactory.getCred(ServiceType.AAF_TopicMgr); + + assertEquals(TOPIC_MANAGER, cred.getIdentity()); + assertEquals(TOPIC_MANAGER + ":" + new AafDecrypt().decrypt(MANAGER_PASS), cred.toString()); + } + + private void givenDmaapConfig() { + given(dmaapConfig.getProperty("UseAAF", "false")).willReturn(USE_AAF); + given(dmaapConfig.getProperty("aaf.URL", "https://authentication.domain.netset.com:8100/proxy/")).willReturn(AAF_URL); + given(dmaapConfig.getProperty("aaf.AdminUser", "noMechId@domain.netset.com")).willReturn(ADMIN_USER); + given(dmaapConfig.getProperty("aaf.TopicMgrUser", "noMechId@domain.netset.com")).willReturn(TOPIC_MANAGER); + given(dmaapConfig.getProperty("aaf.AdminPassword", "notSet")).willReturn(ADMIN_PASS); + given(dmaapConfig.getProperty("aaf.TopicMgrPassword", "notSet")).willReturn(MANAGER_PASS); + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/aaf/AafServiceImplTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/aaf/AafServiceImplTest.java new file mode 100644 index 0000000..ffd130e --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/aaf/AafServiceImplTest.java @@ -0,0 +1,208 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.aaf; + +import static org.junit.Assert.assertEquals; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.verifyZeroInteractions; + +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(JUnitParamsRunner.class) +public class AafServiceImplTest { + + private static final String AAF_URL = "https://aaf.url/"; + private static final String IDENTITY = "dmaap-bc@onap.org"; + private static final boolean USE_AAF = true; + private static final int CREATED = 201; + private static final int OK = 200; + @Mock + private AafConnection aafConnection; + private AafServiceImpl aafService; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + given(aafConnection.postAaf(any(AafObject.class), anyString())).willReturn(CREATED); + given(aafConnection.delAaf(any(AafObject.class), anyString())).willReturn(OK); + aafService = new AafServiceImpl(USE_AAF, AAF_URL, IDENTITY, aafConnection); + } + + @Test + public void shouldReturnCorrectIdentity() { + + assertEquals(IDENTITY, aafService.getIdentity()); + } + + @Test + public void shouldAddPermission() { + DmaapPerm perm = new DmaapPerm("perm", "type", "action"); + + int status = aafService.addPerm(perm); + + then(aafConnection).should().postAaf(perm, AAF_URL + "authz/perm"); + assertEquals(CREATED, status); + } + + + @Test + public void shouldAddDmaapGrant() { + DmaapGrant grant = new DmaapGrant(new DmaapPerm("perm", "type", "action"), "roles"); + + int status = aafService.addGrant(grant); + + then(aafConnection).should().postAaf(grant, AAF_URL + "authz/role/perm"); + assertEquals(CREATED, status); + } + + @Test + public void shouldAddUserRole() { + AafUserRole userRole = new AafUserRole("ident", "role"); + + int status = aafService.addUserRole(userRole); + + then(aafConnection).should().postAaf(userRole, AAF_URL + "authz/userRole"); + assertEquals(CREATED, status); + } + + @Test + public void shouldAddRole() { + AafRole role = new AafRole("ns", "role"); + + int status = aafService.addRole(role); + + then(aafConnection).should().postAaf(role, AAF_URL + "authz/role"); + assertEquals(CREATED, status); + } + + @Test + public void shouldAddNamespace() { + AafNamespace ns = new AafNamespace("ns", "ident"); + + int status = aafService.addNamespace(ns); + + then(aafConnection).should().postAaf(ns, AAF_URL + "authz/ns"); + assertEquals(CREATED, status); + } + + @Test + public void shouldNotConnectToAafDuringCreate() { + aafService = new AafServiceImpl(false, AAF_URL, IDENTITY, aafConnection); + DmaapPerm perm = new DmaapPerm("perm", "type", "action"); + + int status = aafService.addPerm(perm); + + verifyZeroInteractions(aafConnection); + assertEquals(CREATED, status); + } + + @Test + @Parameters({"401", "403", "409", "200", "500"}) + public void shouldHandleErrorDuringCreate(int aafServiceReturnedCode) { + given(aafConnection.postAaf(any(AafObject.class), anyString())).willReturn(aafServiceReturnedCode); + DmaapPerm perm = new DmaapPerm("perm", "type", "action"); + + int status = aafService.addPerm(perm); + + assertEquals(aafServiceReturnedCode, status); + } + + @Test + @Parameters({"401", "403", "404", "200", "500"}) + public void shouldHandleErrorDuringDelete(int aafServiceReturnedCode) { + given(aafConnection.delAaf(any(AafObject.class), anyString())).willReturn(aafServiceReturnedCode); + DmaapPerm perm = new DmaapPerm("perm", "type", "action"); + + int status = aafService.delPerm(perm, false); + + assertEquals(aafServiceReturnedCode, status); + } + + @Test + public void shouldDeletePermission() { + DmaapPerm perm = new DmaapPerm("permName", "type", "action"); + + int status = aafService.delPerm(perm, false); + + then(aafConnection).should().delAaf(any(AafEmpty.class), eq(AAF_URL + "authz/perm/permName/type/action")); + assertEquals(OK, status); + } + + @Test + public void shouldDeletePermissionWithForce() { + DmaapPerm perm = new DmaapPerm("permName", "type", "action"); + + int status = aafService.delPerm(perm, true); + + then(aafConnection).should().delAaf(any(AafEmpty.class), eq(AAF_URL + "authz/perm/permName/type/action?force=true")); + assertEquals(OK, status); + } + + @Test + public void shouldDeleteNamespace() { + AafNamespace ns = new AafNamespace("nsName", "ident"); + + int status = aafService.delNamespace(ns, false); + + then(aafConnection).should().delAaf(any(AafEmpty.class), eq(AAF_URL + "authz/ns/nsName")); + assertEquals(OK, status); + } + + @Test + public void shouldDeleteNamespaceWithForce() { + AafNamespace ns = new AafNamespace("nsName", "ident"); + + int status = aafService.delNamespace(ns, true); + + then(aafConnection).should().delAaf(any(AafEmpty.class), eq(AAF_URL + "authz/ns/nsName?force=true")); + assertEquals(OK, status); + } + + @Test + public void shouldReturnExpectedCodeDuringPostWhenUseAffIsSetToFalse() { + aafService = new AafServiceImpl(false, AAF_URL, IDENTITY, aafConnection); + DmaapPerm perm = new DmaapPerm("perm", "type", "action"); + + int status = aafService.addPerm(perm); + + assertEquals(CREATED, status); + } + + @Test + public void shouldReturnExpectedCodeDuringDeleteWhenUseAffIsSetToFalse() { + aafService = new AafServiceImpl(false, AAF_URL, IDENTITY, aafConnection); + DmaapPerm perm = new DmaapPerm("perm", "type", "action"); + + int status = aafService.delPerm(perm, false); + + assertEquals(OK, status); + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/aaf/AafUserRoleTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/aaf/AafUserRoleTest.java new file mode 100644 index 0000000..88fff87 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/aaf/AafUserRoleTest.java @@ -0,0 +1,58 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 IBM Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 IBM + * =================================================================== + * 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.aaf; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import org.junit.Before; +import org.junit.Test; + +public class AafUserRoleTest { + + AafUserRole aafUserRole; + + @Before + public void setUp() { + aafUserRole = new AafUserRole("xyz", "admin"); + } + + @Test + public void testGetIdentity() { + aafUserRole.setIdentity("xyz"); + assertEquals("xyz", aafUserRole.getIdentity()); + } + + @Test + public void testGetRole() { + aafUserRole.setRole("admin"); + assertEquals("admin", aafUserRole.getRole()); + } + + @Test + public void toJSON() { + AafUserRole role = new AafUserRole("test", "admin"); + assertThat(role.toJSON(), is(" { \"user\": \"test\", \"role\": \"admin\" }")); + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/authentication/AafLurAndFishTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/authentication/AafLurAndFishTest.java new file mode 100644 index 0000000..af6aba4 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/authentication/AafLurAndFishTest.java @@ -0,0 +1,54 @@ +/*- + * ============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.authentication; + +import static org.junit.Assert.assertTrue; + +import javax.ws.rs.core.Application; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Before; +import org.junit.Test; + +public class AafLurAndFishTest extends JerseyTest { + + @Before + public void setUp() throws Exception { + System.setProperty("ConfigFile", "src/test/resources/dmaapbc.properties"); + } + + @Override + protected Application configure() { + return new ResourceConfig() + .register( AafLurAndFish.class ); + } + + @Test + public void constructorTest() { + try { + AafLurAndFish p = new AafLurAndFish(); + } catch ( AuthenticationErrorException err ) { + + } + + assertTrue( true ); + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/authentication/AllowAllTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/authentication/AllowAllTest.java new file mode 100644 index 0000000..9b6ee01 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/authentication/AllowAllTest.java @@ -0,0 +1,38 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.authentication; + +import org.junit.Test; + +import static org.junit.Assert.fail; + +public class AllowAllTest { + + private AllowAll allowAll = new AllowAll(); + + @Test + public void check_shouldPassValidationForAllPerms() { + try { + allowAll.check(null, null, null); + } catch (Exception e) { + fail("No exception should be thrown"); + } + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/authentication/ApiPermsTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/authentication/ApiPermsTest.java new file mode 100644 index 0000000..ea749ce --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/authentication/ApiPermsTest.java @@ -0,0 +1,52 @@ +/*- + * ============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.authentication; + +import static org.junit.Assert.assertTrue; + +import javax.ws.rs.core.Application; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Test; + +import org.onap.dmaap.dbcapi.authentication.ApiPerms; + + +public class ApiPermsTest extends JerseyTest { + + @Override + protected Application configure() { + return new ResourceConfig() + .register( ApiPerms.class ); + } + + @Test + public void bootTest() { + ApiPerms p = new ApiPerms(); + + p.setBootMap(); + + p.setEnvMap(); + + + assertTrue( true ); + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/authentication/ApiPolicyTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/authentication/ApiPolicyTest.java new file mode 100644 index 0000000..7b9fbb3 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/authentication/ApiPolicyTest.java @@ -0,0 +1,82 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.authentication; + +import org.junit.Test; +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; + +import java.util.Properties; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class ApiPolicyTest { + + private Properties properties = new Properties(); + private ApiPolicy apiPolicy; + + @Test + public void check_shouldExecuteAuthorizationApi() throws Exception { + properties.put("ApiPermission.Class", "org.onap.dmaap.dbcapi.authentication.ApiPolicyTest$DummyApiAuthorization"); + apiPolicy = new ApiPolicy(properties); + + apiPolicy.check("mechId", "pwd", new DmaapPerm("api.perm", "*", "GET")); + + assertTrue(((DummyApiAuthorization) apiPolicy.getPerm()).isCheckExecuted()); + } + + @Test + public void isPermissionClassSet_shouldReturnTrueForValidApiPermClass() { + properties.put("ApiPermission.Class", "org.onap.dmaap.dbcapi.authentication.ApiPolicyTest$DummyApiAuthorization"); + apiPolicy = new ApiPolicy(properties); + + assertTrue(apiPolicy.isPermissionClassSet()); + } + + @Test + public void isPermissionClassSet_shouldReturnFalseWhenPropertyIsNotSet() { + apiPolicy = new ApiPolicy(properties); + + assertFalse(apiPolicy.isPermissionClassSet()); + } + + @Test + public void isPermissionClassSet_shouldReturnFalseWhenWrongClassIsSet() { + properties.put("ApiPermission.Class", "org.onap.dmaap.dbcapi.authentication.NotExisting"); + apiPolicy = new ApiPolicy(properties); + + assertFalse(apiPolicy.isPermissionClassSet()); + } + + public static class DummyApiAuthorization implements ApiAuthorizationCheckInterface { + + private boolean checkExecuted = false; + + @Override + public void check(String mechid, String pwd, DmaapPerm p) { + checkExecuted = true; + } + + boolean isCheckExecuted() { + return checkExecuted; + } + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/client/DrProvConnectionTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/client/DrProvConnectionTest.java new file mode 100644 index 0000000..4c44e0a --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/client/DrProvConnectionTest.java @@ -0,0 +1,136 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.client; + +import static org.junit.Assert.assertTrue; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import java.util.ArrayList; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DR_Pub; +import org.onap.dmaap.dbcapi.model.DR_Sub; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.Feed; +import org.onap.dmaap.dbcapi.service.DcaeLocationService; +import org.onap.dmaap.dbcapi.service.MR_ClusterService; +import org.onap.dmaap.dbcapi.service.TopicService; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +public class DrProvConnectionTest { + + private static final String fmt = "%24s: %s%n"; + private static DmaapObjectFactory factory = new DmaapObjectFactory(); + + ReflectionHarness rh = new ReflectionHarness(); + + DrProvConnection ns; + MR_ClusterService mcs; + TopicService ts; + + @Before + public void setUp() throws Exception { + ns = new DrProvConnection(); + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.DrProvConnection", "get", "idNotSet@namespaceNotSet:pwdNotSet" ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.DrProvConnection", "set", v ); + + } + + @Test + public void test3() { + String locname = "central-demo"; + + DcaeLocationService dls = new DcaeLocationService(); + DcaeLocation loc = factory.genDcaeLocation( "central" ); + dls.addDcaeLocation( loc ); + + ApiError err = new ApiError(); + String[] hl = { "host1", "host2", "host3" }; + ns.makeFeedConnection( ); + ns.makeFeedConnection( "01" ); + ns.makeSubPostConnection( "part0/part1/part2/part3/part4" ); + ns.makeSubPutConnection( "44" ); + ns.makeIngressConnection( "01", "aUser", "10.10.10.10", "aNode" ); + ns.makeEgressConnection( "01", "aNode" ); + ns.makeNodesConnection( "someVar" ); + Feed feed = new Feed( "dgl feed 1" , + "v1.0", + "dgl feed 1 for testing", + "TEST", + "unclassified" + ); + ArrayList<DR_Pub> pubs = new ArrayList<DR_Pub>(); + pubs.add( new DR_Pub( "central-demo" ) ); + feed.setPubs(pubs); + + String resp = ns.doPostFeed( feed, err ); + resp = ns.doPutFeed( feed, err ); + resp = ns.doDeleteFeed( feed, err ); + + int i = ns.doXgressPost( err ); + + DR_Sub sub = factory.genDrSub( "central", feed.getFeedId() ); + assertTrue( sub != null ); + String sr = ns.doPostDr_Sub( sub, err ); + /* + * TODO: + - create a new DR_Sub based on a simulated response + - update using ns.doPutDr_Sub( sub, err ); + */ + } + + @Test + public void test4() { + ApiError err = new ApiError(); + String resp = ns.doGetNodes( err ); + ns.makeNodesConnection( "someVar", "host1|host2" ); + resp = ns.doPutNodes( err ); + try { + InputStream is = new FileInputStream(new File("/src/test/resources/dmaapbc.properties")); + String body = ns.bodyToString( is ); + } catch ( FileNotFoundException fnfe ) { + } + } + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/client/MrProvConnectionTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/client/MrProvConnectionTest.java new file mode 100644 index 0000000..0614cf9 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/client/MrProvConnectionTest.java @@ -0,0 +1,103 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.client; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.service.DcaeLocationService; +import org.onap.dmaap.dbcapi.service.MR_ClusterService; +import org.onap.dmaap.dbcapi.service.TopicService; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +public class MrProvConnectionTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + MrProvConnection ns; + MR_ClusterService mcs; + TopicService ts; + + @Before + public void setUp() throws Exception { + ns = new MrProvConnection(); + ts = new TopicService(); + mcs = new MR_ClusterService(); + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrProvConnection", "get", "idNotSet@namespaceNotSet:pwdNotSet" ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrProvConnection", "set", v ); + + } + + @Test + public void test3() { + String locname = "central-demo"; + + DcaeLocationService dls = new DcaeLocationService(); + DcaeLocation loc = new DcaeLocation( "CLLI1234", "central-onap", locname, "aZone", "10.10.10.0/24" ); + dls.addDcaeLocation( loc ); + + ApiError err = new ApiError(); + + MR_Cluster cluster = new MR_Cluster( locname, "localhost", "http", "3904" ); + mcs.addMr_Cluster( cluster, err ); + ns.makeTopicConnection( cluster ); + Topic topic = new Topic(); + topic.setTopicName( "test5" ); + String resp = ns.doPostTopic( topic, err ); + + try { + InputStream is = new FileInputStream(new File("/src/test/resources/dmaapbc.properties")); + String body = ns.bodyToString( is ); + } catch ( FileNotFoundException fnfe ) { + } + + } + + + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/client/MrTopicConnectionTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/client/MrTopicConnectionTest.java new file mode 100644 index 0000000..af33ec6 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/client/MrTopicConnectionTest.java @@ -0,0 +1,101 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.client; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.InputStream; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.service.DcaeLocationService; +import org.onap.dmaap.dbcapi.service.MR_ClusterService; +import org.onap.dmaap.dbcapi.service.TopicService; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +public class MrTopicConnectionTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + MrTopicConnection ns; + MR_ClusterService mcs; + TopicService ts; + + @Before + public void setUp() throws Exception { + ns = new MrTopicConnection( "aUser", "aPwd" ); + ts = new TopicService(); + mcs = new MR_ClusterService(); + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "get", "idNotSet@namespaceNotSet:pwdNotSet" ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "set", v ); + + } + + @Test + public void test3() { + String locname = "central-demo"; + + DcaeLocationService dls = new DcaeLocationService(); + DcaeLocation loc = new DcaeLocation( "CLLI1234", "central-onap", locname, "aZone", "10.10.10.0/24" ); + dls.addDcaeLocation( loc ); + + ApiError err = new ApiError(); + + MR_Cluster cluster = new MR_Cluster( locname, "localhost", "http", "3904"); + mcs.addMr_Cluster( cluster, err ); + ns.makeTopicConnection( cluster, "org.onap.dmaap.anInterestingTopic", "" ); + String msg = "{ 'key': '1234', 'val': 'hello world' }"; + ApiError e2 = ns.doPostMessage( msg ); + + try { + InputStream is = new FileInputStream(new File("/src/test/resources/dmaapbc.properties")); + String body = ns.bodyToString( is ); + } catch ( FileNotFoundException fnfe ) { + } + + } + + + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/DBFieldHandlerTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/DBFieldHandlerTest.java new file mode 100644 index 0000000..f68b9ed --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/DBFieldHandlerTest.java @@ -0,0 +1,110 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 IBM + * =================================================================== + * 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.database; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import org.junit.Test; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; +import org.onap.dmaap.dbcapi.model.ReplicationType; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +public class DBFieldHandlerTest extends BaseLoggingClass { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + private static class TopicReplicationTypeHandler implements DBFieldHandler.SqlOp { + public Object get(ResultSet rs, int index) throws Exception { + int val = rs.getInt(index); + + return (ReplicationType.valueOf(val)); + } + + public void set(PreparedStatement ps, int index, Object val) throws Exception { + if (val == null) { + ps.setInt(index, 0); + return; + } + @SuppressWarnings("unchecked") + ReplicationType rep = (ReplicationType) val; + ps.setInt(index, rep.getValue()); + } + } + + @Test + public void test1() { + // rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "get", + // "idNotSet@namespaceNotSet:pwdNotSet" ); + } + + @Test + public void test2() { + String v = "Validate"; + // rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "set", v ); + } + + @Test + public void test3() { + try { + DBFieldHandler fh = new DBFieldHandler(String.class, "aString", 1); + } catch (Exception e) { + errorLogger.error("Error", e); + } + } + + @Test + public void test4() { + try { + DBFieldHandler fh = new DBFieldHandler(String.class, "aString", 1, null); + } catch (Exception e) { + errorLogger.error("Error", e); + } + } + + @Test + public void testfesc() { + String sampleString = "@xyz,ww;,"; + String finalString = DBFieldHandler.fesc(sampleString); + assertEquals("@axyz@cww@s@c", finalString); + } + + @Test + public void testfunesc() { + String sampleString = "@axyz@cww@s@c"; + String convertedString = DBFieldHandler.funesc(sampleString); + assertEquals("@xyz,ww;,", convertedString); + } + + @Test + public void testfescWithNull() { + String sampleString1 = DBFieldHandler.fesc(null); + String sampleString2 = DBFieldHandler.funesc(null); + assertNull(null, sampleString1); + assertNull(null, sampleString2); + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/DBMapTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/DBMapTest.java new file mode 100644 index 0000000..abd4aee --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/DBMapTest.java @@ -0,0 +1,84 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.database; + +import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; +import org.onap.dmaap.dbcapi.util.Singleton; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import java.util.*; + +public class DBMapTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + + private static Singleton<Dmaap> dmaap; + private static Map<String, DcaeLocation> dcaeLocations; + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + //rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "get", "idNotSet@namespaceNotSet:pwdNotSet" ); + + } + + @Test + public void test2() { + String v = "Validate"; + //rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "set", v ); + + } + + @Test + public void test3() { + try { + dmaap = new DBSingleton<Dmaap>(Dmaap.class, "dmaap"); + Dmaap nd = new Dmaap.DmaapBuilder().createDmaap(); + dmaap.update(nd); + } catch (Exception e ) { + } + try { + dcaeLocations = new DBMap<DcaeLocation>(DcaeLocation.class, "dcae_location", "dcae_location_name"); + } catch (Exception e ) { + } + + } + + + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/DBSingletonTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/DBSingletonTest.java new file mode 100644 index 0000000..003f250 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/DBSingletonTest.java @@ -0,0 +1,67 @@ + +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.database; + +import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class DBSingletonTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + + @Test + public void test3() { + + try { + DBSingleton<Dmaap> dmaap = new DBSingleton<Dmaap>(Dmaap.class, "dmaap"); + Dmaap d = new Dmaap.DmaapBuilder().createDmaap(); + dmaap.init( d ); + d = dmaap.get(); + d.setDmaapName( "foo" ); + dmaap.update( d ); + dmaap.remove(); + } catch (Exception e ) { + } + + } + + + + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/LoadSchemaTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/LoadSchemaTest.java new file mode 100644 index 0000000..99065d3 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/LoadSchemaTest.java @@ -0,0 +1,68 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.database; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +public class LoadSchemaTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + LoadSchema ls; + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.database.LoadSchema", "get", "idNotSet@namespaceNotSet:pwdNotSet" ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.database.LoadSchema", "set", v ); + + } + + @Test + public void test3() { + LoadSchema.loadSchema(); + } + + + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/TableHandlerTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/TableHandlerTest.java new file mode 100644 index 0000000..978f3ad --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/database/TableHandlerTest.java @@ -0,0 +1,106 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.database; + +import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import java.sql.*; + +public class TableHandlerTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + private static class TopicReplicationTypeHandler implements DBFieldHandler.SqlOp { + public Object get(ResultSet rs, int index) throws Exception { + int val = rs.getInt(index); + + return (ReplicationType.valueOf(val)); + } + public void set(PreparedStatement ps, int index, Object val) throws Exception { + if (val == null) { + ps.setInt(index, 0); + return; + } + @SuppressWarnings("unchecked") + ReplicationType rep = (ReplicationType) val; + ps.setInt(index, rep.getValue()); + } + } + + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "get", "idNotSet@namespaceNotSet:pwdNotSet" ); + + } + + @Test + public void test2() { + String v = "Validate"; + //rh.reflect( "org.onap.dmaap.dbcapi.aaf.client.MrTopicConnection", "set", v ); + + } + + @Test + public void test3() { + DBFieldHandler.SqlOp trth = new TopicReplicationTypeHandler(); + TableHandler.setSpecialCase("topic", "replication_case", trth); + + try { + ConnectionFactory cf = new ConnectionFactory(); + TableHandler th = new TableHandler( cf, TopicReplicationTypeHandler.class, "foo", "bar" ); + DBFieldHandler.SqlOp t = th.getSpecialCase( "foo", "bar" ); + assert( trth == t ); + } catch (Exception e ) { + } + try { + + TableHandler th = new TableHandler( TopicReplicationTypeHandler.class, "foo", "bar" ); + DBFieldHandler.SqlOp t = th.getSpecialCase( "foo", "bar" ); + assert( trth == t ); + } catch (Exception e ) { + } + + } + + + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/BrTopicTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/BrTopicTest.java new file mode 100644 index 0000000..11e7c85 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/BrTopicTest.java @@ -0,0 +1,59 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright 2019 IBM + * ================================================================================ + * 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 static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; + +public class BrTopicTest { + + BrTopic brTopic; + + @Before + public void setUp() { + brTopic = new BrTopic(); + } + + @Test + public void testGetBrSource() { + brTopic.setBrSource("brSource"); + assertEquals("brSource", brTopic.getBrSource()); + } + + @Test + public void testGetBrTarget() { + brTopic.setBrTarget("brTarget"); + assertEquals("brTarget", brTopic.getBrTarget()); + } + + @Test + public void testGetTopicCount() { + brTopic.setTopicCount(1); + assertEquals(1, brTopic.getTopicCount()); + } + + @Test + public void testGetMmAgentName() { + brTopic.setMmAgentName("Test"); + assertEquals("Test", brTopic.getMmAgentName()); + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DRNodeTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DRNodeTest.java new file mode 100644 index 0000000..ce23656 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DRNodeTest.java @@ -0,0 +1,86 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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 static org.junit.Assert.*; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +public class DRNodeTest { + String f, d, h, v; + + @Before + public void setUp() throws Exception { + v = "1"; + f = "node01.onap.org"; + h = "zlpdrns01.cloud.onap.org"; + d = "central-onap"; + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testDRNodeClassDefaultConstructor() { + + DR_Node t = new DR_Node(); + + assertTrue( t.getFqdn() == null ); + assertTrue( t.getDcaeLocationName() == null ); + assertTrue( t.getHostName() == null ); + assertTrue( t.getVersion() == null ); + + } + + @Test + public void testDRNodeClassConstructor() { + + DR_Node t = new DR_Node( f, d, h, v ); + + assertTrue( f.equals( t.getFqdn() )); + assertTrue( d.equals( t.getDcaeLocationName() )); + assertTrue( h.equals( t.getHostName() )); + assertTrue( v.equals( t.getVersion() )); + + } + + @Test + public void testDRNodeClassSetters() { + + DR_Node t = new DR_Node(); + + t.setFqdn( f ); + assertTrue( f.equals( t.getFqdn() )); + t.setDcaeLocationName( d ); + assertTrue( d.equals( t.getDcaeLocationName() )); + t.setHostName( h ); + assertTrue( h.equals( t.getHostName() )); + t.setVersion( v ); + assertTrue( v.equals( t.getVersion() )); + + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DRPubTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DRPubTest.java new file mode 100644 index 0000000..191f364 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DRPubTest.java @@ -0,0 +1,90 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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 static org.junit.Assert.*; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +public class DRPubTest { + String d, un, up, f, p; + + @Before + public void setUp() throws Exception { + d = "central-onap"; + un = "user1"; + up = "secretW0rd"; + f = "234"; + p = "678"; + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testDRPubClassDefaultConstructor() { + + DR_Pub t = new DR_Pub(); + + assertTrue( t.getDcaeLocationName() == null ); + assertTrue( t.getUsername() == null ); + assertTrue( t.getUserpwd() == null ); + assertTrue( t.getFeedId() == null ); + assertTrue( t.getPubId() == null ); + + } + + @Test + public void testDRPubClassConstructor() { + + DR_Pub t = new DR_Pub( d, un, up, f, p ); + + assertTrue( d.equals( t.getDcaeLocationName() )); + assertTrue( un.equals( t.getUsername() )); + assertTrue( up.equals( t.getUserpwd() )); + assertTrue( f.equals( t.getFeedId() )); + assertTrue( p.equals( t.getPubId() )); + } + + @Test + public void testDRPubClassSetters() { + + DR_Pub t = new DR_Pub(); + + t.setDcaeLocationName( d ); + assertTrue( d.equals( t.getDcaeLocationName() )); + t.setUsername( un ); + assertTrue( un.equals( t.getUsername() )); + t.setUserpwd( up ); + assertTrue( up.equals( t.getUserpwd() )); + t.setFeedId( f ); + assertTrue( f.equals( t.getFeedId() )); + t.setPubId( p ); + assertTrue( p.equals( t.getPubId() )); + + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DRSubTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DRSubTest.java new file mode 100644 index 0000000..95cf9c9 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DRSubTest.java @@ -0,0 +1,155 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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 static org.junit.Assert.*; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +public class DRSubTest { + String d, un, up, f, du, lu, s, o; + Boolean u100, susp; + + @Before + public void setUp() throws Exception { + d = "central-onap"; + un = "user1"; + up = "secretW0rd"; + f = "22"; + s = "sub123"; + du = "sub.server.onap.org:8443/deliver/here"; + lu = "https://drps.onap.org:8443/sublog/123"; + u100 = true; + susp = false; + o = "joe"; + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testDRSubClassDefaultConstructor() { + + DR_Sub t = new DR_Sub(); + + assertTrue( t.getDcaeLocationName() == null ); + assertTrue( t.getUsername() == null ); + assertTrue( t.getUserpwd() == null ); + assertTrue( t.getFeedId() == null ); + assertTrue( t.getDeliveryURL() == null ); + assertTrue( t.getLogURL() == null ); + assertTrue( t.getSubId() == null ); + assertTrue( ! t.isUse100() ); + assertTrue( ! t.isSuspended() ); + assertTrue( t.getOwner() == null ); + assertTrue( t.isGuaranteedDelivery() == false ); + assertTrue( t.isGuaranteedSequence() == false ); + assertTrue( t.isPrivilegedSubscriber() == false ); + assertTrue( t.isDecompress() == false ); + } + + @Test + public void testDRSubClassConstructor() { + + DR_Sub t = new DR_Sub( d, un, up, f, du, lu, u100 ); + + assertTrue( d.equals( t.getDcaeLocationName() )); + assertTrue( un.equals( t.getUsername() )); + assertTrue( up.equals( t.getUserpwd() )); + assertTrue( f.equals( t.getFeedId() )); + assertTrue( du.equals( t.getDeliveryURL() ) ); + assertTrue( lu.equals( t.getLogURL() ) ); + assertTrue( t.isUse100() ); + assertTrue( ! t.isSuspended() ); + } + + @Test + public void testDRSubClassSetters() { + + DR_Sub t = new DR_Sub(); + + t.setDcaeLocationName( d ); + assertTrue( d.equals( t.getDcaeLocationName() )); + t.setUsername( un ); + assertTrue( un.equals( t.getUsername() )); + t.setUserpwd( up ); + assertTrue( up.equals( t.getUserpwd() )); + t.setFeedId( f ); + assertTrue( f.equals( t.getFeedId() )); + t.setSubId( s ); + assertTrue( s.equals( t.getSubId() )); + t.setDeliveryURL( du ); + assertTrue( du.equals( t.getDeliveryURL() ) ); + t.setLogURL( lu ); + assertTrue( lu.equals( t.getLogURL() ) ); + boolean v = true; + t.setGuaranteedDelivery( v ); + assertTrue( t.isGuaranteedDelivery() == v ); + t.setGuaranteedSequence(v); + assertTrue( t.isGuaranteedSequence() == v ); + t.setPrivilegedSubscriber(v); + assertTrue( t.isPrivilegedSubscriber() == v ); + t.setDecompress(v); + assertTrue( t.isDecompress() == v ); + } + + @Test + public void testJSONfromONAP() { + + + DR_Sub s = new DR_Sub( d, un, up, f, du, lu, u100 ); + String j = s.toProvJSON(); + + DR_Sub t = new DR_Sub( j ); + + assertTrue( un.equals( t.getUsername() )); + assertTrue( up.equals( t.getUserpwd() )); + //assertTrue( f.equals( t.getFeedId() )); + assertTrue( du.equals( t.getDeliveryURL() ) ); + //assertTrue( lu.equals( t.getLogURL() ) ); + assertTrue( ! t.isSuspended() ); + + } + + @Test + public void testJSONfromATT() { + + + DR_Sub s = new DR_Sub( d, un, up, f, du, lu, u100 ); + + DR_Sub t = new DR_Sub( s.toProvJSONforATT() ); + + assertTrue( un.equals( t.getUsername() )); + assertTrue( up.equals( t.getUserpwd() )); + //assertTrue( f.equals( t.getFeedId() )); + assertTrue( du.equals( t.getDeliveryURL() ) ); + // assertTrue( lu.equals( t.getLogURL() ) ); + assertTrue( ! t.isSuspended() ); + + } + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DcaeLocationTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DcaeLocationTest.java new file mode 100644 index 0000000..6652bb0 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DcaeLocationTest.java @@ -0,0 +1,94 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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 static org.junit.Assert.*; + +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +public class DcaeLocationTest { + String c, dl, dln, osz, s, edge; + + @Before + public void setUp() throws Exception { + c = "ABCDE888NJ"; + dl = "central-node"; + edge = "local-node"; + dln = "hollywood"; + osz = "california"; + s = "10.10.10.1"; + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testDcaeLocationDefaultConstructor() { + + DcaeLocation t = new DcaeLocation(); + + assertTrue( t.getClli() == null ); + assertTrue( t.getDcaeLayer() == null ); + assertTrue( t.getDcaeLocationName() == null ); + assertTrue( t.getOpenStackAvailabilityZone() == null ); + assertTrue( t.getSubnet() == null ); + + } + + @Test + public void testDcaeLocationClassConstructor() { + + DcaeLocation t = new DcaeLocation( c, dl, dln, osz, s ); + + assertTrue( c.equals( t.getClli() )); + assertTrue( dl.equals( t.getDcaeLayer() )); + assertTrue( dln.equals( t.getDcaeLocationName() )); + assertTrue( osz.equals( t.getOpenStackAvailabilityZone() )); + assertTrue( s.equals( t.getSubnet() )); + } + + @Test + public void testDmaapClassSetters() { + + DcaeLocation t = new DcaeLocation(); + + t.setClli( c ); + assertTrue( c.equals( t.getClli() )); + t.setDcaeLayer( dl ); + assertTrue( dl.equals( t.getDcaeLayer() )); + assertTrue( t.isCentral() ); + t.setDcaeLayer( edge ); + assertTrue( edge.equals( t.getDcaeLayer() )); + assertTrue( t.isLocal() ); + t.setDcaeLocationName( dln ); + assertTrue( dln.equals( t.getDcaeLocationName() )); + t.setOpenStackAvailabilityZone( osz ); + assertTrue( osz.equals( t.getOpenStackAvailabilityZone() )); + t.setSubnet( s ); + assertTrue( s.equals( t.getSubnet() )); + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DmaapTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DmaapTest.java new file mode 100644 index 0000000..cb0c22f --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/DmaapTest.java @@ -0,0 +1,103 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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 static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class DmaapTest { + private String ver, tnr, dn, dpu, lu, bat, nk, ako; + + @Before + public void setUp() throws Exception { + ver = "1"; + tnr = "org.onap.dmaap"; + dn = "onap"; + dpu = "https://drps.dmaap.onap.org:8081"; + lu = "http://drps.dmaap.onap.org:8080/feedlog"; + bat = "org.onap.dcae.dmaap.MM_AGENT_TOPIC"; + nk = "foo"; + ako = "bar"; + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testDmaapClassDefaultConstructor() { + + Dmaap t = new Dmaap.DmaapBuilder().createDmaap(); + + assertTrue( t.getVersion() == null ); + assertTrue( t.getTopicNsRoot() == null ); + assertTrue( t.getDmaapName() == null ); + assertTrue( t.getDrProvUrl() == null ); + assertTrue( t.getLoggingUrl() == null ); + assertTrue( t.getBridgeAdminTopic() == null ); + assertTrue( t.getNodeKey() == null ); + assertTrue( t.getAccessKeyOwner() == null ); + + } + + @Test + public void testDmaapClassConstructor() { + + Dmaap t = new Dmaap.DmaapBuilder().setVer(ver).setTnr(tnr).setDn(dn).setDpu(dpu).setLu(lu).setBat(bat).setNk(nk).setAko(ako).createDmaap(); + + assertTrue( ver.equals( t.getVersion() )); + assertTrue( tnr.equals( t.getTopicNsRoot() )); + assertTrue( dn.equals( t.getDmaapName() )); + assertTrue( dpu.equals( t.getDrProvUrl() )); + assertTrue( lu.equals( t.getLoggingUrl() )); + assertTrue( bat.equals( t.getBridgeAdminTopic() )); + assertTrue( nk.equals( t.getNodeKey() )); + assertTrue( ako.equals( t.getAccessKeyOwner() )); + + } + + @Test + public void testDmaapClassSetters() { + + Dmaap t = new Dmaap.DmaapBuilder().createDmaap(); + + t.setVersion( ver ); + assertTrue( ver.equals( t.getVersion() )); + t.setTopicNsRoot( tnr ); + assertTrue( tnr.equals( t.getTopicNsRoot() )); + t.setDmaapName( dn ); + assertTrue( dn.equals( t.getDmaapName() )); + t.setDrProvUrl( dpu ); + assertTrue( dpu.equals( t.getDrProvUrl() )); + t.setLoggingUrl( lu ); + assertTrue( lu.equals( t.getLoggingUrl() )); + t.setBridgeAdminTopic( bat ); + assertTrue( bat.equals( t.getBridgeAdminTopic() )); + t.setNodeKey( nk ); + assertTrue( nk.equals( t.getNodeKey() )); + t.setAccessKeyOwner( ako ); + assertTrue( ako.equals( t.getAccessKeyOwner() )); + + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/FeedTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/FeedTest.java new file mode 100644 index 0000000..4fdc9a1 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/FeedTest.java @@ -0,0 +1,116 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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 static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +import java.util.ArrayList; + + +public class FeedTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + String n, v, d, o, a; + + @Before + public void setUp() throws Exception { + System.setProperty("ConfigFile", "src/test/resources/dmaapbc.properties"); + n = "Chicken Feed"; + v = "1.0"; + d = "A daily helping of chicken eating metrics"; + o = "ab123"; + a = "Unrestricted"; + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.model.Feed", "get", null ); + + } + + @Test + public void test2() { + Feed t = new Feed( n, v, d, o, a ); + + ArrayList<DR_Sub> subs = new ArrayList<DR_Sub>(); + DR_Sub sub = new DR_Sub( "central", "user", "pwd", "22", "server.onap.org/deliv", "log.onap.org/logs", true ); + subs.add( sub ); + t.setSubs( subs ); + + assertTrue( n.equals( t.getFeedName() )); + assertTrue( v.equals( t.getFeedVersion() )); + assertTrue( d.equals( t.getFeedDescription() )); + assertTrue( o.equals( t.getOwner() )); + assertTrue( a.equals( t.getAsprClassification() ) ); + assertTrue( ! t.isSuspended() ); + } + + @Test + public void test3() { + + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.model.Feed", "set", v ); + } + + @Test + public void test4() { + String s = String.format( "{ \"%s\": \"%s\", \"%s\": \"%s\", \"%s\": \"%s\", \"%s\": \"%s\", \"%s\": false, \"%s\": { \"%s\": \"%s\", \"%s\": \"%s\", \"%s\": \"%s\" }, \"%s\": { \"%s\": \"%s\", \"%s\": [ { \"%s\": \"%s\", \"%s\": \"%s\" } ] } }", + "name", n, + "version", v, + "description", d, + "publisher", a, + "suspend", + "links", + "publish", "https://feed.onap.org/publish/22", + "subscribe" , Feed.getSubProvURL( "22" ), + "log" , "https://feed.onap.org/log/22", + "authorization", + "classification", a, + "endpoint_ids" , "id", "king", "password", "henry" ); + + + Feed t = new Feed( s ); + + assertTrue( n.equals( t.getFeedName() )); + assertTrue( v.equals( t.getFeedVersion() )); + assertTrue( d.equals( t.getFeedDescription() )); + assertTrue( a.equals( t.getAsprClassification() ) ); + assertTrue( ! t.isSuspended() ); + + String o = t.toString(); + + } + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/JUnitTestSuite.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/JUnitTestSuite.java new file mode 100644 index 0000000..69e1b69 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/JUnitTestSuite.java @@ -0,0 +1,41 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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 ch.qos.logback.classic.Logger; +import junit.framework.TestSuite; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +@RunWith(Suite.class) +@SuiteClasses({DmaapTest.class}) +public class JUnitTestSuite { + + static Logger logger; + + public static void main(String[] args) { + logger.info("Running the test suite"); + + TestSuite tstSuite = new TestSuite(); + logger.info("Total Test Counts " + tstSuite.countTestCases()); + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/MRClientTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/MRClientTest.java new file mode 100644 index 0000000..ba95a85 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/MRClientTest.java @@ -0,0 +1,111 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright (C) 2019 IBM. + * ================================================================================ + * 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 static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +public class MRClientTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + String d, t, f, c, m; + + @Before + public void setUp() throws Exception { + d = "central-onap"; + t = "org.onap.dmaap.interestingTopic"; + f = "mrc.onap.org:3904/events/org.onap.dmaap.interestingTopic"; + c = "publisher"; + m = "m12345"; + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test1() { + + // can't use simple reflection to test for null since null constructor + // initializes some fields. + // rh.reflect( "org.onap.dmaap.dbcapi.model.MR_Client", "get", null ); + // so brute force instead... + String[] a = { "put", "view" }; + MR_Client m = new MR_Client(); + + assertTrue(null == m.getDcaeLocationName()); + assertTrue(null == m.getFqtn()); + assertTrue(null == m.getClientRole()); + assertTrue(null == m.getAction()); + + } + + @Test + public void test2() { + String[] a = { "put", "view" }; + MR_Client m = new MR_Client(d, f, c, a); + + assertTrue(d.equals(m.getDcaeLocationName())); + assertTrue(f.equals(m.getFqtn())); + assertTrue(c.equals(m.getClientRole())); + String[] ma = m.getAction(); + assertTrue(a.length == ma.length); + for (int i = 0; i < a.length; i++) { + assertTrue(a[i].equals(ma[i])); + } + } + + @Test + public void test3() { + + String v = "Validate"; + rh.reflect("org.onap.dmaap.dbcapi.model.MR_Client", "set", v); + } + + @Test + public void test4() { + MR_Client mrClient = new MR_Client(); + String stringArray[] = { "test" }; + mrClient.setAction(stringArray); + mrClient.hasAction(""); + mrClient.setMrClientId("mrClientId"); + mrClient.setTopicURL("testTopicURL"); + mrClient.setClientIdentity("clientIdentity"); + + assertEquals("clientIdentity", mrClient.getClientIdentity()); + assertEquals("testTopicURL", mrClient.getTopicURL()); + assertEquals("mrClientId", mrClient.getMrClientId()); + assertEquals(false, mrClient.isPublisher()); + assertEquals(false, mrClient.isSubscriber()); + assertEquals("test", mrClient.getAction()[0]); + + } + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/MR_ClusterTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/MR_ClusterTest.java new file mode 100644 index 0000000..2200627 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/MR_ClusterTest.java @@ -0,0 +1,135 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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 static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; +public class MR_ClusterTest { + String d, fqdn, repGrp, p1, p2, prot, p0; + + ReflectionHarness rh = new ReflectionHarness(); + + @Before + public void setUp() throws Exception { + d = "central-onap"; + fqdn = "mr.onap.org"; + repGrp = "zeppelin"; + prot = "http"; + p0 = "3904"; + p1 = "9092"; + p2 = "2323"; + + + + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void testMR_ClusterClassDefaultConstructor() { + + MR_Cluster t = new MR_Cluster(); + + assertTrue( t.getDcaeLocationName() == null ); + assertTrue( t.getFqdn() == null ); + + } + + @Test + public void testMR_ClusterClassConstructor() { + + MR_Cluster t = new MR_Cluster( d, fqdn, prot, p0); + + assertTrue( t.getDcaeLocationName() == d ); + assertTrue( t.getFqdn() == fqdn ); + assertTrue( t.getTopicProtocol() == prot ); + assertTrue( t.getTopicPort() == p0 ); + + // pass null params to trigger default settings + t = new MR_Cluster( d, fqdn, null, null ); + + assertTrue( t.getDcaeLocationName() == d ); + assertTrue( t.getFqdn() == fqdn ); + assertTrue( t.getTopicProtocol() != null ); + assertTrue( t.getTopicPort() != null ); + } + + @Test + public void testMR_ClusterManyArgsClassConstructor() { + + MR_Cluster t = new MR_Cluster( d, fqdn, prot, p0, repGrp, p1, p2 ); + + assertTrue( t.getDcaeLocationName() == d ); + assertTrue( t.getFqdn() == fqdn ); + assertTrue( t.getTopicProtocol() == prot ); + assertTrue( t.getTopicPort() == p0 ); + assertTrue( t.getReplicationGroup() == repGrp ); + assertTrue( t.getSourceReplicationPort() == p1 ); + assertTrue( t.getTargetReplicationPort() == p2 ); + + // pass null params to trigger default settings + t = new MR_Cluster( d, fqdn, null, null, null, null, null ); + + assertTrue( t.getDcaeLocationName() == d ); + assertTrue( t.getFqdn() == fqdn ); + assertTrue( t.getTopicProtocol() != null ); + assertTrue( t.getTopicPort() != null ); + assertTrue( t.getReplicationGroup() != null ); + assertTrue( t.getSourceReplicationPort() != null ); + assertTrue( t.getTargetReplicationPort() != null ); + } + + @Test + public void testw3() { + + MR_Cluster t = new MR_Cluster(); + + assertTrue( t.getDcaeLocationName() == null ); + assertTrue( t.getFqdn() == null ); + + String override = "cluster2.onap.org"; + String topic2 = "org.onap.topic2"; + String fqtn = t.genTopicURL( override, topic2 ); + assertTrue( fqtn.contains( override) && fqtn.contains(topic2)); + + fqtn = t.genTopicURL( null, "org.onap.topic2" ); + assertTrue(fqtn.contains(topic2)); + } + + + + @Test + public void testsetter() { + + String v = "validate"; + + + rh.reflect( "org.onap.dmaap.dbcapi.model.MR_Cluster", "set", v ); + + } + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/MirrorMakerTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/MirrorMakerTest.java new file mode 100644 index 0000000..39de2be --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/MirrorMakerTest.java @@ -0,0 +1,101 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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 static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +import java.util.ArrayList; + + +public class MirrorMakerTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.model.MirrorMaker", "get", null ); + + } + @Test + public void test2() { + + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.model.MirrorMaker", "set", v ); + } + + @Test + public void test3() { + String f = "org.onap.interestingTopic"; + String c1 = "cluster1.onap.org"; + String c2 = "cluster2.onap.org"; + MirrorMaker t = new MirrorMaker( c1, c2 ); + String m = t.getMmName(); + + MirrorMaker.genKey( c1, c2 ); + + assertTrue( c1.equals( t.getSourceCluster() )); + assertTrue( c2.equals( t.getTargetCluster() )); + } + + + @Test + public void test4() { + String f = "org.onap.interestingTopic"; + String c1 = "cluster1.onap.org"; + String c2 = "cluster2.onap.org"; + String p1 = "9092"; + String p2 = "2081"; + MirrorMaker t = new MirrorMaker( c1, c2 ); + String m = t.getMmName(); + + + ArrayList<String> topics = new ArrayList<String>(); + topics.add( f ); + t.setTopics( topics ); + t.addTopic( "org.onap.topic2" ); + + int i = t.getTopicCount(); + + String s = t.getWhitelistUpdateJSON(); + + s = t.createMirrorMaker(p1, p2); + + } + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/TestRunner.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/TestRunner.java new file mode 100644 index 0000000..16b48e3 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/TestRunner.java @@ -0,0 +1,41 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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 ch.qos.logback.classic.Logger; +import org.junit.runner.JUnitCore; +import org.junit.runner.Result; +import org.junit.runner.notification.Failure; +import org.onap.dmaap.dbcapi.logging.BaseLoggingClass; + +public class TestRunner extends BaseLoggingClass { + + private static Logger logger; + + public static void main(String[] args) { + + Result result = JUnitCore.runClasses(JUnitTestSuite.class); + for (Failure failure : result.getFailures()) { + logger.info(failure.toString()); + + } + logger.info(String.valueOf(result.wasSuccessful())); + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/TopicTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/TopicTest.java new file mode 100644 index 0000000..5da3aed --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/model/TopicTest.java @@ -0,0 +1,87 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 IBM + * ================================================================================ + * 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 static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +public class TopicTest { + + ReflectionHarness rh = new ReflectionHarness(); + + String f, t, d, e, o; + + @Before + public void setUp() throws Exception { + f = "org.onap.dmaap.interestingTopic"; + t = "interestingTopic"; + d = "A so very interesting topic"; + e = "Yes"; + o = "m12345"; + } + + @After + public void tearDown() throws Exception { + } + + @Test + public void test1() { + rh.reflect("org.onap.dmaap.dbcapi.model.Topic", "get", null); + } + + @Test + public void test2() { + Topic obj = new Topic(f, t, d, e, o); + assertTrue(f.equals(obj.getFqtn())); + assertTrue(t.equals(obj.getTopicName())); + assertTrue(d.equals(obj.getTopicDescription())); + assertTrue(e.equals(obj.getTnxEnabled())); + assertTrue(o.equals(obj.getOwner())); + } + + @Test + public void test3() { + String v = "Validate"; + rh.reflect("org.onap.dmaap.dbcapi.model.Topic", "set", v); + } + + @Test + public void getNumClientsHavingMRClientListNull() { + Topic obj = new Topic(f, t, d, e, o); + obj.setClients(null); + assertEquals(0, obj.getNumClients()); + } + + @Test + public void testTopicInitializationWithInvalidJsonString() { + String json = "{\"key\":\"value\""; + Topic obj = new Topic(json); + assertEquals(DmaapObject_Status.INVALID, obj.getStatus()); + } + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/AAFAuthenticationFilterTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/AAFAuthenticationFilterTest.java new file mode 100644 index 0000000..76fe914 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/AAFAuthenticationFilterTest.java @@ -0,0 +1,195 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.resources; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +import java.io.PrintWriter; +import java.io.StringWriter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.aaf.cadi.filter.CadiFilter; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +@RunWith(MockitoJUnitRunner.class) +public class AAFAuthenticationFilterTest { + + @Spy + private AAFAuthenticationFilter filter; + @Mock + private FilterConfig filterConfig; + @Mock + private CadiFilter cadiFilterMock; + @Mock + private HttpServletRequest servletRequest; + @Mock + private HttpServletResponse servletResponse; + @Mock + private FilterChain filterChain; + @Mock + private DmaapConfig dmaapConfig; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Before + public void setUp() throws Exception { + doReturn(dmaapConfig).when(filter).getConfig(); + } + + @Test + public void init_shouldNotInitializeCADI_whenAafIsNotUsed() throws Exception { + //given + doReturn("false").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.CADI_AUTHN_FLAG), anyString()); + + //when + filter.init(filterConfig); + + //then + assertFalse(filter.isCadiEnabled()); + assertNull(filter.getCadiFilter()); + } + + @Test + public void doFilter_shouldSkipCADI_whenAafIsNotUsed() throws Exception { + //given + doReturn("false").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.CADI_AUTHN_FLAG), anyString()); + filter.init(filterConfig); + filter.setCadiFilter(cadiFilterMock); + + //when + filter.doFilter(servletRequest, servletResponse, filterChain); + + //then + verify(filterChain).doFilter(servletRequest,servletResponse); + verifyZeroInteractions(cadiFilterMock,servletRequest,servletResponse); + } + + @Test + public void init_shouldFail_whenAafIsUsed_andCadiPropertiesHasNotBeenSet() throws Exception { + //given + doReturn("true").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.CADI_AUTHN_FLAG), anyString()); + doReturn("").when(dmaapConfig).getProperty(AAFAuthenticationFilter.CADI_PROPERTIES); + + //then + thrown.expect(ServletException.class); + thrown.expectMessage("Cannot initialize CADI filter.CADI properties not available."); + + //when + filter.init(filterConfig); + } + + @Test + public void init_shouldFail_whenAafIsUsed_andInvalidCadiPropertiesSet() throws Exception { + //given + String invalidFilePath = "src/test/resources/notExisting.properties"; + doReturn("true").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.CADI_AUTHN_FLAG), anyString()); + doReturn(invalidFilePath).when(dmaapConfig).getProperty(AAFAuthenticationFilter.CADI_PROPERTIES); + + //then + thrown.expect(ServletException.class); + thrown.expectMessage("Could not load CADI properties file: "+invalidFilePath); + + //when + filter.init(filterConfig); + } + + /* + * See https://jira.onap.org/browse/DMAAP-1361 for why this is commented out + @Test + public void init_shouldInitializeCADI_whenAafIsUsed_andValidCadiPropertiesSet() throws Exception { + //given + doReturn("true").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.CADI_AUTHN_FLAG), anyString()); + doReturn("src/test/resources/cadi.properties").when(dmaapConfig).getProperty(AAFAuthenticationFilter.CADI_PROPERTIES); + + //when + filter.init(filterConfig); + + //then + assertTrue(filter.isCadiEnabled()); + assertNotNull(filter.getCadiFilter()); + } + + @Test + public void doFilter_shouldUseCADIfilter_andAuthenticateUser_whenAAFisUsed_andUserIsValid() throws Exception{ + //given + initCADIFilter(); + doReturn(200).when(servletResponse).getStatus(); + + //when + filter.doFilter(servletRequest,servletResponse,filterChain); + + //then + verify(cadiFilterMock).doFilter(servletRequest,servletResponse,filterChain); + verify(servletResponse).getStatus(); + verifyNoMoreInteractions(servletResponse); + verifyZeroInteractions(filterChain, servletRequest); + } + + @Test + public void doFilter_shouldUseCADIfilter_andReturnAuthenticationError_whenAAFisUsed_andUserInvalid() throws Exception{ + //given + String errorResponseJson = "{\"code\":401,\"message\":\"invalid or no credentials provided\",\"fields\":\"Authentication\",\"2xx\":false}"; + initCADIFilter(); + doReturn(401).when(servletResponse).getStatus(); + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + doReturn(pw).when(servletResponse).getWriter(); + + //when + filter.doFilter(servletRequest,servletResponse,filterChain); + + //then + verify(cadiFilterMock).doFilter(servletRequest,servletResponse,filterChain); + verify(servletResponse).getStatus(); + verify(servletResponse).setContentType("application/json"); + verifyZeroInteractions(filterChain, servletRequest); + assertEquals(errorResponseJson, sw.toString()); + } + + private void initCADIFilter() throws Exception{ + doReturn("true").when(dmaapConfig).getProperty(eq(AAFAuthenticationFilter.CADI_AUTHN_FLAG), anyString()); + doReturn("src/test/resources/cadi.properties").when(dmaapConfig).getProperty(AAFAuthenticationFilter.CADI_PROPERTIES); + filter.init(filterConfig); + filter.setCadiFilter(cadiFilterMock); + } +*/ +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/AAFAuthorizationFilterTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/AAFAuthorizationFilterTest.java new file mode 100644 index 0000000..ba11b01 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/AAFAuthorizationFilterTest.java @@ -0,0 +1,172 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.resources; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +import java.io.PrintWriter; +import java.io.StringWriter; +import com.sun.security.auth.UserPrincipal; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.service.DmaapService; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import org.onap.dmaap.dbcapi.util.PermissionBuilder; + +@RunWith(MockitoJUnitRunner.class) +public class AAFAuthorizationFilterTest { + + @Spy + private AAFAuthorizationFilter filter; + @Mock + private FilterConfig filterConfig; + @Mock + private HttpServletRequest servletRequest; + @Mock + private HttpServletResponse servletResponse; + @Mock + private FilterChain filterChain; + @Mock + private DmaapConfig dmaapConfig; + @Mock + private PermissionBuilder permissionBuilder; + @Mock + private DmaapService dmaapService; + + @Before + public void setUp() throws Exception { + filter.setPermissionBuilder(permissionBuilder); + doReturn(dmaapConfig).when(filter).getConfig(); + doReturn(dmaapService).when(filter).getDmaapService(); + } + + @Test + public void init_shouldNotInitializePermissionBuilder_whenAAFnotUsed() throws Exception { + //given + filter.setPermissionBuilder(null); + configureAAFUsage(false); + + //when + filter.init(filterConfig); + + //then + assertNull(filter.getPermissionBuilder()); + } + + @Test + public void init_shouldInitializePermissionBuilder_whenAAFisUsed() throws Exception { + //given + filter.setPermissionBuilder(null); + configureAAFUsage(true); + //doReturn(provideEmptyInstance()).when(dmaapService).getDmaap(); + when(dmaapService.getDmaap()).thenReturn(mock(Dmaap.class)); + + //when + filter.init(filterConfig); + + //then + assertNotNull(permissionBuilder); + } + + @Test + public void doFilter_shouldSkipAuthorization_whenAAFnotUsed() throws Exception { + //given + filter.setCadiEnabled(false); + + //when + filter.doFilter(servletRequest,servletResponse,filterChain); + + //then + verify(filterChain).doFilter(servletRequest,servletResponse); + verifyNoMoreInteractions(filterChain); + verifyZeroInteractions(permissionBuilder, servletRequest, servletResponse); + } + + @Test + public void doFilter_shouldPass_whenUserHasPermissionToResourceEndpoint() throws Exception { + //given + String user = "johnny"; + String permission = "org.onap.dmaap-bc.api.topics|mr|GET"; + when(permissionBuilder.buildPermission(servletRequest)).thenReturn(permission); + configureServletRequest(permission, user, true); + filter.setCadiEnabled(true); + + //when + filter.doFilter(servletRequest,servletResponse,filterChain); + + //then + verify(filterChain).doFilter(servletRequest,servletResponse); + verify(permissionBuilder).updateDmaapInstance(); + verifyZeroInteractions(servletResponse); + } + + @Test + public void doFilter_shouldReturnError_whenUserDontHavePermissionToResourceEndpoint() throws Exception { + //given + String user = "jack"; + String permission = "org.onap.dmaap-bc.api.topics|mr|GET"; + when(permissionBuilder.buildPermission(servletRequest)).thenReturn(permission); + configureServletRequest(permission, user, false); + filter.setCadiEnabled(true); + + String errorMsgJson = "{\"code\":403,\"message\":\"User "+user+" does not have permission " + + permission +"\",\"fields\":\"Authorization\",\"2xx\":false}"; + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + when(servletResponse.getWriter()).thenReturn(pw); + + //when + filter.doFilter(servletRequest,servletResponse,filterChain); + + //then + verifyZeroInteractions(filterChain); + verify(permissionBuilder).updateDmaapInstance(); + verify(servletResponse).setStatus(403); + assertEquals(errorMsgJson, sw.toString()); + } + + private void configureServletRequest(String permission, String user, boolean isUserInRole) { + when(servletRequest.getUserPrincipal()).thenReturn(new UserPrincipal(user)); + when(servletRequest.isUserInRole(permission)).thenReturn(isUserInRole); + } + + private void configureAAFUsage(Boolean isUsed) { + doReturn(isUsed.toString()).when(dmaapConfig).getProperty(eq(AAFAuthorizationFilter.CADI_AUTHZ_FLAG), anyString()); + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DR_NodeResourceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DR_NodeResourceTest.java new file mode 100644 index 0000000..f131d8f --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DR_NodeResourceTest.java @@ -0,0 +1,236 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.resources; + +import org.glassfish.jersey.server.ResourceConfig; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DR_Node; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Response; + +import static javax.ws.rs.client.Entity.entity; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + + +public class DR_NodeResourceTest { + + private static final DmaapObjectFactory DMAAP_OBJECT_FACTORY = new DmaapObjectFactory(); + private static FastJerseyTestContainer testContainer; + + @BeforeClass + public static void setUpClass() throws Exception { + DatabaseClass.getDmaap().init(DMAAP_OBJECT_FACTORY.genDmaap()); + + testContainer = new FastJerseyTestContainer(new ResourceConfig() + .register(DR_NodeResource.class)); + testContainer.init(); + } + + @AfterClass + public static void tearDownClass() throws Exception { + testContainer.destroy(); + /*TODO: Cannot cleanup yet until still other Resources tests depends on the static DB content + + DatabaseClass.clearDatabase(); + DatabaseClass.getDmaap().remove();*/ + } + + @Test + public void getDr_Nodes_test() { + Response response = testContainer.target("dr_nodes").request().get(Response.class); + System.out.println("GET dr_subs response=" + response.getStatus()); + + assertEquals(200, response.getStatus()); + assertTrue(response.hasEntity()); + } + + @Test + public void addDr_Node_shouldReturnError_whenNoLocationAndFqdnProvided() { + DR_Node node = new DR_Node(null, null, "hostName", "1.0"); + Entity<DR_Node> requestedEntity = entity(node, APPLICATION_JSON); + + Response response = testContainer.target("dr_nodes") + .request() + .post(requestedEntity, Response.class); + + assertEquals(400, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("dcaeLocation, fqdn", responseError.getFields()); + } + + @Test + public void addDr_Node_shouldReturnError_whenDrNodeWithGiveFqdnAlreadyExists() { + DR_Node node = new DR_Node("fqdn", "location", "hostName", "1.0"); + + addDrNode(node); + Response response = addDrNode(node); + + assertEquals(409, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("fqdn", responseError.getFields()); + assertEquals("Node fqdn already exists", responseError.getMessage()); + } + + @Test + public void addDr_Node_shouldExecuteSuccessfully() { + DR_Node node = new DR_Node("fqdn", "location", "hostName", "1.0"); + + Response response = addDrNode(node); + + assertEquals(200, response.getStatus()); + assertTrue(response.hasEntity()); + assertDrNodeExistInDB(response.readEntity(DR_Node.class)); + } + + @Test + public void updateDr_Node_shouldReturnError_whenNoLocationAndFqdnProvided() { + DR_Node node = new DR_Node(null, null, "hostName", "1.0"); + Entity<DR_Node> requestedEntity = entity(node, APPLICATION_JSON); + + Response response = testContainer.target("dr_nodes") + .path("fqdn") + .request() + .put(requestedEntity, Response.class); + + assertEquals(400, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("dcaeLocation, fqdn", responseError.getFields()); + } + + @Test + public void updateDr_Node_shouldReturnError_whenDrNodeForUpdateDoesNotExistInDb() { + DR_Node node = new DR_Node("fqdn", "location", "hostName", "1.0"); + Entity<DR_Node> requestedEntity = entity(node, APPLICATION_JSON); + + Response response = testContainer.target("dr_nodes") + .path(node.getFqdn()) + .request() + .put(requestedEntity, Response.class); + + assertEquals(404, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("fqdn", responseError.getFields()); + assertEquals("Node " + node.getFqdn() + " does not exist", responseError.getMessage()); + } + + @Test + public void updateDr_Node_ShouldExecuteSuccessfully() { + DR_Node toUpdate = new DR_Node("fqdn", "location", "hostName", "1.0"); + Entity<DR_Node> requestedEntity = entity(toUpdate, APPLICATION_JSON); + + addDrNode(new DR_Node("fqdn", "old_location", "old_hostName", "old_1.0")); + Response response = testContainer.target("dr_nodes") + .path(toUpdate.getFqdn()) + .request() + .put(requestedEntity, Response.class); + + assertEquals(200, response.getStatus()); + assertTrue(response.hasEntity()); + assertEquals(toUpdate, response.readEntity(DR_Node.class)); + } + + @Test + public void deleteDr_Node_shouldReturnError_whenDrNodeForDeleteDoesNotExistInDb() { + Response response = testContainer.target("dr_nodes") + .path("fqdn") + .request() + .delete(); + + assertEquals(404, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("fqdn", responseError.getFields()); + assertEquals("Node fqdn does not exist", responseError.getMessage()); + } + + @Test + public void deleteDr_Node_shouldReturnError_whenNoExistingFqdnProvided() { + Response response = testContainer.target("dr_nodes") + .path("") + .request() + .delete(); + + assertEquals(405, response.getStatus()); + } + + @Test + public void deleteDr_Node_shouldExecuteSuccessfully() { + DR_Node node = new DR_Node("fqdn", "location", "hostName", "1.0"); + + addDrNode(node); + Response response = testContainer.target("dr_nodes") + .path("fqdn") + .request() + .delete(); + + assertEquals(204, response.getStatus()); + } + + @Test + public void getDr_Node_shouldReturnError_whenDrNodeForDeleteDoesNotExistInDb() { + Response response = testContainer.target("dr_nodes") + .path("fqdn") + .request() + .get(); + + assertEquals(404, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("fqdn", responseError.getFields()); + assertEquals("Node fqdn does not exist", responseError.getMessage()); + } + + private Response addDrNode(DR_Node node) { + return testContainer.target("dr_nodes") + .request() + .post(entity(node, APPLICATION_JSON), Response.class); + } + + private void assertDrNodeExistInDB(DR_Node created) { + Response response = testContainer.target("dr_nodes") + .path(created.getFqdn()) + .request() + .get(); + assertEquals(200, response.getStatus()); + assertTrue(response.hasEntity()); + assertEquals(created, response.readEntity(DR_Node.class)); + } + + @Before + public void cleanupDatabase() { + DatabaseClass.clearDatabase(); + } + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DR_PubResourceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DR_PubResourceTest.java new file mode 100644 index 0000000..340f362 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DR_PubResourceTest.java @@ -0,0 +1,291 @@ + +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.resources; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.glassfish.jersey.server.ResourceConfig; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DR_Pub; +import org.onap.dmaap.dbcapi.model.Feed; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; + +public class DR_PubResourceTest { + + private static final DmaapObjectFactory DMAAP_OBJECT_FACTORY = new DmaapObjectFactory(); + + private static final String DCAE_LOCATION_NAME = "central-onap"; + private static final String USERNAME = "user1"; + private static final String USRPWD = "secretW0rd"; + private static final String FEED_ID = "someFakeFeedId"; + private static final String PUB_ID = "0"; + private static FastJerseyTestContainer testContainer; + private static TestFeedCreator testFeedCreator; + + @BeforeClass + public static void setUpClass() throws Exception { + //TODO: init is still needed here to assure that dmaap is not null + DatabaseClass.getDmaap().init(DMAAP_OBJECT_FACTORY.genDmaap()); + + testContainer = new FastJerseyTestContainer(new ResourceConfig() + .register(DmaapResource.class) + .register(DR_PubResource.class) + .register(FeedResource.class)); + + testContainer.init(); + testFeedCreator = new TestFeedCreator(testContainer); + } + + @AfterClass + public static void tearDownClass() throws Exception { + testContainer.destroy(); + /*TODO: Cannot cleanup yet until still other Resources tests depends on the static DB content + + DatabaseClass.clearDatabase(); + DatabaseClass.getDmaap().remove();*/ + } + + @Before + public void cleanupDatabase() { + DatabaseClass.clearDatabase(); + } + + @Test + public void getDr_Pub_test() { + Response resp = testContainer.target("dr_pubs").request().get(Response.class); + assertTrue(resp.getStatus() == 200); + assertTrue(resp.hasEntity()); + } + + @Test + public void addDr_Pub_shallReturnError_whenNoFeedIdAndFeedNameInPubProvided() { + //given + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, PUB_ID); + Entity<DR_Pub> requestedEntity = Entity.entity(drPub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_pubs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(400, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedName", responseError.getFields()); + } + + @Test + public void addDr_Pub_shallReturnError_whenFeedNameProvided_butFeedNotExist() { + //given + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, PUB_ID); + Entity<DR_Pub> requestedEntity = Entity.entity(drPub, MediaType.APPLICATION_JSON); + drPub.setFeedName("feed_name"); + + + //when + Response resp = testContainer.target("dr_pubs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(404, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedName", responseError.getFields()); + + } + + @Test + public void addDr_Pub_shallReturnError_whenFeedIdProvided_butFeedNotExist() { + //given + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, FEED_ID, PUB_ID); + Entity<DR_Pub> requestedEntity = Entity.entity(drPub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_pubs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(404, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedId=" + FEED_ID, responseError.getFields()); + } + + @Test + public void addDr_Pub_shallExecuteSuccessfully_whenValidFeedIdProvided() { + //given + String feedId = assureFeedIsInDB(); + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId); + Entity<DR_Pub> requestedEntity = Entity.entity(drPub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_pubs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(201, resp.getStatus()); + } + + @Test + public void addDr_Pub_shallExecuteSuccessfully_whenValidFeedNameProvided() { + //given + String feedName = "testFeed"; + testFeedCreator.addFeed(feedName, "test feed"); + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, PUB_ID); + drPub.setFeedName(feedName); + Entity<DR_Pub> requestedEntity = Entity.entity(drPub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_pubs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(201, resp.getStatus()); + } + + @Test + public void updateDr_Pub_shallExecuteSuccessfully_whenAddingNewPublisher() { + //given + String pubId = "5"; + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, "feedId", PUB_ID); + Entity<DR_Pub> reqEntity2 = Entity.entity(drPub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_pubs") + .path(pubId) + .request() + .put(reqEntity2, Response.class); + + //then + assertEquals(200, resp.getStatus()); + + } + /*// + // When this test is included, the following error is generated: + Exception in thread "HTTP-Dispatcher" java.lang.AssertionError: State is not RESPONSE (REQUEST) + at jdk.httpserver/sun.net.httpserver.ServerImpl.responseCompleted(ServerImpl.java:814) + at jdk.httpserver/sun.net.httpserver.ServerImpl$Dispatcher.handleEvent(ServerImpl.java:297) + at jdk.httpserver/sun.net.httpserver.ServerImpl$Dispatcher.run(ServerImpl.java:356) + at java.base/java.lang.Thread.run(Thread.java:830) +// I can't figure it out, so created a Jira for now. DMAAP-1358 + @Test + public void updateDr_Pub_shallReturnError_whenPathIsWrong() { + //given + DR_Pub drPub = new DR_Pub(DCAE_LOCATION_NAME, USERNAME, USRPWD, FEED_ID, PUB_ID); + Entity<DR_Pub> reqEntity2 = Entity.entity(drPub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_pubs") + .path("") + .request() + .put(reqEntity2, Response.class); + + //then + assertEquals(405, resp.getStatus()); + }*/ + @Test + public void deleteDr_Pub_shouldDeleteObjectWithSuccess() { + //given + String feedId = assureFeedIsInDB(); + DR_Pub dr_pub = addPub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId); + + //when + Response resp = testContainer.target("dr_pubs") + .path(dr_pub.getPubId()) + .request() + .delete(); + + //then + assertEquals("Shall delete publisher with success", 204, resp.getStatus()); + assertFalse("No entity object shall be returned", resp.hasEntity()); + } + + @Test + public void deleteDr_Pub_shouldReturnErrorResponse_whenGivenPubIdNotFound() { + //given + String notExistingPubId = "6789"; + + //when + Response resp = testContainer.target("dr_pubs") + .path(notExistingPubId) + .request() + .delete(); + + //then + assertEquals("Shall return error, when trying to delete not existing publisher", 404, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("pubId", responseError.getFields()); + } + + @Test + public void get_shallReturnExistingObject() { + //given + String feedId = assureFeedIsInDB(); + DR_Pub dr_Pub = addPub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId); + + //when + Response resp = testContainer.target("dr_pubs") + .path(dr_Pub.getPubId()) + .request() + .get(); + + //then + assertEquals("Publisher shall be found", 200, resp.getStatus()); + assertEquals("Retrieved object shall be equal to eh one put into DB", dr_Pub, resp.readEntity(DR_Pub.class)); + } + + private DR_Pub addPub(String d, String un, String up, String feedId) { + DR_Pub dr_pub = new DR_Pub(d, un, up, feedId, ""); + Entity<DR_Pub> reqEntity2 = Entity.entity(dr_pub, MediaType.APPLICATION_JSON); + Response resp = testContainer.target("dr_pubs").request().post(reqEntity2, Response.class); + System.out.println("POST dr_pubs resp=" + resp.getStatus()); + assertTrue(resp.getStatus() == 201); + dr_pub = resp.readEntity(DR_Pub.class); + return dr_pub; + } + + private String assureFeedIsInDB() { + Feed feed = testFeedCreator.addFeed("PublisherTestFeed", "feed for DR_Pub testing"); + assertNotNull("Feed shall be added into DB properly", feed); + return feed.getFeedId(); + } + + +} + + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DR_SubResourceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DR_SubResourceTest.java new file mode 100644 index 0000000..13b89ea --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DR_SubResourceTest.java @@ -0,0 +1,434 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.resources; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.glassfish.jersey.server.ResourceConfig; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DR_Sub; +import org.onap.dmaap.dbcapi.model.Feed; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; + +public class DR_SubResourceTest { + + private static final DmaapObjectFactory DMAAP_OBJECT_FACTORY = new DmaapObjectFactory(); + + private static final String DCAE_LOCATION_NAME = "central-onap"; + private static final String USERNAME = "user1"; + private static final String USRPWD = "secretW0rd"; + private static final String DELIVERY_URL = "https://subscriber.onap.org/delivery/id"; + private static final String LOG_URL = "https://dr-prov/sublog/id"; + private static final String DELIVERY_URL_TEMPLATE = "https://subscriber.onap.org/delivery/"; + private static final String LOG_URL_TEMPLATE = "https://dr-prov/sublog/"; + private static FastJerseyTestContainer testContainer; + private static TestFeedCreator testFeedCreator; + + @BeforeClass + public static void setUpClass() throws Exception { + //TODO: init is still needed here to assure that dmaap is not null + DatabaseClass.getDmaap().init(DMAAP_OBJECT_FACTORY.genDmaap()); + + testContainer = new FastJerseyTestContainer(new ResourceConfig() + .register(DR_SubResource.class) + .register(FeedResource.class)); + testContainer.init(); + testFeedCreator = new TestFeedCreator(testContainer); + } + + @AfterClass + public static void tearDownClass() throws Exception { + testContainer.destroy(); + /*TODO: Cannot cleanup yet until still other Resources tests depends on the static DB content + + DatabaseClass.clearDatabase(); + DatabaseClass.getDmaap().remove();*/ + } + + @Before + public void cleanupDatabase() { + DatabaseClass.clearDatabase(); + } + + //TODO: figure out generic entity list unmarshall to check the entity list + @Test + public void getDr_Subs_test() { + Response resp = testContainer.target("dr_subs").request().get(Response.class); + System.out.println("GET dr_subs resp=" + resp.getStatus()); + + assertEquals(200, resp.getStatus()); + assertTrue(resp.hasEntity()); + } + + @Test + public void addDr_Sub_shallReturnError_whenNoFeedIdAndFeedNameInSubProvided() { + //given + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, DELIVERY_URL, LOG_URL, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(400, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedName", responseError.getFields()); + } + + @Test + public void addDr_Sub_shallReturnError_whenFeedNameProvided_butFeedNotExist() { + //given + String notExistingFeedName = "notRealFead"; + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, DELIVERY_URL, LOG_URL, true); + drSub.setFeedName(notExistingFeedName); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(404, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedName", responseError.getFields()); + } + + @Test + public void addDr_Sub_shallReturnError_whenFeedNameProvided_andManyFeedsWithTheSameNameInDB() { + //given + String notDistinctFeedName = "notDistinctFeedName"; + Feed feed1 = new Feed(notDistinctFeedName, "1.0", "description", "dgl", "unrestricted"); + Feed feed2 = new Feed(notDistinctFeedName, "2.0", "description", "dgl", "unrestricted"); + DatabaseClass.getFeeds().put("1", feed1); + DatabaseClass.getFeeds().put("2", feed2); + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, DELIVERY_URL, LOG_URL, true); + drSub.setFeedName(notDistinctFeedName); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(409, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedName", responseError.getFields()); + } + + @Test + public void addDr_Sub_shallReturnError_whenFeedIdProvided_butFeedNotExist() { + //given + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, "someFakeFeedId", DELIVERY_URL, LOG_URL, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(404, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertTrue(responseError.getFields().contains("feedId")); + } + + @Test + public void addDr_Sub_shallExecuteSuccessfully_whenValidFeedIdProvided() { + //given + String feedId = assureFeedIsInDB(); + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId, DELIVERY_URL, LOG_URL, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(201, resp.getStatus()); + assertTrue(resp.hasEntity()); + DR_Sub created = resp.readEntity(DR_Sub.class); + assertSubscriptionExistInDB(created); + } + + @Test + public void addDr_Sub_shallExecuteSuccessfully_whenValidFeedNameProvided() { + //given + String feedName = "testFeed"; + testFeedCreator.addFeed(feedName, "test feed"); + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, DELIVERY_URL, LOG_URL, true); + drSub.setFeedName(feedName); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .request() + .post(requestedEntity, Response.class); + + //then + assertEquals(201, resp.getStatus()); + assertTrue(resp.hasEntity()); + DR_Sub created = resp.readEntity(DR_Sub.class); + assertSubscriptionExistInDB(created); + } + + + @Test + public void updateDr_Sub_shallReturnError_whenNoFeedIdInSubProvided() { + //given + String subId = "1234"; + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, null, DELIVERY_URL, LOG_URL, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .path(subId) + .request() + .put(requestedEntity, Response.class); + + //then + assertEquals(400, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("feedId", responseError.getFields()); + } + + @Test + public void updateDr_Sub_shallReturnError_whenNoDCAELocationInSubProvided() { + //given + String subId = "1234"; + DR_Sub drSub = new DR_Sub(null, USERNAME, USRPWD, "someFeedId", DELIVERY_URL, LOG_URL, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .path(subId) + .request() + .put(requestedEntity, Response.class); + + //then + assertEquals(400, resp.getStatus()); + ApiError responseError = resp.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("dcaeLocationName", responseError.getFields()); + } + + @Test + public void updateDr_Sub_shallReturnError_whenFeedWithGivenIdInSubNotExists() { + //given + String subId = "1234"; + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, "someFeedId", DELIVERY_URL, LOG_URL, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .path(subId) + .request() + .put(requestedEntity, Response.class); + + //then + assertEquals(404, resp.getStatus()); + assertNotNull(resp.readEntity(ApiError.class)); + } + + @Test + public void updateDr_Sub_shallReturnSuccess_whenAddingNewSubscription() { + //given + String subId = "31"; + String feedId = assureFeedIsInDB(); + DR_Sub drSub = new DR_Sub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId, null, null, true); + Entity<DR_Sub> requestedEntity = Entity.entity(drSub, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .path(subId) + .request() + .put(requestedEntity, Response.class); + + //then + assertEquals(200, resp.getStatus()); + + DR_Sub createdDrSub = resp.readEntity(DR_Sub.class); + assertNotNull(createdDrSub.getLastMod()); + assertEquals(subId, createdDrSub.getSubId()); + assertEquals(DCAE_LOCATION_NAME, createdDrSub.getDcaeLocationName()); + assertEquals(USERNAME, createdDrSub.getUsername()); + assertEquals(USRPWD, createdDrSub.getUserpwd()); + assertEquals(DELIVERY_URL_TEMPLATE + subId, createdDrSub.getDeliveryURL()); + assertEquals(LOG_URL_TEMPLATE + subId, createdDrSub.getLogURL()); + + assertSubscriptionExistInDB(createdDrSub); + } + + @Test + public void updateDr_Sub_shallReturnSuccess_whenUpdatingExistingSubscription() { + //given + String feedId = assureFeedIsInDB(); + DR_Sub existingDrSub = addSub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId); + DR_Sub drSubUpdate = new DR_Sub("newDcaeLocationName", "newUserName", "newUserPwd", feedId, null, null, false); + Entity<DR_Sub> requestedEntity = Entity.entity(drSubUpdate, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target("dr_subs") + .path(existingDrSub.getSubId()) + .request() + .put(requestedEntity, Response.class); + + //then + assertEquals(200, resp.getStatus()); + + DR_Sub updatedDrSub = resp.readEntity(DR_Sub.class); + assertNotNull(updatedDrSub.getLastMod()); + assertEquals(existingDrSub.getSubId(), updatedDrSub.getSubId()); + assertEquals(drSubUpdate.getDcaeLocationName(), updatedDrSub.getDcaeLocationName()); + assertEquals(drSubUpdate.getUsername(), updatedDrSub.getUsername()); + assertEquals(drSubUpdate.getUserpwd(), updatedDrSub.getUserpwd()); + assertEquals(DELIVERY_URL_TEMPLATE + existingDrSub.getSubId(), updatedDrSub.getDeliveryURL()); + assertEquals(LOG_URL_TEMPLATE + existingDrSub.getSubId(), updatedDrSub.getLogURL()); + + assertSubscriptionExistInDB(updatedDrSub); + } + + @Test + public void deleteDr_Sub_shouldDeleteSubscriptionWithSuccess() { + //given + String feedId = assureFeedIsInDB(); + DR_Sub dr_sub = addSub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId); + + //when + Response resp = testContainer.target("dr_subs") + .path(dr_sub.getSubId()) + .request() + .delete(); + + //then + assertEquals("Shall delete subscription with success", 204, resp.getStatus()); + assertFalse("No entity object shall be returned",resp.hasEntity()); + assertSubscriptionNotExistInDB(dr_sub.getSubId()); + } + + @Test + public void deleteDr_Sub_shouldReturnErrorResponse_whenGivenSubIdNotFound() { + //given + String notExistingSubId = "6789"; + + //when + Response resp = testContainer.target("dr_subs") + .path(notExistingSubId) + .request() + .delete(); + + //then + assertEquals("Shall return error, when trying to delete not existing subscription", 404, resp.getStatus()); + assertNotNull(resp.readEntity(ApiError.class)); + } + + @Test + public void get_shallReturnExistingObject() { + //given + String feedId = assureFeedIsInDB(); + DR_Sub dr_sub = addSub(DCAE_LOCATION_NAME, USERNAME, USRPWD, feedId); + + //when + Response resp = testContainer.target("dr_subs") + .path(dr_sub.getSubId()) + .request() + .get(); + + //ten + assertEquals("Subscription shall be found",200, resp.getStatus()); + assertEquals("Retrieved object shall be equal to eh one put into DB", dr_sub, resp.readEntity(DR_Sub.class)); + } + + @Test + public void get_shouldReturnError_whenSubWithIdNotFound() { + //given + String notExistingSubId = "1234"; + + //when + Response resp = testContainer.target("dr_subs") + .path(notExistingSubId) + .request() + .get(); + + //then + assertEquals("Subscription shall not be found", 404, resp.getStatus()); + assertNotNull(resp.readEntity(ApiError.class)); + } + + private DR_Sub addSub(String d, String un, String up, String feedId) { + DR_Sub dr_sub = new DR_Sub(d, un, up, feedId, + "https://subscriber.onap.org/foo", "https://dr-prov/sublog", true); + + Entity<DR_Sub> reqEntity2 = Entity.entity(dr_sub, MediaType.APPLICATION_JSON); + Response resp = testContainer.target("dr_subs").request().post(reqEntity2, Response.class); + System.out.println("POST dr_subs resp=" + resp.getStatus()); + assertEquals(201, resp.getStatus()); + dr_sub = resp.readEntity(DR_Sub.class); + + return dr_sub; + } + + private String assureFeedIsInDB() { + Feed feed = testFeedCreator.addFeed("SubscriberTestFeed", "feed for DR_Sub testing"); + assertNotNull("Feed shall be added into DB properly", feed); + return feed.getFeedId(); + } + + + private void assertSubscriptionNotExistInDB(String subId) { + assertEquals(404, testContainer.target("dr_subs") + .path(subId) + .request() + .get() + .getStatus()); + } + + private void assertSubscriptionExistInDB(DR_Sub sub) { + Response response = testContainer.target("dr_subs") + .path(sub.getSubId()) + .request() + .get(); + assertEquals(200, response.getStatus()); + assertTrue(response.hasEntity()); + assertEquals(sub, response.readEntity(DR_Sub.class)); + } +} + + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DcaeLocationResourceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DcaeLocationResourceTest.java new file mode 100644 index 0000000..ff07927 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DcaeLocationResourceTest.java @@ -0,0 +1,129 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.resources; + +import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.server.ResourceConfig; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.Path; +import javax.ws.rs.GET; + + +public class DcaeLocationResourceTest extends JerseyTest { + + static DmaapObjectFactory factory = new DmaapObjectFactory(); + + @Override + protected Application configure() { + return new ResourceConfig( DcaeLocationResource.class ); + } + + private static final String fmt = "%24s: %s%n"; + + + +/* may conflict with test framework! + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } +*/ + + + + @Test + public void GetTest() { + Response resp = target( "dcaeLocations").request().get( Response.class ); + System.out.println( "GET feed resp=" + resp.getStatus() ); + + assertTrue( resp.getStatus() == 200 ); + } + @Test + public void PostTest() { + DcaeLocation loc = factory.genDcaeLocation( "central" ); + Entity<DcaeLocation> reqEntity = Entity.entity( loc, MediaType.APPLICATION_JSON ); + Response resp = target( "dcaeLocations").request().post( reqEntity, Response.class ); + System.out.println( "POST dcaeLocation resp=" + resp.getStatus() + " " + resp.readEntity( String.class ) ); + if ( resp.getStatus() != 409 ) { + assertTrue( resp.getStatus() == 201 ); + } + + resp = target( "dcaeLocations"). + path( loc.getDcaeLocationName()).request().get( Response.class ); + System.out.println( "GET feed resp=" + resp.getStatus() ); + + assertTrue( resp.getStatus() == 200 ); + } + + @Test + public void PutTest() { + DcaeLocation loc = factory.genDcaeLocation( "edge" ); + Entity<DcaeLocation> reqEntity = Entity.entity( loc, MediaType.APPLICATION_JSON ); + Response resp = target( "dcaeLocations").request().post( reqEntity, Response.class ); + System.out.println( "POST dcaeLocation resp=" + resp.getStatus() + " " + resp.readEntity( String.class ) ); + if ( resp.getStatus() != 409 ) { + assertTrue( resp.getStatus() == 201 ); + } + + + loc.setClli("ATLCTYNJ9999"); + reqEntity = Entity.entity( loc, MediaType.APPLICATION_JSON ); + resp = target( "dcaeLocations"). + path( loc.getDcaeLocationName()).request().put( reqEntity, Response.class ); + System.out.println( "PUT dcaeLocation resp=" + resp.getStatus() + " " + resp.readEntity( String.class ) ); + assertTrue( resp.getStatus() == 201 ); + + } + + @Test + public void DelTest() { + DcaeLocation loc = factory.genDcaeLocation( "edge" ); + Entity<DcaeLocation> reqEntity = Entity.entity( loc, MediaType.APPLICATION_JSON ); + Response resp = target( "dcaeLocations").request().post( reqEntity, Response.class ); + System.out.println( "POST dcaeLocation resp=" + resp.getStatus() + " " + resp.readEntity( String.class ) ); + if ( resp.getStatus() != 409 ) { + assertTrue( resp.getStatus() == 201 ); + } + + resp = target( "dcaeLocations"). + path( loc.getDcaeLocationName()).request().delete( Response.class ); + System.out.println( "DELETE dcaeLocation resp=" + resp.getStatus() + " " + resp.readEntity( String.class ) ); + assertTrue( resp.getStatus() == 204 ); + } + + + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DmaapResourceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DmaapResourceTest.java new file mode 100644 index 0000000..29ccb40 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/DmaapResourceTest.java @@ -0,0 +1,92 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.resources; + +import static org.junit.Assert.assertTrue; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.glassfish.jersey.server.ResourceConfig; +import org.glassfish.jersey.test.JerseyTest; +import org.junit.Test; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; + + +public class DmaapResourceTest extends JerseyTest { + + static DmaapObjectFactory factory = new DmaapObjectFactory(); + + @Override + protected Application configure() { + return new ResourceConfig( DmaapResource.class ); + //return new ResourceConfig( HelloResource.class ); + } + + private static final String fmt = "%24s: %s%n"; + + + +/* may conflict with test framework! + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } +*/ + + + + @Test + public void GetTest() { + Response resp = target( "dmaap").request().get( Response.class ); + assertTrue( resp.getStatus() == 200 ); + } + @Test + public void PostTest() { + + Dmaap dmaap = factory.genDmaap(); + Entity<Dmaap> reqEntity = Entity.entity( dmaap, MediaType.APPLICATION_JSON ); + Response resp = target( "dmaap").request().post( reqEntity, Response.class ); + System.out.println( resp.getStatus() ); + assertTrue( resp.getStatus() == 200 ); + } + + @Test + public void PutTest() { + + Dmaap dmaap = factory.genDmaap(); + Entity<Dmaap> reqEntity = Entity.entity( dmaap, MediaType.APPLICATION_JSON ); + + dmaap.setVersion( "2" ); + Response resp = target( "dmaap").request().put( reqEntity, Response.class ); + System.out.println( resp.getStatus() ); + assertTrue( resp.getStatus() == 200 ); + } + + + + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/FastJerseyTestContainer.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/FastJerseyTestContainer.java new file mode 100644 index 0000000..8d38a9f --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/FastJerseyTestContainer.java @@ -0,0 +1,39 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.resources; + +import org.glassfish.jersey.test.JerseyTest; + +import javax.ws.rs.core.Application; + +class FastJerseyTestContainer extends JerseyTest { + + FastJerseyTestContainer(Application jaxrsApplication) { + super(jaxrsApplication); + } + + void init() throws Exception { + this.setUp(); + } + + void destroy() throws Exception { + this.tearDown(); + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/FeedResourceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/FeedResourceTest.java new file mode 100644 index 0000000..89dca8a --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/FeedResourceTest.java @@ -0,0 +1,104 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.resources; +import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.service.*; +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import java.util.*; +import java.sql.*; + +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.server.ResourceConfig; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.Path; +import javax.ws.rs.GET; + + +public class FeedResourceTest extends JerseyTest { + + @Override + protected Application configure() { + return new ResourceConfig( FeedResource.class ); + } + + private static final String fmt = "%24s: %s%n"; + + + +/* may conflict with test framework! + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } +*/ + + + + @Test + public void GetTest() { + Response resp = target( "feeds").request().get( Response.class ); + System.out.println( "GET feed resp=" + resp.getStatus() ); + + assertTrue( resp.getStatus() == 200 ); + } + @Test + public void PostTest() { + Feed feed = new Feed( "aPostTest", "1.0", "a unit test", "dgl", "unrestricted" ); + Entity<Feed> reqEntity = Entity.entity( feed, MediaType.APPLICATION_JSON ); + Response resp = target( "feeds").request().post( reqEntity, Response.class ); + System.out.println( "POST feed resp=" + resp.getStatus() ); + assertTrue( resp.getStatus() == 200 ); + } + +/* + @Test + public void PutTest() { + + Feed feed = new Feed( "aPutTest", "1.0", "a unit test", "dgl", "unrestricted" ); + Entity<Feed> reqEntity = Entity.entity( feed, MediaType.APPLICATION_JSON ); + Response resp = target( "feeds").request().post( reqEntity, Response.class ); + System.out.println( "POST feed resp=" + resp.getStatus() ); + String postResp = resp.readEntity( String.class ); + System.out.println( "postResp=" + postResp ); + Feed rFeed = new Feed( postResp ); getting a null pointer here + rFeed.setSuspended( true ); + String target = new String ("feeds/" + rFeed.getFeedId() ); + System.out.println( "PUT feed target=" + target ); + reqEntity = Entity.entity( rFeed, MediaType.APPLICATION_JSON ); + resp = target( target ).request().put( reqEntity, Response.class ); + System.out.println( "PUT feed resp=" + resp.getStatus() ); + assertTrue( resp.getStatus() == 200 ); + } +*/ + + + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/InfoResourceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/InfoResourceTest.java new file mode 100644 index 0000000..3f57f58 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/InfoResourceTest.java @@ -0,0 +1,71 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.resources; +import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.service.*; +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import java.util.*; +import java.sql.*; + +import org.glassfish.jersey.test.JerseyTest; +import org.glassfish.jersey.server.ResourceConfig; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Application; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.Path; +import javax.ws.rs.GET; + + +public class InfoResourceTest extends JerseyTest { + + @Override + protected Application configure() { + return new ResourceConfig( InfoResource.class ); + } + + private static final String fmt = "%24s: %s%n"; + + + +/* may conflict with test framework! + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } +*/ + + + + @Test + public void GetTest() { + Response resp = target( "info").request().get( Response.class ); + assertTrue( resp.getStatus() == 204 ); + } + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/MR_ClientResourceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/MR_ClientResourceTest.java new file mode 100644 index 0000000..abe2e45 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/MR_ClientResourceTest.java @@ -0,0 +1,304 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.resources; + +import org.glassfish.jersey.server.ResourceConfig; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.MR_Client; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; + +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Response; + +import static javax.ws.rs.client.Entity.entity; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +public class MR_ClientResourceTest { + + private static final DmaapObjectFactory DMAAP_OBJECT_FACTORY = new DmaapObjectFactory(); + private static FastJerseyTestContainer testContainer; + + @BeforeClass + public static void setUpClass() throws Exception { + DatabaseClass.getDmaap().init(DMAAP_OBJECT_FACTORY.genDmaap()); + + testContainer = new FastJerseyTestContainer(new ResourceConfig() + .register(MR_ClientResource.class).register(MR_ClusterResource.class).register(TopicResource.class)); + testContainer.init(); + } + + @AfterClass + public static void tearDownClass() throws Exception { + testContainer.destroy(); + /*TODO: Cannot cleanup yet until still other Resources tests depends on the static DB content + + DatabaseClass.getDmaap().remove(); + DatabaseClass.clearDatabase();*/ + } + + @Test + public void addMr_Client_shouldReturnErrorWhenNoFqtnProvided() { + Entity<MR_Client> requestedEntity = entity( + new MR_Client("dcaeLocation", null, "clientRole", new String[]{"GET"}), APPLICATION_JSON); + + Response response = testContainer.target("mr_clients") + .request() + .post(requestedEntity, Response.class); + + assertEquals(400, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("fqtn", responseError.getFields()); + } + + @Test + public void addMr_Client_shouldReturnErrorWhenNoLocationProvided() { + Entity<MR_Client> requestedEntity = entity( + new MR_Client(null, "fqtn", "clientRole", new String[]{"GET"}), APPLICATION_JSON); + + Response response = testContainer.target("mr_clients") + .request() + .post(requestedEntity, Response.class); + + assertEquals(400, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("dcaeLocationName", responseError.getFields()); + } + + @Test + public void addMr_Client_shouldReturnErrorWhenNoClientRoleProvided() { + Entity<MR_Client> requestedEntity = entity( + new MR_Client("dcaeLocation", "fqtn", null, new String[]{"GET"}), APPLICATION_JSON); + + Response response = testContainer.target("mr_clients") + .request() + .post(requestedEntity, Response.class); + + assertEquals(400, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("clientRole or clientIdentity", responseError.getFields()); + } + + @Test + public void addMr_Client_shouldReturnErrorWhenNoActionsProvided() { + Entity<MR_Client> requestedEntity = entity( + new MR_Client("dcaeLocation", "fqtn", "clientRole", null), APPLICATION_JSON); + + Response response = testContainer.target("mr_clients") + .request() + .post(requestedEntity, Response.class); + + assertEquals(400, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("action", responseError.getFields()); + } + + @Test + public void addMr_Client_shouldReturnErrorWhereThereIsNoMrClusterAvailable() { + Entity<MR_Client> requestedEntity = entity( + new MR_Client("dcaeLocationName", "fqtn", "clientRole", new String[]{"GET"}), APPLICATION_JSON); + + Response response = testContainer.target("mr_clients") + .request() + .post(requestedEntity, Response.class); + + assertEquals(400, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("dcaeLocationName", responseError.getFields()); + } + + @Test + public void addMr_Client_shouldReturnErrorWhereThereIsNoTopicForFqtnAvailable() { + Entity<MR_Client> requestedEntity = entity( + new MR_Client("dcaeLocation", "fqtn", "clientRole", new String[]{"GET"}), APPLICATION_JSON); + + createMrCluster(new MR_Cluster("dcaeLocation", "fqdn", "protocol", "port")); + + Response response = testContainer.target("mr_clients") + .request() + .post(requestedEntity, Response.class); + + assertEquals(404, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("fqtn", responseError.getFields()); + } + + @Test + public void addMr_Client_shouldAddMrClient() { + Entity<MR_Client> requestedEntity = entity( + new MR_Client("dcaeLocation2", "testTopic", "clientRole", new String[]{"GET"}), APPLICATION_JSON); + + createMrCluster(new MR_Cluster("dcaeLocation2", "fqdn", "protocol", "port")); + createTopic("testTopic"); + + Response response = testContainer.target("mr_clients") + .request() + .post(requestedEntity, Response.class); + + assertEquals(200, response.getStatus()); + assertTrue(response.hasEntity()); + assertMRClientExistInDB(response.readEntity(MR_Client.class)); + } + + @Test + public void deleteMr_Client_shouldDeleteMrClient() { + Entity<MR_Client> requestedEntity = entity( + new MR_Client("dcaeLocation3", "testTopic", "clientRole", new String[]{"GET"}), APPLICATION_JSON); + createMrCluster(new MR_Cluster("dcaeLocation3", "fqdn", "protocol", "port")); + createTopic("testTopic"); + + Response response = testContainer.target("mr_clients") + .request() + .post(requestedEntity, Response.class); + assertEquals(200, response.getStatus()); + + MR_Client mrClientEntity = response.readEntity(MR_Client.class); + Response deleteResponse = testContainer.target("mr_clients") + .path(mrClientEntity.getMrClientId()) + .request() + .delete(); + + assertEquals(204, deleteResponse.getStatus()); + assertMrClientNotExistInDB(mrClientEntity.getMrClientId()); + } + + @Test + public void deleteMr_Clients_shouldReturnMethodNotAllowedCodeWhenClientIdIsMissing() { + Response deleteResponse = testContainer.target("mr_clients") + .request() + .delete(); + + assertEquals(405, deleteResponse.getStatus()); + } + + @Test + public void getMr_Client_shouldReturnErrorWhenThereIsNoClient() { + Response response = testContainer.target("mr_clients") + .path("not_existing_id") + .request() + .get(); + + assertEquals(404, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("mrClientId", responseError.getFields()); + } + + @Test + public void updateMr_Client_shouldReturnErrorWhenNoFqtnProvided() { + MR_Client mrClient = new MR_Client("dcaeLocation", null, "clientRole", new String[]{"GET"}); + Entity<MR_Client> requestedEntity = entity(mrClient, APPLICATION_JSON); + + Response response = testContainer.target("mr_clients") + .path(mrClient.getMrClientId()) + .request() + .put(requestedEntity, Response.class); + + assertEquals(400, response.getStatus()); + ApiError responseError = response.readEntity(ApiError.class); + assertNotNull(responseError); + assertEquals("fqtn", responseError.getFields()); + } + + @Test + public void updateMr_Client_shouldUpdate() { + Entity<MR_Client> requestedEntity = entity( + new MR_Client("dcaeLocation4", "testTopic", "clientRole", new String[]{"GET"}), APPLICATION_JSON); + + createMrCluster(new MR_Cluster("dcaeLocation4", "fqdn", "protocol", "port")); + createTopic("testTopic"); + + Response response = testContainer.target("mr_clients") + .request() + .post(requestedEntity, Response.class); + MR_Client createdMrClient = response.readEntity(MR_Client.class); + createdMrClient.setDcaeLocationName("updatedDcaeLocation"); + + + Response updateResponse = testContainer.target("mr_clients") + .path(createdMrClient.getMrClientId()) + .request() + .put(requestedEntity, Response.class); + + assertEquals(200, updateResponse.getStatus()); + assertTrue(updateResponse.hasEntity()); + assertMRClientExistInDB(updateResponse.readEntity(MR_Client.class)); + + } + + @Test + public void getMr_Clients_test() { + Response response = testContainer.target("mr_clients").request().get(Response.class); + System.out.println("GET dr_subs response=" + response.getStatus()); + + assertEquals(200, response.getStatus()); + assertTrue(response.hasEntity()); + } + + + private void createMrCluster(MR_Cluster cluster) { + Response response = testContainer.target("mr_clusters") + .request() + .post(entity(cluster, APPLICATION_JSON), Response.class); + assertEquals(201, response.getStatus()); + } + + private void createTopic(String tname) { + Topic topic = new Topic(); + topic.setFqtn(tname); + topic.setFqtn(tname); + DatabaseClass.getTopics().put(topic.getFqtn(), topic); + } + + private void assertMRClientExistInDB(MR_Client created) { + Response response = testContainer.target("mr_clients") + .path(created.getMrClientId()) + .request() + .get(); + assertEquals(200, response.getStatus()); + assertTrue(response.hasEntity()); + MR_Client receivedMrClient = response.readEntity(MR_Client.class); + assertEquals(created.getFqtn(), receivedMrClient.getFqtn()); + assertEquals(created.getDcaeLocationName(), receivedMrClient.getDcaeLocationName()); + } + + private void assertMrClientNotExistInDB(String clientId) { + assertEquals(404, testContainer.target("mr_clients") + .path(clientId) + .request() + .get() + .getStatus()); + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResourceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResourceTest.java new file mode 100644 index 0000000..9027f13 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/MR_ClusterResourceTest.java @@ -0,0 +1,284 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.resources; + +import static javax.ws.rs.client.Entity.entity; +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +import java.util.List; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.Response; +import org.eclipse.jetty.http.HttpStatus; +import org.glassfish.jersey.server.ResourceConfig; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; + +public class MR_ClusterResourceTest { + + private static final DmaapObjectFactory DMAAP_OBJECT_FACTORY = new DmaapObjectFactory(); + private static FastJerseyTestContainer testContainer; + private static final String MR_CLUSTERS_TARGET = "mr_clusters"; + + @BeforeClass + public static void setUpClass() throws Exception { + DatabaseClass.getDmaap().init(DMAAP_OBJECT_FACTORY.genDmaap()); + + testContainer = new FastJerseyTestContainer(new ResourceConfig() + .register(MR_ClusterResource.class).register(DcaeLocationResource.class)); + testContainer.init(); + } + + @AfterClass + public static void tearDownClass() throws Exception { + testContainer.destroy(); + /*TODO: Cannot cleanup yet until still other Resources tests depends on the static DB content + + DatabaseClass.getDmaap().remove(); + DatabaseClass.clearDatabase();*/ + } + + @Before + public void setUpClusterAndLocation() { + DatabaseClass.clearDatabase(); + } + + @Test + public void getMrClusters_shouldReturnEmptyList_whenNoMrClustersInDataBase() { + //when + Response resp = testContainer.target(MR_CLUSTERS_TARGET).request().get(Response.class); + + //then + assertEquals(HttpStatus.OK_200, resp.getStatus()); + assertTrue(resp.hasEntity()); + + List<MR_Cluster> mrClusters = resp.readEntity(new GenericType<List<MR_Cluster>>() { + }); + assertTrue(mrClusters.isEmpty()); + } + + @Test + public void addMrCluster_shouldReturnValidationError_whenDcaeLocationNameNotProvided() { + //given + Entity<MR_Cluster> requestEntity = entity(new MR_Cluster(), APPLICATION_JSON); + + //when + Response resp = testContainer.target(MR_CLUSTERS_TARGET).request().post(requestEntity, Response.class); + + //then + assertEquals(HttpStatus.BAD_REQUEST_400, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("dcaeLocationName", errorObj.getFields()); + } + + @Test + public void addMrCluster_shouldReturnValidationError_whenFqdnNotProvided() { + //given + MR_Cluster mr_cluster = new MR_Cluster(); + mr_cluster.setDcaeLocationName("central-cloud"); + Entity<MR_Cluster> requestEntity = entity(mr_cluster, APPLICATION_JSON); + + //when + Response resp = testContainer.target(MR_CLUSTERS_TARGET).request().post(requestEntity, Response.class); + + //then + assertEquals(HttpStatus.BAD_REQUEST_400, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("fqdn", errorObj.getFields()); + } + + @Test + public void addMrCluster_shouldAddMrClusterToDatabase() { + //given + MR_Cluster mrCluster = DMAAP_OBJECT_FACTORY.genMR_Cluster("edge"); + Entity<MR_Cluster> requestEntity = entity(mrCluster, APPLICATION_JSON); + + //when + Response resp = testContainer.target(MR_CLUSTERS_TARGET).request().post(requestEntity, Response.class); + + //then + assertEquals(HttpStatus.CREATED_201, resp.getStatus()); + assertTrue(resp.hasEntity()); + MR_Cluster respEntity = resp.readEntity(MR_Cluster.class); + assertTrue(respEntity.isStatusValid()); + } + + @Test + public void addMrCluster_shouldReturnInvalidMrCluster_whenClusterCannotBeAddedToDatabase() { + //given + MR_Cluster mrCluster = DMAAP_OBJECT_FACTORY.genMR_Cluster("central"); + Entity<MR_Cluster> requestEntity = entity(mrCluster, APPLICATION_JSON); + prepareDcaeLocationForCentralCluster(); + + //when + Response resp = testContainer.target(MR_CLUSTERS_TARGET).request().post(requestEntity, Response.class); + + //then + assertEquals(HttpStatus.OK_200, resp.getStatus()); + assertTrue(resp.hasEntity()); + MR_Cluster respEntity = resp.readEntity(MR_Cluster.class); + assertFalse(respEntity.isStatusValid()); + } + + private void prepareDcaeLocationForCentralCluster() { + DcaeLocation centralDcaeLoc = DMAAP_OBJECT_FACTORY.genDcaeLocation("central"); + centralDcaeLoc.setStatus(DmaapObject_Status.VALID); + DatabaseClass.getDcaeLocations().put(centralDcaeLoc.getDcaeLocationName(), centralDcaeLoc); + } + + @Test + public void updateMrCluster_shouldReturnValidationError_whenDcaeLocationNameNotProvided() { + //given + Entity<MR_Cluster> requestEntity = entity(new MR_Cluster(), APPLICATION_JSON); + + //when + Response resp = testContainer.target(MR_CLUSTERS_TARGET).path("clusterId") + .request().put(requestEntity, Response.class); + + //then + assertEquals(HttpStatus.BAD_REQUEST_400, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("dcaeLocationName", errorObj.getFields()); + } + + @Test + public void updateMrCluster_shouldReturnApiError_whenMrClusterWithGivenIdNotFound() { + //given + MR_Cluster mr_cluster = new MR_Cluster(); + mr_cluster.setDcaeLocationName("central-cloud"); + Entity<MR_Cluster> requestEntity = entity(mr_cluster, APPLICATION_JSON); + + //when + Response resp = testContainer.target(MR_CLUSTERS_TARGET).path("notExistingMrCluster") + .request().put(requestEntity, Response.class); + + //then + assertEquals(HttpStatus.NOT_FOUND_404, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("dcaeLocationName", errorObj.getFields()); + } + + @Test + public void updateMrCluster_shouldUpdateClusterInDatabase() { + //given + String newReplicationGroup = "someNewReplicationGroup"; + prepareDcaeLocationForEdgeCluster(); + String clusterId = provideExistingEdgeMRClusterId(); + MR_Cluster changedMrCluster = DMAAP_OBJECT_FACTORY.genMR_Cluster("edge"); + changedMrCluster.setReplicationGroup(newReplicationGroup); + Entity<MR_Cluster> requestEntity = entity(changedMrCluster, APPLICATION_JSON); + + //when + Response resp = testContainer.target(MR_CLUSTERS_TARGET).path(clusterId) + .request().put(requestEntity, Response.class); + + //then + assertEquals(HttpStatus.CREATED_201, resp.getStatus()); + assertTrue(resp.hasEntity()); + MR_Cluster respEntity = resp.readEntity(MR_Cluster.class); + assertTrue(respEntity.isStatusValid()); + assertEquals(newReplicationGroup, respEntity.getReplicationGroup()); + } + + private void prepareDcaeLocationForEdgeCluster() { + DcaeLocation edgeDcaeLoc = DMAAP_OBJECT_FACTORY.genDcaeLocation("edge"); + edgeDcaeLoc.setStatus(DmaapObject_Status.VALID); + DatabaseClass.getDcaeLocations().put(edgeDcaeLoc.getDcaeLocationName(), edgeDcaeLoc); + } + + private String provideExistingEdgeMRClusterId() { + MR_Cluster cluster = DMAAP_OBJECT_FACTORY.genMR_Cluster("edge"); + cluster.setStatus(DmaapObject_Status.VALID); + DatabaseClass.getMr_clusters().put(cluster.getDcaeLocationName(), cluster); + return cluster.getDcaeLocationName(); + } + + @Test + public void deleteMr_Cluster_shouldReturnApiError_whenTryingToDeleteNotExistingMrCluster() { + //when + Response resp = testContainer.target(MR_CLUSTERS_TARGET).path("notExistingClusterId") + .request().delete(Response.class); + + //then + assertEquals(HttpStatus.NOT_FOUND_404, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("dcaeLocationName", errorObj.getFields()); + } + + @Test + public void deleteMr_Cluster_shouldRemoveMrClusterFromDatabase() { + //given + String clusterId = provideExistingEdgeMRClusterId(); + + //when + Response resp = testContainer.target(MR_CLUSTERS_TARGET).path(clusterId) + .request().delete(Response.class); + + //then + assertEquals(HttpStatus.NO_CONTENT_204, resp.getStatus()); + assertFalse(resp.hasEntity()); + } + + @Test + public void getMr_Cluster_shouldReturnApiError_whenTryingToGetNotExistingMrCluster() { + //when + Response resp = testContainer.target(MR_CLUSTERS_TARGET).path("notExistingClusterId") + .request().get(Response.class); + + //then + assertEquals(HttpStatus.OK_200, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("dcaeLocationName", errorObj.getFields()); + } + + @Test + public void getMr_Cluster_shouldReturnExistingMrCluster() { + //given + String clusterId = provideExistingEdgeMRClusterId(); + + //when + Response resp = testContainer.target(MR_CLUSTERS_TARGET).path(clusterId) + .request().get(Response.class); + + //then + assertEquals(HttpStatus.CREATED_201, resp.getStatus()); + assertTrue(resp.hasEntity()); + MR_Cluster mrCluster = resp.readEntity(MR_Cluster.class); + assertEquals(clusterId, mrCluster.getDcaeLocationName()); + } + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/RequestTimeLogFilterTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/RequestTimeLogFilterTest.java new file mode 100644 index 0000000..0c88c0c --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/RequestTimeLogFilterTest.java @@ -0,0 +1,78 @@ +/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dmaap
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.resources;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Matchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import com.att.eelf.configuration.EELFLogger;
+import java.time.Clock;
+import java.time.Instant;
+import java.time.ZoneId;
+import javax.ws.rs.container.ContainerRequestContext;
+import javax.ws.rs.container.ContainerResponseContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+
+@RunWith(MockitoJUnitRunner.class)
+public class RequestTimeLogFilterTest {
+
+ private Clock clock ;
+ private RequestTimeLogFilter requestTimeLogFilter;
+ public static final long START = 1L;
+ @Mock
+ private ContainerRequestContext requestContext;
+ @Mock
+ private ContainerResponseContext responseContext;
+ @Mock
+ private EELFLogger logger;
+
+
+ @Before
+ public void setup() {
+ clock = Clock.fixed(Instant.parse("1970-01-01T00:00:10Z"), ZoneId.systemDefault());
+ requestTimeLogFilter = new RequestTimeLogFilter(logger, clock);
+ }
+
+ @Test
+ public void shouldHaveDefaultConstructor() {
+ assertNotNull(new RequestTimeLogFilter());
+ }
+
+ @Test
+ public void filterShouldSetStartTimestampProperty() {
+ requestTimeLogFilter.filter(requestContext);
+ verify(requestContext).setProperty("start",clock.millis());
+ }
+
+ @Test
+ public void filterShouldPrintElapsedTime() {
+ when(requestContext.getProperty("start")).thenReturn(START);
+
+ requestTimeLogFilter.filter(requestContext, responseContext);
+
+ verify(logger).info(anyString(),eq(clock.millis() - START));
+ }
+}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/RequiredCheckerTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/RequiredCheckerTest.java new file mode 100644 index 0000000..f07058b --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/RequiredCheckerTest.java @@ -0,0 +1,86 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA 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.resources; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.dmaap.dbcapi.model.ApiError; + +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static org.junit.Assert.fail; + +public class RequiredCheckerTest { + + private static final String NAME = "field_name"; + @Rule + public ExpectedException thrown = ExpectedException.none(); + private RequiredChecker requiredChecker = new RequiredChecker(); + + + @Test + public void required_shouldThrowExceptionWhenObjectIsNull() throws RequiredFieldException { + thrown.expect(RequiredFieldException.class); + thrown.expect(new ApiErrorMatcher(new ApiError(BAD_REQUEST.getStatusCode(), + "missing required field", NAME))); + + requiredChecker.required(NAME, null); + } + + @Test + public void required_shouldThrowExceptionWhenRegexValidationFailed() throws RequiredFieldException { + thrown.expect(RequiredFieldException.class); + thrown.expect(new ApiErrorMatcher(new ApiError(BAD_REQUEST.getStatusCode(), + "value 'with white space' violates regexp check '^\\S+$'", NAME))); + + requiredChecker.required(NAME, "with white space", "^\\S+$"); + } + + @Test + public void required_shouldPassValidation() { + try { + requiredChecker.required(NAME, "value", "^\\S+$"); + } catch (RequiredFieldException e) { + fail("No exception should be thrown"); + } + } + + class ApiErrorMatcher extends BaseMatcher { + + private final ApiError expectedApiEror; + + ApiErrorMatcher(ApiError expectedApiEror) { + this.expectedApiEror = expectedApiEror; + } + + @Override + public boolean matches(Object exception) { + return expectedApiEror.equals(((RequiredFieldException) exception).getApiError()); + } + + @Override + public void describeTo(Description description) { + description.appendText("Following ApiError is expected: ").appendValue(expectedApiEror); + } + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/RequiredFieldExceptionTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/RequiredFieldExceptionTest.java new file mode 100644 index 0000000..d3dcc42 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/RequiredFieldExceptionTest.java @@ -0,0 +1,51 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Modifications Copyright (c) 2019 IBM + * =================================================================== + * 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.resources; + +import static javax.ws.rs.core.Response.Status.BAD_REQUEST; +import static org.junit.Assert.assertEquals; + +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.model.ApiError; + +public class RequiredFieldExceptionTest { + ApiError apiError; + RequiredFieldException requiredFieldException; + String expectedValue; + + @Before + public void setUp() { + apiError = new ApiError(BAD_REQUEST.getStatusCode(), "value 'with white space' violates regexp check '^\\S+$'", + "field_name"); + + expectedValue = "RequiredFieldException{" + "apiError=" + apiError + '}'; + + requiredFieldException = new RequiredFieldException(apiError); + } + + @Test + public void testRequiredFieldExceptionToString() { + assertEquals(expectedValue, requiredFieldException.toString()); + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/ResponseBuilderTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/ResponseBuilderTest.java new file mode 100644 index 0000000..ff61d14 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/ResponseBuilderTest.java @@ -0,0 +1,96 @@ +/* + * ============LICENSE_START======================================================= + * PNF-REGISTRATION-HANDLER + * ================================================================================ + * Copyright (C) 2019 NOKIA 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.resources; + +import org.junit.Test; +import org.onap.dmaap.dbcapi.model.ApiError; + +import javax.ws.rs.core.Response; + +import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static javax.ws.rs.core.Response.Status.SERVICE_UNAVAILABLE; +import static javax.ws.rs.core.Response.Status.UNAUTHORIZED; +import static org.junit.Assert.assertEquals; + +public class ResponseBuilderTest { + + private static final String OBJECT = "Objcect"; + private static final String MESSAGE = "msg"; + private static final int CODE = 100; + private ResponseBuilder responseBuilder = new ResponseBuilder(); + + @Test + public void success_shouldCreateResponseWithOKStatusCode() { + + Response response = responseBuilder.success(OBJECT); + + assertEquals(OBJECT, response.getEntity()); + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + } + + @Test + public void success_shouldCreateResponseWithDefinedStatusCode() { + + Response response = responseBuilder.success(CODE, OBJECT); + + assertEquals(OBJECT, response.getEntity()); + assertEquals(CODE, response.getStatus()); + } + + @Test + public void unauthorized_shouldCreateCorrectResponse() { + + ApiError error = new ApiError(UNAUTHORIZED.getStatusCode(), MESSAGE, "Authorization"); + Response response = responseBuilder.unauthorized(MESSAGE); + + assertEquals(error, response.getEntity()); + assertEquals(error.getCode(), response.getStatus()); + } + + @Test + public void unavailable_shouldCreateCorrectResponse() { + + ApiError error = new ApiError(SERVICE_UNAVAILABLE.getStatusCode(), + "Request is unavailable due to unexpected condition"); + Response response = responseBuilder.unavailable(); + + assertEquals(error, response.getEntity()); + assertEquals(error.getCode(), response.getStatus()); + } + + @Test + public void notFound_shouldCreateCorrectResponse() { + ApiError error = new ApiError(NOT_FOUND.getStatusCode(), "Requested object not found"); + Response response = responseBuilder.notFound(); + + assertEquals(error, response.getEntity()); + assertEquals(error.getCode(), response.getStatus()); + } + + @Test + public void error_shouldCreateCorrectResponse() { + ApiError error = new ApiError(CODE, "Some Error"); + Response response = responseBuilder.error(error); + + assertEquals(error, response.getEntity()); + assertEquals(error.getCode(), response.getStatus()); + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/TestFeedCreator.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/TestFeedCreator.java new file mode 100644 index 0000000..e4dedb1 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/TestFeedCreator.java @@ -0,0 +1,49 @@ +/*-
+ * ============LICENSE_START=======================================================
+ * org.onap.dmaap
+ * ================================================================================
+ * Copyright (C) 2019 Nokia 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.resources;
+
+import static org.junit.Assert.assertTrue;
+
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import org.onap.dmaap.dbcapi.model.Feed;
+
+
+public class TestFeedCreator {
+
+
+ private final FastJerseyTestContainer testContainer;
+
+ public TestFeedCreator(FastJerseyTestContainer testContainer) {
+ this.testContainer = testContainer;
+ }
+
+ Feed addFeed(String name, String desc) {
+ Feed feed = new Feed(name, "1.0", desc, "dgl", "unrestricted");
+ Entity<Feed> reqEntity = Entity.entity(feed, MediaType.APPLICATION_JSON);
+ Response resp = testContainer.target("feeds").request().post(reqEntity, Response.class);
+ int rc = resp.getStatus();
+ System.out.println("POST feed resp=" + rc);
+ assertTrue(rc == 200 || rc == 409);
+ feed = resp.readEntity(Feed.class);
+ return feed;
+ }
+}
diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/TopicResourceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/TopicResourceTest.java new file mode 100644 index 0000000..5b7c46d --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/resources/TopicResourceTest.java @@ -0,0 +1,356 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.resources; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertFalse; + +import java.util.List; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; + +import org.eclipse.jetty.http.HttpStatus; +import org.glassfish.jersey.server.ResourceConfig; +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.dmaap.dbcapi.database.DatabaseClass; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.model.FqtnType; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.model.ReplicationType; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; + +public class TopicResourceTest { + + private static final DmaapObjectFactory DMAAP_OBJECT_FACTORY = new DmaapObjectFactory(); + private static final String TOPICS_TARGET = "topics"; + + private static FastJerseyTestContainer testContainer; + + @BeforeClass + public static void setUpClass() throws Exception { + //TODO: init is still needed here to assure that dmaap is not null + DatabaseClass.getDmaap().init(DMAAP_OBJECT_FACTORY.genDmaap()); + + testContainer = new FastJerseyTestContainer(new ResourceConfig() + .register(TopicResource.class)); + testContainer.init(); + } + + @AfterClass + public static void tearDownClass() throws Exception { + testContainer.destroy(); + } + + @Before + public void setUpClusterAndLocation() { + DatabaseClass.clearDatabase(); + + DcaeLocation centralDcaeLoc = DMAAP_OBJECT_FACTORY.genDcaeLocation("central"); + centralDcaeLoc.setStatus(DmaapObject_Status.VALID); + DatabaseClass.getDcaeLocations().put(centralDcaeLoc.getDcaeLocationName(), centralDcaeLoc); + + MR_Cluster cluster = DMAAP_OBJECT_FACTORY.genMR_Cluster("central"); + cluster.setStatus(DmaapObject_Status.VALID); + DatabaseClass.getMr_clusters().put(cluster.getDcaeLocationName(), cluster); + } + + @Test + public void getTopics_shouldReturnEmptyList_whenNoTopicsInDataBase() { + //when + Response resp = testContainer.target(TOPICS_TARGET).request().get(Response.class); + + //then + assertEquals(HttpStatus.OK_200, resp.getStatus()); + assertTrue(resp.hasEntity()); + + List<Topic> topics = resp.readEntity(new GenericType<List<Topic>>() { + }); + assertTrue(topics.isEmpty()); + } + + @Test + public void getTopics_shouldReturnTopicsRegisteredInDataBase() { + //given + Topic topic1 = DMAAP_OBJECT_FACTORY.genSimpleTopic("testTopic1"); + Topic topic2 = DMAAP_OBJECT_FACTORY.genSimpleTopic("testTopic2"); + DatabaseClass.getTopics().put(topic1.getFqtn(), topic1); + DatabaseClass.getTopics().put(topic2.getFqtn(), topic2); + + //when + Response resp = testContainer.target(TOPICS_TARGET).request().get(Response.class); + + //then + assertEquals(HttpStatus.OK_200, resp.getStatus()); + assertTrue(resp.hasEntity()); + + List<Topic> topics = resp.readEntity(new GenericType<List<Topic>>() { + }); + assertEquals(2, topics.size()); + assertTrue(topics.contains(topic1)); + assertTrue(topics.contains(topic2)); + } + + @Test + public void getTopics_shouldReturnValidationError_whenTopicNameIsInvalid() { + //given + String topicName = "wrong Topic Name"; + + //when + Response resp = testContainer.target(TOPICS_TARGET).path(topicName).request().get(Response.class); + + //then + assertEquals(HttpStatus.BAD_REQUEST_400, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("topicName", errorObj.getFields()); + } + + @Test + public void getTopic_shouldReturnError_whenRequestedTopicNotFound() { + //given + String topicName = "notExistingTopic"; + + //when + Response resp = testContainer.target(TOPICS_TARGET).path(topicName).request().get(Response.class); + + //then + assertEquals(HttpStatus.NOT_FOUND_404, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("fqtn", errorObj.getFields()); + } + + @Test + public void getTopic_shouldReturnTopicInformation_whenRequestedTopicExists() { + //given + Topic topic1 = DMAAP_OBJECT_FACTORY.genSimpleTopic("testTopic1"); + DatabaseClass.getTopics().put(topic1.getFqtn(), topic1); + + //when + Response resp = testContainer.target(TOPICS_TARGET).path(topic1.getFqtn()).request().get(Response.class); + + //then + assertEquals(HttpStatus.OK_200, resp.getStatus()); + assertTrue(resp.hasEntity()); + Topic retrievedTopic = resp.readEntity(Topic.class); + assertEquals(topic1, retrievedTopic); + } + + + @Test + public void deleteTopic_shouldReturnError_whenTopicNotFound() { + //given + String topicName = "notExisting"; + + //when + Response resp = testContainer.target(TOPICS_TARGET).path(topicName).request().delete(Response.class); + + //then + assertEquals(HttpStatus.NOT_FOUND_404, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("fqtn", errorObj.getFields()); + } + + @Test + public void deleteTopic_shouldDeleteTopicFromDataBase_whenFound() { + //given + Topic topic = DMAAP_OBJECT_FACTORY.genSimpleTopic("testTopic"); + DatabaseClass.getTopics().put(topic.getFqtn(), topic); + + //when + Response resp = testContainer.target(TOPICS_TARGET).path(topic.getFqtn()).request().delete(Response.class); + + //then + assertEquals(HttpStatus.NO_CONTENT_204, resp.getStatus()); + assertFalse(resp.hasEntity()); + } + + @Test + public void addTopic_shouldReturnValidationError_whenTopicNameIsInvalid() { + //given + Topic topic = DMAAP_OBJECT_FACTORY.genSimpleTopic("wrong topic name with spaces"); + Entity<Topic> requestedEntity = Entity.entity(topic, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target(TOPICS_TARGET).request().post(requestedEntity, Response.class); + + //then + assertEquals(HttpStatus.BAD_REQUEST_400, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("topicName", errorObj.getFields()); + } + + @Test + public void addTopic_shouldReturnValidationError_whenTopicDescriptionNotProvided() { + //given + Topic topic = DMAAP_OBJECT_FACTORY.genSimpleTopic("topicName"); + topic.setTopicDescription(null); + Entity<Topic> requestedEntity = Entity.entity(topic, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target(TOPICS_TARGET).request().post(requestedEntity, Response.class); + + //then + assertEquals(HttpStatus.BAD_REQUEST_400, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("topicDescription", errorObj.getFields()); + } + + @Test + public void addTopic_shouldReturnValidationError_whenTopicOwnerNotProvided() { + //given + Topic topic = DMAAP_OBJECT_FACTORY.genSimpleTopic("topicName"); + topic.setOwner(null); + Entity<Topic> requestedEntity = Entity.entity(topic, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target(TOPICS_TARGET).request().post(requestedEntity, Response.class); + + //then + assertEquals(HttpStatus.BAD_REQUEST_400, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("owner", errorObj.getFields()); + } + + @Test + public void addTopic_shouldReturnError_whenTopicAlreadyExist() { + //given + Topic topic = DMAAP_OBJECT_FACTORY.genSimpleTopic("topicName"); + DatabaseClass.getTopics().put(topic.getFqtn(), topic); + Entity<Topic> requestedEntity = Entity.entity(topic, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target(TOPICS_TARGET).request().post(requestedEntity, Response.class); + + //then + assertEquals(HttpStatus.CONFLICT_409, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("fqtn", errorObj.getFields()); + } + + @Test + public void addTopic_shouldReturnExistingTopic_whenTopicAlreadyExist_andUseExistingQueryParamUsed() { + //given + Topic topic = DMAAP_OBJECT_FACTORY.genSimpleTopic("topicName"); + DatabaseClass.getTopics().put(topic.getFqtn(), topic); + Entity<Topic> requestedEntity = Entity.entity(topic, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target(TOPICS_TARGET).queryParam("useExisting", true).request() + .post(requestedEntity, Response.class); + + //then + assertEquals(HttpStatus.CREATED_201, resp.getStatus()); + assertTrue(resp.hasEntity()); + assertEquals(topic, resp.readEntity(Topic.class)); + } + + @Test + public void addTopic_shouldReturnError_whenAddingTopicWithInvalidGlobalMRclusterHostname() { + Topic topic = DMAAP_OBJECT_FACTORY.genSimpleTopic("topicName"); + topic.setReplicationCase(ReplicationType.REPLICATION_CENTRAL_TO_GLOBAL); + topic.setGlobalMrURL("some.invalid.Glob$al.M@R.ur)l"); + Entity<Topic> requestedEntity = Entity.entity(topic, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target(TOPICS_TARGET).request().post(requestedEntity, Response.class); + + //then + assertEquals(HttpStatus.INTERNAL_SERVER_ERROR_500, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals("globalMrURL", errorObj.getFields()); + } + + @Test + public void addTopic_shouldAddTopicWithDefaultOptionalValues_whenNotProvided() { + Topic topic = DMAAP_OBJECT_FACTORY.genSimpleTopic("topicName"); + Entity<Topic> requestedEntity = Entity.entity(topic, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target(TOPICS_TARGET).request().post(requestedEntity, Response.class); + + //then + assertEquals(HttpStatus.CREATED_201, resp.getStatus()); + assertTrue(resp.hasEntity()); + Topic createdTopic = resp.readEntity(Topic.class); + assertEquals(topic, createdTopic); + assertEquals(FqtnType.FQTN_LEGACY_FORMAT, createdTopic.getFqtnStyle()); + assertEquals("2", createdTopic.getPartitionCount()); + assertEquals("1", createdTopic.getReplicationCount()); + } + + @Test + public void addTopic_shouldAddTopicWithOriginalOptionalValues_whenProvided() { + Topic topic = DMAAP_OBJECT_FACTORY.genSimpleTopic("topicName"); + topic.setFqtnStyle(FqtnType.FQTN_PROJECTID_FORMAT); + topic.setFqtn(topic.genFqtn()); + topic.setPartitionCount("6"); + topic.setReplicationCount("9"); + Entity<Topic> requestedEntity = Entity.entity(topic, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target(TOPICS_TARGET).request().post(requestedEntity, Response.class); + + //then + assertEquals(HttpStatus.CREATED_201, resp.getStatus()); + assertTrue(resp.hasEntity()); + Topic createdTopic = resp.readEntity(Topic.class); + assertEquals(topic, createdTopic); + assertEquals(FqtnType.FQTN_PROJECTID_FORMAT, createdTopic.getFqtnStyle()); + assertEquals("6", createdTopic.getPartitionCount()); + assertEquals("9", createdTopic.getReplicationCount()); + } + + @Test + public void updateTopic_shouldReturnError_withInformationThatItIsNotSupported() { + //given + Topic topic = DMAAP_OBJECT_FACTORY.genSimpleTopic("topicName"); + DatabaseClass.getTopics().put(topic.getFqtn(), topic); + topic.setOwner("newOwner"); + Entity<Topic> requestedEntity = Entity.entity(topic, MediaType.APPLICATION_JSON); + + //when + Response resp = testContainer.target(TOPICS_TARGET).path(topic.getFqtn()).request() + .put(requestedEntity, Response.class); + + //then + assertEquals(HttpStatus.BAD_REQUEST_400, resp.getStatus()); + assertTrue(resp.hasEntity()); + ApiError errorObj = resp.readEntity(ApiError.class); + assertEquals(TopicResource.UNSUPPORTED_PUT_MSG, errorObj.getMessage()); + } + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/server/JettyServerTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/server/JettyServerTest.java new file mode 100644 index 0000000..35c9243 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/server/JettyServerTest.java @@ -0,0 +1,79 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.server; + +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; +import org.onap.dmaap.dbcapi.util.DmaapConfig; +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import java.util.Properties; + +public class JettyServerTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + + JettyServer m = null; + + @Before + public void setUp() throws Exception { + Properties p = DmaapConfig.getConfig(); + try { + m = new JettyServer(p); + } catch (Exception e ) { + } + } + + @After + public void tearDown() throws Exception { + try { + m.getServer().stop(); + } catch (Exception e ) { + } + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.server.JettyServer", "get", null ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.server.JettyServer", "set", v ); + + } + + @Test + public void test3() { + } + + + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/server/MainTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/server/MainTest.java new file mode 100644 index 0000000..0e74f45 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/server/MainTest.java @@ -0,0 +1,79 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.server; + +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class MainTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + Main m; + + + @Before + public void setUp() throws Exception { + //m = new Main(); + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.server.Main", "get", null ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.server.Main", "set", v ); + + } + +/* + @Test + public void test3() { + String[] args = { "--help", "--version" }; + + try { + m.main( args ); + } catch (Exception e ) { + } + + } +*/ + + + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/AafPermissionServiceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/AafPermissionServiceTest.java new file mode 100644 index 0000000..716736e --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/AafPermissionServiceTest.java @@ -0,0 +1,141 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.service; + +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.dmaap.dbcapi.aaf.AafService; +import org.onap.dmaap.dbcapi.aaf.AafUserRole; +import org.onap.dmaap.dbcapi.aaf.DmaapGrant; +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.MR_Client; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status.INVALID; +import static org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status.VALID; + +@RunWith(JUnitParamsRunner.class) +public class AafPermissionServiceTest { + + private static final String ROLE = "dmaap.mr.demoTopic.publisher"; + private static final String IDENTITY = "dmaap-bc@dmaap-bc.onap.org"; + private static final String TOPIC_PERM = "org.onap.dmaap.mr.topic"; + private static final String FQTN = "org.onap.dmaap.mr.demoTopic"; + private static final String PUB_ACTION = "pub"; + private static final int INTERNAL_SERVER_ERROR = 500; + @Mock + private AafService aafService; + @Mock + private DmaapService dmaapService; + @Mock + private MR_Client mrClient; + private AafPermissionService aafPermissionService; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + aafPermissionService = new AafPermissionService(aafService, dmaapService); + given(mrClient.getClientIdentity()).willReturn(IDENTITY); + given(mrClient.getFqtn()).willReturn(FQTN); + given(mrClient.getAction()).willReturn(new String[]{PUB_ACTION}); + given(dmaapService.getTopicPerm()).willReturn(TOPIC_PERM); + } + + @Test + @Parameters({"201", "409"}) + public void shouldAssignClientToRole(int aafServiceReturnedCode) { + AafUserRole userRole = new AafUserRole(IDENTITY, ROLE); + given(aafService.addUserRole(userRole)).willReturn(aafServiceReturnedCode); + + ApiError apiError = aafPermissionService.assignClientToRole(mrClient, ROLE); + + then(aafService).should().addUserRole(userRole); + then(mrClient).should().setStatus(VALID); + assertOkStatus(apiError); + } + + @Test + public void shouldReturnErrorStatusWhenClientWasNotAssignedToRole() { + AafUserRole userRole = new AafUserRole(IDENTITY, ROLE); + given(aafService.addUserRole(userRole)).willReturn(INTERNAL_SERVER_ERROR); + + ApiError apiError = aafPermissionService.assignClientToRole(mrClient, ROLE); + + then(mrClient).should().setStatus(INVALID); + assertErrorStatus(apiError, INTERNAL_SERVER_ERROR); + } + + @Test + @Parameters({"201", "409"}) + public void shouldGrantActionPermissionForClientRole(int aafServiceReturnedCode) { + DmaapGrant grant = new DmaapGrant(new DmaapPerm(TOPIC_PERM, ":topic." + FQTN, PUB_ACTION), ROLE); + given(mrClient.getClientRole()).willReturn(ROLE); + given(aafService.addGrant(grant)).willReturn(aafServiceReturnedCode); + + ApiError apiError = aafPermissionService.grantClientRolePerms(mrClient); + + then(aafService).should().addGrant(grant); + then(mrClient).should().setStatus(VALID); + assertOkStatus(apiError); + } + + @Test + public void shouldReturnErrorStatusWhenPermissionWasNotGrantToRole() { + DmaapGrant grant = new DmaapGrant(new DmaapPerm(TOPIC_PERM, ":topic." + FQTN, PUB_ACTION), ROLE); + given(mrClient.getClientRole()).willReturn(ROLE); + given(aafService.addGrant(grant)).willReturn(INTERNAL_SERVER_ERROR); + + ApiError apiError = aafPermissionService.grantClientRolePerms(mrClient); + + then(mrClient).should().setStatus(INVALID); + assertErrorStatus(apiError, INTERNAL_SERVER_ERROR); + } + + @Test + public void shouldReturnOkStatusWhenClientRoleIsNull() { + given(mrClient.getClientRole()).willReturn(null); + + ApiError apiError = aafPermissionService.grantClientRolePerms(mrClient); + + verifyZeroInteractions(aafService); + then(mrClient).should().setStatus(VALID); + assertOkStatus(apiError); + } + + private void assertErrorStatus(ApiError apiError, int code) { + assertEquals(code, apiError.getCode()); + } + + private void assertOkStatus(ApiError apiError) { + assertTrue(apiError.is2xx()); + assertEquals("OK", apiError.getMessage()); + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/AafTopicSetupServiceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/AafTopicSetupServiceTest.java new file mode 100644 index 0000000..0ca406a --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/AafTopicSetupServiceTest.java @@ -0,0 +1,470 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.service; + +import junitparams.JUnitParamsRunner; +import junitparams.Parameters; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.dmaap.dbcapi.aaf.AafNamespace; +import org.onap.dmaap.dbcapi.aaf.AafRole; +import org.onap.dmaap.dbcapi.aaf.AafService; +import org.onap.dmaap.dbcapi.aaf.AafUserRole; +import org.onap.dmaap.dbcapi.aaf.DmaapGrant; +import org.onap.dmaap.dbcapi.aaf.DmaapPerm; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +import java.util.List; + +import static com.google.common.collect.Lists.newArrayList; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.BDDMockito.given; + +@RunWith(JUnitParamsRunner.class) +public class AafTopicSetupServiceTest { + + private static final int INTERNAL_SERVER_ERROR = 500; + private static final int NOT_FOUND = 404; + private static final int CREATED = 201; + private static final int OK = 200; + private static final String TOPIC_NS_ROOT = "org.onap.dmaap.mr"; + private static final String TOPIC_PERM = "org.onap.dmaap.mr.topic"; + private static final String TOPIC_FQTN = "org.onap.dmaap.mr.sample_topic"; + private static final String IDENTITY = "dmaap-bc@dmaap-bc.onap.org"; + private AafServiceStub aafService = new AafServiceStub(); + @Mock + private DmaapService dmaapService; + @Mock + private DmaapConfig dmaapConfig; + private AafTopicSetupService aafTopicSetupService; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + Dmaap dmaap = new Dmaap(); + dmaap.setTopicNsRoot(TOPIC_NS_ROOT); + given(dmaapService.getDmaap()).willReturn(dmaap); + given(dmaapService.getTopicPerm()).willReturn(TOPIC_PERM); + given(dmaapConfig.getProperty("aaf.CreateTopicRoles", "true")).willReturn("true"); + given(dmaapConfig.getProperty("MR.ClientDeleteLevel", "0")).willReturn("2"); + aafTopicSetupService = new AafTopicSetupService(aafService, dmaapService, dmaapConfig); + } + + @Test + @Parameters({"201", "409"}) + public void shouldCreatePublisherSubscriberViewerPermissions(int aafServiceReturnedCode) { + aafService.givenReturnCode(aafServiceReturnedCode); + + aafTopicSetupService.aafTopicSetup(givenTopic(TOPIC_FQTN)); + + aafService.shouldAddPerm(new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "pub")); + aafService.shouldAddPerm(new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "sub")); + aafService.shouldAddPerm(new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "view")); + } + + @Test + public void shouldReturnOkStatusWhenNoError() { + aafService.givenReturnCode(201); + + ApiError apiError = aafTopicSetupService.aafTopicSetup(givenTopic(TOPIC_FQTN)); + + assertOkStatus(apiError); + } + + @Test + @Parameters({"201", "409"}) + public void shouldAddNamespace(int aafServiceReturnedCode) { + aafService.givenReturnCode(aafServiceReturnedCode); + Topic topic = givenTopic(TOPIC_FQTN); + + aafTopicSetupService.aafTopicSetup(topic); + + AafNamespace namespace = new AafNamespace(TOPIC_FQTN, IDENTITY); + aafService.shouldAddNamespace(namespace); + } + + @Test + @Parameters({"201", "409"}) + public void shouldCretePublisherRoleAndSetItToTopic(int aafServiceReturnedCode) { + aafService.givenReturnCode(aafServiceReturnedCode); + Topic topic = givenTopic(TOPIC_FQTN); + + aafTopicSetupService.aafTopicSetup(topic); + + AafRole role = new AafRole(TOPIC_FQTN, "publisher"); + aafService.shouldAddRole(role); + assertEquals(role.getFullyQualifiedRole(), topic.getPublisherRole()); + } + + @Test + @Parameters({"201", "409"}) + public void shouldCreteSubscriberRoleAndSetItToTopic(int aafServiceReturnedCode) { + aafService.givenReturnCode(aafServiceReturnedCode); + Topic topic = givenTopic(TOPIC_FQTN); + + aafTopicSetupService.aafTopicSetup(topic); + + AafRole role = new AafRole(TOPIC_FQTN, "subscriber"); + aafService.shouldAddRole(role); + assertEquals(role.getFullyQualifiedRole(), topic.getSubscriberRole()); + } + + @Test + @Parameters({"201", "409"}) + public void shouldGrantPubAndViewPermissionToPublisherRole(int aafServiceReturnedCode) { + aafService.givenReturnCode(aafServiceReturnedCode); + + aafTopicSetupService.aafTopicSetup(givenTopic(TOPIC_FQTN)); + + AafRole role = new AafRole(TOPIC_FQTN, "publisher"); + DmaapPerm pubPerm = new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "pub"); + DmaapPerm viewPerm = new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "view"); + aafService.shouldAddGrant(new DmaapGrant(pubPerm, role.getFullyQualifiedRole())); + aafService.shouldAddGrant(new DmaapGrant(viewPerm, role.getFullyQualifiedRole())); + } + + @Test + @Parameters({"201", "409"}) + public void shouldGrantSubAndViewPermissionToSubscriberRole(int aafServiceReturnedCode) { + aafService.givenReturnCode(aafServiceReturnedCode); + + aafTopicSetupService.aafTopicSetup(givenTopic(TOPIC_FQTN)); + + AafRole role = new AafRole(TOPIC_FQTN, "subscriber"); + DmaapPerm subPerm = new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "sub"); + DmaapPerm viewPerm = new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "view"); + aafService.shouldAddGrant(new DmaapGrant(subPerm, role.getFullyQualifiedRole())); + aafService.shouldAddGrant(new DmaapGrant(viewPerm, role.getFullyQualifiedRole())); + } + + @Test + public void shouldCreateOnlyPermissionsWhenCreateTopicRolesIsFalse() { + given(dmaapConfig.getProperty("aaf.CreateTopicRoles", "true")).willReturn("false"); + + aafTopicSetupService.aafTopicSetup(givenTopic(TOPIC_FQTN)); + + aafService.shouldAddPerm(new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "pub")); + aafService.shouldAddPerm(new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "sub")); + aafService.shouldAddPerm(new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "view")); + aafService.shouldHaveNoNamespaceRolesAndGrantsAdded(); + } + + @Test + public void shouldCreateOnlyPermissionsWhenTopicFqtnDoesntStartWithNsRoot() { + + String topicFqtn = "sample_topic"; + aafTopicSetupService.aafTopicSetup(givenTopic(topicFqtn)); + + aafService.shouldAddPerm(new DmaapPerm(TOPIC_PERM, ":topic." + topicFqtn, "pub")); + aafService.shouldAddPerm(new DmaapPerm(TOPIC_PERM, ":topic." + topicFqtn, "sub")); + aafService.shouldAddPerm(new DmaapPerm(TOPIC_PERM, ":topic." + topicFqtn, "view")); + aafService.shouldHaveNoNamespaceRolesAndGrantsAdded(); + } + + @Test + public void shouldHandleExceptionWhenTopicSnRootIsNotDefined() { + Dmaap dmaap = new Dmaap(); + dmaap.setTopicNsRoot(null); + given(dmaapService.getDmaap()).willReturn(dmaap); + + ApiError apiError = aafTopicSetupService.aafTopicSetup(givenTopic(TOPIC_FQTN)); + + assertErrorStatus(apiError, INTERNAL_SERVER_ERROR); + } + + @Test + public void shouldHandleExceptionWhenPermissionCreationWasFailed() { + aafService.givenAddPermStatus(NOT_FOUND); + + ApiError apiError = aafTopicSetupService.aafTopicSetup(givenTopic(TOPIC_FQTN)); + + assertErrorStatus(apiError, INTERNAL_SERVER_ERROR); + } + + @Test + public void shouldHandleExceptionWhenNamespaceCreationWasFailed() { + aafService.givenAddNamespaceStatus(NOT_FOUND); + + ApiError apiError = aafTopicSetupService.aafTopicSetup(givenTopic(TOPIC_FQTN)); + + assertErrorStatus(apiError, INTERNAL_SERVER_ERROR); + } + + @Test + public void shouldHandleExceptionWhenRoleCreationWasFailed() { + aafService.givenAddRoleStatus(NOT_FOUND); + + ApiError apiError = aafTopicSetupService.aafTopicSetup(givenTopic(TOPIC_FQTN)); + + assertErrorStatus(apiError, INTERNAL_SERVER_ERROR); + } + + @Test + public void shouldHandleExceptionWhenGrantPermToRoleWasFailed() { + aafService.givenAddGrantStatus(NOT_FOUND); + + ApiError apiError = aafTopicSetupService.aafTopicSetup(givenTopic(TOPIC_FQTN)); + + assertErrorStatus(apiError, NOT_FOUND); + } + + @Test + @Parameters({"200", "404"}) + public void shouldremovePublisherSubscriberViewerPermissions(int aafServiceReturnedCode) { + aafService.givenReturnCode(aafServiceReturnedCode); + + aafTopicSetupService.aafTopicCleanup(givenTopic(TOPIC_FQTN)); + + aafService.shouldRemovePerm(new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "pub")); + aafService.shouldRemovePerm(new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "sub")); + aafService.shouldRemovePerm(new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "view")); + } + + @Test + @Parameters({"200", "404"}) + public void shouldRemoveNamespace(int aafServiceReturnedCode) { + aafService.givenReturnCode(aafServiceReturnedCode); + Topic topic = givenTopic(TOPIC_FQTN); + + aafTopicSetupService.aafTopicCleanup(topic); + + AafNamespace namespace = new AafNamespace(TOPIC_FQTN, IDENTITY); + aafService.shouldRemoveNamespace(namespace); + } + + @Test + public void shouldRemoveOnlyPermissionsWhenCreateTopicRolesIsFalse() { + given(dmaapConfig.getProperty("aaf.CreateTopicRoles", "true")).willReturn("false"); + + aafTopicSetupService.aafTopicCleanup(givenTopic(TOPIC_FQTN)); + + aafService.shouldRemovePerm(new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "pub")); + aafService.shouldRemovePerm(new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "sub")); + aafService.shouldRemovePerm(new DmaapPerm(TOPIC_PERM, ":topic." + TOPIC_FQTN, "view")); + aafService.shouldNotRemoveNamespace(); + } + + @Test + public void shouldRemoveOnlyPermissionsWhenTopicFqtnDoesntStartWithNsRoot() { + + String topicFqtn = "sample_topic"; + aafTopicSetupService.aafTopicCleanup(givenTopic(topicFqtn)); + + aafService.shouldRemovePerm(new DmaapPerm(TOPIC_PERM, ":topic." + topicFqtn, "pub")); + aafService.shouldRemovePerm(new DmaapPerm(TOPIC_PERM, ":topic." + topicFqtn, "sub")); + aafService.shouldRemovePerm(new DmaapPerm(TOPIC_PERM, ":topic." + topicFqtn, "view")); + aafService.shouldNotRemoveNamespace(); + } + + @Test + public void shouldHandleExceptionWhenPermissionRemovalWasFailed() { + aafService.givenRemovePermStatus(INTERNAL_SERVER_ERROR); + + ApiError apiError = aafTopicSetupService.aafTopicCleanup(givenTopic(TOPIC_FQTN)); + + assertErrorStatus(apiError, INTERNAL_SERVER_ERROR); + } + + @Test + public void shouldHandleExceptionWhenNamespaceRemovalWasFailed() { + aafService.givenRemoveNamespaceStatus(INTERNAL_SERVER_ERROR); + + ApiError apiError = aafTopicSetupService.aafTopicCleanup(givenTopic(TOPIC_FQTN)); + + assertErrorStatus(apiError, INTERNAL_SERVER_ERROR); + } + + @Test + public void shouldNotPerformCleanupWhenDeleteLevelIsLessThanTwo() { + given(dmaapConfig.getProperty("MR.ClientDeleteLevel", "0")).willReturn("0"); + + ApiError apiError = aafTopicSetupService.aafTopicCleanup(givenTopic(TOPIC_FQTN)); + + aafService.shouldNotPerformCleanup(); + assertOkStatus(apiError); + } + + @Test + public void shouldNotPerformCleanupWhenDeleteLevelIsNotNumericValue() { + given(dmaapConfig.getProperty("MR.ClientDeleteLevel", "0")).willReturn("not number"); + + ApiError apiError = aafTopicSetupService.aafTopicCleanup(givenTopic(TOPIC_FQTN)); + + aafService.shouldNotPerformCleanup(); + assertOkStatus(apiError); + } + + private Topic givenTopic(String topicFqtn) { + Topic topic = new Topic(); + topic.setFqtn(topicFqtn); + return topic; + } + + private void assertOkStatus(ApiError apiError) { + assertTrue(apiError.is2xx()); + assertEquals("OK", apiError.getMessage()); + } + + private void assertErrorStatus(ApiError apiError, int code) { + assertEquals(code, apiError.getCode()); + } + + private class AafServiceStub implements AafService { + + private AafNamespace addedNamespace; + private AafNamespace removedNamespace; + private List<DmaapPerm> addedPerms = newArrayList(); + private List<DmaapPerm> removedPerms = newArrayList(); + private List<AafRole> addedRoles = newArrayList(); + private List<DmaapGrant> addedGrants = newArrayList(); + private int addNamespaceStatus = CREATED; + private int addGrantStatus = CREATED; + private int addRoleStatus = CREATED; + private int addPermStatus = CREATED; + private int removePermStatus = OK; + private int removeNamespaceStatus = OK; + + @Override + public String getIdentity() { + return IDENTITY; + } + + @Override + public int addPerm(DmaapPerm perm) { + this.addedPerms.add(perm); + return addPermStatus; + } + + @Override + public int delPerm(DmaapPerm perm, boolean force) { + removedPerms.add(perm); + return removePermStatus; + } + + @Override + public int addGrant(DmaapGrant grant) { + addedGrants.add(grant); + return addGrantStatus; + } + + @Override + public int addUserRole(AafUserRole ur) { + throw new UnsupportedOperationException(); + } + + @Override + public int addRole(AafRole role) { + this.addedRoles.add(role); + return addRoleStatus; + } + + @Override + public int addNamespace(AafNamespace namespace) { + this.addedNamespace = namespace; + return addNamespaceStatus; + } + + @Override + public int delNamespace(AafNamespace namespace, boolean force) { + this.removedNamespace = namespace; + return removeNamespaceStatus; + } + + void givenReturnCode(int status) { + this.addNamespaceStatus = status; + this.addGrantStatus = status; + this.addRoleStatus = status; + this.addPermStatus = status; + this.removePermStatus = status; + this.removeNamespaceStatus = status; + } + + void givenAddNamespaceStatus(int addNamespaceStatus) { + this.addNamespaceStatus = addNamespaceStatus; + } + + void givenRemoveNamespaceStatus(int removeNamespaceStatus) { + this.removeNamespaceStatus = removeNamespaceStatus; + } + + void givenAddGrantStatus(int addGrantStatus) { + this.addGrantStatus = addGrantStatus; + } + + void givenAddRoleStatus(int addRoleStatus) { + this.addRoleStatus = addRoleStatus; + } + + void givenAddPermStatus(int addPermStatus) { + this.addPermStatus = addPermStatus; + } + + void givenRemovePermStatus(int removePermStatus) { + this.removePermStatus = removePermStatus; + } + + void shouldAddPerm(DmaapPerm perm) { + assertTrue(addedPerms.contains(perm)); + } + + void shouldRemovePerm(DmaapPerm perm) { + assertTrue(removedPerms.contains(perm)); + } + + void shouldAddNamespace(AafNamespace namespace) { + assertEquals(namespace, this.addedNamespace); + } + + void shouldRemoveNamespace(AafNamespace namespace) { + assertEquals(namespace, this.removedNamespace); + } + + void shouldAddRole(AafRole role) { + assertTrue(addedRoles.contains(role)); + } + + void shouldAddGrant(DmaapGrant grant) { + assertTrue(addedGrants.contains(grant)); + } + + void shouldHaveNoNamespaceRolesAndGrantsAdded() { + assertNull(this.addedNamespace); + assertTrue(this.addedGrants.isEmpty()); + assertTrue(this.addedRoles.isEmpty()); + } + + void shouldNotRemoveNamespace() { + assertNull(this.removedNamespace); + } + + void shouldNotPerformCleanup() { + shouldNotRemoveNamespace(); + assertTrue(removedPerms.isEmpty()); + } + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/ApiServiceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/ApiServiceTest.java new file mode 100644 index 0000000..c860e55 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/ApiServiceTest.java @@ -0,0 +1,60 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.service; + +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class ApiServiceTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + ApiService ds; + + @Before + public void setUp() throws Exception { + ds = new ApiService(); + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + //rh.reflect( "org.onap.dmaap.dbcapi.service.ApiService", "get", null ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.service.ApiService", "set", v ); + + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/CredentialsParserTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/CredentialsParserTest.java new file mode 100644 index 0000000..ae5becc --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/CredentialsParserTest.java @@ -0,0 +1,58 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.service; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class CredentialsParserTest { + + private CredentialsParser credentialsParser = new CredentialsParser(); + + @Test + public void parse_shouldReturnEmptyCredentialsWhenAuthorizationHeaderIsNull() { + + Credentials credentials = credentialsParser.parse(null); + + assertTrue(credentials.getId().isEmpty()); + assertTrue(credentials.getPwd().isEmpty()); + } + + @Test + public void parse_shouldReturnEmptyCredentialsWhenAuthorizationHeaderIsEmpty() { + + Credentials credentials = credentialsParser.parse(""); + + assertTrue(credentials.getId().isEmpty()); + assertTrue(credentials.getPwd().isEmpty()); + } + + @Test + public void parse_shouldParseCorrectCredentials() { + + Credentials credentials = credentialsParser.parse("Basic dXNlcjpwYXNzd29yZA=="); + + assertEquals("user", credentials.getId()); + assertEquals("password", credentials.getPwd()); + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/DR_NodeServiceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/DR_NodeServiceTest.java new file mode 100644 index 0000000..307d5b5 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/DR_NodeServiceTest.java @@ -0,0 +1,96 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.service; + +import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import java.util.List; + +public class DR_NodeServiceTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + static DmaapObjectFactory factory = new DmaapObjectFactory(); + + DR_NodeService ns; + + @Before + public void setUp() throws Exception { + ns = new DR_NodeService(); + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.service.DR_NodeService", "get", null ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.service.DR_NodeService", "set", v ); + + } + + @Test + public void test3() { + String f = "drsn01.onap.org"; + String locname = "central-demo"; + + DcaeLocationService dls = new DcaeLocationService(); + DcaeLocation loc = factory.genDcaeLocation( "central" ); + dls.addDcaeLocation( loc ); + + ApiError err = new ApiError(); + DR_Node node = new DR_Node( f, locname, "zplvm009.onap.org", "1.0.46" ); + DR_Node n2 = ns.addDr_Node( node, err ); + + if ( n2 != null ) { + n2 = ns.getDr_Node( f, err ); + } + + List<DR_Node> l = ns.getAllDr_Nodes(); + if ( n2 != null ) { + n2.setVersion( "1.0.47" ); + n2 = ns.updateDr_Node( n2, err ); + } + + n2 = ns.removeDr_Node( f, err ); + + + } + + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/DcaeLocationServiceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/DcaeLocationServiceTest.java new file mode 100644 index 0000000..e0b32a4 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/DcaeLocationServiceTest.java @@ -0,0 +1,144 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.service; + +import org.junit.Test; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.DmaapObject; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; + +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; + +public class DcaeLocationServiceTest { + + private static final String LOCATION_A = "locationA"; + private static final String LOCATION_B = "locationB"; + private DcaeLocationService locationService = new DcaeLocationService(new HashMap<>()); + + @Test + public void getAllDcaeLocations_shouldReturnEmptyCollection() { + + List<DcaeLocation> allDcaeLocations = locationService.getAllDcaeLocations(); + + assertTrue(allDcaeLocations.isEmpty()); + } + + @Test + public void addDcaeLocation_shouldAddLocationToMap() { + DcaeLocation locationA = createDcaeLocation(LOCATION_A); + + DcaeLocation addedLocation = locationService.addDcaeLocation(locationA); + + assertEquals(locationA, locationService.getDcaeLocation(LOCATION_A)); + assertSame(locationA, addedLocation); + } + + @Test + public void addDcaeLocation_shouldSetStatusAndLastModDate() { + DcaeLocation locationA = createDcaeLocation(LOCATION_A); + Date creationDate = new Date(10); + locationA.setLastMod(creationDate); + + DcaeLocation addedLocation = locationService.addDcaeLocation(locationA); + + assertTrue(addedLocation.getLastMod().after(creationDate)); + assertEquals(DmaapObject.DmaapObject_Status.VALID, addedLocation.getStatus()); + } + + @Test + public void updateDcaeLocation_shouldUpdateLocationAndLastModDate() { + DcaeLocation location = createDcaeLocation(LOCATION_A); + Date creationDate = new Date(10); + location.setLastMod(creationDate); + locationService.addDcaeLocation(location); + + DcaeLocation updatedLocation = locationService.updateDcaeLocation(location); + + assertTrue(updatedLocation.getLastMod().after(creationDate)); + assertSame(location, updatedLocation); + } + + @Test + public void updateDcaeLocation_shouldShouldReturnNullWhenLocationNameIsEmpty() { + DcaeLocation location = createDcaeLocation(""); + + DcaeLocation updatedLocation = locationService.updateDcaeLocation(location); + + assertNull(updatedLocation); + assertTrue(locationService.getAllDcaeLocations().isEmpty()); + } + + @Test + public void removeDcaeLocation_shouldRemoveLocationFromService() { + locationService.addDcaeLocation(createDcaeLocation(LOCATION_A)); + + locationService.removeDcaeLocation(LOCATION_A); + + assertTrue(locationService.getAllDcaeLocations().isEmpty()); + } + + @Test + public void getCentralLocation_shouldGetFirstCentralLocation() { + locationService.addDcaeLocation(createDcaeLocation(LOCATION_A, "layerA")); + locationService.addDcaeLocation(createDcaeLocation(LOCATION_B, "centralLayer")); + + assertEquals(LOCATION_B, locationService.getCentralLocation()); + } + + @Test + public void getCentralLocation_shouldReturnDefaultCentralLocationNameWhenThereIsNoCentralLocation() { + locationService.addDcaeLocation(createDcaeLocation(LOCATION_A, "layerA")); + + assertEquals("aCentralLocation", locationService.getCentralLocation()); + } + + @Test + public void isEdgeLocation_shouldReturnTrueForNotCentralLocation() { + locationService.addDcaeLocation(createDcaeLocation(LOCATION_A, "layerA")); + locationService.addDcaeLocation(createDcaeLocation(LOCATION_B, "centralLayer")); + + assertTrue(locationService.isEdgeLocation(LOCATION_A)); + assertFalse(locationService.isEdgeLocation(LOCATION_B)); + } + + @Test + public void isEdgeLocation_shouldReturnFalseWhenLocationDoesNotExist() { + locationService.addDcaeLocation(createDcaeLocation(LOCATION_A, "layerA")); + + assertFalse(locationService.isEdgeLocation("not_existing_location")); + } + + private DcaeLocation createDcaeLocation(String locationName) { + return createDcaeLocation(locationName, "dcaeLayer"); + } + + private DcaeLocation createDcaeLocation(String locationName, String dcaeLayer) { + return new DcaeLocation("clli", dcaeLayer, locationName, "openStackAvailabilityZone", "subnet"); + } + + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/DmaapServiceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/DmaapServiceTest.java new file mode 100644 index 0000000..b8b660f --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/DmaapServiceTest.java @@ -0,0 +1,90 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.service; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +public class DmaapServiceTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + DmaapService ds; + + @Before + public void setUp() throws Exception { + ds = new DmaapService(); + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + //rh.reflect( "org.onap.dmaap.dbcapi.service.DmaapService", "get", null ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.service.DmaapService", "set", v ); + + } + + @Test + public void test3() { + Dmaap nd = new Dmaap.DmaapBuilder().setVer("1").setTnr("org.onap.dmaap").setDn("onap-demo").setDpu("drps.demo.onap.org").setLu("").setBat("MMAGENT_TOPIC").setNk("").setAko("").createDmaap(); + ds.addDmaap( nd ); + } + + @Test + public void test4() { + Dmaap d = ds.getDmaap(); + + } + + @Test + public void test5() { + Dmaap nd = new Dmaap.DmaapBuilder().setVer("2").setTnr("org.onap.dmaap").setDn("onap-demo").setDpu("drps.demo.onap.org").setLu("").setBat("MMAGENT_TOPIC").setNk("").setAko("").createDmaap(); + ds.updateDmaap( nd ); + + } + + @Test + public void test6() { + String t = ds.getTopicPerm(); + String t2 = ds.getTopicPerm( "val2" ); + String t3 = ds.getBridgeAdminFqtn(); + + boolean b = ds.testCreateMmaTopic(); + + } + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/Dr_PubServiceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/Dr_PubServiceTest.java new file mode 100644 index 0000000..2cfe475 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/Dr_PubServiceTest.java @@ -0,0 +1,108 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.service; + +import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import java.util.List; +import java.util.ArrayList; + +public class Dr_PubServiceTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + DR_PubService ns; + FeedService fs; + + @Before + public void setUp() throws Exception { + ns = new DR_PubService(); + fs = new FeedService(); + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.service.DR_PubService", "get", null ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.service.DR_PubService", "set", v ); + + } + + @Test + public void test3() { + String locname = "central-demo"; + + DcaeLocationService dls = new DcaeLocationService(); + DcaeLocation loc = new DcaeLocation( "CLLI1234", "central-onap", locname, "aZone", "10.10.10.0/24" ); + dls.addDcaeLocation( loc ); + + ApiError err = new ApiError(); + Feed f = new Feed( "aTest", "1.0", "a unit test", "dgl", "unrestricted" ); + f = fs.addFeed( f, err ); + + assertTrue( f != null ); + DR_Pub node = new DR_Pub( locname, "aUser", "aPwd", f.getFeedId(), "pubId01" ); + DR_Pub n2 = ns.addDr_Pub( node ); + DR_Pub node2 = new DR_Pub( locname, "aUser", "aPwd", f.getFeedId() ); + n2 = ns.addDr_Pub( node2 ); + + if ( n2 != null ) { + n2 = ns.getDr_Pub( n2.getPubId(), err ); + } + + List<DR_Pub> l = ns.getAllDr_Pubs(); + if ( n2 != null ) { + n2 = ns.updateDr_Pub( n2 ); + } + + n2 = ns.removeDr_Pub( n2.getPubId(), err ); + + + } + + @Test + public void test4() { + ArrayList<DR_Pub> l = ns.getDr_PubsByFeedId( "1" ); + + + } + + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/FeedServiceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/FeedServiceTest.java new file mode 100644 index 0000000..478647b --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/FeedServiceTest.java @@ -0,0 +1,102 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.service; + +import java.util.List; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.Feed; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +public class FeedServiceTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + FeedService ds; + + @Before + public void setUp() throws Exception { + ds = new FeedService(); + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.service.FeedService", "get", null ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.service.FeedService", "set", v ); + + } + + @Test + public void test3() { + ApiError err = new ApiError(); + + Feed f = new Feed( "aTest", "1.0", "a unit test", "dgl", "unrestricted" ); + f = ds.addFeed( f, err ); + System.out.println( "f=" + f ); + + ds.updateFeed( f, err ); + + ds.removeFeed( f, err ); + } + + @Test + public void test4() { + ApiError err = new ApiError(); + Feed f = ds.getFeed( "aName", err ); + + f = ds.getFeedByName( "aName", "1.0", err ); + + f = ds.getFeedPure( "aName", err ); + } + + @Test + public void test5() { + List<Feed> f = ds.getAllFeeds( "aName", "1.0", "startsWith" ); + + } + + + @Test + public void syncTestHard() { + ApiError err = new ApiError(); + ds.sync( true, err ); + + assert( 200 == err.getCode()); + } + + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/MR_ClientServiceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/MR_ClientServiceTest.java new file mode 100644 index 0000000..e80697a --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/MR_ClientServiceTest.java @@ -0,0 +1,135 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.service; + +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.DcaeLocation; +import org.onap.dmaap.dbcapi.model.MR_Client; +import org.onap.dmaap.dbcapi.model.MR_Cluster; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +public class MR_ClientServiceTest { + + private static final String fmt = "%24s: %s%n"; + + private static DmaapObjectFactory factory = new DmaapObjectFactory(); + + ReflectionHarness rh = new ReflectionHarness(); + + private TopicService ts; + private MR_ClusterService mcs; + private MR_ClientService cls; + private DcaeLocationService dls; + + private String f; + private String locname; + + @Before + public void setUp() throws Exception { + ts = new TopicService(); + mcs = new MR_ClusterService(); + cls = new MR_ClientService(); + f = "mrsn01.onap.org"; + locname = "central-demo"; + + dls = new DcaeLocationService(); + DcaeLocation loc = factory.genDcaeLocation( "central" ); + dls.addDcaeLocation( loc ); + + ApiError err = new ApiError(); + String[] h = { "zplvm009.onap.org", "zplvm007.onap.org", "zplvm008.onap.org" }; + MR_Cluster node = factory.genMR_Cluster( "central" ); + MR_Cluster n2 = mcs.addMr_Cluster( node, err ); + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.service.MR_ClientService", "get", null ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.service.MR_ClientService", "set", v ); + + } + + @Test + public void test3() { + Topic topic = factory.genSimpleTopic( "test3" ); + ApiError err = new ApiError(); + Topic nTopic = ts.addTopic( topic, err, false ); + if ( nTopic != null ) { + assertTrue( nTopic.getTopicName().equals( topic.getTopicName() )); + } + + MR_Client c = factory.genPublisher( "edge", topic.getFqtn() ); + + c = cls.addMr_Client( c, topic, err ); + + } + + @Test + public void test4() { + List<MR_Client> l = cls.getAllMr_Clients(); + + List<MR_Client> al = cls.getAllMrClients( "foo" ); + + List<MR_Client> al2 = cls.getClientsByLocation( "central" ); + } + + @Test + public void AddSubscriberToTopic() { + Topic topic = factory.genSimpleTopic( "test5" ); + ApiError err = new ApiError(); + Topic nTopic = ts.addTopic( topic, err, false ); + if ( nTopic != null ) { + assertTrue( nTopic.getTopicName().equals( topic.getTopicName() )); + } + MR_Client c = factory.genPublisher( "central", topic.getFqtn() ); + + c = cls.addMr_Client( c, topic, err ); + assertTrue( c != null ); + + c = factory.genSubscriber( "central", topic.getFqtn() ); + c = cls.addMr_Client( c, topic, err ); + assertTrue( err.getCode() == 200 ); + + + } + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/MR_ClusterServiceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/MR_ClusterServiceTest.java new file mode 100644 index 0000000..8ae2667 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/MR_ClusterServiceTest.java @@ -0,0 +1,127 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.service; + +import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import java.util.List; + +public class MR_ClusterServiceTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + MR_ClusterService ns; + + @Before + public void setUp() throws Exception { + ns = new MR_ClusterService(); + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.service.MR_ClusterService", "get", null ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.service.MR_ClusterService", "set", v ); + + } + + @Test + public void test3() { + String f = "mrsn01.onap.org"; + String locname = "central-demo"; + + DcaeLocationService dls = new DcaeLocationService(); + DcaeLocation loc = new DcaeLocation( "CLLI1234", "some-onap", locname, "aZone", "10.10.10.0/24" ); + dls.addDcaeLocation( loc ); + + ApiError err = new ApiError(); + String[] h = { "zplvm009.onap.org", "zplvm007.onap.org", "zplvm008.onap.org" }; + MR_Cluster node = new MR_Cluster( locname, f, "http", "3904"); + MR_Cluster n2 = ns.addMr_Cluster( node, err ); + + if ( n2 != null ) { + n2 = ns.getMr_Cluster( f, err ); + } + + List<MR_Cluster> l = ns.getAllMr_Clusters(); + if ( n2 != null ) { + n2 = ns.updateMr_Cluster( n2, err ); + } + + n2 = ns.removeMr_Cluster( f, err ); + + + } + +/* + @Test + public void test4() { + List<MR_Client> l = cls.getAllMr_Clients(); + + ArrayList<MR_Client> al = cls.getAllMrClients( "foo" ); + + ArrayList<MR_Client> al2 = cls.getClientsByLocation( "central" ); + } + + @Test + public void test5() { + Topic topic = new Topic(); + ApiError err = new ApiError(); + topic.setTopicName( "test3" ); + topic.setFqtnStyle( FqtnType.Validator("none") ); + topic.getFqtn(); + Topic nTopic = ts.addTopic( topic, err ); + if ( nTopic != null ) { + assertTrue( nTopic.getTopicName().equals( topic.getTopicName() )); + } + String[] actions = { "pub", "view" }; + MR_Client c = new MR_Client( "central-onap", "org.onap.dmaap.demo.interestingTopic2", "org.onap.clientApp.publisher", actions ); + + c = cls.addMr_Client( c, topic, err ); + if ( c != null ) { + actions[0] = "sub"; + c.setAction( actions ); + c = cls.updateMr_Client( c, err ); + assertTrue( err.getCode() == 200 ); + } + } +*/ + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/MirrorMakerServiceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/MirrorMakerServiceTest.java new file mode 100644 index 0000000..f247bad --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/MirrorMakerServiceTest.java @@ -0,0 +1,185 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.service; + +import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.testframework.DmaapObjectFactory; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import java.util.List; +import java.util.ArrayList; + +public class MirrorMakerServiceTest { + + private static final String fmt = "%24s: %s%n"; + private static DmaapObjectFactory factory = new DmaapObjectFactory(); + ReflectionHarness rh = new ReflectionHarness(); + + private MirrorMakerService mms; + private TopicService ts; + private MR_ClusterService mcs; + private MR_ClientService cls; + private DcaeLocationService dls; + + private Topic replicationTopic; + + + DmaapService ds; + String locname; + + @Before + public void setUp() throws Exception { + mms = new MirrorMakerService(); + ts = new TopicService(); + assert( ts != null ); + mcs = new MR_ClusterService(); + assert( mcs != null ); + Dmaap nd = factory.genDmaap(); + ds = new DmaapService(); + ds.addDmaap( nd ); + ts = new TopicService(); + mcs = new MR_ClusterService(); + cls = new MR_ClientService(); + + dls = new DcaeLocationService(); + DcaeLocation loc = factory.genDcaeLocation( "central" ); + locname = loc.getDcaeLocationName(); + dls.addDcaeLocation( loc ); + loc = factory.genDcaeLocation( "edge"); + dls.addDcaeLocation( loc ); + + ApiError err = new ApiError(); + + MR_Cluster node = factory.genMR_Cluster( "central" ); + mcs.addMr_Cluster( node, err); + node = factory.genMR_Cluster("edge" ); + mcs.addMr_Cluster(node, err); + + + String t = "org.onap.dmaap.bridgingTopic"; + replicationTopic = factory.genSimpleTopic(t); + replicationTopic.setReplicationCase( ReplicationType.REPLICATION_EDGE_TO_CENTRAL ); + + String c = "publisher"; + String[] a = { "sub", "view" }; + MR_Client sub = factory.genMR_Client("central", replicationTopic.getFqtn(), c, a ); + String[] b = { "pub", "view" }; + MR_Client pub = factory.genMR_Client( "edge", replicationTopic.getFqtn(), c, b ); + ArrayList<MR_Client> clients = new ArrayList<MR_Client>(); + + clients.add( sub ); + clients.add( pub ); + + replicationTopic.setClients( clients ); + + } + + @After + public void tearDown() throws Exception { + } + + +// @Test +// public void test_getters() { +// +// +// rh.reflect( "org.onap.dmaap.dbcapi.service.MirrorMakerService", "get", null ); +// +// } + + @Test + public void test_setters() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.service.MirrorMakerService", "set", v ); + + } + + + + @Test + public void CreateMirrorMakerWithSingleTopic() { + ApiError err = new ApiError(); + + + Topic nTopic = ts.addTopic(replicationTopic, err, true ); + + assertTrue( err.getCode() == 200 ); + + List<String> mma = mms.getAllMirrorMakers(); + } + + @Test + public void DeleteMirrorMakerWithSingleTopic() { + + ApiError err = new ApiError(); + Topic nTopic = ts.addTopic(replicationTopic, err, true ); + replicationTopic.setTopicDescription("modified topic"); + nTopic = ts.updateTopic( replicationTopic, err ); + + assertTrue( err.getCode() == 200 ); + + + List<String> mma = mms.getAllMirrorMakers(); + + int nMM = mma.size(); + assertTrue( nMM >= 1); + + String name = mma.get(0); + + MirrorMaker mm = mms.getMirrorMaker(name); + + mms.delMirrorMaker(mm); + + mma = mms.getAllMirrorMakers(); + + assertTrue( mma.size() == (nMM-1) ); + } + + @Test + public void SplitMirrorMakerWithSingleTopic() { + + ApiError err = new ApiError(); + + + Topic nTopic = ts.addTopic( replicationTopic, err, true ); + replicationTopic.setTopicDescription("modified topic"); + nTopic = ts.updateTopic( replicationTopic, err ); + + + assertTrue( err.getCode() == 200 ); + List<String> mma = mms.getAllMirrorMakers(); + + int nMM = mma.size(); + assertTrue( nMM >= 1); + + String name = mma.get(0); + + MirrorMaker mm = mms.getMirrorMaker(name); + + MirrorMaker mm2 = mms.splitMM(mm); + + } + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/MirrorMakerServiceTestMockito.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/MirrorMakerServiceTestMockito.java new file mode 100644 index 0000000..5beadc6 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/MirrorMakerServiceTestMockito.java @@ -0,0 +1,97 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 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.service; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.verifyZeroInteractions; + +import java.io.PrintWriter; +import java.io.StringWriter; +import javax.servlet.FilterChain; +import javax.servlet.FilterConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.aaf.cadi.filter.CadiFilter; +import org.onap.dmaap.dbcapi.model.MirrorMaker; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +@RunWith(MockitoJUnitRunner.class) +public class MirrorMakerServiceTestMockito { + + @Spy + private MirrorMakerService service; + + @Mock + private CadiFilter cadiFilterMock; + @Mock + private HttpServletRequest servletRequest; + @Mock + private HttpServletResponse servletResponse; + + @Mock + private DmaapConfig dmaapConfig; + + @Mock + private MirrorMaker mm = new MirrorMaker(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Before + public void setUp() throws Exception { + + } + + @Test + public void init_normalConstructor() throws Exception { + //given + + + //when + + + //then + assertEquals( MirrorMakerService.getProvUserPwd(), MirrorMakerService.PROV_PWD_DEFAULT); + assertEquals( MirrorMakerService.getDefaultConsumerPort(), MirrorMakerService.TARGET_REPLICATION_PORT_DEFAULT); + assertEquals( MirrorMakerService.getDefaultProducerPort(), MirrorMakerService.SOURCE_REPLICATION_PORT_DEFAULT); + } + + // Todo: learn how to make more tests in Mockito + + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/TopicServiceTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/TopicServiceTest.java new file mode 100644 index 0000000..a37ce02 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/service/TopicServiceTest.java @@ -0,0 +1,305 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.service; + +import com.google.common.collect.ImmutableMap; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Matcher; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.dmaap.dbcapi.model.ApiError; +import org.onap.dmaap.dbcapi.model.MR_Client; +import org.onap.dmaap.dbcapi.model.Topic; +import org.onap.dmaap.dbcapi.util.DmaapConfig; + +import javax.ws.rs.core.Response; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static com.google.common.collect.Iterables.getOnlyElement; +import static com.google.common.collect.Lists.newArrayList; +import static javax.ws.rs.core.Response.Status.NOT_FOUND; +import static javax.ws.rs.core.Response.Status.OK; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.then; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.onap.dmaap.dbcapi.model.ReplicationType.REPLICATION_GLOBAL_TO_FQDN; + +@RunWith(MockitoJUnitRunner.class) +public class TopicServiceTest { + + private static final String TOPIC_FQTN = "topic_1"; + private static final String GLOBAL_MR_HOST = "global.mr.host"; + private TopicService topicService; + @Mock + private MR_ClientService clientService; + @Mock + private DmaapConfig dmaapConfig; + @Mock + private MR_ClusterService clusters; + @Mock + private DcaeLocationService locations; + @Mock + private MirrorMakerService bridge; + @Mock + private AafTopicSetupService aafTopicSetupService; + + @Before + public void setUp() throws Exception { + given(dmaapConfig.getProperty("MR.globalHost", "global.host.not.set")).willReturn(GLOBAL_MR_HOST); + given(aafTopicSetupService.aafTopicSetup(any(Topic.class))).willReturn(new ApiError(200, "OK")); + given(aafTopicSetupService.aafTopicCleanup(any(Topic.class))).willReturn(new ApiError(200, "OK")); + createTopicService(); + } + + @Test + public void getTopics_shouldReturnTopicsReceivedDuringServiceCreation() { + + ImmutableMap<String, Topic> topics = ImmutableMap.of(TOPIC_FQTN, new Topic()); + topicService = new TopicService(topics, clientService, dmaapConfig, clusters, locations, bridge, aafTopicSetupService); + + assertEquals(topics, topicService.getTopics()); + } + + @Test + public void getAllTopics_shouldReturnTopicsWithClients() { + + ArrayList<MR_Client> mrClients = newArrayList(new MR_Client()); + given(clientService.getAllMrClients(TOPIC_FQTN)).willReturn(mrClients); + + List<Topic> allTopics = topicService.getAllTopics(); + + assertThat(getOnlyElement(allTopics), hasCorrectFqtn(TOPIC_FQTN)); + assertEquals(mrClients, getOnlyElement(allTopics).getClients()); + } + + @Test + public void getAllTopicsWithoutClients_shouldReturnNoClients() { + + List<Topic> allTopics = topicService.getAllTopicsWithoutClients(); + + assertThat(getOnlyElement(allTopics), hasCorrectFqtn(TOPIC_FQTN)); + assertNull(getOnlyElement(allTopics).getClients()); + verifyZeroInteractions(clientService); + } + + @Test + public void getAllTopics_shouldCacheClients() { + + ArrayList<MR_Client> mrClients = newArrayList(new MR_Client()); + given(clientService.getAllMrClients(TOPIC_FQTN)).willReturn(mrClients); + + topicService.getAllTopics(); + List<Topic> allTopics = topicService.getAllTopicsWithoutClients(); + + assertThat(getOnlyElement(allTopics), hasCorrectFqtn(TOPIC_FQTN)); + assertEquals(mrClients, getOnlyElement(allTopics).getClients()); + } + + @Test + public void getTopic_shouldReturnTopicByFqtn() { + + ApiError apiError = new ApiError(); + Topic topic = topicService.getTopic(TOPIC_FQTN, apiError); + + assertThat(topic, hasCorrectFqtn(TOPIC_FQTN)); + assertEquals(OK.getStatusCode(), apiError.getCode()); + } + + @Test + public void getTopic_shouldReturnTopicWithMrClients() { + + ArrayList<MR_Client> mrClients = newArrayList(new MR_Client()); + given(clientService.getAllMrClients(TOPIC_FQTN)).willReturn(mrClients); + + Topic topic = topicService.getTopic(TOPIC_FQTN, new ApiError()); + + assertThat(topic, hasCorrectFqtn(TOPIC_FQTN)); + assertEquals(mrClients, topic.getClients()); + } + + @Test + public void getTopic_shouldReturnError() { + + ApiError apiError = new ApiError(); + Topic topic = topicService.getTopic("not_existing", apiError); + + assertNull(topic); + assertEquals(NOT_FOUND.getStatusCode(), apiError.getCode()); + } + + @Test + public void addTopic_shouldAddNewTopic() { + Topic newTopic = createTopic(""); + + ApiError apiError = new ApiError(); + Topic addedTopic = topicService.addTopic(newTopic, apiError, true); + + assertSame(newTopic, addedTopic); + assertEquals(OK.getStatusCode(), apiError.getCode()); + assertNotNull(topicService.getTopic(addedTopic.getFqtn(), new ApiError())); + } + + @Test + public void addTopic_shouldReturnErrorWhenTopicAlreadyExists() { + Topic newTopic = createTopic(""); + + ApiError apiError = new ApiError(); + Topic addedTopic = topicService.addTopic(newTopic, apiError, false); + Topic secondAddedTopic = topicService.addTopic(addedTopic, apiError, false); + + assertNull(secondAddedTopic); + assertEquals(Response.Status.CONFLICT.getStatusCode(), apiError.getCode()); + } + + @Test + public void addTopic_shouldAddTheSameTopicWhenUseExistingIsSet() { + Topic newTopic = createTopic(""); + + ApiError apiError = new ApiError(); + Topic addedTopic = topicService.addTopic(newTopic, apiError, false); + Topic secondAddedTopic = topicService.addTopic(addedTopic, apiError, true); + + assertSame(addedTopic, secondAddedTopic); + assertEquals(OK.getStatusCode(), apiError.getCode()); + assertNotNull(topicService.getTopic(secondAddedTopic.getFqtn(), new ApiError())); + } + + + @Test + public void addTopic_shouldSetGlobalMrURL() { + Topic newTopic = createTopic(TOPIC_FQTN); + newTopic.setReplicationCase(REPLICATION_GLOBAL_TO_FQDN); + + ApiError apiError = new ApiError(); + Topic addedTopic = topicService.addTopic(newTopic, apiError, true); + + assertEquals(OK.getStatusCode(), apiError.getCode()); + assertEquals(GLOBAL_MR_HOST, addedTopic.getGlobalMrURL()); + } + + @Test + public void addTopic_shouldReturnErrorWhenGlobalMrURLIsInvalid() { + given(dmaapConfig.getProperty("MR.globalHost", "global.host.not.set")).willReturn("invalid@host"); + createTopicService(); + Topic newTopic = createTopic(TOPIC_FQTN); + newTopic.setReplicationCase(REPLICATION_GLOBAL_TO_FQDN); + + ApiError apiError = new ApiError(); + Topic addedTopic = topicService.addTopic(newTopic, apiError, true); + + assertEquals(500, apiError.getCode()); + assertNull(addedTopic); + } + + @Test + public void removeTopic_shouldFailIfTopicDoesNotExist() { + ApiError apiError = new ApiError(); + + Topic removedTopic = topicService.removeTopic("not_existing_fqtn", apiError); + + assertNull(removedTopic); + assertEquals(NOT_FOUND.getStatusCode(), apiError.getCode()); + assertTrue(topicService.getTopics().containsKey(TOPIC_FQTN)); + } + + @Test + public void removeTopic_shouldExecuteAafCleanup() { + ApiError apiError = new ApiError(); + + Topic removedTopic = topicService.removeTopic(TOPIC_FQTN, apiError); + + then(aafTopicSetupService).should().aafTopicCleanup(removedTopic); + assertEquals(OK.getStatusCode(), apiError.getCode()); + } + + @Test + public void removeTopic_shouldRemoveEachMrClientAssignedToTopic() { + ApiError apiError = new ApiError(); + MR_Client mrClient = new MR_Client(); + mrClient.setMrClientId("mrClientId"); + + given(clientService.getAllMrClients(TOPIC_FQTN)).willReturn(newArrayList(mrClient)); + + topicService.removeTopic(TOPIC_FQTN, apiError); + + then(clientService).should().removeMr_Client(mrClient.getMrClientId(), false, apiError); + assertEquals(OK.getStatusCode(), apiError.getCode()); + } + + @Test + public void removeTopic_shouldRemoveTopicFromCache() { + ApiError apiError = new ApiError(); + + topicService.removeTopic(TOPIC_FQTN, apiError); + + assertTrue(topicService.getTopics().isEmpty()); + assertEquals(OK.getStatusCode(), apiError.getCode()); + } + + @Test + public void removeTopic_shouldFailIfAafCleanupWasFailed() { + ApiError apiError = new ApiError(); + given(aafTopicSetupService.aafTopicCleanup(any(Topic.class))).willReturn(new ApiError(404, "sth went wrong")); + + Topic removedTopic = topicService.removeTopic(TOPIC_FQTN, apiError); + + assertNull(removedTopic); + assertEquals(404, apiError.getCode()); + assertTrue(topicService.getTopics().containsKey(TOPIC_FQTN)); + } + + private void createTopicService() { + Map<String, Topic> mrTopics = new HashMap<>(); + mrTopics.put(TOPIC_FQTN, createTopic(TOPIC_FQTN)); + topicService = new TopicService(mrTopics, clientService, dmaapConfig, clusters, locations, bridge, aafTopicSetupService); + } + + private Topic createTopic(String fqtn) { + return new Topic(fqtn, "name", "desc", "tnxEnabled", "owner"); + } + + public static Matcher<Topic> hasCorrectFqtn(final String fqtn) { + return new BaseMatcher<Topic>() { + public boolean matches(Object o) { + return fqtn.equals(((Topic) o).getFqtn()); + } + + public void describeTo(Description description) { + description.appendText("Topics should should be equal. Expected fqtn: ").appendValue(fqtn); + } + }; + } + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/testframework/DmaapObjectFactory.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/testframework/DmaapObjectFactory.java new file mode 100644 index 0000000..9d45a54 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/testframework/DmaapObjectFactory.java @@ -0,0 +1,128 @@ +/* + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.testframework; + +import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.util.RandomInteger; + +public class DmaapObjectFactory { + + /* + * we use localhost for most references so that connection attempts will resolve and not retry + * but still we expect that requests will fail. + */ + private static final String fmt = "%24s: %s%n"; + private static final String dmaap_name = "onap-ut"; + private static final String dmaap_ver = "1"; + private static final String dmaap_topic_root = "org.onap.dmaap"; + private static final String dmaap_dr = "https://localhost:8443"; + private static final String dmaap_log_url = "http://localhost:8080/log"; + private static final String dmaap_mm_topic = "org.onap.dmaap.dcae.MM_AGENT_TOPIC"; + private static final String central_loc = "SanFrancisco"; + private static final String central_layer = "central-cloud"; + private static final String central_clli = "SFCAL19240"; + private static final String central_zone = "osaz01"; + private static final String central_subnet = "10.10.10.0/24"; + private static final String central_cluster_fqdn = "localhost"; + private static final String pub_role = "org.onap.vnfapp.publisher"; + private static final String sub_role = "org.onap.vnfapp.subscriber"; + private static final String edge_loc = "Atlanta"; + private static final String edge_layer = "edge-cloud"; + private static final String edge_clli = "ATLGA10245"; + private static final String edge_zone = "osaz02"; + private static final String edge_subnet = "10.10.20.0/24"; + private static final String edge_cluster_fqdn = "localhost"; + private static final String[]hosts = { "host1", "host2", "host3" }; + private static final String port = "3904"; + private static final String prot = "http"; + + public Dmaap genDmaap() { + return new Dmaap.DmaapBuilder().setVer(dmaap_ver).setTnr(dmaap_topic_root).setDn(dmaap_name).setDpu(dmaap_dr).setLu(dmaap_log_url).setBat(dmaap_mm_topic).setNk("nk").setAko("ako").createDmaap(); + } + + public DcaeLocation genDcaeLocation( String layer ) { + if ( layer.contains( "edge" ) ) { + return new DcaeLocation( edge_clli, edge_layer, edge_loc, edge_zone, edge_subnet ); + } + return new DcaeLocation( central_clli, central_layer, central_loc, central_zone, central_subnet ); + } + + + public MR_Cluster genMR_Cluster( String layer ) { + if ( layer.contains( "edge" ) ) { + return new MR_Cluster( edge_loc, edge_cluster_fqdn, prot, port ); + } + return new MR_Cluster( central_loc, central_cluster_fqdn, prot, port ); + } + + public Topic genSimpleTopic( String tname ) { + Topic t = new Topic(); + t.setTopicName( tname ); + t.setFqtnStyle( FqtnType.Validator("none") ); + t.setTopicDescription( "a simple Topic named " + tname ); + t.setOwner( "ut"); + t.setFqtn(t.genFqtn()); + return t; + } + + public MR_Client genMR_Client( String l, String f, String r, String[] a ) { + if ( l.contains( "edge" ) ) { + return new MR_Client( edge_loc, f, r, a ); + } + return new MR_Client( central_loc, f, r, a ); + } + + public MR_Client genPublisher( String layer, String fqtn ) { + String[] actions = { "pub", "view" }; + return genMR_Client( layer, fqtn, pub_role, actions ); + } + public MR_Client genSubscriber( String layer, String fqtn ) { + String[] actions = { "sub", "view" }; + return genMR_Client( layer, fqtn, sub_role, actions ); + } + + public DR_Sub genDrSub( String l, String feed ) { + String un = "user1"; + String up = "secretW0rd"; + String du = "sub.server.onap.org:8443/deliver/here"; + String lu = "https://drps.onap.org:8443/sublog/123"; + boolean u100 = true; + + if ( l.contains( "edge" ) ) { + return new DR_Sub( edge_loc, un, up, feed, du, lu, u100 ); + } + return new DR_Sub( central_loc, un, up, feed, du, lu, u100 ); + } + + public DR_Node genDR_Node( String l ) { + String version = "1.0.1"; + RandomInteger ri = new RandomInteger( 1000 ); + int i = ri.next(); + String fqdn = String.format( "drns%d.onap.org", i ); + String host = String.format( "host%d.onap.org", i ); + + if ( l.contains( "edge" ) ) { + return new DR_Node( fqdn, edge_loc, host, version ); + } + return new DR_Node( fqdn, central_loc, host, version ); + } + + +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/testframework/ReflectionHarness.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/testframework/ReflectionHarness.java new file mode 100644 index 0000000..be4b754 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/testframework/ReflectionHarness.java @@ -0,0 +1,169 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.testframework; + +import static java.lang.System.err; +import static java.lang.System.out; +import static org.junit.Assert.assertTrue; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; + +public class ReflectionHarness { + private static final String fmt = "%24s: %s%n"; + + + // following 2 functions taken from: http://tutorials.jenkov.com/java-reflection/getters-setters.html + public static boolean isGetter(Method method){ + if(!method.getName().startsWith("get")) return false; + if(method.getParameterTypes().length != 0) return false; + if(void.class.equals(method.getReturnType())) return false; + return true; + } + + public static boolean isSetter(Method method){ + if(!method.getName().startsWith("set")) return false; + if(method.getParameterTypes().length != 1) return false; + return true; + } + + private void testGetter( Class<?> c, Method m, Class<?>[] pType, String val ) { + out.format( fmt, "testGetter: Method Name", m.getName() ); + Class retType = m.getReturnType(); + out.format( fmt, "testGetter: Return Type ", retType ); + out.format( fmt, "testGetter: val ", (val != null)?val:"null" ); + assertTrue( pType.length == 0 ); + + try { + Object t = c.newInstance(); + + try { + m.setAccessible(true); + Object o = m.invoke( t ); + + if( retType.equals( Class.forName( "java.lang.String" ) ) ) { + if ( val == null ) { + out.format( fmt, "testGetter: expected null, got ", (o != null)?o:"null" ); + assert( o == null ); + } else { + out.format( fmt, "testGetter: expected val, got ", (o != null)?o:"null" ); + assert( o.equals( val ) ); + } + } else { + out.format( fmt, "testGetter: " + m.getName() + " untested retType", retType ); + + } + + } catch (InvocationTargetException e ) { + Throwable cause = e.getCause(); + err.format( "%s() returned %x%n", m.getName(), cause.getMessage() ); + } + + } catch (ClassNotFoundException nfe ){ + nfe.printStackTrace(); + } catch (IllegalArgumentException ae ) { + ae.printStackTrace(); + } catch (InstantiationException ie ) { + ie.printStackTrace(); + } catch (IllegalAccessException iae ) { + iae.printStackTrace(); + } + } + + private void testSetter( Class<?> c, Method m, Class<?>[] pType ) { + //out.format( fmt, "testSetter: Method Name", m.getName() ); + Class retType = m.getReturnType(); + //out.format( fmt, "testSetter: Return Type ", retType ); + //out.format( fmt, "testSetter: val ", (val != null)?val:"null" ); + assertTrue( pType.length == 1 ); + + try { + Object t = c.newInstance(); + + try { + m.setAccessible(true); + //out.format( fmt, "testSetter: " + m.getName() + " to try pType", pType[0] ); + if ( pType[0].equals( Class.forName( "java.lang.String" ) ) ) { + String val = "Validate123"; + Object o = m.invoke( t, val ); + } else if ( pType[0].equals( boolean.class ) ) { // note primitive class notation + boolean b = true; + Object o = m.invoke( t, b ); + } else { + out.format( fmt, "testSetter: " + m.getName() + " untested pType", pType[0] ); + } + + } catch (InvocationTargetException e ) { + Throwable cause = e.getCause(); + err.format( "%s() returned %x%n", m.getName(), cause.getMessage() ); + } + + } catch (ClassNotFoundException nfe ){ + nfe.printStackTrace(); + } catch (IllegalArgumentException ae ) { + ae.printStackTrace(); + } catch (InstantiationException ie ) { + ie.printStackTrace(); + } catch (IllegalAccessException iae ) { + iae.printStackTrace(); + } + } + + public void reflect(String... args) { + try { + Class<?> c = Class.forName(args[0]); + Method[] allMethods = c.getDeclaredMethods(); + String methodPrefix = args[1]; + for (Method m : allMethods) { + if (!m.getName().startsWith(methodPrefix)) { + continue; + } + //out.format("%s%n", m.toGenericString()); + + //out.format(fmt, "ReturnType", m.getReturnType()); + //out.format(fmt, "GenericReturnType", m.getGenericReturnType()); + + Class<?>[] pType = m.getParameterTypes(); + Type[] gpType = m.getGenericParameterTypes(); + for (int i = 0; i < pType.length; i++) { + //out.format(fmt,"ParameterType", pType[i]); + //out.format(fmt,"GenericParameterType", gpType[i]); + } + if ( isGetter( m ) ) { + testGetter( c, m, pType , args[2]); + } else if ( isSetter( m ) ) { + testSetter( c, m, pType ); + } + + Class<?>[] xType = m.getExceptionTypes(); + Type[] gxType = m.getGenericExceptionTypes(); + for (int i = 0; i < xType.length; i++) { + //out.format(fmt,"ExceptionType", xType[i]); + //out.format(fmt,"GenericExceptionType", gxType[i]); + } + } + + // production code should handle these exceptions more gracefully + } catch (ClassNotFoundException x) { + x.printStackTrace(); + } + } +} diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/DmaapConfigTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/DmaapConfigTest.java new file mode 100644 index 0000000..6ef05c0 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/DmaapConfigTest.java @@ -0,0 +1,72 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.util; + +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class DmaapConfigTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + DmaapConfig g; + + + @Before + public void setUp() throws Exception { + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.util.DmaapConfig", "get", "" ); + + } + + @Test + public void test2() { + String v = "Validate"; + rh.reflect( "org.onap.dmaap.dbcapi.util.DmaapConfig", "set", v ); + + } + + @Test + public void test3() { + + String f = g.getConfigFileName(); + } + + + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/DmaapTimestampTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/DmaapTimestampTest.java new file mode 100644 index 0000000..33d1d17 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/DmaapTimestampTest.java @@ -0,0 +1,42 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.util; + +import org.junit.Test; + +import java.util.Date; + +import static org.junit.Assert.assertTrue; + +public class DmaapTimestampTest { + + private DmaapTimestamp dmaapTimestamp = new DmaapTimestamp(); + + @Test + public void mark_shouldUpdateTimestamp() { + dmaapTimestamp = new DmaapTimestamp(new Date(10)); + Date timestamp = dmaapTimestamp.getVal(); + + dmaapTimestamp.mark(); + + assertTrue(timestamp.before(dmaapTimestamp.getVal())); + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/FqdnTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/FqdnTest.java new file mode 100644 index 0000000..7c7815f --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/FqdnTest.java @@ -0,0 +1,33 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 IBM 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.util; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class FqdnTest { + + @Test + public void testIsValid() { + assertTrue(Fqdn.isValid("www.ibm.com")); + assertFalse(Fqdn.isValid("testuser@ibm.com")); + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/GraphTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/GraphTest.java new file mode 100644 index 0000000..770ee65 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/GraphTest.java @@ -0,0 +1,102 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2018 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.util; + +import org.onap.dmaap.dbcapi.model.*; +import org.onap.dmaap.dbcapi.service.*; +import org.onap.dmaap.dbcapi.testframework.ReflectionHarness; + +import static org.junit.Assert.*; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import java.util.*; + +public class GraphTest { + + private static final String fmt = "%24s: %s%n"; + + ReflectionHarness rh = new ReflectionHarness(); + + Graph g; + + + @Before + public void setUp() throws Exception { + HashMap<String, String> hm = new HashMap<String,String>(); + g = new Graph( hm ); + } + + @After + public void tearDown() throws Exception { + } + + + @Test + public void test1() { + + + rh.reflect( "org.onap.dmaap.dbcapi.util.Graph", "get", "idNotSet@namespaceNotSet:pwdNotSet" ); + + } + + @Test + public void test2() { + String v = "Validate"; + //rh.reflect( "org.onap.dmaap.dbcapi.util.Graph", "set", v ); + + } + + @Test + public void test3() { + String loc = "central-onap"; + String[] actions = { "pub", "sub" }; + DcaeLocationService dls = new DcaeLocationService(); + DcaeLocation dl = new DcaeLocation( "CLLI123", "central-layer", loc, "aZone", "10.10.10.10" ); + dls.addDcaeLocation( dl ); + MR_Client mrc = new MR_Client(); + mrc.setAction( actions ); + List<MR_Client> cl = new ArrayList<MR_Client>(); + cl.add( mrc ); + cl.add( new MR_Client( loc, "aTopic", "ignore", actions ) ); + + g = new Graph( cl, true ); + + HashMap<String, String> hm = new HashMap<String, String>(); + + + String s = g.put( "aKey", "aVal" ); + s = g.get( "aKey" ); + + s = g.getCentralLoc(); + g.setHasCentral( true ); + g.hasCentral(); + + hm = g.getGraph(); + + Collection<String> k = g.getKeys(); + + } + + + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/PermissionBuilderTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/PermissionBuilderTest.java new file mode 100644 index 0000000..8db9d2e --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/PermissionBuilderTest.java @@ -0,0 +1,164 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.util; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.atMost; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import javax.servlet.http.HttpServletRequest; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.dmaap.dbcapi.model.Dmaap; +import org.onap.dmaap.dbcapi.model.DmaapObject.DmaapObject_Status; +import org.onap.dmaap.dbcapi.service.DmaapService; + +@RunWith(MockitoJUnitRunner.class) +public class PermissionBuilderTest { + + private static final String DMAAP_NAME = "mr"; + private PermissionBuilder permissionBuilder; + @Mock + private DmaapConfig dmaapConfig; + @Mock + private DmaapService dmaapService; + @Mock + private HttpServletRequest request; + + + @Test + public void updateDmaapInstance_shouldSetBootInstance_whenDmaapIsNotInitialized() { + //given + doReturn(null).when(dmaapService).getDmaap(); + permissionBuilder = new PermissionBuilder(dmaapConfig, dmaapService); + + //when + permissionBuilder.updateDmaapInstance(); + + //then + assertEquals(PermissionBuilder.BOOT_INSTANCE, permissionBuilder.getInstance()); + } + + @Test + public void updateDmaapInstance_shouldSetBootInstance_whenDmaapIsInitializedWithDefaultInstance() { + //given + doReturn(provideDefaultInstance()).when(dmaapService).getDmaap(); + permissionBuilder = new PermissionBuilder(dmaapConfig, dmaapService); + + //when + permissionBuilder.updateDmaapInstance(); + + //then + assertEquals(PermissionBuilder.BOOT_INSTANCE, permissionBuilder.getInstance()); + } + + @Test + public void updateDmaapInstance_shouldSetRealInstance_whenDmaapServiceProvidesOne() { + //given + when(dmaapService.getDmaap()).thenReturn(provideDefaultInstance(), provideRealInstance(DMAAP_NAME)); + permissionBuilder = new PermissionBuilder(dmaapConfig, dmaapService); + + //when + permissionBuilder.updateDmaapInstance(); + + //then + assertEquals(DMAAP_NAME, permissionBuilder.getInstance()); + } + + @Test + public void updateDmaapInstance_shouldNotUpdateDmaapInstance_whenAlreadyInitializedWithRealInstance() { + //given + when(dmaapService.getDmaap()).thenReturn(provideRealInstance(DMAAP_NAME), provideRealInstance("newName")); + permissionBuilder = new PermissionBuilder(dmaapConfig, dmaapService); + + //when + permissionBuilder.updateDmaapInstance(); + + //then + assertEquals(DMAAP_NAME, permissionBuilder.getInstance()); + verify(dmaapService, atMost(1)).getDmaap(); + } + + @Test + public void buildPermission_shouldBuildPermissionWithBootInstance() { + //given + String path = "/dmaap"; + String method = "GET"; + initPermissionBuilder(path, method, provideDefaultInstance()); + + //when + String permission = permissionBuilder.buildPermission(request); + + //then + assertEquals("org.onap.dmaap-bc.api.dmaap|boot|GET", permission); + } + + @Test + public void buildPermission_shouldBuildPermissionWithRealInstance() { + //given + String path = "/dmaap"; + String method = "GET"; + initPermissionBuilder(path, method, provideRealInstance(DMAAP_NAME)); + + //when + String permission = permissionBuilder.buildPermission(request); + + //then + assertEquals("org.onap.dmaap-bc.api.dmaap|mr|GET", permission); + } + + @Test + public void buildPermission_shouldBuildPermissionWhenUrlContainsId() { + //given + String path = "/topics/topic_id_123"; + String method = "GET"; + initPermissionBuilder(path, method, provideRealInstance(DMAAP_NAME)); + + //when + String permission = permissionBuilder.buildPermission(request); + + //then + assertEquals("org.onap.dmaap-bc.api.topics|mr|GET", permission); + } + + private void initPermissionBuilder(String path, String method, Dmaap dmaapInstance) { + when(dmaapConfig.getProperty(PermissionBuilder.API_NS_PROP, PermissionBuilder.DEFAULT_API_NS)) + .thenReturn(PermissionBuilder.DEFAULT_API_NS); + when(dmaapService.getDmaap()).thenReturn(dmaapInstance); + permissionBuilder = new PermissionBuilder(dmaapConfig, dmaapService); + + when(request.getPathInfo()).thenReturn(path); + when(request.getMethod()).thenReturn(method); + } + + private Dmaap provideDefaultInstance() { + return new Dmaap.DmaapBuilder().setVer("0").setTnr("").setDn("").setDpu("").setLu("").setBat("").setNk("").setAko("").createDmaap(); + } + + private Dmaap provideRealInstance(String dmaapName) { + Dmaap dmaap = new Dmaap.DmaapBuilder().setVer("1").setTnr("org.onap.dmaap").setDn(dmaapName).setDpu("https://dmaap-dr-prov:8443").setLu("").setBat("DCAE_MM_AGENT").setNk("").setAko("").createDmaap(); + dmaap.setStatus(DmaapObject_Status.VALID); + return dmaap; + } + +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/RandomIntegerTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/RandomIntegerTest.java new file mode 100644 index 0000000..1184cdb --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/RandomIntegerTest.java @@ -0,0 +1,40 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.util; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class RandomIntegerTest { + + private static final int RANGE = 10; + private RandomInteger ri = new RandomInteger(RANGE); + + @Test + public void next_shouldReturnIntegerFromGivenRange() { + + int next = ri.next(); + + assertTrue(next >= 0 && next <= RANGE); + } + +} + diff --git a/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/RandomStringTest.java b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/RandomStringTest.java new file mode 100644 index 0000000..e549dc3 --- /dev/null +++ b/dmaap-bc/src/test/java/org/onap/dmaap/dbcapi/util/RandomStringTest.java @@ -0,0 +1,60 @@ +/*- + * ============LICENSE_START======================================================= + * org.onap.dmaap + * ================================================================================ + * Copyright (C) 2019 Nokia 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.util; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +public class RandomStringTest { + + private static final int LENGTH = 10; + @Rule + public ExpectedException thrown = ExpectedException.none(); + private RandomString randomString = new RandomString(LENGTH); + + @Test + public void nextString_shouldReturnStringWithGivenLength() { + + String nextString = randomString.nextString(); + + assertEquals(LENGTH, nextString.length()); + } + + @Test + public void nextString_shouldReturnAlphanumeric() { + + String nextString = randomString.nextString(); + + assertTrue(nextString.matches("[a-z0-9]*")); + } + + @Test + public void constructor_shouldThrowExceptionForNegativeLength() { + + thrown.expect(IllegalArgumentException.class); + + new RandomString(-1); + } +}
\ No newline at end of file diff --git a/dmaap-bc/src/test/resources/cadi.properties b/dmaap-bc/src/test/resources/cadi.properties new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/dmaap-bc/src/test/resources/cadi.properties diff --git a/dmaap-bc/src/test/resources/dmaapbc.properties b/dmaap-bc/src/test/resources/dmaapbc.properties new file mode 100644 index 0000000..5290032 --- /dev/null +++ b/dmaap-bc/src/test/resources/dmaapbc.properties @@ -0,0 +1,274 @@ +# Copyright © 2018 AT&T, Amdocs, Bell Canada 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. + + +##################################################### +# +# Hooks for specific environment configurations +# +##################################################### +# Indicator for whether to use AAF for authentication +#UseAAF: false + +# Stub out southbound calls for Unit Test cases to run. e.g. not timeout +# Comment out in other environments to get default (No) +UnitTest: Yes + + +##################################################### +# +# Settings for Southbound API: Datarouter +# +##################################################### + +# URI to retrieve dynamic DR configuration +ProvisioningURI: /internal/prov + +# indicator for handling feed delete: +# DeleteOnDR - means use the DR API to DELETE a feed. (default for backwards compatibility) +# SimulateDelete - means preserve the feed on DR (after cleaning it up), and mark as DELETED in DBCL. Better for cloudify environments. +Feed.deleteHandling: DeleteOnDR + +########################################################### +# The following properties default to match ONAP DR instance. +# However, there are some non-ONAP DR instances that require other values. +# Sets the X-DR-ON-BEHALF-OF HTTP Header value +#DR.onBehalfHeader: +# Value for the Content-Type Header in DR Feed API +#DR.feedContentType: +# Value for the Content-Type Header in DR Subscription API +#DR.subContentType: +# +# END OF properties helpful for non-ONAP DR instance. +############################################################ + +##################################################### +# +# Settings for Soutbound API: Postgresql +# +##################################################### +# flag indicates if we are using postgresql +UsePGSQL: false + +# postgres host name +# Need to connect to PG primary service, designated by service.name2 +DB.host: none + +# postgres schema name +#DB.schema: {{ .Values.postgres.config.pgDatabase }} + +# postgres user name +#DB.user: {{ .Values.postgres.config.pgUserName }} + +# postgres user password +DB.cred: none + + +##################################################### +# +# Settings for Soutbound API: Message Router +# +##################################################### +# indicator for multi-site (locations) deployment. Give clue to buscontroller whether +# there is a need for message replication between edge and central. +# ONAP Casablanca is a single site deployment +MR.multisite: true + +# FQDN of primary message router. +# In ONAP Casablanca, there is only 1 message router service, so use that. +# In a multi-site, MR cluster deployment, use the CNAME DNS entry which resolves to the primary central MR +MR.CentralCname: notSet.onap.org + +# Indicator for whether we want hostname verification on SSL connection to MR +MR.hostnameVerify: false + +# MR Client Delete Level thoroughness: +# 0 = don't delete +# 1 = delete from persistent store +# 2 = delete from persistent store (DB) and authorization store (AAF) +MR.ClientDeleteLevel: 1 + +# namespace of MR Topic Factory +MR.TopicFactoryNS: org.onap.dmaap.mr.topicFactory + +# AAF Role assigned to Topic Manager Identity +MR.TopicMgrRole: org.onap.dmaap-bc.TopicMgr + +# MR topic ProjectID (used in certain topic name generation formats) +MR.projectID: 23456 + +# Use Basic Authentication when provisioning topics +#MR.authentication: basicAuth + +# MR topic name style (default is FQTN_LEGACY_FORMAT) +MR.topicStyle: FQTN_LEGACY_FORMAT +# +# end of MR Related Properties +################################################################################ + + +##################################################### +# +# Settings for Southbound API: CADI +# +##################################################### +# path to cadi.properties +#cadi.properties: /opt/app/osaaf/local/org.onap.dmaap-bc.props + +##################################################### +# +# Settings for Southbound API: AAF proxy +# +##################################################### +# URL of the AAF server +aaf.URL: https://localhost:8100/proxy + +# TopicMgr Identity +aaf.TopicMgrUser: idNotSet@namespaceNotSet + +# Password for TopicMgr identity +aaf.TopicMgrPassword: pwdNotSet + +# Buscontroller Admin Identity +aaf.AdminUser: idNotSet@namespaceNotSet + +# Admin Password +aaf.AdminPassword: pwdNotSet + +# Identity that is owner of any created namespaces for topics +#aaf.NsOwnerIdentity: ownerNotSet@namespaceNotSet.org + + +# this overrides the Class used for Decryption. +# This allows for a plugin encryption/decryption method if needed. +# Call this Class for decryption at runtime. +#AafDecryption.Class: com.company.proprietaryDecryptor + +# location of the codec keyfile used to decrypt passwords in this properties file before they are passed to AAF +# Not used in ONAP, but possibly used with Decryption override class. +CredentialCodecKeyfile: etc/LocalKey + +# +# endof AAF Properties +#################################################### + + +##################################################### +# +# Settings for authorization of DBCAPI +# +##################################################### +# Namespace for URI values for the API used to create AAF permissions +# e.g. if ApiNamespace is X.Y.dmaapbc.api then for URI /mr_clients we create AAF perm X.Y.dmaapbc.api.mr_clients +ApiNamespace: org.onap.dmaapBC.api + +# If API authorization is required, then implement a class to enforce it. +# This overrides the Class used for API permission check. +ApiPermission.Class: org.onap.dmaap.dbcapi.authentication.AllowAll + +##################################################### +# +# Settings for Southbound API: MirrorMaker provisioning +# +##################################################### +# AAF Role of client publishing MM prov cmds +MM.ProvRole: org.onap.dmaapBC.MMprov.prov + +# AAF identity when publishing MM prov cmds +MM.ProvUserMechId: idNotSet@namespaceNotSet + +# pwd for Identity used to publish MM prov cmds +MM.ProvUserPwd: pwdNotSet + +# AAF Role of MirrorMaker agent subscribed to prov cmds. +MM.AgentRole: org.onap.dmaapBC.MMagent.agent + +##################################################### +# +# Certificate Management +# +##################################################### + +# Indicates how we are expecting certificates to be provided: +# cadi - a set of artifacts will be downloaded from AAF at deployment time, and details will be in a cadi properties file +# legacy (default) - artifacts will be installed manually or some other way and details will be in this file +CertificateManagement: legacy + +# When CertificateManagement is cadi, then this is where all the cadi properties will be. +# Note that the cadi properties include where the cert is, and the encrypted passwords to read. +cadi.properties: /opt/app/osaaf/local/org.onap.dmaap-bc.props + +########################################################################################### +# When CertificateManagement is legacy, we need to provide more details about cert handling: +#CertificateManagement: legacy +# the type of keystore for https (for legacy CertificateManagment only) +KeyStoreType: jks + +# path to the keystore file (for legacy CertificateManagment only) +KeyStoreFile: etc/keystore + +# password for the https keystore (for legacy CertificateManagment only) +KeyStorePassword: changeit +# password for the private key in the https keystore (for legacy CertificateManagment only) +KeyPassword: changeit + +# type of truststore for https (for legacy CertificateManagment only) +TrustStoreType: jks + +# path to the truststore for https (for legacy CertificateManagment only) +TrustStoreFile: ${DMAAPBC_TSTOREFILE} + +# password for the https truststore (for legacy CertificateManagment only) +TrustStorePassword: changeit +# +# END OF legacy CertificateManagement properties +########################################################################################### + + +##################################################### +# +# HTTP Server Configuration +# +##################################################### + +# Allow http access to dbcapi +HttpAllowed: true + +# listen to http port within this container (server) +IntHttpPort: 8080 + +# listen to https port within this container (server) +# set to 0 if no certificates are available. +IntHttpsPort: 0 + + +inHttpsPort: 0 + +##################################################### +# +# Deprecated properties +# +##################################################### +# csit: stubs out some southbound APIs for csit (deprecated) +#csit: No +# name of this DMaaP instance (deprecated) +#DmaapName: onap-cit +# external port number for https taking port mapping into account (deprecated) +#ExtHttpsPort: 443 +# path to the file used to trigger an orderly shutdown (deprecated) +#QuiesceFile: etc/SHUTDOWN +# FQDN of DR Prov Server (deprecated) +#DR.provhost: localhost +# root of topic namespace (decrecated) +#topicNsRoot: org.onap.dcae.dmaap |