diff options
Diffstat (limited to 'ms')
145 files changed, 2713 insertions, 943 deletions
diff --git a/ms/blueprintsprocessor/application/pom.xml b/ms/blueprintsprocessor/application/pom.xml index f6ef2ed29..16a2d456e 100755 --- a/ms/blueprintsprocessor/application/pom.xml +++ b/ms/blueprintsprocessor/application/pom.xml @@ -17,13 +17,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>parent</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <relativePath>../parent</relativePath> </parent> diff --git a/ms/blueprintsprocessor/application/src/main/docker/Dockerfile b/ms/blueprintsprocessor/application/src/main/docker/Dockerfile index 1035915f1..bd1b3804a 100755 --- a/ms/blueprintsprocessor/application/src/main/docker/Dockerfile +++ b/ms/blueprintsprocessor/application/src/main/docker/Dockerfile @@ -9,9 +9,16 @@ FROM omahoco1/alpine-java-python # add entrypoint COPY startService.sh /startService.sh +RUN addgroup -S onap && adduser -S onap -G onap +RUN chown onap:onap /startService.sh +RUN touch /velocity.log && chmod 777 /velocity.log +RUN chown onap:onap /velocity.log RUN chmod 777 /startService.sh && dos2unix /startService.sh # add application COPY --from=extractor /opt /opt +RUN mkdir -p /opt/app/onap/blueprints/deploy +RUN chown onap:onap /opt -R +USER onap ENTRYPOINT [ "/startService.sh" ] diff --git a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties index 5beebd8e8..bf5e23bc9 100755 --- a/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties +++ b/ms/blueprintsprocessor/application/src/main/resources/application-dev.properties @@ -129,13 +129,32 @@ blueprintsprocessor.messageconsumer.self-service-api.type=kafka-basic-auth blueprintsprocessor.messageconsumer.self-service-api.bootstrapServers=127.0.0.1:9092 blueprintsprocessor.messageconsumer.self-service-api.groupId=receiver-id blueprintsprocessor.messageconsumer.self-service-api.topic=receiver.t -blueprintsprocessor.messageconsumer.self-service-api.clientId=default-client-id +blueprintsprocessor.messageconsumer.self-service-api.clientId=request-receiver-client-id blueprintsprocessor.messageconsumer.self-service-api.pollMillSec=1000 +#### Security settings +#### SSL +#blueprintsprocessor.messageconsumer.self-service-api.truststore=/path/to/truststore.jks +#blueprintsprocessor.messageconsumer.self-service-api.truststorePassword=truststorePassword +#blueprintsprocessor.messageconsumer.self-service-api.keystore=/path/to/keystore.jks +#blueprintsprocessor.messageconsumer.self-service-api.keystorePassword=keystorePassword +#### SCRAM +#blueprintsprocessor.messageconsumer.self-service-api.scramUsername=test-user +#blueprintsprocessor.messageconsumer.self-service-api.scramPassword=testUserPassword + +# Kafka audit service Configurations +## Audit request +blueprintsprocessor.messageproducer.self-service-api.audit.kafkaEnable=false +blueprintsprocessor.messageproducer.self-service-api.audit.request.type=kafka-basic-auth +blueprintsprocessor.messageproducer.self-service-api.audit.request.bootstrapServers=127.0.0.1:9092 +blueprintsprocessor.messageproducer.self-service-api.audit.request.clientId=audit-request-producer-client-id +blueprintsprocessor.messageproducer.self-service-api.audit.request.topic=audit-request-producer.t + +## Audit response +blueprintsprocessor.messageproducer.self-service-api.audit.response.type=kafka-basic-auth +blueprintsprocessor.messageproducer.self-service-api.audit.response.bootstrapServers=127.0.0.1:9092 +blueprintsprocessor.messageproducer.self-service-api.audit.response.clientId=audit-response-producer-client-id +blueprintsprocessor.messageproducer.self-service-api.audit.response.topic=audit-response-producer.t -blueprintsprocessor.messageproducer.self-service-api.type=kafka-basic-auth -blueprintsprocessor.messageproducer.self-service-api.bootstrapServers=127.0.0.1:9092 -blueprintsprocessor.messageproducer.self-service-api.clientId=default-client-id -blueprintsprocessor.messageproducer.self-service-api.topic=producer.t # Message prioritization kakfa properties, Enable if Prioritization service is needed # Deploy message-prioritization function along with blueprintsprocessor application. diff --git a/ms/blueprintsprocessor/application/src/main/resources/application.properties b/ms/blueprintsprocessor/application/src/main/resources/application.properties index 74549b0ae..6fb737edc 100755 --- a/ms/blueprintsprocessor/application/src/main/resources/application.properties +++ b/ms/blueprintsprocessor/application/src/main/resources/application.properties @@ -103,20 +103,35 @@ blueprintsprocessor.restclient.aai-data.additionalHeaders.X-TransactionId=cds-tr blueprintsprocessor.restclient.aai-data.additionalHeaders.X-FromAppId=cds-app-id blueprintsprocessor.restclient.aai-data.additionalHeaders.Accept=application/json -# Kafka-message-lib Configuration -blueprintsprocessor.messageconsumer.self-service-api.kafkaEnable=false -blueprintsprocessor.messageconsumer.self-service-api.type=kafka-basic-auth -blueprintsprocessor.messageconsumer.self-service-api.bootstrapServers=127.0.0.1:9092 -blueprintsprocessor.messageconsumer.self-service-api.topic=receiver.t -blueprintsprocessor.messageconsumer.self-service-api.groupId=receiver-id -blueprintsprocessor.messageconsumer.self-service-api.clientId=default-client-id -blueprintsprocessor.messageconsumer.self-service-api.pollMillSec=1000 - -blueprintsprocessor.messageproducer.self-service-api.type=kafka-basic-auth -blueprintsprocessor.messageproducer.self-service-api.bootstrapServers=127.0.0.1:9092 -blueprintsprocessor.messageproducer.self-service-api.clientId=default-client-id -blueprintsprocessor.messageproducer.self-service-api.topic=producer.t - +# Kafka audit service Configurations +## Audit request +blueprintsprocessor.messageproducer.self-service-api.audit.kafkaEnable=false +blueprintsprocessor.messageproducer.self-service-api.audit.request.type=kafka-basic-auth +blueprintsprocessor.messageproducer.self-service-api.audit.request.bootstrapServers=127.0.0.1:9092 +blueprintsprocessor.messageproducer.self-service-api.audit.request.clientId=audit-request-producer-client-id +blueprintsprocessor.messageproducer.self-service-api.audit.request.topic=audit-request-producer.t +#### Security settings +#### SSL +#blueprintsprocessor.messageproducer.self-service-api.audit.request.truststore=/path/to/truststore.jks +#blueprintsprocessor.messageproducer.self-service-api.audit.request.truststorePassword=truststorePassword +#blueprintsprocessor.messageproducer.self-service-api.audit.request.keystore=/path/to/keystore.jks +#blueprintsprocessor.messageproducer.self-service-api.audit.request.keystorePassword=keystorePassword +#### SCRAM +#blueprintsprocessor.messageproducer.self-service-api.audit.request.scramUsername=test-user +#blueprintsprocessor.messageproducer.self-service-api.audit.request.scramPassword=testUserPassword + +## Audit response +blueprintsprocessor.messageproducer.self-service-api.audit.response.type=kafka-basic-auth +blueprintsprocessor.messageproducer.self-service-api.audit.response.bootstrapServers=127.0.0.1:9092 +blueprintsprocessor.messageproducer.self-service-api.audit.response.clientId=audit-response-producer-client-id +blueprintsprocessor.messageproducer.self-service-api.audit.response.topic=audit-response-producer.t + +# Message prioritization kakfa properties, Enable if Prioritization service is needed +# Deploy message-prioritization function along with blueprintsprocessor application. +#blueprintsprocessor.messageconsumer.prioritize-input.type=kafka-streams-basic-auth +#blueprintsprocessor.messageconsumer.prioritize-input.bootstrapServers=127.0.0.1:9092 +#blueprintsprocessor.messageconsumer.prioritize-input.applicationId=cds-controller +#blueprintsprocessor.messageconsumer.prioritize-input.topic=prioritize-input-topic blueprintprocessor.remoteScriptCommand.enabled=true diff --git a/ms/blueprintsprocessor/application/src/test/resources/application.properties b/ms/blueprintsprocessor/application/src/test/resources/application.properties index cb3419397..c6e957b32 100644 --- a/ms/blueprintsprocessor/application/src/test/resources/application.properties +++ b/ms/blueprintsprocessor/application/src/test/resources/application.properties @@ -74,14 +74,26 @@ blueprintsprocessor.cliExecutor.enabled=true blueprintsprocessor.remoteScriptCommand.enabled=false -# Kafka-message-lib Configuration -blueprintsprocessor.messageclient.self-service-api.topic=producer.t -blueprintsprocessor.messageclient.self-service-api.type=kafka-basic-auth -blueprintsprocessor.messageclient.self-service-api.bootstrapServers=127.0.0.1:9092 -blueprintsprocessor.messageclient.self-service-api.consumerTopic=receiver.t -blueprintsprocessor.messageclient.self-service-api.groupId=receiver-id -blueprintsprocessor.messageclient.self-service-api.clientId=default-client-id -blueprintsprocessor.messageclient.self-service-api.kafkaEnable=false +# Kafka-message-lib Configurations +blueprintsprocessor.messageconsumer.self-service-api.kafkaEnable=false +blueprintsprocessor.messageconsumer.self-service-api.type=kafka-basic-auth +blueprintsprocessor.messageconsumer.self-service-api.bootstrapServers=127.0.0.1:9092 +blueprintsprocessor.messageconsumer.self-service-api.groupId=receiver-id +blueprintsprocessor.messageconsumer.self-service-api.topic=receiver.t +blueprintsprocessor.messageconsumer.self-service-api.clientId=request-receiver-client-id +blueprintsprocessor.messageconsumer.self-service-api.pollMillSec=1000 + +# Kafka audit service Configurations +blueprintsprocessor.messageproducer.self-service-api.audit.kafkaEnable=false +blueprintsprocessor.messageproducer.self-service-api.audit.request.type=kafka-basic-auth +blueprintsprocessor.messageproducer.self-service-api.audit.request.bootstrapServers=127.0.0.1:9092 +blueprintsprocessor.messageproducer.self-service-api.audit.request.clientId=audit-request-producer-client-id +blueprintsprocessor.messageproducer.self-service-api.audit.request.topic=audit-request-producer.t + +blueprintsprocessor.messageproducer.self-service-api.audit.response.type=kafka-basic-auth +blueprintsprocessor.messageproducer.self-service-api.audit.response.bootstrapServers=127.0.0.1:9092 +blueprintsprocessor.messageproducer.self-service-api.audit.response.clientId=audit-response-producer-client-id +blueprintsprocessor.messageproducer.self-service-api.audit.response.topic=audit-response-producer.t endpoints.user.name=eHbVUbJAj4AG2522cSbrOQ== diff --git a/ms/blueprintsprocessor/cba-parent/pom.xml b/ms/blueprintsprocessor/cba-parent/pom.xml index e0ad43a8e..7b57962c2 100644 --- a/ms/blueprintsprocessor/cba-parent/pom.xml +++ b/ms/blueprintsprocessor/cba-parent/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>parent</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <relativePath>../parent</relativePath> </parent> diff --git a/ms/blueprintsprocessor/functions/ansible-awx-executor/pom.xml b/ms/blueprintsprocessor/functions/ansible-awx-executor/pom.xml index 9c699bab6..7be13dece 100644 --- a/ms/blueprintsprocessor/functions/ansible-awx-executor/pom.xml +++ b/ms/blueprintsprocessor/functions/ansible-awx-executor/pom.xml @@ -14,18 +14,19 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>functions</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId> <artifactId>ansible-awx-executor</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <name>Blueprints Processor Function - Ansible AWX Executor</name> <description>Blueprints Processor Function - Ansible Executor</description> diff --git a/ms/blueprintsprocessor/functions/cli-executor/pom.xml b/ms/blueprintsprocessor/functions/cli-executor/pom.xml index 28d96ad73..867809479 100644 --- a/ms/blueprintsprocessor/functions/cli-executor/pom.xml +++ b/ms/blueprintsprocessor/functions/cli-executor/pom.xml @@ -14,18 +14,19 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>functions</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId> <artifactId>cli-executor</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <name>Blueprints Processor Function - CLI Executor</name> <description>Blueprints Processor Function - CLI Executor</description> diff --git a/ms/blueprintsprocessor/functions/config-snapshots/pom.xml b/ms/blueprintsprocessor/functions/config-snapshots/pom.xml index 0f6c10e89..4aa3ebbb1 100644 --- a/ms/blueprintsprocessor/functions/config-snapshots/pom.xml +++ b/ms/blueprintsprocessor/functions/config-snapshots/pom.xml @@ -14,18 +14,19 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>functions</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId> <artifactId>config-snapshots</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <name>Blueprints Processor Function - Config Snapshots</name> <description>Blueprints Processor Function - Config Snapshots</description> diff --git a/ms/blueprintsprocessor/functions/config-snapshots/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/config/snapshots/ComponentConfigSnapshotsExecutor.kt b/ms/blueprintsprocessor/functions/config-snapshots/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/config/snapshots/ComponentConfigSnapshotsExecutor.kt index 0bf4e5f32..311e95bc2 100644 --- a/ms/blueprintsprocessor/functions/config-snapshots/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/config/snapshots/ComponentConfigSnapshotsExecutor.kt +++ b/ms/blueprintsprocessor/functions/config-snapshots/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/config/snapshots/ComponentConfigSnapshotsExecutor.kt @@ -194,7 +194,7 @@ open class ComponentConfigSnapshotsExecutor(private val cfgSnapshotService: Reso private fun setNodeOutputProperties(status: String, snapshot: String) { setAttribute(OUTPUT_STATUS, status.asJsonPrimitive()) setAttribute(OUTPUT_SNAPSHOT, snapshot.asJsonPrimitive()) - log.info("Setting output $OUTPUT_STATUS=$status, $OUTPUT_SNAPSHOT=$snapshot ") + log.debug("Setting output $OUTPUT_STATUS=$status") } /** diff --git a/ms/blueprintsprocessor/functions/message-prioritizaion/pom.xml b/ms/blueprintsprocessor/functions/message-prioritizaion/pom.xml index d12a1f2b3..4c38c53d2 100644 --- a/ms/blueprintsprocessor/functions/message-prioritizaion/pom.xml +++ b/ms/blueprintsprocessor/functions/message-prioritizaion/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>functions</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId> diff --git a/ms/blueprintsprocessor/functions/message-prioritizaion/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/message/prioritization/MessagePrioritizationConsumerTest.kt b/ms/blueprintsprocessor/functions/message-prioritizaion/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/message/prioritization/MessagePrioritizationConsumerTest.kt index 35bc49402..7e6bf68be 100644 --- a/ms/blueprintsprocessor/functions/message-prioritizaion/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/message/prioritization/MessagePrioritizationConsumerTest.kt +++ b/ms/blueprintsprocessor/functions/message-prioritizaion/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/message/prioritization/MessagePrioritizationConsumerTest.kt @@ -38,7 +38,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.functions.message.prioritization.s import org.onap.ccsdk.cds.blueprintsprocessor.functions.message.prioritization.utils.MessagePrioritizationSample import org.onap.ccsdk.cds.blueprintsprocessor.message.BluePrintMessageLibConfiguration import org.onap.ccsdk.cds.blueprintsprocessor.message.service.BluePrintMessageLibPropertyService -import org.onap.ccsdk.cds.blueprintsprocessor.message.service.KafkaBasicAuthMessageProducerService +import org.onap.ccsdk.cds.blueprintsprocessor.message.service.KafkaMessageProducerService import org.onap.ccsdk.cds.blueprintsprocessor.nats.BluePrintNatsLibConfiguration import org.onap.ccsdk.cds.blueprintsprocessor.nats.service.BluePrintNatsLibPropertyService import org.onap.ccsdk.cds.blueprintsprocessor.nats.utils.NatsClusterUtils @@ -72,15 +72,27 @@ import kotlin.test.assertNotNull "spring.jpa.properties.hibernate.show_sql=false", "spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl", - "blueprintsprocessor.messageconsumer.prioritize-input.type=kafka-streams-basic-auth", + "blueprintsprocessor.messageconsumer.prioritize-input.type=kafka-streams-scram-ssl-auth", "blueprintsprocessor.messageconsumer.prioritize-input.bootstrapServers=127.0.0.1:9092", "blueprintsprocessor.messageconsumer.prioritize-input.applicationId=test-prioritize-application", "blueprintsprocessor.messageconsumer.prioritize-input.topic=prioritize-input-topic", + "blueprintsprocessor.messageconsumer.prioritize-input.truststore=/path/to/truststore.jks", + "blueprintsprocessor.messageconsumer.prioritize-input.truststorePassword=truststorePassword", + "blueprintsprocessor.messageconsumer.prioritize-input.keystore=/path/to/keystore.jks", + "blueprintsprocessor.messageconsumer.prioritize-input.keystorePassword=keystorePassword", + "blueprintsprocessor.messageconsumer.prioritize-input.scramUsername=test-user", + "blueprintsprocessor.messageconsumer.prioritize-input.scramPassword=testUserPassword", // To send initial test message - "blueprintsprocessor.messageproducer.prioritize-input.type=kafka-basic-auth", + "blueprintsprocessor.messageproducer.prioritize-input.type=kafka-scram-ssl-auth", "blueprintsprocessor.messageproducer.prioritize-input.bootstrapServers=127.0.0.1:9092", "blueprintsprocessor.messageproducer.prioritize-input.topic=prioritize-input-topic", + "blueprintsprocessor.messageproducer.prioritize-input.truststore=/path/to/truststore.jks", + "blueprintsprocessor.messageproducer.prioritize-input.truststorePassword=truststorePassword", + "blueprintsprocessor.messageproducer.prioritize-input.keystore=/path/to/keystore.jks", + "blueprintsprocessor.messageproducer.prioritize-input.keystorePassword=keystorePassword", + "blueprintsprocessor.messageproducer.prioritize-input.scramUsername=test-user", + "blueprintsprocessor.messageproducer.prioritize-input.scramPassword=testUserPassword", "blueprintsprocessor.nats.cds-controller.type=token-auth", "blueprintsprocessor.nats.cds-controller.host=nats://localhost:4222", @@ -241,7 +253,7 @@ open class MessagePrioritizationConsumerTest { /** Send sample message with every 1 sec */ val blueprintMessageProducerService = bluePrintMessageLibPropertyService - .blueprintMessageProducerService("prioritize-input") as KafkaBasicAuthMessageProducerService + .blueprintMessageProducerService("prioritize-input") as KafkaMessageProducerService launch { MessagePrioritizationSample.sampleMessages(MessageState.NEW.name, 2).forEach { delay(100) diff --git a/ms/blueprintsprocessor/functions/netconf-executor/pom.xml b/ms/blueprintsprocessor/functions/netconf-executor/pom.xml index 2ff7106ec..69b42e016 100644 --- a/ms/blueprintsprocessor/functions/netconf-executor/pom.xml +++ b/ms/blueprintsprocessor/functions/netconf-executor/pom.xml @@ -14,18 +14,19 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>functions</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId> <artifactId>netconf-executor</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <name>Blueprints Processor Function - Netconf Executor</name> <description>Blueprints Processor Function - Netconf Executor</description> diff --git a/ms/blueprintsprocessor/functions/pom.xml b/ms/blueprintsprocessor/functions/pom.xml index de21f40f1..4d417f38b 100755 --- a/ms/blueprintsprocessor/functions/pom.xml +++ b/ms/blueprintsprocessor/functions/pom.xml @@ -15,13 +15,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>parent</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <relativePath>../parent</relativePath> </parent> diff --git a/ms/blueprintsprocessor/functions/python-executor/pom.xml b/ms/blueprintsprocessor/functions/python-executor/pom.xml index 0cd8a11ae..c6480fade 100644 --- a/ms/blueprintsprocessor/functions/python-executor/pom.xml +++ b/ms/blueprintsprocessor/functions/python-executor/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>functions</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId> diff --git a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt index ddfaf9ac2..d66e8b374 100644 --- a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt +++ b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutor.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2019 IBM. + * 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. @@ -17,6 +17,10 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.python.executor import com.fasterxml.jackson.databind.JsonNode +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.TimeoutCancellationException +import kotlinx.coroutines.async +import kotlinx.coroutines.withTimeout import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.PrepareRemoteEnvInput import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.RemoteIdentifier @@ -51,14 +55,19 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic const val INPUT_ENDPOINT_SELECTOR = "endpoint-selector" const val INPUT_DYNAMIC_PROPERTIES = "dynamic-properties" const val INPUT_ARGUMENT_PROPERTIES = "argument-properties" + const val INPUT_COMMAND = "command" const val INPUT_PACKAGES = "packages" const val DEFAULT_SELECTOR = "remote-python" + const val INPUT_ENV_PREPARE_TIMEOUT = "env-prepare-timeout" + const val INPUT_EXECUTE_TIMEOUT = "execution-timeout" const val ATTRIBUTE_EXEC_CMD_STATUS = "status" const val ATTRIBUTE_PREPARE_ENV_LOG = "prepare-environment-logs" const val ATTRIBUTE_EXEC_CMD_LOG = "execute-command-logs" const val ATTRIBUTE_RESPONSE_DATA = "response-data" + const val DEFAULT_ENV_PREPARE_TIMEOUT_IN_SEC = 120 + const val DEFAULT_EXECUTE_TIMEOUT_IN_SEC = 180 } override suspend fun processNB(executionRequest: ExecutionServiceInput) { @@ -95,6 +104,16 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic ?.rootFieldsToMap()?.toSortedMap()?.values?.joinToString(" ") { formatNestedJsonNode(it) } val command = getOperationInput(INPUT_COMMAND).asText() + + /** + * Timeouts that are specific to the command executor. + * Note: the interface->input->timeout is the component level timeout. + */ + val envPrepTimeout = getOptionalOperationInput(INPUT_ENV_PREPARE_TIMEOUT)?.asInt() + ?: DEFAULT_ENV_PREPARE_TIMEOUT_IN_SEC + val executionTimeout = getOptionalOperationInput(INPUT_EXECUTE_TIMEOUT)?.asInt() + ?: DEFAULT_EXECUTE_TIMEOUT_IN_SEC + var scriptCommand = command.replace(pythonScript.name, pythonScript.absolutePath) if (args != null && args.isNotEmpty()) { scriptCommand = scriptCommand.plus(" ").plus(args) @@ -116,9 +135,10 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic requestId = processId, remoteIdentifier = RemoteIdentifier( blueprintName = blueprintName, - blueprintVersion = blueprintVersion - ), - packages = packages + blueprintVersion = blueprintVersion), + packages = packages, + timeOut = envPrepTimeout.toLong() + ) val prepareEnvOutput = remoteScriptExecutionService.prepareEnv(prepareEnvInput) log.info("$ATTRIBUTE_PREPARE_ENV_LOG - ${prepareEnvOutput.response}") @@ -132,10 +152,26 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic } else { setNodeOutputProperties(prepareEnvOutput.status.name.asJsonPrimitive(), logsEnv, "".asJsonPrimitive()) } + } else { + // set env preparation log to empty... + setAttribute(ATTRIBUTE_PREPARE_ENV_LOG, "".asJsonPrimitive()) } - - // if Env preparation was successful, then proceed with command execution in this Env - if (bluePrintRuntimeService.getBluePrintError().errors.isEmpty()) { + } catch (grpcEx: io.grpc.StatusRuntimeException) { + val grpcErrMsg = "Command failed during env. preparation... timeout($envPrepTimeout) requestId ($processId)." + setAttribute(ATTRIBUTE_PREPARE_ENV_LOG, grpcErrMsg.asJsonPrimitive()) + setNodeOutputErrors(status = grpcErrMsg, message = "${grpcEx.status}".asJsonPrimitive()) + log.error(grpcErrMsg, grpcEx) + addError(grpcErrMsg) + } catch (e: Exception) { + val timeoutErrMsg = "Command executor failed during env. preparation.. timeout($envPrepTimeout) requestId ($processId)." + setAttribute(ATTRIBUTE_PREPARE_ENV_LOG, e.message.asJsonPrimitive()) + setNodeOutputErrors(status = timeoutErrMsg, message = "${e.message}".asJsonPrimitive()) + log.error("Failed to process on remote executor requestId ($processId)", e) + addError(timeoutErrMsg) + } + // if Env preparation was successful, then proceed with command execution in this Env + if (bluePrintRuntimeService.getBluePrintError().errors.isEmpty()) { + try { // Populate command execution properties and pass it to the remote server val properties = dynamicProperties?.returnNullIfMissing()?.rootFieldsToMap() ?: hashMapOf() @@ -143,25 +179,41 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic requestId = processId, remoteIdentifier = RemoteIdentifier(blueprintName = blueprintName, blueprintVersion = blueprintVersion), command = scriptCommand, - properties = properties - ) - val remoteExecutionOutput = remoteScriptExecutionService.executeCommand(remoteExecutionInput) + properties = properties, + timeOut = implementation.timeout.toLong()) + + val remoteExecutionOutputDeferred = GlobalScope.async { + remoteScriptExecutionService.executeCommand(remoteExecutionInput) + } + + val remoteExecutionOutput = withTimeout(implementation.timeout * 1000L) { + remoteExecutionOutputDeferred.await() + } + checkNotNull(remoteExecutionOutput) { + "Error: Request-id $processId did not return a restul from remote command execution." + } val logs = JacksonUtils.jsonNodeFromObject(remoteExecutionOutput.response) if (remoteExecutionOutput.status != StatusType.SUCCESS) { setNodeOutputErrors(remoteExecutionOutput.status.name, logs, remoteExecutionOutput.payload) } else { - setNodeOutputProperties( - remoteExecutionOutput.status.name.asJsonPrimitive(), logs, - remoteExecutionOutput.payload - ) + setNodeOutputProperties(remoteExecutionOutput.status.name.asJsonPrimitive(), logs, + remoteExecutionOutput.payload) } + } catch (timeoutEx: TimeoutCancellationException) { + val timeoutErrMsg = "Command executor timed out executing after $executionTimeout seconds requestId ($processId)" + setNodeOutputErrors(status = timeoutErrMsg, message = "".asJsonPrimitive()) + log.error(timeoutErrMsg, timeoutEx) + } catch (grpcEx: io.grpc.StatusRuntimeException) { + val timeoutErrMsg = "Command executor timed out executing after $executionTimeout seconds requestId ($processId)" + setNodeOutputErrors(status = timeoutErrMsg, message = "".asJsonPrimitive()) + log.error("Command executor time out during GRPC call", grpcEx) + } catch (e: Exception) { + log.error("Failed to process on remote executor requestId ($processId)", e) } - } catch (e: Exception) { - log.error("Failed to process on remote executor", e) - } finally { - remoteScriptExecutionService.close() } + log.debug("Trying to close GRPC channel. request ($processId)") + remoteScriptExecutionService.close() } override suspend fun recoverNB(runtimeException: RuntimeException, executionRequest: ExecutionServiceInput) { @@ -201,7 +253,6 @@ open class ComponentRemotePythonExecutor(private val remoteScriptExecutionServic log.info("Executor message : $message") setAttribute(ATTRIBUTE_RESPONSE_DATA, artifacts) log.info("Executor artifacts: $artifacts") - addError(status, ATTRIBUTE_EXEC_CMD_LOG, message.toString()) } } diff --git a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/scripts/BlueprintPythonHost.kt b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/scripts/BlueprintPythonHost.kt index 93fe2b1f5..3d2f10ec0 100644 --- a/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/scripts/BlueprintPythonHost.kt +++ b/ms/blueprintsprocessor/functions/python-executor/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/scripts/BlueprintPythonHost.kt @@ -15,7 +15,9 @@ */ package org.onap.ccsdk.cds.blueprintsprocessor.functions.python.executor.scripts +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServiceDomains import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.updateErrorMessage import org.python.core.PyObject import org.python.util.PythonInterpreter @@ -42,6 +44,10 @@ open class BlueprintPythonHost(private val bluePrintPython: BluePrintPython) { bluePrintPython.moduleName = "Blueprint Python Script [Class Name = $interfaceName]" try { return blueprintPythonInterpreterProxy.getPythonInstance(properties) + } catch (e: BluePrintProcessorException) { + val errorMsg = "Failed to get python instance." + throw e.updateErrorMessage(ExecutionServiceDomains.PYTHON_EXECUTOR, errorMsg, + "Error in environment properties") } catch (e: Exception) { throw BluePrintProcessorException("Failed to execute Jython component $e", e) } diff --git a/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt b/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt index 3d58afad8..5e57b9eb7 100644 --- a/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt +++ b/ms/blueprintsprocessor/functions/python-executor/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/python/executor/ComponentRemotePythonExecutorTest.kt @@ -30,6 +30,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StatusType import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.StepData import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.RemoteScriptExecutionService import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintError import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType import org.onap.ccsdk.cds.controllerblueprints.core.putJsonElement @@ -90,6 +91,7 @@ class ComponentRemotePythonExecutorTest { val componentRemotePythonExecutor = ComponentRemotePythonExecutor(remoteScriptExecutionService) val bluePrintRuntime = mockk<DefaultBluePrintRuntimeService>("123456-1000") + every { bluePrintRuntime.getBluePrintError() } answers { BluePrintError() } // successful case. every { bluePrintRuntime.setNodeTemplateAttributeValue(any(), any(), any()) } answers {} val input = getMockedOutput(bluePrintRuntime) diff --git a/ms/blueprintsprocessor/functions/resource-resolution/pom.xml b/ms/blueprintsprocessor/functions/resource-resolution/pom.xml index d2aecf0cf..8b0b7e798 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/pom.xml +++ b/ms/blueprintsprocessor/functions/resource-resolution/pom.xml @@ -14,18 +14,19 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>functions</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId> <artifactId>resource-resolution</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <packaging>jar</packaging> <name>Blueprints Processor Function - Resource Resolution</name> diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceAssignmentRuntimeService.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceAssignmentRuntimeService.kt index a65ec585b..8087f7e3f 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceAssignmentRuntimeService.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceAssignmentRuntimeService.kt @@ -23,6 +23,10 @@ class ResourceAssignmentRuntimeService(private var id: String, private var blueP resourceStore[key] = value } + fun getResolutionStore(): MutableMap<String, JsonNode> { + return resourceStore.mapValues { e -> e.value.deepCopy() as JsonNode }.toMutableMap() + } + fun getResolutionStore(key: String): JsonNode { return resourceStore[key] ?: throw BluePrintProcessorException("failed to get execution property ($key)") diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt index 8f6069160..b934940b1 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceResolutionConstants.kt @@ -30,4 +30,5 @@ object ResourceResolutionConstants { const val RESOURCE_RESOLUTION_INPUT_RESOURCE_ID = "resource-id" const val RESOURCE_RESOLUTION_INPUT_RESOURCE_TYPE = "resource-type" const val RESOURCE_RESOLUTION_INPUT_RESOLUTION_SUMMARY = "resolution-summary" + const val METADATA_TRANSFORM_TEMPLATE = "transform-template" } diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceSourceProperties.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceSourceProperties.kt index 636e81dda..7a7edc92b 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceSourceProperties.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/ResourceSourceProperties.kt @@ -51,6 +51,8 @@ open class RestResourceSource : ResourceSourceProperties() { lateinit var verb: String @get:JsonProperty("payload") var payload: String? = null + @get:JsonProperty("resolved-payload") + var resolvedPayload: String? = null lateinit var type: String @get:JsonProperty("endpoint-selector") var endpointSelector: String? = null diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt index 0bfd7e4e2..2640b5b85 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DatabaseResourceAssignmentProcessor.kt @@ -23,10 +23,12 @@ import org.onap.ccsdk.cds.blueprintsprocessor.db.PrimaryDBLibGenericService import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.DatabaseResourceSource import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServiceDomains import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException -import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty import org.onap.ccsdk.cds.controllerblueprints.core.isNotEmpty +import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty import org.onap.ccsdk.cds.controllerblueprints.core.nullToEmpty +import org.onap.ccsdk.cds.controllerblueprints.core.updateErrorMessage import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.onap.ccsdk.cds.controllerblueprints.resource.dict.KeyIdentifier import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment @@ -64,6 +66,10 @@ open class DatabaseResourceAssignmentProcessor( } // Check the value has populated for mandatory case ResourceAssignmentUtils.assertTemplateKeyValueNotNull(resourceAssignment) + } catch (e: BluePrintProcessorException) { + val errorMsg = "Failed to process Database resource resolution in template key ($resourceAssignment) assignments." + throw e.updateErrorMessage(ExecutionServiceDomains.RESOURCE_RESOLUTION, errorMsg, + "Wrong resource definition or DB resolution failed.") } catch (e: Exception) { ResourceAssignmentUtils.setFailedResourceDataValue(resourceAssignment, e.message) throw BluePrintProcessorException("Failed in template key ($resourceAssignment) assignments with: ${e.message}", e) @@ -101,7 +107,7 @@ open class DatabaseResourceAssignmentProcessor( "DatabaseResource ($dSource) dictionary information: " + "Query:($sql), input-key-mapping:($inputKeyMapping), output-key-mapping:(${sourceProperties.outputKeyMapping})" ) - val jdbcTemplate = blueprintDBLibService(sourceProperties) + val jdbcTemplate = blueprintDBLibService(sourceProperties, dSource) val rows = jdbcTemplate.query(sql, populateNamedParameter(inputKeyMapping)) if (rows.isNullOrEmpty()) { @@ -111,12 +117,12 @@ open class DatabaseResourceAssignmentProcessor( } } - private fun blueprintDBLibService(sourceProperties: DatabaseResourceSource): BluePrintDBLibGenericService { + private fun blueprintDBLibService(sourceProperties: DatabaseResourceSource, selector: String): BluePrintDBLibGenericService { return if (isNotEmpty(sourceProperties.endpointSelector)) { val dbPropertiesJson = raRuntimeService.resolveDSLExpression(sourceProperties.endpointSelector!!) bluePrintDBLibPropertyService.JdbcTemplate(dbPropertiesJson) } else { - primaryDBLibGenericService + bluePrintDBLibPropertyService.JdbcTemplate(selector) } } diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DefaultResourceResolutionProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DefaultResourceResolutionProcessor.kt index 7705c1102..2921cb6fb 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DefaultResourceResolutionProcessor.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/DefaultResourceResolutionProcessor.kt @@ -19,7 +19,9 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.pro import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServiceDomains import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.updateErrorMessage import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment import org.slf4j.LoggerFactory import org.springframework.beans.factory.config.ConfigurableBeanFactory @@ -49,6 +51,10 @@ open class DefaultResourceResolutionProcessor : ResourceAssignmentProcessor() { } // Check the value has populated for mandatory case ResourceAssignmentUtils.assertTemplateKeyValueNotNull(resourceAssignment) + } catch (e: BluePrintProcessorException) { + val errorMsg = "Failed to process default resource resolution in template key ($resourceAssignment) assignments." + throw e.updateErrorMessage(ExecutionServiceDomains.RESOURCE_RESOLUTION, errorMsg, + "Wrong default value was set.") } catch (e: Exception) { ResourceAssignmentUtils.setFailedResourceDataValue(resourceAssignment, e.message) throw BluePrintProcessorException("Failed in template key ($resourceAssignment) assignments with: ${e.message}", e) diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/InputResourceResolutionProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/InputResourceResolutionProcessor.kt index f04a787db..d078a2d70 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/InputResourceResolutionProcessor.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/InputResourceResolutionProcessor.kt @@ -20,8 +20,10 @@ package org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.pro import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.DatabaseResourceSource import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.PREFIX_RESOURCE_RESOLUTION_PROCESSOR import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServiceDomains import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.isNotEmpty +import org.onap.ccsdk.cds.controllerblueprints.core.updateErrorMessage import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment import org.springframework.beans.factory.config.ConfigurableBeanFactory @@ -48,6 +50,10 @@ open class InputResourceResolutionProcessor : ResourceAssignmentProcessor() { } // Check the value has populated for mandatory case ResourceAssignmentUtils.assertTemplateKeyValueNotNull(resourceAssignment) + } catch (e: BluePrintProcessorException) { + val errorMsg = "Failed to process input resource resolution in template key ($resourceAssignment) assignments." + throw e.updateErrorMessage(ExecutionServiceDomains.RESOURCE_RESOLUTION, errorMsg, + "Wrong input value was set.") } catch (e: Exception) { ResourceAssignmentUtils.setFailedResourceDataValue(resourceAssignment, e.message) throw BluePrintProcessorException("Failed in template key ($resourceAssignment) assignments with : (${e.message})", e) diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt index 5d9226876..7596d7d8c 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/processor/RestResourceResolutionProcessor.kt @@ -1,6 +1,6 @@ /* - * Copyright © 2018 IBM. - * Modifications Copyright © 2017-2019 AT&T, Bell Canada + * Copyright © 2018 - 2020 IBM. + * Modifications Copyright © 2017-2020 AT&T, Bell Canada * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,10 +22,12 @@ import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.Rest import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.utils.ResourceAssignmentUtils import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BluePrintRestLibPropertyService import org.onap.ccsdk.cds.blueprintsprocessor.rest.service.BlueprintWebClientService +import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.ExecutionServiceDomains import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException -import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty import org.onap.ccsdk.cds.controllerblueprints.core.isNotEmpty +import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty import org.onap.ccsdk.cds.controllerblueprints.core.nullToEmpty +import org.onap.ccsdk.cds.controllerblueprints.core.updateErrorMessage import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.onap.ccsdk.cds.controllerblueprints.resource.dict.KeyIdentifier import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment @@ -76,8 +78,7 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS checkNotNull(sourceProperties.inputKeyMapping) { "failed to get input-key-mappings for $dName under $dSource properties" } val resolvedInputKeyMapping = resolveInputKeyMappingVariables(inputKeyMapping).toMutableMap() - sourceProperties.inputKeyMapping - ?.mapValues { raRuntimeService.getDictionaryStore(it.value) } + inputKeyMapping?.mapValues { raRuntimeService.getDictionaryStore(it.value) } ?.map { KeyIdentifier(it.key, it.value) } ?.let { resourceAssignment.keyIdentifiers.addAll(it) } @@ -114,6 +115,10 @@ open class RestResourceResolutionProcessor(private val blueprintRestLibPropertyS } // Check the value has populated for mandatory case ResourceAssignmentUtils.assertTemplateKeyValueNotNull(resourceAssignment) + } catch (e: BluePrintProcessorException) { + val errorMsg = "Failed to process REST resource resolution in template key ($resourceAssignment) assignments." + throw e.updateErrorMessage(ExecutionServiceDomains.RESOURCE_RESOLUTION, errorMsg, + "Wrong resource definition or resolution failed.") } catch (e: Exception) { ResourceAssignmentUtils.setFailedResourceDataValue(resourceAssignment, e.message) throw BluePrintProcessorException("Failed in template key ($resourceAssignment) assignments with: ${e.message}", e) diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt index 7bb757b8e..497b26803 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtils.kt @@ -39,6 +39,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile import org.onap.ccsdk.cds.controllerblueprints.core.nullToEmpty import org.onap.ccsdk.cds.controllerblueprints.core.rootFieldsToMap import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintRuntimeService +import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintVelocityTemplateService import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonReactorUtils import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils.Companion.hasLogProtect @@ -127,6 +128,32 @@ class ResourceAssignmentUtils { raRuntimeService.putResolutionStore(resourceAssignment.name, value) raRuntimeService.putDictionaryStore(resourceAssignment.dictionaryName!!, value) resourceAssignment.property!!.value = value + + val metadata = resourceAssignment.property?.metadata + metadata?.get(ResourceResolutionConstants.METADATA_TRANSFORM_TEMPLATE) + ?.let { if (it.contains("$")) it else null } + ?.let { template -> + val resolutionStore = raRuntimeService.getResolutionStore() + .mapValues { e -> e.value.asText() } as MutableMap<String, Any> + val newValue: JsonNode + try { + newValue = BluePrintVelocityTemplateService + .generateContent(template, null, true, resolutionStore) + .also { if (hasLogProtect(metadata)) + logger.info("Transformed value: $resourceAssignment.name") + else + logger.info("Transformed value: $value -> $it") } + .let { v -> v.asJsonType() } + } catch (e: Exception) { + throw BluePrintProcessorException( + "transform-template failed: $template", e) + } + with(resourceAssignment) { + raRuntimeService.putResolutionStore(this.name, newValue) + raRuntimeService.putDictionaryStore(this.dictionaryName!!, newValue) + this.property!!.value = newValue + } + } } fun setFailedResourceDataValue(resourceAssignment: ResourceAssignment, message: String?) { @@ -203,18 +230,40 @@ class ResourceAssignmentUtils { resourceAssignments: List<ResourceAssignment>, resourceDefinitions: Map<String, ResourceDefinition> ): String { + val emptyTextNode = TextNode.valueOf("") val resolutionSummaryList = resourceAssignments.map { val definition = resourceDefinitions[it.name] - val payload = definition?.sources?.get(it.dictionarySource) + val description = definition?.property?.description ?: "" + val value = it.property?.value + ?.let { v -> if (v.isNullOrMissing()) emptyTextNode else v } + ?: emptyTextNode + + var payload: JsonNode = definition?.sources?.get(it.dictionarySource) ?.properties?.get("resolved-payload") + ?.let { p -> if (p.isNullOrMissing()) emptyTextNode else p } + ?: emptyTextNode + val metadata = definition?.property?.metadata ?.map { e -> DictionaryMetadataEntry(e.key, e.value) } ?.toMutableList() ?: mutableListOf() - val description = definition?.property?.description + + val keyIdentifiers: MutableList<KeyIdentifier> = it.keyIdentifiers.map { k -> + if (k.value.isNullOrMissing()) KeyIdentifier(k.name, emptyTextNode) else k + }.toMutableList() + ResolutionSummary( - it.name, it.property?.value, it.property?.required, it.property?.type, - it.keyIdentifiers, description, metadata, it.dictionaryName, - it.dictionarySource, payload, it.status, it.message + it.name, + value, + it.property?.required ?: false, + it.property?.type ?: "", + keyIdentifiers, + description, + metadata, + it.dictionaryName ?: "", + it.dictionarySource ?: "", + payload, + it.status ?: "", + it.message ?: "" ) } // Wrapper needed for integration with SDNC diff --git a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt index 9df8fb7d7..7746b5c41 100644 --- a/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt +++ b/ms/blueprintsprocessor/functions/resource-resolution/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/functions/resource/resolution/utils/ResourceAssignmentUtilsTest.kt @@ -29,6 +29,7 @@ import kotlinx.coroutines.runBlocking import org.junit.Before import org.junit.Test import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceAssignmentRuntimeService +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants.METADATA_TRANSFORM_TEMPLATE import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive import org.onap.ccsdk.cds.controllerblueprints.core.asJsonType import org.onap.ccsdk.cds.controllerblueprints.core.data.DataType @@ -180,8 +181,8 @@ class ResourceAssignmentUtilsTest { "resolution-summary":[ { "name":"pnf-id", - "value":null, - "required":null, + "value":"", + "required":false, "type":"string", "key-identifiers":[], "dictionary-description":"pnf-id", @@ -191,8 +192,8 @@ class ResourceAssignmentUtilsTest { "dictionary-name":"pnf-id", "dictionary-source":"input", "request-payload":{"mock":true}, - "status":null, - "message":null + "status":"", + "message":"" } ] } @@ -333,6 +334,26 @@ class ResourceAssignmentUtilsTest { ) } + @Test + fun `transform resolved value with inline template`() { + resourceAssignmentRuntimeService.putResolutionStore("vnf_name", "abc-vnf".asJsonType()) + resourceAssignment = ResourceAssignment() + resourceAssignment.name = "int_pktgen_private_net_id" + resourceAssignment.property = PropertyDefinition() + resourceAssignment.property!!.type = "string" + val value = "".asJsonType() + + // Enable transform template + resourceAssignment.property!!.metadata = + mutableMapOf(METADATA_TRANSFORM_TEMPLATE to "\${vnf_name}_private2") + + ResourceAssignmentUtils + .setResourceDataValue(resourceAssignment, resourceAssignmentRuntimeService, value) + + assertEquals("abc-vnf_private2", + resourceAssignment.property!!.value!!.asText()) + } + private fun initInputMapAndExpectedValuesForPrimitiveType() { inputMapToTestPrimitiveTypeWithValue = "1.2.3.1".asJsonType() val keyValue = mutableMapOf<String, String>() diff --git a/ms/blueprintsprocessor/functions/restconf-executor/pom.xml b/ms/blueprintsprocessor/functions/restconf-executor/pom.xml index 8208f5f4e..fdc72b2bd 100644 --- a/ms/blueprintsprocessor/functions/restconf-executor/pom.xml +++ b/ms/blueprintsprocessor/functions/restconf-executor/pom.xml @@ -14,18 +14,19 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>functions</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId> <artifactId>restconf-executor</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <name>Blueprints Processor Function - Restconf Executor</name> <description>Blueprints Processor Function - Restconf Executor</description> diff --git a/ms/blueprintsprocessor/functions/restful-executor/pom.xml b/ms/blueprintsprocessor/functions/restful-executor/pom.xml index fa4acf641..f5dce168e 100644 --- a/ms/blueprintsprocessor/functions/restful-executor/pom.xml +++ b/ms/blueprintsprocessor/functions/restful-executor/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>functions</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor.functions</groupId> diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/pom.xml b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/pom.xml index def1ed0b3..6f0791c4e 100644 --- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/pom.xml +++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/pom.xml @@ -15,13 +15,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>blueprints</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>blueprint-core</artifactId> diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt index acb158d89..310c9b05b 100644 --- a/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt +++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-core/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/core/BluePrintProcessorException.kt @@ -17,6 +17,7 @@ package org.onap.ccsdk.cds.controllerblueprints.core +import org.apache.commons.lang.exception.ExceptionUtils import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogException import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogExceptionFluent import org.onap.ccsdk.cds.error.catalog.core.ErrorMessage @@ -56,6 +57,14 @@ open class BluePrintProcessorException : ErrorCatalogException, ErrorCatalogExce return this.updateGrpc(type) } + override fun convertToHttp(): BluePrintProcessorException { + return this.inverseToHttp() + } + + override fun convertToGrpc(): BluePrintProcessorException { + return this.inverseToHttp() + } + override fun payloadMessage(message: String): BluePrintProcessorException { return this.updatePayloadMessage(message) } @@ -82,10 +91,26 @@ fun processorException(message: String): BluePrintProcessorException { return BluePrintProcessorException(message) } +fun processorException(message: String, cause: Throwable): BluePrintProcessorException { + return BluePrintProcessorException(message, cause) +} + +fun processorException(cause: Throwable, message: String, vararg args: Any?): BluePrintProcessorException { + return BluePrintProcessorException(cause, message, args) +} + fun processorException(code: Int, message: String): BluePrintProcessorException { return processorException(message).code(code) } +fun processorException(code: Int, message: String, cause: Throwable): BluePrintProcessorException { + return processorException(message, cause).code(code) +} + +fun processorException(code: Int, cause: Throwable, message: String, vararg args: Any?): BluePrintProcessorException { + return processorException(cause, message, args).code(code) +} + fun httpProcessorException(type: String, message: String): BluePrintProcessorException { return processorException(message).http(type) } @@ -106,17 +131,29 @@ fun grpcProcessorException(type: String, domain: String, message: String): BlueP fun httpProcessorException(type: String, domain: String, message: String, cause: Throwable): BluePrintProcessorException { - val bluePrintProcessorException = processorException(message).http(type) - return bluePrintProcessorException.addDomainAndErrorMessage(domain, message, cause) + val bluePrintProcessorException = processorException(message, cause).http(type) + return bluePrintProcessorException.addDomainAndErrorMessage(domain, message, ExceptionUtils.getRootCauseMessage(cause)) } fun grpcProcessorException(type: String, domain: String, message: String, cause: Throwable): BluePrintProcessorException { - val bluePrintProcessorException = processorException(message).grpc(type) - return bluePrintProcessorException.addDomainAndErrorMessage(domain, message, cause) + val bluePrintProcessorException = processorException(message, cause).grpc(type) + return bluePrintProcessorException.addDomainAndErrorMessage(domain, message, ExceptionUtils.getRootCauseMessage(cause)) +} + +fun httpProcessorException(type: String, domain: String, message: String, cause: Throwable, vararg args: Any?): + BluePrintProcessorException { + val bluePrintProcessorException = processorException(cause, message, args).http(type) + return bluePrintProcessorException.addDomainAndErrorMessage(domain, message, ExceptionUtils.getRootCauseMessage(cause)) +} + +fun grpcProcessorException(type: String, domain: String, message: String, cause: Throwable, vararg args: Any?): + BluePrintProcessorException { + val bluePrintProcessorException = processorException(cause, message, args).grpc(type) + return bluePrintProcessorException.addDomainAndErrorMessage(domain, message, ExceptionUtils.getRootCauseMessage(cause)) } -fun BluePrintProcessorException.updateErrorMessage(domain: String, message: String, cause: Throwable): +fun BluePrintProcessorException.updateErrorMessage(domain: String, message: String, cause: String): BluePrintProcessorException { return this.addDomainAndErrorMessage(domain, message, cause).domain(domain) .addErrorPayloadMessage(message) @@ -132,8 +169,7 @@ fun BluePrintProcessorException.updateErrorMessage(domain: String, message: Stri private fun BluePrintProcessorException.addDomainAndErrorMessage( domain: String, message: String, - cause: Throwable = Throwable() + cause: String = "" ): BluePrintProcessorException { - return this.addSubError(ErrorMessage(domain, message, cause.message - ?: "")).domain(domain) + return this.addSubError(ErrorMessage(domain, message, cause)).domain(domain) } diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-proto/pom.xml b/ms/blueprintsprocessor/modules/blueprints/blueprint-proto/pom.xml index 11ce0e27c..b71085f3d 100644 --- a/ms/blueprintsprocessor/modules/blueprints/blueprint-proto/pom.xml +++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-proto/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>blueprints</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>blueprint-proto</artifactId> diff --git a/ms/blueprintsprocessor/modules/blueprints/blueprint-validation/pom.xml b/ms/blueprintsprocessor/modules/blueprints/blueprint-validation/pom.xml index 0a5818ecd..d87f25a3c 100644 --- a/ms/blueprintsprocessor/modules/blueprints/blueprint-validation/pom.xml +++ b/ms/blueprintsprocessor/modules/blueprints/blueprint-validation/pom.xml @@ -16,13 +16,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>blueprints</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>blueprint-validation</artifactId> diff --git a/ms/blueprintsprocessor/modules/blueprints/pom.xml b/ms/blueprintsprocessor/modules/blueprints/pom.xml index 0ea6a1eee..a2b19ccec 100644 --- a/ms/blueprintsprocessor/modules/blueprints/pom.xml +++ b/ms/blueprintsprocessor/modules/blueprints/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>modules</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>blueprints</artifactId> diff --git a/ms/blueprintsprocessor/modules/blueprints/resource-dict/pom.xml b/ms/blueprintsprocessor/modules/blueprints/resource-dict/pom.xml index c26301a5a..6fa99c0fb 100644 --- a/ms/blueprintsprocessor/modules/blueprints/resource-dict/pom.xml +++ b/ms/blueprintsprocessor/modules/blueprints/resource-dict/pom.xml @@ -16,13 +16,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>blueprints</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>resource-dict</artifactId> diff --git a/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt b/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt index 77025c5a4..70f151b66 100644 --- a/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt +++ b/ms/blueprintsprocessor/modules/blueprints/resource-dict/src/main/kotlin/org/onap/ccsdk/cds/controllerblueprints/resource/dict/ResourceDefinition.kt @@ -112,25 +112,25 @@ data class DictionaryMetadataEntry(val name: String, val value: String) */ data class ResolutionSummary( val name: String, - val value: JsonNode?, - val required: Boolean?, - val type: String?, + val value: JsonNode, + val required: Boolean, + val type: String, @JsonProperty("key-identifiers") val keyIdentifiers: MutableList<KeyIdentifier>, @JsonProperty("dictionary-description") - val dictionaryDescription: String?, + val dictionaryDescription: String, @JsonProperty("dictionary-metadata") val dictionaryMetadata: MutableList<DictionaryMetadataEntry>, @JsonProperty("dictionary-name") - val dictionaryName: String?, + val dictionaryName: String, @JsonProperty("dictionary-source") - val dictionarySource: String?, + val dictionarySource: String, @JsonProperty("request-payload") - val requestPayload: JsonNode?, + val requestPayload: JsonNode, @JsonProperty("status") - val status: String?, + val status: String, @JsonProperty("message") - val message: String? + val message: String ) /** * Interface for Source Definitions (ex Input Source, diff --git a/ms/blueprintsprocessor/modules/commons/db-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/db-lib/pom.xml index c91cb5351..71ef22062 100644 --- a/ms/blueprintsprocessor/modules/commons/db-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/db-lib/pom.xml @@ -15,13 +15,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>commons</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>db-lib</artifactId> diff --git a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BluePrintDBLibConfiguration.kt b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BluePrintDBLibConfiguration.kt index 0d737f4ca..637031972 100644 --- a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BluePrintDBLibConfiguration.kt +++ b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/BluePrintDBLibConfiguration.kt @@ -66,7 +66,7 @@ class DBLibConstants { // list of database const val MARIA_DB: String = "maria-db" - const val PRIMARY_DB: String = "processor-db" + const val PROCESSOR_DB: String = "processor-db" const val MYSQL_DB: String = "mysql-db" const val ORACLE_DB: String = "oracle-db" const val POSTGRES_DB: String = "postgres-db" diff --git a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/BluePrintDBLibPropertyService.kt b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/BluePrintDBLibPropertyService.kt index 35baf9314..e686e8396 100644 --- a/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/BluePrintDBLibPropertyService.kt +++ b/ms/blueprintsprocessor/modules/commons/db-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/db/primary/BluePrintDBLibPropertyService.kt @@ -20,10 +20,11 @@ import com.fasterxml.jackson.databind.JsonNode import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertiesService import org.onap.ccsdk.cds.blueprintsprocessor.db.BluePrintDBLibGenericService import org.onap.ccsdk.cds.blueprintsprocessor.db.DBDataSourceProperties -import org.onap.ccsdk.cds.blueprintsprocessor.db.DBLibConstants +import org.onap.ccsdk.cds.blueprintsprocessor.db.DBLibConstants.Companion.MARIA_DB +import org.onap.ccsdk.cds.blueprintsprocessor.db.DBLibConstants.Companion.MYSQL_DB +import org.onap.ccsdk.cds.blueprintsprocessor.db.DBLibConstants.Companion.PROCESSOR_DB import org.onap.ccsdk.cds.blueprintsprocessor.db.MariaDataSourceProperties import org.onap.ccsdk.cds.blueprintsprocessor.db.MySqlDataSourceProperties -import org.onap.ccsdk.cds.blueprintsprocessor.db.PrimaryDataSourceProperties import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.springframework.stereotype.Service @@ -31,79 +32,45 @@ import org.springframework.stereotype.Service @Service class BluePrintDBLibPropertyService(private var bluePrintPropertiesService: BluePrintPropertiesService) { - fun JdbcTemplate(jsonNode: JsonNode): BluePrintDBLibGenericService { - val dBConnetionProperties = dBDataSourceProperties(jsonNode) - return blueprintDBDataSourceService(dBConnetionProperties) - } + fun JdbcTemplate(jsonNode: JsonNode): BluePrintDBLibGenericService = + blueprintDBDataSourceService(dBDataSourceProperties(jsonNode)) - fun JdbcTemplate(selector: String): BluePrintDBLibGenericService { - val prefix = "blueprintsprocessor.db.$selector" - val dBConnetionProperties = dBDataSourceProperties(prefix) - return blueprintDBDataSourceService(dBConnetionProperties) - } + fun JdbcTemplate(selector: String): BluePrintDBLibGenericService = + blueprintDBDataSourceService(dBDataSourceProperties("blueprintsprocessor.db.$selector")) - private fun dBDataSourceProperties(jsonNode: JsonNode): DBDataSourceProperties { - val type = jsonNode.get("type").textValue() - return when (type) { - DBLibConstants.MYSQL_DB -> { - JacksonUtils.readValue(jsonNode, MySqlDataSourceProperties::class.java)!! - } - DBLibConstants.MARIA_DB -> { - JacksonUtils.readValue(jsonNode, MariaDataSourceProperties::class.java)!! - } - else -> { - throw BluePrintProcessorException("Rest adaptor($type) is not supported") - } - } - } + private fun dBDataSourceProperties(jsonNode: JsonNode): DBDataSourceProperties = + when (val type = jsonNode.get("type").textValue()) { + MYSQL_DB -> JacksonUtils.readValue(jsonNode, MySqlDataSourceProperties::class.java) + MARIA_DB -> JacksonUtils.readValue(jsonNode, MariaDataSourceProperties::class.java) + else -> { + throw BluePrintProcessorException( + "DB type ($type) is not supported. Valid types: $MARIA_DB, $MYSQL_DB") + } + }!! - private fun dBDataSourceProperties(prefix: String): DBDataSourceProperties { - val type = bluePrintPropertiesService.propertyBeanType("$prefix.type", String::class.java) - return when (type) { - DBLibConstants.MARIA_DB -> { - mariaDBConnectionProperties(prefix) - } - DBLibConstants.MYSQL_DB -> { - mySqlDBConnectionProperties(prefix) - } - DBLibConstants.ORACLE_DB -> { - TODO("not implemented") - } - DBLibConstants.POSTGRES_DB -> { - TODO("not implemented") + private fun dBDataSourceProperties(prefix: String): DBDataSourceProperties = + bluePrintPropertiesService.propertyBeanType("$prefix.type", String::class.java).let { + return when (it) { + MARIA_DB, PROCESSOR_DB -> mariaDBConnectionProperties(prefix) + MYSQL_DB -> mySqlDBConnectionProperties(prefix) + else -> { + throw BluePrintProcessorException( + "DB type ($it) is not supported. Valid types: $MARIA_DB, $MYSQL_DB, $PROCESSOR_DB") + } + } } - DBLibConstants.PRIMARY_DB -> { - primaryDBConnectionProperties(prefix) - } - else -> { - throw BluePrintProcessorException("Rest adaptor($type) is not supported") - } - } - } - private fun blueprintDBDataSourceService(dBConnetionProperties: DBDataSourceProperties): BluePrintDBLibGenericService { - when (dBConnetionProperties) { - is MariaDataSourceProperties -> { - return MariaDatabaseConfiguration(dBConnetionProperties) - } - is MySqlDataSourceProperties -> { - return MySqlDatabaseConfiguration(dBConnetionProperties) + private fun blueprintDBDataSourceService(dBConnetionProperties: DBDataSourceProperties): BluePrintDBLibGenericService = + when (dBConnetionProperties) { + is MariaDataSourceProperties -> MariaDatabaseConfiguration(dBConnetionProperties) + is MySqlDataSourceProperties -> MySqlDatabaseConfiguration(dBConnetionProperties) + else -> throw BluePrintProcessorException( + "Failed to create db configuration for ${dBConnetionProperties.url}") } - else -> { - throw BluePrintProcessorException("couldn't get rest service for") - } - } - } - - private fun mySqlDBConnectionProperties(prefix: String): MySqlDataSourceProperties { - return bluePrintPropertiesService.propertyBeanType(prefix, MySqlDataSourceProperties::class.java) - } - private fun mariaDBConnectionProperties(prefix: String): MariaDataSourceProperties { - return bluePrintPropertiesService.propertyBeanType(prefix, MariaDataSourceProperties::class.java) - } + private fun mySqlDBConnectionProperties(prefix: String): MySqlDataSourceProperties = + bluePrintPropertiesService.propertyBeanType(prefix, MySqlDataSourceProperties::class.java) - private fun primaryDBConnectionProperties(prefix: String): PrimaryDataSourceProperties { - return bluePrintPropertiesService.propertyBeanType(prefix, PrimaryDataSourceProperties::class.java) - } + private fun mariaDBConnectionProperties(prefix: String): MariaDataSourceProperties = + bluePrintPropertiesService.propertyBeanType(prefix, MariaDataSourceProperties::class.java) } diff --git a/ms/blueprintsprocessor/modules/commons/dmaap-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/dmaap-lib/pom.xml index a2fd4985a..2e54d3c51 100644 --- a/ms/blueprintsprocessor/modules/commons/dmaap-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/dmaap-lib/pom.xml @@ -18,13 +18,14 @@ ~ limitations under the License. ~ ============LICENSE_END========================================================= --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>commons</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>dmaap-lib</artifactId> diff --git a/ms/blueprintsprocessor/modules/commons/grpc-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/grpc-lib/pom.xml index 30067fb4e..af20c5d08 100644 --- a/ms/blueprintsprocessor/modules/commons/grpc-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/grpc-lib/pom.xml @@ -15,13 +15,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>commons</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>grpc-lib</artifactId> diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/message-lib/pom.xml index 04dd73688..cf287e280 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/message-lib/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>commons</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>message-lib</artifactId> diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/BluePrintMessageLibConfiguration.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/BluePrintMessageLibConfiguration.kt index cc4c7fa4a..c6587c799 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/BluePrintMessageLibConfiguration.kt +++ b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/BluePrintMessageLibConfiguration.kt @@ -61,6 +61,10 @@ class MessageLibConstants { const val PROPERTY_MESSAGE_CONSUMER_PREFIX = "blueprintsprocessor.messageconsumer." const val PROPERTY_MESSAGE_PRODUCER_PREFIX = "blueprintsprocessor.messageproducer." const val TYPE_KAFKA_BASIC_AUTH = "kafka-basic-auth" + const val TYPE_KAFKA_SCRAM_SSL_AUTH = "kafka-scram-ssl-auth" + const val TYPE_KAFKA_SSL_AUTH = "kafka-ssl-auth" const val TYPE_KAFKA_STREAMS_BASIC_AUTH = "kafka-streams-basic-auth" + const val TYPE_KAFKA_STREAMS_SSL_AUTH = "kafka-streams-ssl-auth" + const val TYPE_KAFKA_STREAMS_SCRAM_SSL_AUTH = "kafka-streams-scram-ssl-auth" } } diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/BluePrintMessageLibData.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/BluePrintMessageLibData.kt index 005223d9b..ac35fbf2c 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/BluePrintMessageLibData.kt +++ b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/BluePrintMessageLibData.kt @@ -17,49 +17,238 @@ package org.onap.ccsdk.cds.blueprintsprocessor.message +import org.apache.kafka.clients.CommonClientConfigs +import org.apache.kafka.clients.consumer.ConsumerConfig +import org.apache.kafka.clients.producer.ProducerConfig +import org.apache.kafka.common.config.SaslConfigs +import org.apache.kafka.common.config.SslConfigs +import org.apache.kafka.common.security.auth.SecurityProtocol +import org.apache.kafka.common.security.scram.ScramLoginModule +import org.apache.kafka.common.serialization.ByteArrayDeserializer +import org.apache.kafka.common.serialization.ByteArraySerializer +import org.apache.kafka.common.serialization.StringDeserializer +import org.apache.kafka.common.serialization.StringSerializer import org.apache.kafka.streams.StreamsConfig -/** Producer Properties **/ -open class MessageProducerProperties { +/** Common Properties **/ +abstract class CommonProperties { lateinit var type: String + lateinit var topic: String + lateinit var bootstrapServers: String + + open fun getConfig(): HashMap<String, Any> { + val configProps = hashMapOf<String, Any>() + configProps[ProducerConfig.BOOTSTRAP_SERVERS_CONFIG] = bootstrapServers + return configProps + } } +/** Message Producer */ +/** Message Producer Properties **/ +abstract class MessageProducerProperties : CommonProperties() + +/** Basic Auth */ open class KafkaBasicAuthMessageProducerProperties : MessageProducerProperties() { - lateinit var bootstrapServers: String - var topic: String? = null + var clientId: String? = null // strongest producing guarantee var acks: String = "all" var retries: Int = 0 // ensure we don't push duplicates var enableIdempotence: Boolean = true + + override fun getConfig(): HashMap<String, Any> { + val configProps = super.getConfig() + configProps[ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java + configProps[ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG] = ByteArraySerializer::class.java + configProps[ProducerConfig.ACKS_CONFIG] = acks + configProps[ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG] = enableIdempotence + if (clientId != null) { + configProps[ProducerConfig.CLIENT_ID_CONFIG] = clientId!! + } + return configProps + } } -/** Consumer Properties **/ +/** SSL Auth */ +open class KafkaSslAuthMessageProducerProperties : KafkaBasicAuthMessageProducerProperties() { + lateinit var truststore: String + lateinit var truststorePassword: String + var truststoreType: String = SslConfigs.DEFAULT_SSL_TRUSTSTORE_TYPE + var keystore: String? = null + var keystorePassword: String? = null + var keystoreType: String = SslConfigs.DEFAULT_SSL_KEYSTORE_TYPE + var sslEndpointIdentificationAlgorithm: String = "" -open class MessageConsumerProperties { - lateinit var type: String + override fun getConfig(): HashMap<String, Any> { + val configProps = super.getConfig() + configProps[CommonClientConfigs.SECURITY_PROTOCOL_CONFIG] = SecurityProtocol.SSL.toString() + configProps[SslConfigs.SSL_TRUSTSTORE_TYPE_CONFIG] = truststoreType + configProps[SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG] = truststore!! + configProps[SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG] = truststorePassword!! + if (keystore != null) { + configProps[SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG] = keystore!! + configProps[SslConfigs.SSL_KEYSTORE_TYPE_CONFIG] = keystoreType + configProps[SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG] = keystorePassword!! + } + configProps[SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG] = sslEndpointIdentificationAlgorithm + + return configProps + } } -open class KafkaStreamsConsumerProperties : MessageConsumerProperties() { - lateinit var bootstrapServers: String +/** (SASL) SCRAM SSL Auth */ +class KafkaScramSslAuthMessageProducerProperties : KafkaSslAuthMessageProducerProperties() { + var saslMechanism: String = "SCRAM-SHA-512" + lateinit var scramUsername: String + lateinit var scramPassword: String + + override fun getConfig(): HashMap<String, Any> { + val configProps = super.getConfig() + configProps[CommonClientConfigs.SECURITY_PROTOCOL_CONFIG] = SecurityProtocol.SASL_SSL.toString() + configProps[SaslConfigs.SASL_MECHANISM] = saslMechanism + configProps[SaslConfigs.SASL_JAAS_CONFIG] = "${ScramLoginModule::class.java.canonicalName} required " + + "username=\"${scramUsername}\" " + + "password=\"${scramPassword}\";" + return configProps + } +} + +/** Consumer */ +abstract class MessageConsumerProperties : CommonProperties() +/** Kafka Streams */ +/** Streams properties */ + +/** Basic Auth */ +open class KafkaStreamsBasicAuthConsumerProperties : MessageConsumerProperties() { lateinit var applicationId: String - lateinit var topic: String var autoOffsetReset: String = "latest" var processingGuarantee: String = StreamsConfig.EXACTLY_ONCE + + override fun getConfig(): HashMap<String, Any> { + val configProperties = super.getConfig() + configProperties[StreamsConfig.APPLICATION_ID_CONFIG] = applicationId + configProperties[ConsumerConfig.AUTO_OFFSET_RESET_CONFIG] = autoOffsetReset + configProperties[StreamsConfig.PROCESSING_GUARANTEE_CONFIG] = processingGuarantee + return configProperties + } } -open class KafkaStreamsBasicAuthConsumerProperties : KafkaStreamsConsumerProperties() +/** SSL Auth */ +open class KafkaStreamsSslAuthConsumerProperties : KafkaStreamsBasicAuthConsumerProperties() { + lateinit var truststore: String + lateinit var truststorePassword: String + var truststoreType: String = SslConfigs.DEFAULT_SSL_TRUSTSTORE_TYPE + var keystore: String? = null + var keystorePassword: String? = null + var keystoreType: String = SslConfigs.DEFAULT_SSL_KEYSTORE_TYPE + var sslEndpointIdentificationAlgorithm: String = "" -open class KafkaMessageConsumerProperties : MessageConsumerProperties() { - lateinit var bootstrapServers: String + override fun getConfig(): HashMap<String, Any> { + val configProps = super.getConfig() + configProps[CommonClientConfigs.SECURITY_PROTOCOL_CONFIG] = SecurityProtocol.SSL.toString() + configProps[SslConfigs.SSL_TRUSTSTORE_TYPE_CONFIG] = truststoreType + configProps[SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG] = truststore!! + configProps[SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG] = truststorePassword!! + if (keystore != null) { + configProps[SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG] = keystore!! + configProps[SslConfigs.SSL_KEYSTORE_TYPE_CONFIG] = keystoreType + configProps[SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG] = keystorePassword!! + } + configProps[SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG] = sslEndpointIdentificationAlgorithm + return configProps + } +} + +/** (SASL) SCRAM SSL Auth */ +class KafkaStreamsScramSslAuthConsumerProperties : KafkaStreamsSslAuthConsumerProperties() { + var saslMechanism: String = "SCRAM-SHA-512" + lateinit var scramUsername: String + lateinit var scramPassword: String + + override fun getConfig(): HashMap<String, Any> { + val configProps = super.getConfig() + configProps[CommonClientConfigs.SECURITY_PROTOCOL_CONFIG] = SecurityProtocol.SASL_SSL.toString() + configProps[SaslConfigs.SASL_MECHANISM] = saslMechanism + configProps[SaslConfigs.SASL_JAAS_CONFIG] = "${ScramLoginModule::class.java.canonicalName} required " + + "username=\"${scramUsername}\" " + + "password=\"${scramPassword}\";" + return configProps + } +} + +/** Message Consumer */ +/** Message Consumer Properties **/ +/** Basic Auth */ +open class KafkaBasicAuthMessageConsumerProperties : MessageConsumerProperties() { lateinit var groupId: String lateinit var clientId: String - var topic: String? = null var autoCommit: Boolean = true var autoOffsetReset: String = "latest" var pollMillSec: Long = 1000 var pollRecords: Int = -1 + + override fun getConfig(): HashMap<String, Any> { + val configProperties = super.getConfig() + configProperties[ConsumerConfig.GROUP_ID_CONFIG] = groupId + configProperties[ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG] = autoCommit + /** + * earliest: automatically reset the offset to the earliest offset + * latest: automatically reset the offset to the latest offset + */ + configProperties[ConsumerConfig.AUTO_OFFSET_RESET_CONFIG] = autoOffsetReset + configProperties[ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.java + configProperties[ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG] = ByteArrayDeserializer::class.java + configProperties[ConsumerConfig.CLIENT_ID_CONFIG] = clientId + + /** To handle Back pressure, Get only configured record for processing */ + if (pollRecords > 0) { + configProperties[ConsumerConfig.MAX_POLL_RECORDS_CONFIG] = pollRecords + } + + return configProperties + } } -open class KafkaBasicAuthMessageConsumerProperties : KafkaMessageConsumerProperties() +/** SSL Auth */ +open class KafkaSslAuthMessageConsumerProperties : KafkaBasicAuthMessageConsumerProperties() { + lateinit var truststore: String + lateinit var truststorePassword: String + var truststoreType: String = SslConfigs.DEFAULT_SSL_TRUSTSTORE_TYPE + var keystore: String? = null + var keystorePassword: String? = null + var keystoreType: String = SslConfigs.DEFAULT_SSL_KEYSTORE_TYPE + var sslEndpointIdentificationAlgorithm: String = "" + + override fun getConfig(): HashMap<String, Any> { + val configProps = super.getConfig() + configProps[CommonClientConfigs.SECURITY_PROTOCOL_CONFIG] = SecurityProtocol.SSL.toString() + configProps[SslConfigs.SSL_TRUSTSTORE_TYPE_CONFIG] = truststoreType + configProps[SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG] = truststore!! + configProps[SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG] = truststorePassword!! + if (keystore != null) { + configProps[SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG] = keystore!! + configProps[SslConfigs.SSL_KEYSTORE_TYPE_CONFIG] = keystoreType + configProps[SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG] = keystorePassword!! + } + configProps[SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG] = sslEndpointIdentificationAlgorithm + return configProps + } +} + +/** (SASL) SCRAM SSL Auth */ +class KafkaScramSslAuthMessageConsumerProperties : KafkaSslAuthMessageConsumerProperties() { + var saslMechanism: String = "SCRAM-SHA-512" + lateinit var scramUsername: String + lateinit var scramPassword: String + + override fun getConfig(): HashMap<String, Any> { + val configProps = super.getConfig() + configProps[CommonClientConfigs.SECURITY_PROTOCOL_CONFIG] = SecurityProtocol.SASL_SSL.toString() + configProps[SaslConfigs.SASL_MECHANISM] = saslMechanism + configProps[SaslConfigs.SASL_JAAS_CONFIG] = "${ScramLoginModule::class.java.canonicalName} required " + + "username=\"${scramUsername}\" " + + "password=\"${scramPassword}\";" + return configProps + } +} diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/MessagePropertiesDSL.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/MessagePropertiesDSL.kt index 88039466d..c659fdb8b 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/MessagePropertiesDSL.kt +++ b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/MessagePropertiesDSL.kt @@ -99,6 +99,20 @@ class MessageProducerRelationshipTemplateBuilder(name: String, description: Stri BluePrintTypes.kafkaBasicAuthMessageProducerProperties(block) ) } + + fun kafkaSslAuth(block: KafkaSslAuthMessageProducerPropertiesAssignmentBuilder.() -> Unit) { + property( + BluePrintConstants.PROPERTY_CONNECTION_CONFIG, + BluePrintTypes.kafkaSslAuthMessageProducerProperties(block) + ) + } + + fun kafkaScramSslAuth(block: KafkaScramSslAuthMessageProducerPropertiesAssignmentBuilder.() -> Unit) { + property( + BluePrintConstants.PROPERTY_CONNECTION_CONFIG, + BluePrintTypes.kafkaScramSslAuthMessageProducerProperties(block) + ) + } } fun BluePrintTypes.kafkaBasicAuthMessageProducerProperties(block: KafkaBasicAuthMessageProducerPropertiesAssignmentBuilder.() -> Unit): JsonNode { @@ -108,9 +122,23 @@ fun BluePrintTypes.kafkaBasicAuthMessageProducerProperties(block: KafkaBasicAuth return assignments.asJsonType() } +fun BluePrintTypes.kafkaSslAuthMessageProducerProperties(block: KafkaSslAuthMessageProducerPropertiesAssignmentBuilder.() -> Unit): JsonNode { + val assignments = KafkaSslAuthMessageProducerPropertiesAssignmentBuilder().apply(block).build() + assignments[KafkaSslAuthMessageProducerProperties::type.name] = + MessageLibConstants.TYPE_KAFKA_SSL_AUTH.asJsonPrimitive() + return assignments.asJsonType() +} + +fun BluePrintTypes.kafkaScramSslAuthMessageProducerProperties(block: KafkaScramSslAuthMessageProducerPropertiesAssignmentBuilder.() -> Unit): JsonNode { + val assignments = KafkaScramSslAuthMessageProducerPropertiesAssignmentBuilder().apply(block).build() + assignments[KafkaScramSslAuthMessageProducerProperties::type.name] = + MessageLibConstants.TYPE_KAFKA_SCRAM_SSL_AUTH.asJsonPrimitive() + return assignments.asJsonType() +} + open class MessageProducerPropertiesAssignmentBuilder : PropertiesAssignmentBuilder() -class KafkaBasicAuthMessageProducerPropertiesAssignmentBuilder : MessageProducerPropertiesAssignmentBuilder() { +open class KafkaBasicAuthMessageProducerPropertiesAssignmentBuilder : MessageProducerPropertiesAssignmentBuilder() { fun bootstrapServers(bootstrapServers: String) = bootstrapServers(bootstrapServers.asJsonPrimitive()) @@ -141,6 +169,61 @@ class KafkaBasicAuthMessageProducerPropertiesAssignmentBuilder : MessageProducer property(KafkaBasicAuthMessageProducerProperties::enableIdempotence, enableIdempotence) } +open class KafkaSslAuthMessageProducerPropertiesAssignmentBuilder : KafkaBasicAuthMessageProducerPropertiesAssignmentBuilder() { + fun truststore(truststore: String) = truststore(truststore.asJsonPrimitive()) + + fun truststore(truststore: JsonNode) = + property(KafkaSslAuthMessageProducerProperties::truststore, truststore) + + fun truststorePassword(truststorePassword: String) = truststorePassword(truststorePassword.asJsonPrimitive()) + + fun truststorePassword(truststorePassword: JsonNode) = + property(KafkaSslAuthMessageProducerProperties::truststorePassword, truststorePassword) + + fun truststoreType(truststoreType: String) = truststoreType(truststoreType.asJsonPrimitive()) + + fun truststoreType(truststoreType: JsonNode) = + property(KafkaSslAuthMessageProducerProperties::truststoreType, truststoreType) + + fun keystore(keystore: String) = keystore(keystore.asJsonPrimitive()) + + fun keystore(keystore: JsonNode) = + property(KafkaSslAuthMessageProducerProperties::keystore, keystore) + + fun keystorePassword(keystorePassword: String) = keystorePassword(keystorePassword.asJsonPrimitive()) + + fun keystorePassword(keystorePassword: JsonNode) = + property(KafkaSslAuthMessageProducerProperties::keystorePassword, keystorePassword) + + fun keystoreType(keystoreType: String) = keystoreType(keystoreType.asJsonPrimitive()) + + fun keystoreType(keystoreType: JsonNode) = + property(KafkaSslAuthMessageProducerProperties::keystoreType, keystoreType) + + fun sslEndpointIdentificationAlgorithm(sslEndpointIdentificationAlgorithm: String) = + sslEndpointIdentificationAlgorithm(sslEndpointIdentificationAlgorithm.asJsonPrimitive()) + + fun sslEndpointIdentificationAlgorithm(sslEndpointIdentificationAlgorithm: JsonNode) = + property(KafkaSslAuthMessageProducerProperties::sslEndpointIdentificationAlgorithm, sslEndpointIdentificationAlgorithm) +} + +class KafkaScramSslAuthMessageProducerPropertiesAssignmentBuilder : KafkaSslAuthMessageProducerPropertiesAssignmentBuilder() { + fun saslMechanism(saslMechanism: String) = saslMechanism(saslMechanism.asJsonPrimitive()) + + fun saslMechanism(saslMechanism: JsonNode) = + property(KafkaScramSslAuthMessageProducerProperties::saslMechanism, saslMechanism) + + fun scramUsername(scramUsername: String) = scramUsername(scramUsername.asJsonPrimitive()) + + fun scramUsername(scramUsername: JsonNode) = + property(KafkaScramSslAuthMessageProducerProperties::scramUsername, scramUsername) + + fun scramPassword(scramPassword: String) = scramPassword(scramPassword.asJsonPrimitive()) + + fun scramPassword(scramPassword: JsonNode) = + property(KafkaScramSslAuthMessageProducerProperties::scramPassword, scramPassword) +} + /** Relationships Templates DSL for Message Consumer */ fun TopologyTemplateBuilder.relationshipTemplateMessageConsumer( name: String, @@ -166,12 +249,40 @@ class MessageConsumerRelationshipTemplateBuilder(name: String, description: Stri ) } + fun kafkaSslAuth(block: KafkaSslAuthMessageConsumerPropertiesAssignmentBuilder.() -> Unit) { + property( + BluePrintConstants.PROPERTY_CONNECTION_CONFIG, + BluePrintTypes.kafkaSslAuthMessageConsumerProperties(block) + ) + } + + fun kafkaScramSslAuth(block: KafkaScramSslAuthMessageConsumerPropertiesAssignmentBuilder.() -> Unit) { + property( + BluePrintConstants.PROPERTY_CONNECTION_CONFIG, + BluePrintTypes.kafkaScramSslAuthMessageConsumerProperties(block) + ) + } + fun kafkaStreamsBasicAuth(block: KafkaStreamsBasicAuthConsumerPropertiesAssignmentBuilder.() -> Unit) { property( BluePrintConstants.PROPERTY_CONNECTION_CONFIG, BluePrintTypes.kafkaStreamsBasicAuthConsumerProperties(block) ) } + + fun kafkaStreamsSslAuth(block: KafkaStreamsSslAuthConsumerPropertiesAssignmentBuilder.() -> Unit) { + property( + BluePrintConstants.PROPERTY_CONNECTION_CONFIG, + BluePrintTypes.kafkaStreamsSslAuthConsumerProperties(block) + ) + } + + fun kafkaStreamsScramSslAuth(block: KafkaStreamsScramSslAuthConsumerPropertiesAssignmentBuilder.() -> Unit) { + property( + BluePrintConstants.PROPERTY_CONNECTION_CONFIG, + BluePrintTypes.kafkaStreamsScramSslAuthConsumerProperties(block) + ) + } } fun BluePrintTypes.kafkaBasicAuthMessageConsumerProperties(block: KafkaBasicAuthMessageConsumerPropertiesAssignmentBuilder.() -> Unit): JsonNode { @@ -181,6 +292,20 @@ fun BluePrintTypes.kafkaBasicAuthMessageConsumerProperties(block: KafkaBasicAuth return assignments.asJsonType() } +fun BluePrintTypes.kafkaSslAuthMessageConsumerProperties(block: KafkaSslAuthMessageConsumerPropertiesAssignmentBuilder.() -> Unit): JsonNode { + val assignments = KafkaSslAuthMessageConsumerPropertiesAssignmentBuilder().apply(block).build() + assignments[KafkaSslAuthMessageConsumerProperties::type.name] = + MessageLibConstants.TYPE_KAFKA_SSL_AUTH.asJsonPrimitive() + return assignments.asJsonType() +} + +fun BluePrintTypes.kafkaScramSslAuthMessageConsumerProperties(block: KafkaScramSslAuthMessageConsumerPropertiesAssignmentBuilder.() -> Unit): JsonNode { + val assignments = KafkaScramSslAuthMessageConsumerPropertiesAssignmentBuilder().apply(block).build() + assignments[KafkaScramSslAuthMessageConsumerProperties::type.name] = + MessageLibConstants.TYPE_KAFKA_SCRAM_SSL_AUTH.asJsonPrimitive() + return assignments.asJsonType() +} + fun BluePrintTypes.kafkaStreamsBasicAuthConsumerProperties(block: KafkaStreamsBasicAuthConsumerPropertiesAssignmentBuilder.() -> Unit): JsonNode { val assignments = KafkaStreamsBasicAuthConsumerPropertiesAssignmentBuilder().apply(block).build() assignments[KafkaStreamsBasicAuthConsumerProperties::type.name] = @@ -188,81 +313,201 @@ fun BluePrintTypes.kafkaStreamsBasicAuthConsumerProperties(block: KafkaStreamsBa return assignments.asJsonType() } +fun BluePrintTypes.kafkaStreamsSslAuthConsumerProperties(block: KafkaStreamsSslAuthConsumerPropertiesAssignmentBuilder.() -> Unit): JsonNode { + val assignments = KafkaStreamsSslAuthConsumerPropertiesAssignmentBuilder().apply(block).build() + assignments[KafkaStreamsSslAuthConsumerProperties::type.name] = + MessageLibConstants.TYPE_KAFKA_STREAMS_SSL_AUTH.asJsonPrimitive() + return assignments.asJsonType() +} + +fun BluePrintTypes.kafkaStreamsScramSslAuthConsumerProperties(block: KafkaStreamsScramSslAuthConsumerPropertiesAssignmentBuilder.() -> Unit): JsonNode { + val assignments = KafkaStreamsScramSslAuthConsumerPropertiesAssignmentBuilder().apply(block).build() + assignments[KafkaStreamsScramSslAuthConsumerProperties::type.name] = + MessageLibConstants.TYPE_KAFKA_STREAMS_SCRAM_SSL_AUTH.asJsonPrimitive() + return assignments.asJsonType() +} + open class MessageConsumerPropertiesAssignmentBuilder : PropertiesAssignmentBuilder() -open class KafkaMessageConsumerPropertiesAssignmentBuilder : MessageConsumerPropertiesAssignmentBuilder() { +/** KafkaBasicAuthMessageConsumerProperties assignment builder */ +open class KafkaBasicAuthMessageConsumerPropertiesAssignmentBuilder : MessageConsumerPropertiesAssignmentBuilder() { fun bootstrapServers(bootstrapServers: String) = bootstrapServers(bootstrapServers.asJsonPrimitive()) fun bootstrapServers(bootstrapServers: JsonNode) = - property(KafkaMessageConsumerProperties::bootstrapServers, bootstrapServers) + property(KafkaBasicAuthMessageConsumerProperties::bootstrapServers, bootstrapServers) fun groupId(groupId: String) = groupId(groupId.asJsonPrimitive()) fun groupId(groupId: JsonNode) = - property(KafkaMessageConsumerProperties::groupId, groupId) + property(KafkaBasicAuthMessageConsumerProperties::groupId, groupId) fun clientId(clientId: String) = clientId(clientId.asJsonPrimitive()) fun clientId(clientId: JsonNode) = - property(KafkaMessageConsumerProperties::clientId, clientId) + property(KafkaBasicAuthMessageConsumerProperties::clientId, clientId) fun topic(topic: String) = topic(topic.asJsonPrimitive()) fun topic(topic: JsonNode) = - property(KafkaMessageConsumerProperties::topic, topic) + property(KafkaBasicAuthMessageConsumerProperties::topic, topic) fun autoCommit(autoCommit: Boolean) = autoCommit(autoCommit.asJsonPrimitive()) fun autoCommit(autoCommit: JsonNode) = - property(KafkaMessageConsumerProperties::autoCommit, autoCommit) + property(KafkaBasicAuthMessageConsumerProperties::autoCommit, autoCommit) fun autoOffsetReset(autoOffsetReset: String) = autoOffsetReset(autoOffsetReset.asJsonPrimitive()) fun autoOffsetReset(autoOffsetReset: JsonNode) = - property(KafkaMessageConsumerProperties::autoOffsetReset, autoOffsetReset) + property(KafkaBasicAuthMessageConsumerProperties::autoOffsetReset, autoOffsetReset) fun pollMillSec(pollMillSec: Int) = pollMillSec(pollMillSec.asJsonPrimitive()) fun pollMillSec(pollMillSec: JsonNode) = - property(KafkaMessageConsumerProperties::pollMillSec, pollMillSec) + property(KafkaBasicAuthMessageConsumerProperties::pollMillSec, pollMillSec) fun pollRecords(pollRecords: Int) = pollRecords(pollRecords.asJsonPrimitive()) fun pollRecords(pollRecords: JsonNode) = - property(KafkaMessageConsumerProperties::pollRecords, pollRecords) + property(KafkaBasicAuthMessageConsumerProperties::pollRecords, pollRecords) } -/** KafkaBasicAuthMessageConsumerProperties assignment builder */ -class KafkaBasicAuthMessageConsumerPropertiesAssignmentBuilder : KafkaMessageConsumerPropertiesAssignmentBuilder() +open class KafkaSslAuthMessageConsumerPropertiesAssignmentBuilder : KafkaBasicAuthMessageConsumerPropertiesAssignmentBuilder() { + fun truststore(truststore: String) = truststore(truststore.asJsonPrimitive()) + + fun truststore(truststore: JsonNode) = + property(KafkaSslAuthMessageConsumerProperties::truststore, truststore) + + fun truststorePassword(truststorePassword: String) = truststorePassword(truststorePassword.asJsonPrimitive()) + + fun truststorePassword(truststorePassword: JsonNode) = + property(KafkaSslAuthMessageConsumerProperties::truststorePassword, truststorePassword) + + fun truststoreType(truststoreType: String) = truststoreType(truststoreType.asJsonPrimitive()) + + fun truststoreType(truststoreType: JsonNode) = + property(KafkaSslAuthMessageConsumerProperties::truststoreType, truststoreType) + + fun keystore(keystore: String) = keystore(keystore.asJsonPrimitive()) + + fun keystore(keystore: JsonNode) = + property(KafkaSslAuthMessageProducerProperties::keystore, keystore) + + fun keystorePassword(keystorePassword: String) = keystorePassword(keystorePassword.asJsonPrimitive()) + + fun keystorePassword(keystorePassword: JsonNode) = + property(KafkaSslAuthMessageProducerProperties::keystorePassword, keystorePassword) + + fun keystoreType(keystoreType: String) = keystoreType(keystoreType.asJsonPrimitive()) + + fun keystoreType(keystoreType: JsonNode) = + property(KafkaSslAuthMessageProducerProperties::keystoreType, keystoreType) + + fun sslEndpointIdentificationAlgorithm(sslEndpointIdentificationAlgorithm: String) = + sslEndpointIdentificationAlgorithm(sslEndpointIdentificationAlgorithm.asJsonPrimitive()) + + fun sslEndpointIdentificationAlgorithm(sslEndpointIdentificationAlgorithm: JsonNode) = + property(KafkaSslAuthMessageConsumerProperties::sslEndpointIdentificationAlgorithm, sslEndpointIdentificationAlgorithm) +} + +class KafkaScramSslAuthMessageConsumerPropertiesAssignmentBuilder : KafkaSslAuthMessageConsumerPropertiesAssignmentBuilder() { + fun saslMechanism(saslMechanism: String) = saslMechanism(saslMechanism.asJsonPrimitive()) + + fun saslMechanism(saslMechanism: JsonNode) = + property(KafkaScramSslAuthMessageConsumerProperties::saslMechanism, saslMechanism) + + fun scramUsername(scramUsername: String) = scramUsername(scramUsername.asJsonPrimitive()) + + fun scramUsername(scramUsername: JsonNode) = + property(KafkaScramSslAuthMessageConsumerProperties::scramUsername, scramUsername) + + fun scramPassword(scramPassword: String) = scramPassword(scramPassword.asJsonPrimitive()) + + fun scramPassword(scramPassword: JsonNode) = + property(KafkaScramSslAuthMessageConsumerProperties::scramPassword, scramPassword) +} /** KafkaStreamsConsumerProperties assignment builder */ -open class KafkaStreamsConsumerPropertiesAssignmentBuilder : MessageConsumerPropertiesAssignmentBuilder() { +open class KafkaStreamsBasicAuthConsumerPropertiesAssignmentBuilder : MessageConsumerPropertiesAssignmentBuilder() { fun bootstrapServers(bootstrapServers: String) = bootstrapServers(bootstrapServers.asJsonPrimitive()) fun bootstrapServers(bootstrapServers: JsonNode) = - property(KafkaStreamsConsumerProperties::bootstrapServers, bootstrapServers) + property(KafkaStreamsBasicAuthConsumerProperties::bootstrapServers, bootstrapServers) fun applicationId(applicationId: String) = bootstrapServers(applicationId.asJsonPrimitive()) fun applicationId(applicationId: JsonNode) = - property(KafkaStreamsConsumerProperties::applicationId, applicationId) + property(KafkaStreamsBasicAuthConsumerProperties::applicationId, applicationId) fun topic(topic: String) = topic(topic.asJsonPrimitive()) fun topic(topic: JsonNode) = - property(KafkaStreamsConsumerProperties::topic, topic) + property(KafkaStreamsBasicAuthConsumerProperties::topic, topic) fun autoOffsetReset(autoOffsetReset: String) = autoOffsetReset(autoOffsetReset.asJsonPrimitive()) fun autoOffsetReset(autoOffsetReset: JsonNode) = - property(KafkaStreamsConsumerProperties::autoOffsetReset, autoOffsetReset) + property(KafkaStreamsBasicAuthConsumerProperties::autoOffsetReset, autoOffsetReset) fun processingGuarantee(processingGuarantee: String) = processingGuarantee(processingGuarantee.asJsonPrimitive()) fun processingGuarantee(processingGuarantee: JsonNode) = - property(KafkaStreamsConsumerProperties::processingGuarantee, processingGuarantee) + property(KafkaStreamsBasicAuthConsumerProperties::processingGuarantee, processingGuarantee) } -class KafkaStreamsBasicAuthConsumerPropertiesAssignmentBuilder : KafkaStreamsConsumerPropertiesAssignmentBuilder() +open class KafkaStreamsSslAuthConsumerPropertiesAssignmentBuilder : KafkaStreamsBasicAuthConsumerPropertiesAssignmentBuilder() { + fun truststore(truststore: String) = truststore(truststore.asJsonPrimitive()) + + fun truststore(truststore: JsonNode) = + property(KafkaStreamsSslAuthConsumerProperties::truststore, truststore) + + fun truststorePassword(truststorePassword: String) = truststorePassword(truststorePassword.asJsonPrimitive()) + + fun truststorePassword(truststorePassword: JsonNode) = + property(KafkaStreamsSslAuthConsumerProperties::truststorePassword, truststorePassword) + + fun truststoreType(truststoreType: String) = truststoreType(truststoreType.asJsonPrimitive()) + + fun truststoreType(truststoreType: JsonNode) = + property(KafkaStreamsSslAuthConsumerProperties::truststoreType, truststoreType) + + fun keystore(keystore: String) = keystore(keystore.asJsonPrimitive()) + + fun keystore(keystore: JsonNode) = + property(KafkaSslAuthMessageProducerProperties::keystore, keystore) + + fun keystorePassword(keystorePassword: String) = keystorePassword(keystorePassword.asJsonPrimitive()) + + fun keystorePassword(keystorePassword: JsonNode) = + property(KafkaSslAuthMessageProducerProperties::keystorePassword, keystorePassword) + + fun keystoreType(keystoreType: String) = keystoreType(keystoreType.asJsonPrimitive()) + + fun keystoreType(keystoreType: JsonNode) = + property(KafkaSslAuthMessageProducerProperties::keystoreType, keystoreType) + + fun sslEndpointIdentificationAlgorithm(sslEndpointIdentificationAlgorithm: String) = + sslEndpointIdentificationAlgorithm(sslEndpointIdentificationAlgorithm.asJsonPrimitive()) + + fun sslEndpointIdentificationAlgorithm(sslEndpointIdentificationAlgorithm: JsonNode) = + property(KafkaStreamsSslAuthConsumerProperties::sslEndpointIdentificationAlgorithm, sslEndpointIdentificationAlgorithm) +} + +class KafkaStreamsScramSslAuthConsumerPropertiesAssignmentBuilder : KafkaStreamsSslAuthConsumerPropertiesAssignmentBuilder() { + fun saslMechanism(saslMechanism: String) = saslMechanism(saslMechanism.asJsonPrimitive()) + + fun saslMechanism(saslMechanism: JsonNode) = + property(KafkaStreamsScramSslAuthConsumerProperties::saslMechanism, saslMechanism) + + fun scramUsername(scramUsername: String) = scramUsername(scramUsername.asJsonPrimitive()) + + fun scramUsername(scramUsername: JsonNode) = + property(KafkaStreamsScramSslAuthConsumerProperties::scramUsername, scramUsername) + + fun scramPassword(scramPassword: String) = scramPassword(scramPassword.asJsonPrimitive()) + + fun scramPassword(scramPassword: JsonNode) = + property(KafkaStreamsScramSslAuthConsumerProperties::scramPassword, scramPassword) +} diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BluePrintMessageLibPropertyService.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BluePrintMessageLibPropertyService.kt index 44b50af44..67fbef580 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BluePrintMessageLibPropertyService.kt +++ b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BluePrintMessageLibPropertyService.kt @@ -21,7 +21,13 @@ import com.fasterxml.jackson.databind.JsonNode import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertiesService import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaBasicAuthMessageConsumerProperties import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaBasicAuthMessageProducerProperties +import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaScramSslAuthMessageConsumerProperties +import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaScramSslAuthMessageProducerProperties +import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaSslAuthMessageConsumerProperties +import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaSslAuthMessageProducerProperties import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaStreamsBasicAuthConsumerProperties +import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaStreamsScramSslAuthConsumerProperties +import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaStreamsSslAuthConsumerProperties import org.onap.ccsdk.cds.blueprintsprocessor.message.MessageConsumerProperties import org.onap.ccsdk.cds.blueprintsprocessor.message.MessageLibConstants import org.onap.ccsdk.cds.blueprintsprocessor.message.MessageProducerProperties @@ -34,20 +40,32 @@ open class BluePrintMessageLibPropertyService(private var bluePrintPropertiesSer fun blueprintMessageProducerService(jsonNode: JsonNode): BlueprintMessageProducerService { val messageClientProperties = messageProducerProperties(jsonNode) - return blueprintMessageProducerService(messageClientProperties) + return KafkaMessageProducerService(messageClientProperties) } fun blueprintMessageProducerService(selector: String): BlueprintMessageProducerService { val prefix = "${MessageLibConstants.PROPERTY_MESSAGE_PRODUCER_PREFIX}$selector" val messageClientProperties = messageProducerProperties(prefix) - return blueprintMessageProducerService(messageClientProperties) + return KafkaMessageProducerService(messageClientProperties) } fun messageProducerProperties(prefix: String): MessageProducerProperties { val type = bluePrintPropertiesService.propertyBeanType("$prefix.type", String::class.java) return when (type) { MessageLibConstants.TYPE_KAFKA_BASIC_AUTH -> { - kafkaBasicAuthMessageProducerProperties(prefix) + bluePrintPropertiesService.propertyBeanType( + prefix, KafkaBasicAuthMessageProducerProperties::class.java + ) + } + MessageLibConstants.TYPE_KAFKA_SSL_AUTH -> { + bluePrintPropertiesService.propertyBeanType( + prefix, KafkaSslAuthMessageProducerProperties::class.java + ) + } + MessageLibConstants.TYPE_KAFKA_SCRAM_SSL_AUTH -> { + bluePrintPropertiesService.propertyBeanType( + prefix, KafkaScramSslAuthMessageProducerProperties::class.java + ) } else -> { throw BluePrintProcessorException("Message adaptor($type) is not supported") @@ -61,31 +79,18 @@ open class BluePrintMessageLibPropertyService(private var bluePrintPropertiesSer MessageLibConstants.TYPE_KAFKA_BASIC_AUTH -> { JacksonUtils.readValue(jsonNode, KafkaBasicAuthMessageProducerProperties::class.java)!! } - else -> { - throw BluePrintProcessorException("Message adaptor($type) is not supported") + MessageLibConstants.TYPE_KAFKA_SSL_AUTH -> { + JacksonUtils.readValue(jsonNode, KafkaSslAuthMessageProducerProperties::class.java)!! } - } - } - - private fun blueprintMessageProducerService(MessageProducerProperties: MessageProducerProperties): - BlueprintMessageProducerService { - - when (MessageProducerProperties) { - is KafkaBasicAuthMessageProducerProperties -> { - return KafkaBasicAuthMessageProducerService(MessageProducerProperties) + MessageLibConstants.TYPE_KAFKA_SCRAM_SSL_AUTH -> { + JacksonUtils.readValue(jsonNode, KafkaScramSslAuthMessageProducerProperties::class.java)!! } else -> { - throw BluePrintProcessorException("couldn't get Message client service for") + throw BluePrintProcessorException("Message adaptor($type) is not supported") } } } - private fun kafkaBasicAuthMessageProducerProperties(prefix: String): KafkaBasicAuthMessageProducerProperties { - return bluePrintPropertiesService.propertyBeanType( - prefix, KafkaBasicAuthMessageProducerProperties::class.java - ) - } - /** Consumer Property Lib Service Implementation **/ /** Return Message Consumer Service for [jsonNode] definitions. */ @@ -105,11 +110,37 @@ open class BluePrintMessageLibPropertyService(private var bluePrintPropertiesSer fun messageConsumerProperties(prefix: String): MessageConsumerProperties { val type = bluePrintPropertiesService.propertyBeanType("$prefix.type", String::class.java) return when (type) { + /** Message Consumer */ MessageLibConstants.TYPE_KAFKA_BASIC_AUTH -> { - kafkaBasicAuthMessageConsumerProperties(prefix) + bluePrintPropertiesService.propertyBeanType( + prefix, KafkaBasicAuthMessageConsumerProperties::class.java + ) + } + MessageLibConstants.TYPE_KAFKA_SSL_AUTH -> { + bluePrintPropertiesService.propertyBeanType( + prefix, KafkaSslAuthMessageConsumerProperties::class.java + ) } + MessageLibConstants.TYPE_KAFKA_SCRAM_SSL_AUTH -> { + bluePrintPropertiesService.propertyBeanType( + prefix, KafkaScramSslAuthMessageConsumerProperties::class.java + ) + } + /** Stream Consumer */ MessageLibConstants.TYPE_KAFKA_STREAMS_BASIC_AUTH -> { - kafkaStreamsBasicAuthMessageConsumerProperties(prefix) + bluePrintPropertiesService.propertyBeanType( + prefix, KafkaStreamsBasicAuthConsumerProperties::class.java + ) + } + MessageLibConstants.TYPE_KAFKA_STREAMS_SSL_AUTH -> { + bluePrintPropertiesService.propertyBeanType( + prefix, KafkaStreamsSslAuthConsumerProperties::class.java + ) + } + MessageLibConstants.TYPE_KAFKA_STREAMS_SCRAM_SSL_AUTH -> { + bluePrintPropertiesService.propertyBeanType( + prefix, KafkaStreamsScramSslAuthConsumerProperties::class.java + ) } else -> { throw BluePrintProcessorException("Message adaptor($type) is not supported") @@ -120,12 +151,26 @@ open class BluePrintMessageLibPropertyService(private var bluePrintPropertiesSer fun messageConsumerProperties(jsonNode: JsonNode): MessageConsumerProperties { val type = jsonNode.get("type").textValue() return when (type) { + /** Message Consumer */ MessageLibConstants.TYPE_KAFKA_BASIC_AUTH -> { JacksonUtils.readValue(jsonNode, KafkaBasicAuthMessageConsumerProperties::class.java)!! } + MessageLibConstants.TYPE_KAFKA_SSL_AUTH -> { + JacksonUtils.readValue(jsonNode, KafkaSslAuthMessageConsumerProperties::class.java)!! + } + MessageLibConstants.TYPE_KAFKA_SCRAM_SSL_AUTH -> { + JacksonUtils.readValue(jsonNode, KafkaScramSslAuthMessageConsumerProperties::class.java)!! + } + /** Stream Consumer */ MessageLibConstants.TYPE_KAFKA_STREAMS_BASIC_AUTH -> { JacksonUtils.readValue(jsonNode, KafkaStreamsBasicAuthConsumerProperties::class.java)!! } + MessageLibConstants.TYPE_KAFKA_STREAMS_SSL_AUTH -> { + JacksonUtils.readValue(jsonNode, KafkaStreamsSslAuthConsumerProperties::class.java)!! + } + MessageLibConstants.TYPE_KAFKA_STREAMS_SCRAM_SSL_AUTH -> { + JacksonUtils.readValue(jsonNode, KafkaStreamsScramSslAuthConsumerProperties::class.java)!! + } else -> { throw BluePrintProcessorException("Message adaptor($type) is not supported") } @@ -135,28 +180,42 @@ open class BluePrintMessageLibPropertyService(private var bluePrintPropertiesSer private fun blueprintMessageConsumerService(messageConsumerProperties: MessageConsumerProperties): BlueprintMessageConsumerService { - when (messageConsumerProperties) { - is KafkaBasicAuthMessageConsumerProperties -> { - return KafkaBasicAuthMessageConsumerService(messageConsumerProperties) + when (messageConsumerProperties.type) { + /** Message Consumer */ + MessageLibConstants.TYPE_KAFKA_BASIC_AUTH -> { + return KafkaMessageConsumerService( + messageConsumerProperties as KafkaBasicAuthMessageConsumerProperties + ) + } + MessageLibConstants.TYPE_KAFKA_SSL_AUTH -> { + return KafkaMessageConsumerService( + messageConsumerProperties as KafkaSslAuthMessageConsumerProperties + ) + } + MessageLibConstants.TYPE_KAFKA_SCRAM_SSL_AUTH -> { + return KafkaMessageConsumerService( + messageConsumerProperties as KafkaScramSslAuthMessageConsumerProperties + ) } - is KafkaStreamsBasicAuthConsumerProperties -> { - return KafkaStreamsBasicAuthConsumerService(messageConsumerProperties) + /** Stream Consumer */ + MessageLibConstants.TYPE_KAFKA_STREAMS_BASIC_AUTH -> { + return KafkaStreamsConsumerService( + messageConsumerProperties as KafkaStreamsBasicAuthConsumerProperties + ) + } + MessageLibConstants.TYPE_KAFKA_STREAMS_SSL_AUTH -> { + return KafkaStreamsConsumerService( + messageConsumerProperties as KafkaStreamsSslAuthConsumerProperties + ) + } + MessageLibConstants.TYPE_KAFKA_STREAMS_SCRAM_SSL_AUTH -> { + return KafkaStreamsConsumerService( + messageConsumerProperties as KafkaStreamsScramSslAuthConsumerProperties + ) } else -> { - throw BluePrintProcessorException("couldn't get Message client service for") + throw BluePrintProcessorException("couldn't get message client service for ${messageConsumerProperties.type}") } } } - - private fun kafkaBasicAuthMessageConsumerProperties(prefix: String): KafkaBasicAuthMessageConsumerProperties { - return bluePrintPropertiesService.propertyBeanType( - prefix, KafkaBasicAuthMessageConsumerProperties::class.java - ) - } - - private fun kafkaStreamsBasicAuthMessageConsumerProperties(prefix: String): KafkaStreamsBasicAuthConsumerProperties { - return bluePrintPropertiesService.propertyBeanType( - prefix, KafkaStreamsBasicAuthConsumerProperties::class.java - ) - } } diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaBasicAuthMessageConsumerService.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaMessageConsumerService.kt index 3415c8d0d..cdcd4197c 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaBasicAuthMessageConsumerService.kt +++ b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaMessageConsumerService.kt @@ -21,24 +21,20 @@ import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking -import org.apache.kafka.clients.CommonClientConfigs import org.apache.kafka.clients.consumer.Consumer -import org.apache.kafka.clients.consumer.ConsumerConfig import org.apache.kafka.clients.consumer.KafkaConsumer -import org.apache.kafka.common.serialization.ByteArrayDeserializer -import org.apache.kafka.common.serialization.StringDeserializer import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaBasicAuthMessageConsumerProperties import org.onap.ccsdk.cds.controllerblueprints.core.logger import java.nio.charset.Charset import java.time.Duration import kotlin.concurrent.thread -open class KafkaBasicAuthMessageConsumerService( +open class KafkaMessageConsumerService( private val messageConsumerProperties: KafkaBasicAuthMessageConsumerProperties ) : BlueprintMessageConsumerService { - val log = logger(KafkaBasicAuthMessageConsumerService::class) + val log = logger(KafkaMessageConsumerService::class) val channel = Channel<String>() var kafkaConsumer: Consumer<String, ByteArray>? = null @@ -46,24 +42,7 @@ open class KafkaBasicAuthMessageConsumerService( var keepGoing = true fun kafkaConsumer(additionalConfig: Map<String, Any>? = null): Consumer<String, ByteArray> { - val configProperties = hashMapOf<String, Any>() - configProperties[CommonClientConfigs.BOOTSTRAP_SERVERS_CONFIG] = messageConsumerProperties.bootstrapServers - configProperties[ConsumerConfig.GROUP_ID_CONFIG] = messageConsumerProperties.groupId - configProperties[ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG] = messageConsumerProperties.autoCommit - /** - * earliest: automatically reset the offset to the earliest offset - * latest: automatically reset the offset to the latest offset - */ - configProperties[ConsumerConfig.AUTO_OFFSET_RESET_CONFIG] = messageConsumerProperties.autoOffsetReset - configProperties[ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.java - configProperties[ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG] = ByteArrayDeserializer::class.java - configProperties[ConsumerConfig.CLIENT_ID_CONFIG] = messageConsumerProperties.clientId - - /** To handle Back pressure, Get only configured record for processing */ - if (messageConsumerProperties.pollRecords > 0) { - configProperties[ConsumerConfig.MAX_POLL_RECORDS_CONFIG] = messageConsumerProperties.pollRecords - } - // TODO("Security Implementation based on type") + val configProperties = messageConsumerProperties.getConfig() /** add or override already set properties */ additionalConfig?.let { configProperties.putAll(it) } /** Create Kafka consumer */ diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaBasicAuthMessageProducerService.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaMessageProducerService.kt index 8416282af..931f052ed 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaBasicAuthMessageProducerService.kt +++ b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaMessageProducerService.kt @@ -20,28 +20,20 @@ package org.onap.ccsdk.cds.blueprintsprocessor.message.service import org.apache.commons.lang.builder.ToStringBuilder import org.apache.kafka.clients.producer.Callback import org.apache.kafka.clients.producer.KafkaProducer -import org.apache.kafka.clients.producer.ProducerConfig.ACKS_CONFIG -import org.apache.kafka.clients.producer.ProducerConfig.BOOTSTRAP_SERVERS_CONFIG -import org.apache.kafka.clients.producer.ProducerConfig.CLIENT_ID_CONFIG -import org.apache.kafka.clients.producer.ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG -import org.apache.kafka.clients.producer.ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG -import org.apache.kafka.clients.producer.ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG import org.apache.kafka.clients.producer.ProducerRecord import org.apache.kafka.common.header.internals.RecordHeader -import org.apache.kafka.common.serialization.ByteArraySerializer -import org.apache.kafka.common.serialization.StringSerializer -import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaBasicAuthMessageProducerProperties +import org.onap.ccsdk.cds.blueprintsprocessor.message.MessageProducerProperties import org.onap.ccsdk.cds.controllerblueprints.core.asJsonString import org.onap.ccsdk.cds.controllerblueprints.core.defaultToUUID import org.slf4j.LoggerFactory import java.nio.charset.Charset -class KafkaBasicAuthMessageProducerService( - private val messageProducerProperties: KafkaBasicAuthMessageProducerProperties +class KafkaMessageProducerService( + private val messageProducerProperties: MessageProducerProperties ) : BlueprintMessageProducerService { - private val log = LoggerFactory.getLogger(KafkaBasicAuthMessageProducerService::class.java)!! + private val log = LoggerFactory.getLogger(KafkaMessageProducerService::class.java)!! private var kafkaProducer: KafkaProducer<String, ByteArray>? = null @@ -81,26 +73,16 @@ class KafkaBasicAuthMessageProducerService( } fun messageTemplate(additionalConfig: Map<String, ByteArray>? = null): KafkaProducer<String, ByteArray> { - log.trace("Client Properties : ${ToStringBuilder.reflectionToString(messageProducerProperties)}") - val configProps = hashMapOf<String, Any>() - configProps[BOOTSTRAP_SERVERS_CONFIG] = messageProducerProperties.bootstrapServers - configProps[KEY_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java - configProps[VALUE_SERIALIZER_CLASS_CONFIG] = ByteArraySerializer::class.java - configProps[ACKS_CONFIG] = messageProducerProperties.acks - configProps[ENABLE_IDEMPOTENCE_CONFIG] = messageProducerProperties.enableIdempotence - if (messageProducerProperties.clientId != null) { - configProps[CLIENT_ID_CONFIG] = messageProducerProperties.clientId!! - } - // TODO("Security Implementation based on type") + log.trace("Producer client properties : ${ToStringBuilder.reflectionToString(messageProducerProperties)}") + val configProps = messageProducerProperties.getConfig() - // Add additional Properties - if (additionalConfig != null) { + /** Add additional Properties */ + if (additionalConfig != null) configProps.putAll(additionalConfig) - } - if (kafkaProducer == null) { + if (kafkaProducer == null) kafkaProducer = KafkaProducer(configProps) - } + return kafkaProducer!! } } diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaStreamsBasicAuthConsumerService.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaStreamsConsumerService.kt index 0b353d58b..60f2dfa05 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaStreamsBasicAuthConsumerService.kt +++ b/ms/blueprintsprocessor/modules/commons/message-lib/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaStreamsConsumerService.kt @@ -17,27 +17,22 @@ package org.onap.ccsdk.cds.blueprintsprocessor.message.service import kotlinx.coroutines.channels.Channel -import org.apache.kafka.clients.consumer.ConsumerConfig import org.apache.kafka.streams.KafkaStreams -import org.apache.kafka.streams.StreamsConfig -import org.onap.ccsdk.cds.blueprintsprocessor.message.KafkaStreamsBasicAuthConsumerProperties +import org.onap.ccsdk.cds.blueprintsprocessor.message.MessageConsumerProperties import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.logger import java.util.Properties -open class KafkaStreamsBasicAuthConsumerService(private val messageConsumerProperties: KafkaStreamsBasicAuthConsumerProperties) : +open class KafkaStreamsConsumerService(private val messageConsumerProperties: MessageConsumerProperties) : BlueprintMessageConsumerService { - val log = logger(KafkaStreamsBasicAuthConsumerService::class) + val log = logger(KafkaStreamsConsumerService::class) lateinit var kafkaStreams: KafkaStreams private fun streamsConfig(additionalConfig: Map<String, Any>? = null): Properties { val configProperties = Properties() - configProperties[StreamsConfig.APPLICATION_ID_CONFIG] = messageConsumerProperties.applicationId - configProperties[StreamsConfig.BOOTSTRAP_SERVERS_CONFIG] = messageConsumerProperties.bootstrapServers - configProperties[ConsumerConfig.AUTO_OFFSET_RESET_CONFIG] = messageConsumerProperties.autoOffsetReset - configProperties[StreamsConfig.PROCESSING_GUARANTEE_CONFIG] = messageConsumerProperties.processingGuarantee - // TODO("Security Implementation based on type") + /** set consumer properties */ + messageConsumerProperties.getConfig().let { configProperties.putAll(it) } /** add or override already set properties */ additionalConfig?.let { configProperties.putAll(it) } /** Create Kafka consumer */ diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/MessagePropertiesDSLTest.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/MessagePropertiesDSLTest.kt index b10e1023b..612a57d23 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/MessagePropertiesDSLTest.kt +++ b/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/MessagePropertiesDSLTest.kt @@ -27,17 +27,27 @@ import kotlin.test.assertNotNull class MessagePropertiesDSLTest { @Test - fun testMessageProducerDSL() { + fun testScramSslMessageProducerDSL() { val serviceTemplate = serviceTemplate("message-properties-test", "1.0.0", "xxx.@xx.com", "message") { topologyTemplate { - relationshipTemplateMessageProducer("sample-basic-auth", "Message Producer") { - kafkaBasicAuth { + relationshipTemplateMessageProducer("sample-scram-ssl-auth", "Message Producer") { + kafkaScramSslAuth { bootstrapServers("sample-bootstrapServers") clientId("sample-client-id") acks("all") retries(3) enableIdempotence(true) topic("sample-topic") + truststore("/path/to/truststore.jks") + truststorePassword("secretpassword") + truststoreType("JKS") + keystore("/path/to/keystore.jks") + keystorePassword("secretpassword") + keystoreType("JKS") + sslEndpointIdentificationAlgorithm("") + saslMechanism("SCRAM-SHA-512") + scramUsername("sample-user") + scramPassword("secretpassword") } } } @@ -50,27 +60,27 @@ class MessagePropertiesDSLTest { val relationshipTemplates = serviceTemplate.topologyTemplate?.relationshipTemplates assertNotNull(relationshipTemplates, "failed to get relationship templates") assertEquals(1, relationshipTemplates.size, "relationshipTemplates doesn't match") - assertNotNull(relationshipTemplates["sample-basic-auth"], "failed to get sample-basic-auth") + assertNotNull(relationshipTemplates["sample-scram-ssl-auth"], "failed to get sample-scram-ssl-auth") val relationshipTypes = serviceTemplate.relationshipTypes assertNotNull(relationshipTypes, "failed to get relationship types") assertEquals(2, relationshipTypes.size, "relationshipTypes doesn't match") assertNotNull( - relationshipTypes[BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO], - "failed to get ${BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO}" + relationshipTypes[BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO], + "failed to get ${BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO}" ) assertNotNull( - relationshipTypes[BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO_MESSAGE_PRODUCER], - "failed to get ${BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO_MESSAGE_PRODUCER}" + relationshipTypes[BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO_MESSAGE_PRODUCER], + "failed to get ${BluePrintConstants.MODEL_TYPE_RELATIONSHIPS_CONNECTS_TO_MESSAGE_PRODUCER}" ) } @Test - fun testMessageConsumerDSL() { + fun testScramSslAuthMessageConsumerDSL() { val serviceTemplate = serviceTemplate("message-properties-test", "1.0.0", "xxx.@xx.com", "message") { topologyTemplate { - relationshipTemplateMessageConsumer("sample-basic-auth", "Message Consumer") { - kafkaBasicAuth { + relationshipTemplateMessageConsumer("sample-scram-ssl-auth", "Message Consumer") { + kafkaScramSslAuth { bootstrapServers("sample-bootstrapServers") clientId("sample-client-id") groupId("sample-group-id") @@ -79,15 +89,35 @@ class MessagePropertiesDSLTest { autoOffsetReset("latest") pollMillSec(5000) pollRecords(20) + truststore("/path/to/truststore.jks") + truststorePassword("secretpassword") + truststoreType("JKS") + keystore("/path/to/keystore.jks") + keystorePassword("secretpassword") + keystoreType("JKS") + sslEndpointIdentificationAlgorithm("") + saslMechanism("SCRAM-SHA-512") + scramUsername("sample-user") + scramPassword("secretpassword") } } - relationshipTemplateMessageConsumer("sample-stream-basic-auth", "Message Consumer") { - kafkaStreamsBasicAuth { + relationshipTemplateMessageConsumer("sample-stream-scram-ssl-auth", "Message Consumer") { + kafkaStreamsScramSslAuth { bootstrapServers("sample-bootstrapServers") applicationId("sample-application-id") autoOffsetReset("latest") processingGuarantee(StreamsConfig.EXACTLY_ONCE) topic("sample-streaming-topic") + truststore("/path/to/truststore.jks") + truststorePassword("secretpassword") + truststoreType("JKS") + keystore("/path/to/keystore.jks") + keystorePassword("secretpassword") + keystoreType("JKS") + sslEndpointIdentificationAlgorithm("") + saslMechanism("SCRAM-SHA-512") + scramUsername("sample-user") + scramPassword("secretpassword") } } } @@ -100,8 +130,8 @@ class MessagePropertiesDSLTest { val relationshipTemplates = serviceTemplate.topologyTemplate?.relationshipTemplates assertNotNull(relationshipTemplates, "failed to get relationship templates") assertEquals(2, relationshipTemplates.size, "relationshipTemplates doesn't match") - assertNotNull(relationshipTemplates["sample-basic-auth"], "failed to get sample-basic-auth") - assertNotNull(relationshipTemplates["sample-stream-basic-auth"], "failed to get sample-stream-basic-auth") + assertNotNull(relationshipTemplates["sample-scram-ssl-auth"], "failed to get sample-scram-ssl-auth") + assertNotNull(relationshipTemplates["sample-stream-scram-ssl-auth"], "failed to get sample-stream-scram-ssl-auth") val relationshipTypes = serviceTemplate.relationshipTypes assertNotNull(relationshipTypes, "failed to get relationship types") diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageConsumerServiceTest.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageConsumerServiceTest.kt index 823ba7dee..ac08dc7b7 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageConsumerServiceTest.kt +++ b/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageConsumerServiceTest.kt @@ -23,24 +23,35 @@ import kotlinx.coroutines.channels.consumeEach import kotlinx.coroutines.delay import kotlinx.coroutines.launch import kotlinx.coroutines.runBlocking +import org.apache.kafka.clients.CommonClientConfigs import org.apache.kafka.clients.consumer.Consumer +import org.apache.kafka.clients.consumer.ConsumerConfig import org.apache.kafka.clients.consumer.ConsumerRecord import org.apache.kafka.clients.consumer.ConsumerRecords import org.apache.kafka.clients.consumer.MockConsumer import org.apache.kafka.clients.consumer.OffsetResetStrategy +import org.apache.kafka.clients.producer.ProducerConfig import org.apache.kafka.common.TopicPartition +import org.apache.kafka.common.config.SaslConfigs +import org.apache.kafka.common.config.SslConfigs +import org.apache.kafka.common.security.auth.SecurityProtocol +import org.apache.kafka.common.security.scram.ScramLoginModule +import org.apache.kafka.common.serialization.ByteArrayDeserializer +import org.apache.kafka.common.serialization.StringDeserializer import org.junit.Test import org.junit.runner.RunWith import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertiesService import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertyConfiguration import org.onap.ccsdk.cds.blueprintsprocessor.message.BluePrintMessageLibConfiguration import org.onap.ccsdk.cds.blueprintsprocessor.message.MessageConsumerProperties +import org.onap.ccsdk.cds.blueprintsprocessor.message.MessageLibConstants import org.onap.ccsdk.cds.controllerblueprints.core.logger import org.springframework.beans.factory.annotation.Autowired import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration import org.springframework.test.context.TestPropertySource import org.springframework.test.context.junit4.SpringRunner +import kotlin.test.assertEquals import kotlin.test.assertNotNull import kotlin.test.assertTrue @@ -52,18 +63,30 @@ import kotlin.test.assertTrue ) @TestPropertySource( properties = - ["blueprintsprocessor.messageconsumer.sample.type=kafka-basic-auth", + ["blueprintsprocessor.messageconsumer.sample.type=kafka-scram-ssl-auth", "blueprintsprocessor.messageconsumer.sample.bootstrapServers=127.0.0.1:9092", "blueprintsprocessor.messageconsumer.sample.groupId=sample-group", "blueprintsprocessor.messageconsumer.sample.topic=default-topic", "blueprintsprocessor.messageconsumer.sample.clientId=default-client-id", "blueprintsprocessor.messageconsumer.sample.pollMillSec=10", "blueprintsprocessor.messageconsumer.sample.pollRecords=1", + "blueprintsprocessor.messageconsumer.sample.truststore=/path/to/truststore.jks", + "blueprintsprocessor.messageconsumer.sample.truststorePassword=secretpassword", + "blueprintsprocessor.messageconsumer.sample.keystore=/path/to/keystore.jks", + "blueprintsprocessor.messageconsumer.sample.keystorePassword=secretpassword", + "blueprintsprocessor.messageconsumer.sample.scramUsername=sample-user", + "blueprintsprocessor.messageconsumer.sample.scramPassword=secretpassword", - "blueprintsprocessor.messageproducer.sample.type=kafka-basic-auth", + "blueprintsprocessor.messageproducer.sample.type=kafka-scram-ssl-auth", "blueprintsprocessor.messageproducer.sample.bootstrapServers=127.0.0.1:9092", "blueprintsprocessor.messageproducer.sample.topic=default-topic", - "blueprintsprocessor.messageproducer.sample.clientId=default-client-id" + "blueprintsprocessor.messageproducer.sample.clientId=default-client-id", + "blueprintsprocessor.messageproducer.sample.truststore=/path/to/truststore.jks", + "blueprintsprocessor.messageproducer.sample.truststorePassword=secretpassword", + "blueprintsprocessor.messageproducer.sample.keystore=/path/to/keystore.jks", + "blueprintsprocessor.messageproducer.sample.keystorePassword=secretpassword", + "blueprintsprocessor.messageproducer.sample.scramUsername=sample-user", + "blueprintsprocessor.messageproducer.sample.scramPassword=secretpassword" ] ) open class BlueprintMessageConsumerServiceTest { @@ -77,7 +100,7 @@ open class BlueprintMessageConsumerServiceTest { fun testKafkaBasicAuthConsumerService() { runBlocking { val blueprintMessageConsumerService = bluePrintMessageLibPropertyService - .blueprintMessageConsumerService("sample") as KafkaBasicAuthMessageConsumerService + .blueprintMessageConsumerService("sample") as KafkaMessageConsumerService assertNotNull(blueprintMessageConsumerService, "failed to get blueprintMessageConsumerService") val spyBlueprintMessageConsumerService = spyk(blueprintMessageConsumerService, recordPrivateCalls = true) @@ -124,7 +147,7 @@ open class BlueprintMessageConsumerServiceTest { fun testKafkaBasicAuthConsumerWithDynamicFunction() { runBlocking { val blueprintMessageConsumerService = bluePrintMessageLibPropertyService - .blueprintMessageConsumerService("sample") as KafkaBasicAuthMessageConsumerService + .blueprintMessageConsumerService("sample") as KafkaMessageConsumerService assertNotNull(blueprintMessageConsumerService, "failed to get blueprintMessageConsumerService") val spyBlueprintMessageConsumerService = spyk(blueprintMessageConsumerService, recordPrivateCalls = true) @@ -173,12 +196,60 @@ open class BlueprintMessageConsumerServiceTest { } } + @Test + fun testKafkaScramSslAuthConfig() { + + val expectedConfig = mapOf<String, Any>( + ProducerConfig.BOOTSTRAP_SERVERS_CONFIG to "127.0.0.1:9092", + ConsumerConfig.GROUP_ID_CONFIG to "sample-group", + ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG to true, + ConsumerConfig.AUTO_OFFSET_RESET_CONFIG to "latest", + ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG to StringDeserializer::class.java, + ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG to ByteArrayDeserializer::class.java, + ConsumerConfig.CLIENT_ID_CONFIG to "default-client-id", + CommonClientConfigs.SECURITY_PROTOCOL_CONFIG to SecurityProtocol.SASL_SSL.toString(), + SslConfigs.SSL_TRUSTSTORE_TYPE_CONFIG to "JKS", + SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG to "/path/to/truststore.jks", + SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG to "secretpassword", + SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG to "/path/to/keystore.jks", + SslConfigs.SSL_KEYSTORE_TYPE_CONFIG to "JKS", + SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG to "secretpassword", + SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG to "", + SaslConfigs.SASL_MECHANISM to "SCRAM-SHA-512", + SaslConfigs.SASL_JAAS_CONFIG to "${ScramLoginModule::class.java.canonicalName} required " + + "username=\"sample-user\" " + + "password=\"secretpassword\";" + ) + + val messageConsumerProperties = bluePrintMessageLibPropertyService + .messageConsumerProperties("${MessageLibConstants.PROPERTY_MESSAGE_CONSUMER_PREFIX}sample") + + val configProps = messageConsumerProperties.getConfig() + + assertEquals(messageConsumerProperties.topic, + "default-topic", + "Topic doesn't match the expected value" + ) + assertEquals(messageConsumerProperties.type, + "kafka-scram-ssl-auth", + "Authentication type doesn't match the expected value") + + expectedConfig.forEach { + assertTrue(configProps.containsKey(it.key), + "Missing expected kafka config key : ${it.key}") + assertEquals(configProps[it.key], + it.value, + "Unexpected value for ${it.key} got ${configProps[it.key]} instead of ${it.value}" + ) + } + } + /** Integration Kafka Testing, Enable and use this test case only for local desktop testing with real kafka broker */ // @Test fun testKafkaIntegration() { runBlocking { val blueprintMessageConsumerService = bluePrintMessageLibPropertyService - .blueprintMessageConsumerService("sample") as KafkaBasicAuthMessageConsumerService + .blueprintMessageConsumerService("sample") as KafkaMessageConsumerService assertNotNull(blueprintMessageConsumerService, "failed to get blueprintMessageConsumerService") val channel = blueprintMessageConsumerService.subscribe(null) @@ -190,7 +261,7 @@ open class BlueprintMessageConsumerServiceTest { /** Send message with every 1 sec */ val blueprintMessageProducerService = bluePrintMessageLibPropertyService - .blueprintMessageProducerService("sample") as KafkaBasicAuthMessageProducerService + .blueprintMessageProducerService("sample") as KafkaMessageProducerService launch { repeat(5) { delay(100) diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageProducerServiceTest.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageProducerServiceTest.kt index b824189d2..72a47ed56 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageProducerServiceTest.kt +++ b/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/BlueprintMessageProducerServiceTest.kt @@ -20,12 +20,22 @@ import io.mockk.every import io.mockk.mockk import io.mockk.spyk import kotlinx.coroutines.runBlocking +import org.apache.kafka.clients.CommonClientConfigs +import org.apache.kafka.clients.consumer.ConsumerConfig import org.apache.kafka.clients.producer.KafkaProducer +import org.apache.kafka.clients.producer.ProducerConfig import org.apache.kafka.clients.producer.RecordMetadata +import org.apache.kafka.common.config.SaslConfigs +import org.apache.kafka.common.config.SslConfigs +import org.apache.kafka.common.security.auth.SecurityProtocol +import org.apache.kafka.common.security.scram.ScramLoginModule +import org.apache.kafka.common.serialization.ByteArraySerializer +import org.apache.kafka.common.serialization.StringSerializer import org.junit.runner.RunWith import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertiesService import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintPropertyConfiguration import org.onap.ccsdk.cds.blueprintsprocessor.message.BluePrintMessageLibConfiguration +import org.onap.ccsdk.cds.blueprintsprocessor.message.MessageLibConstants import org.springframework.beans.factory.annotation.Autowired import org.springframework.test.annotation.DirtiesContext import org.springframework.test.context.ContextConfiguration @@ -33,6 +43,7 @@ import org.springframework.test.context.TestPropertySource import org.springframework.test.context.junit4.SpringRunner import java.util.concurrent.Future import kotlin.test.Test +import kotlin.test.assertEquals import kotlin.test.assertTrue @RunWith(SpringRunner::class) @@ -43,10 +54,16 @@ import kotlin.test.assertTrue ) @TestPropertySource( properties = - ["blueprintsprocessor.messageproducer.sample.type=kafka-basic-auth", + ["blueprintsprocessor.messageproducer.sample.type=kafka-scram-ssl-auth", "blueprintsprocessor.messageproducer.sample.bootstrapServers=127.0.0.1:9092", "blueprintsprocessor.messageproducer.sample.topic=default-topic", - "blueprintsprocessor.messageproducer.sample.clientId=default-client-id" + "blueprintsprocessor.messageproducer.sample.clientId=default-client-id", + "blueprintsprocessor.messageproducer.sample.truststore=/path/to/truststore.jks", + "blueprintsprocessor.messageproducer.sample.truststorePassword=secretpassword", + "blueprintsprocessor.messageproducer.sample.keystore=/path/to/keystore.jks", + "blueprintsprocessor.messageproducer.sample.keystorePassword=secretpassword", + "blueprintsprocessor.messageproducer.sample.scramUsername=sample-user", + "blueprintsprocessor.messageproducer.sample.scramPassword=secretpassword" ] ) open class BlueprintMessageProducerServiceTest { @@ -55,10 +72,10 @@ open class BlueprintMessageProducerServiceTest { lateinit var bluePrintMessageLibPropertyService: BluePrintMessageLibPropertyService @Test - fun testKafkaBasicAuthProducertService() { + fun testKafkaScramSslAuthProducerService() { runBlocking { val blueprintMessageProducerService = bluePrintMessageLibPropertyService - .blueprintMessageProducerService("sample") as KafkaBasicAuthMessageProducerService + .blueprintMessageProducerService("sample") as KafkaMessageProducerService val mockKafkaTemplate = mockk<KafkaProducer<String, ByteArray>>() @@ -75,4 +92,51 @@ open class BlueprintMessageProducerServiceTest { assertTrue(response, "failed to get command response") } } + + @Test + fun testKafkaScramSslAuthConfig() { + val expectedConfig = mapOf<String, Any>( + ProducerConfig.BOOTSTRAP_SERVERS_CONFIG to "127.0.0.1:9092", + ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG to StringSerializer::class.java, + ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG to ByteArraySerializer::class.java, + ProducerConfig.ACKS_CONFIG to "all", + ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG to true, + ConsumerConfig.CLIENT_ID_CONFIG to "default-client-id", + CommonClientConfigs.SECURITY_PROTOCOL_CONFIG to SecurityProtocol.SASL_SSL.toString(), + SslConfigs.SSL_TRUSTSTORE_TYPE_CONFIG to "JKS", + SslConfigs.SSL_TRUSTSTORE_LOCATION_CONFIG to "/path/to/truststore.jks", + SslConfigs.SSL_TRUSTSTORE_PASSWORD_CONFIG to "secretpassword", + SslConfigs.SSL_KEYSTORE_LOCATION_CONFIG to "/path/to/keystore.jks", + SslConfigs.SSL_KEYSTORE_TYPE_CONFIG to "JKS", + SslConfigs.SSL_KEYSTORE_PASSWORD_CONFIG to "secretpassword", + SslConfigs.SSL_ENDPOINT_IDENTIFICATION_ALGORITHM_CONFIG to "", + SaslConfigs.SASL_MECHANISM to "SCRAM-SHA-512", + SaslConfigs.SASL_JAAS_CONFIG to "${ScramLoginModule::class.java.canonicalName} required " + + "username=\"sample-user\" " + + "password=\"secretpassword\";" + ) + + val messageProducerProperties = bluePrintMessageLibPropertyService + .messageProducerProperties("${MessageLibConstants.PROPERTY_MESSAGE_PRODUCER_PREFIX}sample") + + val configProps = messageProducerProperties.getConfig() + + assertEquals(messageProducerProperties.topic, + "default-topic", + "Topic doesn't match the expected value" + ) + assertEquals(messageProducerProperties.type, + "kafka-scram-ssl-auth", + "Authentication type doesn't match the expected value") + + expectedConfig.forEach { + assertTrue(configProps.containsKey(it.key), + "Missing expected kafka config key : ${it.key}" + ) + assertEquals(configProps[it.key], + it.value, + "Unexpected value for ${it.key} got ${configProps[it.key]} instead of ${it.value}" + ) + } + } } diff --git a/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaStreamsBasicAuthConsumerServiceTest.kt b/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaStreamsConsumerServiceTest.kt index 1657d70b4..c30ab9b02 100644 --- a/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaStreamsBasicAuthConsumerServiceTest.kt +++ b/ms/blueprintsprocessor/modules/commons/message-lib/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/message/service/KafkaStreamsConsumerServiceTest.kt @@ -47,19 +47,27 @@ import kotlin.test.assertNotNull @TestPropertySource( properties = [ - "blueprintsprocessor.messageproducer.sample.type=kafka-basic-auth", + "blueprintsprocessor.messageproducer.sample.type=kafka-scram-ssl-auth", "blueprintsprocessor.messageproducer.sample.bootstrapServers=127.0.0.1:9092", "blueprintsprocessor.messageproducer.sample.topic=default-stream-topic", "blueprintsprocessor.messageproducer.sample.clientId=default-client-id", + "blueprintsprocessor.messageproducer.sample.truststore=/path/to/truststore.jks", + "blueprintsprocessor.messageproducer.sample.truststorePassword=secretpassword", + "blueprintsprocessor.messageproducer.sample.scramUsername=sample-user", + "blueprintsprocessor.messageproducer.sample.scramPassword=secretpassword", - "blueprintsprocessor.messageconsumer.stream-consumer.type=kafka-streams-basic-auth", + "blueprintsprocessor.messageconsumer.stream-consumer.type=kafka-streams-scram-ssl-auth", "blueprintsprocessor.messageconsumer.stream-consumer.bootstrapServers=127.0.0.1:9092", "blueprintsprocessor.messageconsumer.stream-consumer.applicationId=test-streams-application", - "blueprintsprocessor.messageconsumer.stream-consumer.topic=default-stream-topic" + "blueprintsprocessor.messageconsumer.stream-consumer.topic=default-stream-topic", + "blueprintsprocessor.messageproducer.stream-consumer.truststore=/path/to/truststore.jks", + "blueprintsprocessor.messageproducer.stream-consumer.truststorePassword=secretpassword", + "blueprintsprocessor.messageproducer.stream-consumer.scramUsername=sample-user", + "blueprintsprocessor.messageproducer.stream-consumer.scramPassword=secretpassword" ] ) -class KafkaStreamsBasicAuthConsumerServiceTest { +class KafkaStreamsConsumerServiceTest { @Autowired lateinit var bluePrintMessageLibPropertyService: BluePrintMessageLibPropertyService @@ -117,7 +125,7 @@ class KafkaStreamsBasicAuthConsumerServiceTest { /** Send message with every 1 sec */ val blueprintMessageProducerService = bluePrintMessageLibPropertyService - .blueprintMessageProducerService("sample") as KafkaBasicAuthMessageProducerService + .blueprintMessageProducerService("sample") as KafkaMessageProducerService launch { repeat(5) { delay(1000) diff --git a/ms/blueprintsprocessor/modules/commons/nats-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/nats-lib/pom.xml index 338428604..1865b4358 100644 --- a/ms/blueprintsprocessor/modules/commons/nats-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/nats-lib/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>commons</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>nats-lib</artifactId> diff --git a/ms/blueprintsprocessor/modules/commons/pom.xml b/ms/blueprintsprocessor/modules/commons/pom.xml index 3f6f16091..7f3043820 100755 --- a/ms/blueprintsprocessor/modules/commons/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/pom.xml @@ -17,13 +17,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>modules</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>commons</artifactId> diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/pom.xml b/ms/blueprintsprocessor/modules/commons/processor-core/pom.xml index 50259d82a..121214d06 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/processor-core/pom.xml @@ -16,13 +16,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>commons</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>processor-core</artifactId> diff --git a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintProcessorData.kt b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintProcessorData.kt index d94985400..58d0f13c2 100644 --- a/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintProcessorData.kt +++ b/ms/blueprintsprocessor/modules/commons/processor-core/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/core/api/data/BlueprintProcessorData.kt @@ -25,6 +25,7 @@ import io.swagger.annotations.ApiModelProperty import org.onap.ccsdk.cds.controllerblueprints.common.api.EventType import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants import java.util.Date +import java.util.UUID /** * BlueprintProcessorData @@ -33,7 +34,8 @@ import java.util.Date */ open class ExecutionServiceInput { - + @get:ApiModelProperty(required = false, hidden = true) + var correlationUUID: String = UUID.randomUUID().toString() @get:ApiModelProperty(required = true, value = "Headers providing request context.") lateinit var commonHeader: CommonHeader @get:ApiModelProperty(required = true, value = "Provide information about the action to execute.") @@ -51,6 +53,8 @@ open class ExecutionServiceInput { } open class ExecutionServiceOutput { + @get:ApiModelProperty(required = false, hidden = true) + var correlationUUID: String? = null @get:ApiModelProperty(required = true, value = "Headers providing request context.") lateinit var commonHeader: CommonHeader @get:ApiModelProperty(required = true, value = "Provide information about the action to execute.") diff --git a/ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml index 1525882fb..e56742d26 100644 --- a/ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/rest-lib/pom.xml @@ -16,13 +16,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>commons</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>rest-lib</artifactId> diff --git a/ms/blueprintsprocessor/modules/commons/ssh-lib/pom.xml b/ms/blueprintsprocessor/modules/commons/ssh-lib/pom.xml index 3b7ae9f67..a1f096bf2 100644 --- a/ms/blueprintsprocessor/modules/commons/ssh-lib/pom.xml +++ b/ms/blueprintsprocessor/modules/commons/ssh-lib/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>commons</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>ssh-lib</artifactId> diff --git a/ms/blueprintsprocessor/modules/inbounds/configs-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/configs-api/pom.xml index 8e907abcf..6bef263da 100644 --- a/ms/blueprintsprocessor/modules/inbounds/configs-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/configs-api/pom.xml @@ -14,17 +14,18 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>inbounds</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>configs-api</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <packaging>jar</packaging> <name>Blueprints Processor Resource Configurations API</name> @@ -43,5 +44,9 @@ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>blueprint-core</artifactId> </dependency> + <dependency> + <groupId>org.onap.ccsdk.cds.error.catalog</groupId> + <artifactId>error-catalog-services</artifactId> + </dependency> </dependencies> </project> diff --git a/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotException.kt b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ErrorHandling.kt index 1eeea9893..e742e6375 100644 --- a/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotException.kt +++ b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ErrorHandling.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2019 Bell Canada. + * Copyright © 2018-2019 AT&T Intellectual Property. * * 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 + * 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, @@ -13,8 +13,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + package org.onap.ccsdk.cds.blueprintsprocessor.configs.api -class ResourceConfigSnapshotException(message: String) : RuntimeException(message) { - var code: Int = 404 +object ConfigsApiDomains { + // ConfigsApi Domains Constants + const val CONFIGS_API = "org.onap.ccsdk.cds.blueprintsprocessor.configs.api" +} + +object ConfigsApiHttpErrorCodes { + init { + // Register HttpErrorCodes + // HttpErrorCodes.register("", 200) + } +} + +object ConfigsGrpcErrorCodes { + init { + // Register GrpcErrorCodes + // GrpcErrorCodes.register("", 3) + } } diff --git a/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotController.kt b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotController.kt index 0b18fb01f..2a5f4c3ea 100644 --- a/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotController.kt +++ b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotController.kt @@ -24,6 +24,9 @@ import kotlinx.coroutines.runBlocking import org.onap.ccsdk.cds.blueprintsprocessor.functions.config.snapshots.db.ResourceConfigSnapshot import org.onap.ccsdk.cds.blueprintsprocessor.functions.config.snapshots.db.ResourceConfigSnapshotService import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive +import org.onap.ccsdk.cds.controllerblueprints.core.httpProcessorException +import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes +import org.onap.ccsdk.cds.error.catalog.core.utils.errorCauseOrDefault import org.springframework.http.MediaType import org.springframework.http.ResponseEntity import org.springframework.security.access.prepost.PreAuthorize @@ -101,12 +104,17 @@ open class ResourceConfigSnapshotController(private val resourceConfigSnapshotSe resourceType, ResourceConfigSnapshot.Status.valueOf(status.toUpperCase()) ) } catch (ex: NoSuchElementException) { - throw ResourceConfigSnapshotException( - "Could not find configuration snapshot entry for type $resourceType and Id $resourceId" - ) + throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, ConfigsApiDomains.CONFIGS_API, + "Could not find configuration snapshot entry for type $resourceType and Id $resourceId", + ex.errorCauseOrDefault()) + } catch (ex: Exception) { + throw httpProcessorException(ErrorCatalogCodes.INVALID_REQUEST_FORMAT, ConfigsApiDomains.CONFIGS_API, + "Could not find configuration snapshot entry for type $resourceType and Id $resourceId", + ex.errorCauseOrDefault()) } } else { - throw IllegalArgumentException("Missing param. You must specify resource-id and resource-type.") + throw httpProcessorException(ErrorCatalogCodes.INVALID_REQUEST_FORMAT, ConfigsApiDomains.CONFIGS_API, + "Missing param. You must specify resource-id and resource-type.") } var expectedContentType = format diff --git a/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotExceptionHandler.kt b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotExceptionHandler.kt index d4c31e780..2b9bb31f6 100644 --- a/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotExceptionHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotExceptionHandler.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Bell Canada + * Copyright © 2019 - 2020 IBM, Bell Canada * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,106 +16,16 @@ package org.onap.ccsdk.cds.blueprintsprocessor.configs.api -import com.fasterxml.jackson.annotation.JsonFormat -import com.fasterxml.jackson.annotation.JsonInclude -import com.fasterxml.jackson.annotation.JsonTypeInfo -import com.fasterxml.jackson.annotation.JsonTypeName -import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException -import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode -import org.slf4j.LoggerFactory -import org.springframework.dao.EmptyResultDataAccessException -import org.springframework.dao.IncorrectResultSizeDataAccessException -import org.springframework.http.HttpStatus -import org.springframework.http.ResponseEntity -import org.springframework.orm.jpa.JpaObjectRetrievalFailureException -import org.springframework.web.bind.annotation.ExceptionHandler +import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogExceptionHandler +import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogService import org.springframework.web.bind.annotation.RestControllerAdvice -import org.springframework.web.server.ServerWebInputException -import java.io.Serializable -import java.util.Date /** * Handle exceptions in ResourceConfigSnapshot API and provide relevant HTTP status codes and messages * * @author Serge Simard - * @version 1.0 + * @version 2.0 */ @RestControllerAdvice("org.onap.ccsdk.cds.blueprintsprocessor.configs.api") -open class ResourceConfigSnapshotExceptionHandler { - - private val log = LoggerFactory.getLogger(ResourceConfigSnapshotExceptionHandler::class.toString()) - - private val debugMsg = "Resource_Config_Snapshot_ExceptionHandler_Error_Message" - - @ExceptionHandler - fun resourceConfigSnapshotExceptionHandler(e: BluePrintProcessorException): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.BLUEPRINT_PATH_MISSING - return returnError(e, errorCode) - } - - @ExceptionHandler - fun resourceConfigSnapshotExceptionHandler(e: ServerWebInputException): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.INVALID_REQUEST_FORMAT - return returnError(e, errorCode, false) - } - - @ExceptionHandler - fun resourceConfigSnapshotExceptionHandler(e: IllegalArgumentException): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.INVALID_REQUEST_FORMAT - return returnError(e, errorCode, false) - } - - @ExceptionHandler - fun resourceConfigSnapshotExceptionHandler(e: IncorrectResultSizeDataAccessException): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.DUPLICATE_DATA - return returnError(e, errorCode) - } - - @ExceptionHandler - fun resourceConfigSnapshotExceptionHandler(e: EmptyResultDataAccessException): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.RESOURCE_NOT_FOUND - return returnError(e, errorCode, false) - } - - @ExceptionHandler - fun resourceConfigSnapshotExceptionHandler(e: JpaObjectRetrievalFailureException): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.RESOURCE_NOT_FOUND - return returnError(e, errorCode, false) - } - - @ExceptionHandler - fun resourceConfigSnapshotExceptionHandler(e: Exception): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.GENERIC_FAILURE - return returnError(e, errorCode) - } - - @ExceptionHandler - fun resourceConfigSnapshotExceptionHandler(e: ResourceConfigSnapshotException): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.RESOURCE_NOT_FOUND - return returnError(e, errorCode, false) - } - - fun returnError(e: Exception, errorCode: ErrorCode, toBeLogged: Boolean = true): ResponseEntity<ErrorMessage> { - if (toBeLogged) { - log.error(e.message, e) - } else { - log.error(e.message) - } - val errorMessage = - ErrorMessage( - errorCode.message(e.message!!), - errorCode.value, - debugMsg - ) - return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)!!) - } -} - -@JsonInclude(JsonInclude.Include.NON_NULL) -@JsonTypeName("errorMessage") -@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME) -class ErrorMessage(var message: String?, var code: Int?, var debugMessage: String?) : Serializable { - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - var timestamp = Date() -} +open class ResourceConfigSnapshotExceptionHandler(private val errorCatalogService: ErrorCatalogService) : + ErrorCatalogExceptionHandler(errorCatalogService) diff --git a/ms/blueprintsprocessor/modules/inbounds/configs-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ErrorCatalogTestConfiguration.kt b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ErrorCatalogTestConfiguration.kt new file mode 100644 index 000000000..66fc3b2ed --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ErrorCatalogTestConfiguration.kt @@ -0,0 +1,28 @@ +/* + * Copyright © 2020 IBM, Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.configs.api + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration + +@Configuration +@ComponentScan( + basePackages = ["org.onap.ccsdk.cds.error.catalog"] +) +@EnableAutoConfiguration +open class ErrorCatalogTestConfiguration diff --git a/ms/blueprintsprocessor/modules/inbounds/configs-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotControllerTest.kt index d55568df8..b54d92bb0 100644 --- a/ms/blueprintsprocessor/modules/inbounds/configs-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotControllerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/configs/api/ResourceConfigSnapshotControllerTest.kt @@ -35,7 +35,7 @@ import org.springframework.web.reactive.function.BodyInserters @RunWith(SpringRunner::class) @WebFluxTest @ContextConfiguration( - classes = [BluePrintCoreConfiguration::class, BluePrintCatalogService::class] + classes = [BluePrintCoreConfiguration::class, BluePrintCatalogService::class, ErrorCatalogTestConfiguration::class] ) @ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"]) @TestPropertySource(locations = ["classpath:application-test.properties"]) @@ -112,7 +112,7 @@ class ResourceConfigSnapshotControllerTest { webTestClient.get().uri("/api/v1/configs?$arguments") .exchange() - .expectStatus().isBadRequest + .expectStatus().is4xxClientError } } diff --git a/ms/blueprintsprocessor/modules/inbounds/configs-api/src/test/resources/application-test.properties b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/test/resources/application-test.properties index ebd394cc2..69dbe23e2 100644 --- a/ms/blueprintsprocessor/modules/inbounds/configs-api/src/test/resources/application-test.properties +++ b/ms/blueprintsprocessor/modules/inbounds/configs-api/src/test/resources/application-test.properties @@ -1,4 +1,4 @@ -# Copyright © 2019 Bell Canada. +# Copyright © 2019 - 2020 IBM, Bell Canada. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -28,3 +28,8 @@ blueprintsprocessor.blueprintArchivePath=./target/blueprints/archive # Python executor blueprints.processor.functions.python.executor.executionPath=./../../../../components/scripts/python/ccsdk_blueprints blueprints.processor.functions.python.executor.modulePaths=./../../../../components/scripts/python/ccsdk_blueprints + +# Error Managements +error.catalog.applicationId=cds +error.catalog.type=properties +error.catalog.errorDefinitionDir=./../../../application/src/test/resources/ diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/designer-api/pom.xml index edfcdf891..419db8671 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>inbounds</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>designer-api</artifactId> @@ -28,4 +29,11 @@ <name>Blueprints Processor Designer API</name> <description>Blueprints Processor Designer API</description> + + <dependencies> + <dependency> + <groupId>org.onap.ccsdk.cds.error.catalog</groupId> + <artifactId>error-catalog-services</artifactId> + </dependency> + </dependencies> </project> diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandler.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandler.kt index bca77f275..7600979f8 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandler.kt @@ -40,13 +40,20 @@ import org.onap.ccsdk.cds.controllerblueprints.management.api.DownloadAction import org.onap.ccsdk.cds.controllerblueprints.management.api.FileChunk import org.onap.ccsdk.cds.controllerblueprints.management.api.RemoveAction import org.onap.ccsdk.cds.controllerblueprints.management.api.UploadAction +import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes +import org.onap.ccsdk.cds.error.catalog.core.GrpcErrorCodes +import org.onap.ccsdk.cds.error.catalog.core.utils.errorMessageOrDefault +import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogService import org.slf4j.LoggerFactory import org.springframework.security.access.prepost.PreAuthorize import org.springframework.stereotype.Service // TODO("Convert to coroutines handler") @Service -open class BluePrintManagementGRPCHandler(private val bluePrintModelHandler: BluePrintModelHandler) : +open class BluePrintManagementGRPCHandler( + private val bluePrintModelHandler: BluePrintModelHandler, + private val errorCatalogService: ErrorCatalogService +) : BluePrintManagementServiceGrpc.BluePrintManagementServiceImplBase() { private val log = LoggerFactory.getLogger(BluePrintManagementGRPCHandler::class.java) @@ -266,20 +273,42 @@ open class BluePrintManagementGRPCHandler(private val bluePrintModelHandler: Blu private fun failStatus(header: CommonHeader, message: String, e: Exception): BluePrintManagementOutput { log.error(message, e) + return if (e is BluePrintProcessorException) onErrorCatalog(header, message, e) else onError(header, message, e) + } + + private fun onError(header: CommonHeader, message: String, error: Exception): BluePrintManagementOutput { + val code = GrpcErrorCodes.code(ErrorCatalogCodes.GENERIC_FAILURE) return BluePrintManagementOutput.newBuilder() - .setCommonHeader(header) - .setStatus( - Status.newBuilder() - .setTimestamp(currentTimestamp()) - .setMessage(BluePrintConstants.STATUS_FAILURE) - .setErrorMessage(message) - .setCode(500) - .build() - ) - .build() - // return io.grpc.Status.INTERNAL - // .withDescription(message) - // .withCause(e) - // .asException() + .setCommonHeader(header) + .setStatus( + Status.newBuilder() + .setTimestamp(currentTimestamp()) + .setMessage(BluePrintConstants.STATUS_FAILURE) + .setErrorMessage("Error : $message \n Details: ${error.errorMessageOrDefault()}") + .setCode(code) + .build() + ) + .build() + } + + private fun onErrorCatalog(header: CommonHeader, message: String, error: BluePrintProcessorException): + BluePrintManagementOutput { + val err = if (error.protocol == "") { + error.grpc(ErrorCatalogCodes.GENERIC_FAILURE) + } else { + error.convertToGrpc() + } + val errorPayload = errorCatalogService.errorPayload(err.addErrorPayloadMessage(message)) + return BluePrintManagementOutput.newBuilder() + .setCommonHeader(header) + .setStatus( + Status.newBuilder() + .setTimestamp(currentTimestamp()) + .setMessage(BluePrintConstants.STATUS_FAILURE) + .setErrorMessage("Error : ${errorPayload.message}") + .setCode(errorPayload.code) + .build() + ) + .build() } } diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerApiData.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerApiData.kt index 369844445..1d61c7f0c 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerApiData.kt +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerApiData.kt @@ -17,10 +17,6 @@ package org.onap.ccsdk.cds.blueprintsprocessor.designer.api -import com.fasterxml.jackson.annotation.JsonFormat -import com.fasterxml.jackson.annotation.JsonInclude -import com.fasterxml.jackson.annotation.JsonTypeInfo -import com.fasterxml.jackson.annotation.JsonTypeName import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.domain.ResourceDictionary import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.DATA_TYPE_JSON import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.DEFAULT_VERSION_NUMBER @@ -28,8 +24,6 @@ import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintConstants.TOSCA_SPE import org.onap.ccsdk.cds.controllerblueprints.core.data.DataType import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment -import java.io.Serializable -import java.util.Date class BootstrapRequest { var loadModelType: Boolean = false @@ -75,12 +69,3 @@ class AutoMapResponse { var resourceAssignments: List<ResourceAssignment>? = null var dataDictionaries: List<ResourceDictionary>? = null } - -@JsonInclude(JsonInclude.Include.NON_NULL) -@JsonTypeName("errorMessage") -@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME) -class ErrorMessage(var message: String?, var code: Int?, var debugMessage: String?) : Serializable { - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - var timestamp = Date() -} diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerBlueprintExceptionHandler.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerBlueprintExceptionHandler.kt index c140c9a07..a083d7a8b 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerBlueprintExceptionHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/DesignerBlueprintExceptionHandler.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2018-2019 Bell Canada Intellectual Property. + * Copyright © 2019 - 2020 IBM, Bell Canada * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,44 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.onap.ccsdk.cds.blueprintsprocessor.designer.api -import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException -import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode -import org.slf4j.LoggerFactory -import org.springframework.http.HttpStatus -import org.springframework.http.ResponseEntity -import org.springframework.web.bind.annotation.ExceptionHandler -import org.springframework.web.bind.annotation.RestControllerAdvice - /** * ControllerBlueprintExceptionHandler Purpose: Handle exceptions in controllerBlueprint API and provide the right * HTTP code status * - * @author Vinal Patel - * @version 1.0 + * @author Steve Siani + * @version 2.0 */ -@RestControllerAdvice("org.onap.ccsdk.cds.controllerblueprints") -open class DesignerBlueprintExceptionHandler { - - companion object ControllerBlueprintExceptionHandler { - val LOG = LoggerFactory.getLogger(DesignerBlueprintExceptionHandler::class.java) - } - - @ExceptionHandler - fun ControllerBlueprintExceptionHandler(e: BluePrintException): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.valueOf(e.code) - val errorMessage = ErrorMessage(errorCode?.message(e.message!!), errorCode?.value, "ControllerBluePrint_Error_Message") - LOG.error("Error: $errorCode ${e.message}") - return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode!!.httpCode)) - } +import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogExceptionHandler +import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogService +import org.springframework.web.bind.annotation.RestControllerAdvice - @ExceptionHandler - fun ControllerBlueprintExceptionHandler(e: Exception): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.GENERIC_FAILURE - val errorMessage = ErrorMessage(errorCode?.message(e.message!!), errorCode?.value, "ControllerBluePrint_Error_Message") - LOG.error("Error: $errorCode ${e.message}") - return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode!!.httpCode)) - } -} +@RestControllerAdvice("org.onap.ccsdk.cds.blueprintsprocessor.designer.api") +open class DesignerBlueprintExceptionHandler(private val errorCatalogService: ErrorCatalogService) : + ErrorCatalogExceptionHandler(errorCatalogService) diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/enhancer/BluePrintEnhancerServiceImpl.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/enhancer/BluePrintEnhancerServiceImpl.kt index e99f49489..1d534bb73 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/enhancer/BluePrintEnhancerServiceImpl.kt +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/enhancer/BluePrintEnhancerServiceImpl.kt @@ -17,15 +17,22 @@ package org.onap.ccsdk.cds.blueprintsprocessor.designer.api.enhancer +import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.DesignerApiDomains import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.logger +import org.onap.ccsdk.cds.controllerblueprints.core.updateErrorMessage +import org.onap.ccsdk.cds.controllerblueprints.core.httpProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintEnhancerService import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintTypeEnhancerService -import org.onap.ccsdk.cds.controllerblueprints.core.logger import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintFileUtils import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils import org.onap.ccsdk.cds.controllerblueprints.resource.dict.utils.ResourceDictionaryUtils +import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes +import org.onap.ccsdk.cds.error.catalog.core.utils.errorCauseOrDefault import org.springframework.stereotype.Service +import java.io.IOException import java.util.UUID @Service @@ -74,9 +81,17 @@ open class BluePrintEnhancerServiceImpl( if (blueprintRuntimeService.getBluePrintError().errors.isNotEmpty()) { throw BluePrintException(blueprintRuntimeService.getBluePrintError().errors.toString()) } + } catch (e: BluePrintProcessorException) { + val errorMsg = "Error while enriching the CBA package." + throw e.updateErrorMessage(DesignerApiDomains.DESIGNER_API, errorMsg, + "Wrong blueprint definitions or resource definitions.") + } catch (e: IOException) { + throw httpProcessorException(ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API, + "IO Error: CBA file failed enrichment - ${e.message}", e.errorCauseOrDefault()) } catch (e: Exception) { - throw e + throw httpProcessorException(ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API, + "Error in Enriching CBA: ${e.message}", e.errorCauseOrDefault()) + } + return blueprintRuntimeService.bluePrintContext() } - return blueprintRuntimeService.bluePrintContext() - } } diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt index e9839328b..48ca912da 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/BluePrintModelHandler.kt @@ -24,27 +24,34 @@ import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.domain.BlueprintModelSe import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.repository.BlueprintModelContentRepository import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.repository.BlueprintModelRepository import org.onap.ccsdk.cds.blueprintsprocessor.db.primary.repository.BlueprintModelSearchRepository +import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.DesignerApiDomains import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.BootstrapRequest -import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.WorkFlowData import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.WorkFlowSpecRequest import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.WorkFlowSpecResponse +import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.WorkFlowData import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.WorkFlowsResponse import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.load.BluePrintDatabaseLoadService import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.utils.BluePrintEnhancerUtils import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException +import org.onap.ccsdk.cds.controllerblueprints.core.logger +import org.onap.ccsdk.cds.controllerblueprints.core.httpProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.updateErrorMessage +import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName +import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile +import org.onap.ccsdk.cds.controllerblueprints.core.deleteNBDir import org.onap.ccsdk.cds.controllerblueprints.core.config.BluePrintLoadConfiguration import org.onap.ccsdk.cds.controllerblueprints.core.data.DataType -import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode -import org.onap.ccsdk.cds.controllerblueprints.core.deleteNBDir +import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintEnhancerService -import org.onap.ccsdk.cds.controllerblueprints.core.logger -import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile -import org.onap.ccsdk.cds.controllerblueprints.core.normalizedPathName import org.onap.ccsdk.cds.controllerblueprints.core.scripts.BluePrintCompileCache import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintContext import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintFileUtils import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils +import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes +import org.onap.ccsdk.cds.error.catalog.core.utils.errorCauseOrDefault +import org.onap.ccsdk.cds.error.catalog.core.utils.errorMessageOrDefault import org.springframework.core.io.ByteArrayResource import org.springframework.core.io.Resource import org.springframework.data.domain.Page @@ -115,17 +122,29 @@ open class BluePrintModelHandler( workFlowData.inputs = workFlow.inputs workFlowData.outputs = workFlow.outputs - for ((k, v) in workFlow.inputs!!) { - addDataType(v.type, blueprintContext, wfRes) + if (workFlow.inputs != null) { + for ((k, v) in workFlow.inputs!!) { + addPropertyInfo(v, blueprintContext, wfRes) + } } - for ((k, v) in workFlow.outputs!!) { - addDataType(v.type, blueprintContext, wfRes) + if (workFlow.outputs != null) { + for ((k, v) in workFlow.outputs!!) { + addPropertyInfo(v, blueprintContext, wfRes) + } } + wfRes.workFlowData = workFlowData return wfRes } + private fun addPropertyInfo(prop: PropertyDefinition, ctx: BluePrintContext, res: WorkFlowSpecResponse) { + addDataType(prop.type, ctx, res) + if (prop.entrySchema != null && prop.entrySchema!!.type != null) { + addDataType(prop.entrySchema!!.type, ctx, res) + } + } + private fun addDataType(name: String, ctx: BluePrintContext, res: WorkFlowSpecResponse) { var data = ctx.dataTypeByName(name) if (data != null) { @@ -135,8 +154,10 @@ open class BluePrintModelHandler( } private fun addParentDataType(data: DataType, ctx: BluePrintContext, res: WorkFlowSpecResponse) { - for ((k, v) in data.properties!!) { - addDataType(v.type, ctx, res) + if (data.properties != null) { + for ((k, v) in data.properties!!) { + addPropertyInfo(v, ctx, res) + } } } @@ -188,10 +209,8 @@ open class BluePrintModelHandler( try { return upload(filePart, false) } catch (e: IOException) { - throw BluePrintException( - ErrorCode.IO_FILE_INTERRUPT.value, - "Error in Save CBA: ${e.message}", e - ) + throw httpProcessorException(ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API, + "Error in Save CBA: ${e.message}", e.errorCauseOrDefault()) } } @@ -239,11 +258,11 @@ open class BluePrintModelHandler( val archiveByteArray = download(name, version) val fileName = "${name}_$version.zip" return prepareResourceEntity(fileName, archiveByteArray) - } catch (e: BluePrintException) { - throw BluePrintException( - ErrorCode.RESOURCE_NOT_FOUND.value, - String.format("Error while " + "downloading the CBA file: %s", e.message), e - ) + } catch (e: BluePrintProcessorException) { + e.http(ErrorCatalogCodes.RESOURCE_NOT_FOUND) + val errorMsg = "Error while downloading the CBA file by Blueprint Name ($name) and Version ($version)." + throw e.updateErrorMessage(DesignerApiDomains.DESIGNER_API, errorMsg, + "Wrong resource definition or resolution failed.") } } @@ -259,15 +278,15 @@ open class BluePrintModelHandler( try { blueprintModel = getBlueprintModel(id) } catch (e: BluePrintException) { - throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, String.format("Error while " + "downloading the CBA file: %s", e.message), e) + throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, + "Error while downloading the CBA file: couldn't get blueprint modelby ID ($id)", + e.errorCauseOrDefault()) } val fileName = "${blueprintModel.artifactName}_${blueprintModel.artifactVersion}.zip" val file = blueprintModel.blueprintModelContent?.content - ?: throw BluePrintException( - ErrorCode.RESOURCE_NOT_FOUND.value, - String.format("Error while downloading the CBA file: couldn't get model content") - ) + ?: throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, + "Error while downloading the CBA file: couldn't get model content") return prepareResourceEntity(fileName, file) } @@ -296,7 +315,7 @@ open class BluePrintModelHandler( blueprintModel = dbBlueprintModel.get() } else { val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id) - throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg) + throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, msg) } return blueprintModel } @@ -317,7 +336,7 @@ open class BluePrintModelHandler( return blueprintModel } else { val msg = String.format(BLUEPRINT_MODEL_NAME_VERSION_FAILURE_MSG, name, version) - throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg) + throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, msg) } } @@ -331,10 +350,8 @@ open class BluePrintModelHandler( @Throws(BluePrintException::class) open fun getBlueprintModelSearch(id: String): BlueprintModelSearch { return blueprintModelSearchRepository.findById(id) - ?: throw BluePrintException( - ErrorCode.RESOURCE_NOT_FOUND.value, - String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id) - ) + ?: throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, + String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id)) } /** @@ -385,7 +402,7 @@ open class BluePrintModelHandler( blueprintModelRepository.delete(dbBlueprintModel.get()) } else { val msg = String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, id) - throw BluePrintException(ErrorCode.RESOURCE_NOT_FOUND.value, msg) + throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, msg) } } @@ -410,11 +427,14 @@ open class BluePrintModelHandler( try { val enhancedByteArray = enrichBlueprintFileSource(filePart) return BluePrintEnhancerUtils.prepareResourceEntity("enhanced-cba.zip", enhancedByteArray) - } catch (e: IOException) { - throw BluePrintException( - ErrorCode.IO_FILE_INTERRUPT.value, - "Error in Enriching CBA: ${e.message}", e - ) + } catch (e: BluePrintProcessorException) { + e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT) + val errorMsg = "Error while enhancing the CBA package." + throw e.updateErrorMessage(DesignerApiDomains.DESIGNER_API, errorMsg, + "Wrong CBA file provided, please verify and enrich Again.") + } catch (e: Exception) { + throw httpProcessorException(ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API, + "EnrichBlueprint: ${e.message}", e.errorCauseOrDefault()) } } @@ -429,11 +449,14 @@ open class BluePrintModelHandler( open suspend fun publishBlueprint(filePart: FilePart): BlueprintModelSearch { try { return upload(filePart, true) + } catch (e: BluePrintProcessorException) { + e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT) + val errorMsg = "Error in Publishing CBA." + throw e.updateErrorMessage(DesignerApiDomains.DESIGNER_API, errorMsg, + "Wrong CBA provided, please verify and enrich your CBA.") } catch (e: Exception) { - throw BluePrintException( - ErrorCode.IO_FILE_INTERRUPT.value, - "Error in Publishing CBA: ${e.message}", e - ) + throw httpProcessorException(ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API, + "Error in Publishing CBA: ${e.message}", e.errorCauseOrDefault()) } } @@ -453,15 +476,16 @@ open class BluePrintModelHandler( val blueprintId = blueprintsProcessorCatalogService.saveToDatabase(saveId, compressedFile, validate) return blueprintModelSearchRepository.findById(blueprintId) - ?: throw BluePrintException( - ErrorCode.RESOURCE_NOT_FOUND.value, - String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, blueprintId) - ) + ?: throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, + String.format(BLUEPRINT_MODEL_ID_FAILURE_MSG, blueprintId)) + } catch (e: BluePrintException) { + e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT) + val errorMsg = "Error in Upload CBA." + throw e.updateErrorMessage(DesignerApiDomains.DESIGNER_API, errorMsg, + "Wrong enriched CBA.") } catch (e: IOException) { - throw BluePrintException( - ErrorCode.IO_FILE_INTERRUPT.value, - "Error in Upload CBA: ${e.message}", e - ) + throw httpProcessorException(ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API, + "Error in Upload CBA: ${e.errorMessageOrDefault()}", e.errorCauseOrDefault()) } finally { // Clean blueprint script cache val cacheKey = BluePrintFileUtils @@ -478,15 +502,13 @@ open class BluePrintModelHandler( try { val blueprintModel = getBlueprintModelByNameAndVersion(name, version) return blueprintModel.blueprintModelContent?.content - ?: throw BluePrintException( - ErrorCode.RESOURCE_NOT_FOUND.value, - String.format("Error while downloading the CBA file: couldn't get model content") - ) + ?: throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, + "Error while downloading the CBA file: couldn't get model content") } catch (e: BluePrintException) { - throw BluePrintException( - ErrorCode.RESOURCE_NOT_FOUND.value, - String.format("Error while " + "downloading the CBA file: %s", e.message), e - ) + e.http(ErrorCatalogCodes.RESOURCE_NOT_FOUND) + val errorMsg = "Fail to get Blueprint Model content." + throw e.updateErrorMessage(DesignerApiDomains.DESIGNER_API, errorMsg, + "Wrong name and version was provide.") } } @@ -506,11 +528,13 @@ open class BluePrintModelHandler( bluePrintEnhancerService.enhance(blueprintWorkingDir) return BluePrintEnhancerUtils.compressEnhanceDirAndReturnByteArray(blueprintWorkingDir, blueprintArchive) + } catch (e: BluePrintException) { + e.http(ErrorCatalogCodes.IO_FILE_INTERRUPT) + val errorMsg = "Fail Enriching the CBA." + throw e.updateErrorMessage(DesignerApiDomains.DESIGNER_API, errorMsg) } catch (e: IOException) { - throw BluePrintException( - ErrorCode.IO_FILE_INTERRUPT.value, - "Error in Enriching CBA: ${e.message}", e - ) + throw httpProcessorException(ErrorCatalogCodes.IO_FILE_INTERRUPT, DesignerApiDomains.DESIGNER_API, + "Error while Enriching the CBA file.", e.errorCauseOrDefault()) } finally { BluePrintEnhancerUtils.cleanEnhancer(blueprintArchive, blueprintWorkingDir) } diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/ModelTypeHandler.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/ModelTypeHandler.kt index a364f3678..d11c128f0 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/ModelTypeHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/ModelTypeHandler.kt @@ -17,10 +17,13 @@ package org.onap.ccsdk.cds.blueprintsprocessor.designer.api.handler +import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.DesignerApiDomains import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.domain.ModelType import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.repository.ModelTypeRepository import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.utils.ModelTypeValidator import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException +import org.onap.ccsdk.cds.controllerblueprints.core.httpProcessorException +import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes import org.slf4j.LoggerFactory import org.springframework.stereotype.Service @@ -42,7 +45,8 @@ open class ModelTypeHandler(private val modelTypeRepository: ModelTypeRepository return if (modelType != null) { modelType } else { - throw BluePrintException("couldn't get modelType($modelTypeName)") + throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, + "couldn't get modelType($modelTypeName)") } } diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/ResourceDictionaryHandler.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/ResourceDictionaryHandler.kt index 0f0bfef6d..20895efce 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/ResourceDictionaryHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/handler/ResourceDictionaryHandler.kt @@ -20,13 +20,16 @@ package org.onap.ccsdk.cds.blueprintsprocessor.designer.api.handler import com.google.common.base.Preconditions import org.apache.commons.collections.CollectionUtils import org.apache.commons.lang3.StringUtils +import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.DesignerApiDomains import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.domain.ResourceDictionary import org.onap.ccsdk.cds.blueprintsprocessor.designer.api.repository.ResourceDictionaryRepository import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintException import org.onap.ccsdk.cds.controllerblueprints.core.checkNotEmpty +import org.onap.ccsdk.cds.controllerblueprints.core.httpProcessorException import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceDefinition import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceSourceMapping import org.onap.ccsdk.cds.controllerblueprints.resource.dict.factory.ResourceSourceMappingFactory +import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes import org.springframework.stereotype.Service @Service @@ -46,7 +49,8 @@ class ResourceDictionaryHandler(private val resourceDictionaryRepository: Resour return if (resourceDictionaryDb != null) { resourceDictionaryDb } else { - throw BluePrintException(String.format("couldn't get resource dictionary for name (%s)", name)) + throw httpProcessorException(ErrorCatalogCodes.RESOURCE_NOT_FOUND, DesignerApiDomains.DESIGNER_API, + String.format("couldn't get resource dictionary for name (%s)", name)) } } diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandlerTest.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandlerTest.kt index 35e440554..d6694de9e 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandlerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BluePrintManagementGRPCHandlerTest.kt @@ -54,7 +54,7 @@ import kotlin.test.assertTrue @RunWith(SpringRunner::class) @ContextConfiguration( - classes = [DesignerApiTestConfiguration::class] + classes = [DesignerApiTestConfiguration::class, ErrorCatalogTestConfiguration::class] ) @TestPropertySource(locations = ["classpath:application-test.properties"]) class BluePrintManagementGRPCHandlerTest { diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelControllerTest.kt index 0e33884a0..9489f2882 100644 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelControllerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/BlueprintModelControllerTest.kt @@ -63,7 +63,7 @@ import kotlin.test.assertTrue @RunWith(SpringRunner::class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @ContextConfiguration( - classes = [DesignerApiTestConfiguration::class] + classes = [DesignerApiTestConfiguration::class, ErrorCatalogTestConfiguration::class] ) @TestPropertySource(locations = ["classpath:application-test.properties"]) @FixMethodOrder(MethodSorters.NAME_ASCENDING) diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/ErrorCatalogTestConfiguration.kt b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/ErrorCatalogTestConfiguration.kt new file mode 100644 index 000000000..d081dc5ab --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/designer/api/ErrorCatalogTestConfiguration.kt @@ -0,0 +1,28 @@ +/* + * Copyright © 2020 IBM, Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.designer.api + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration + +@Configuration +@ComponentScan( + basePackages = ["org.onap.ccsdk.cds.error.catalog"] +) +@EnableAutoConfiguration +open class ErrorCatalogTestConfiguration diff --git a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/resources/application-test.properties b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/resources/application-test.properties index e22e522ee..5e3e66172 100755 --- a/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/resources/application-test.properties +++ b/ms/blueprintsprocessor/modules/inbounds/designer-api/src/test/resources/application-test.properties @@ -1,5 +1,5 @@ # -# Copyright © 2019 IBM. +# Copyright © 2019 - 2020 IBM, Bell Canada. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -36,6 +36,11 @@ blueprintsprocessor.blueprintDeployPath=./target/blueprints/deploy blueprintsprocessor.blueprintArchivePath=./target/blueprints/archive blueprintsprocessor.blueprintWorkingPath=./target/blueprints/work +# Error Managements +error.catalog.applicationId=cds +error.catalog.type=properties +error.catalog.errorDefinitionDir=./../../../application/src/test/resources/ + # Python executor blueprints.processor.functions.python.executor.executionPath=./../../../../components/scripts/python/ccsdk_blueprints blueprints.processor.functions.python.executor.modulePaths=./../../../../components/scripts/python/ccsdk_blueprints diff --git a/ms/blueprintsprocessor/modules/inbounds/health-api-common/pom.xml b/ms/blueprintsprocessor/modules/inbounds/health-api-common/pom.xml index 9b98a1fc3..9ee9e98c0 100644 --- a/ms/blueprintsprocessor/modules/inbounds/health-api-common/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/health-api-common/pom.xml @@ -15,13 +15,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>inbounds</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>health-api-common</artifactId> diff --git a/ms/blueprintsprocessor/modules/inbounds/health-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/health-api/pom.xml index f9866a8ed..f27b20da1 100644 --- a/ms/blueprintsprocessor/modules/inbounds/health-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/health-api/pom.xml @@ -15,13 +15,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>inbounds</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>health-api</artifactId> @@ -35,7 +36,7 @@ <dependency> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>health-api-common</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </dependency> </dependencies> </project> diff --git a/ms/blueprintsprocessor/modules/inbounds/pom.xml b/ms/blueprintsprocessor/modules/inbounds/pom.xml index 88e7ac235..18b6fd00d 100644 --- a/ms/blueprintsprocessor/modules/inbounds/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/pom.xml @@ -15,13 +15,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>modules</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>inbounds</artifactId> diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml index bec0d1850..42d8f087c 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>inbounds</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>resource-api</artifactId> @@ -38,5 +39,9 @@ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>blueprint-core</artifactId> </dependency> + <dependency> + <groupId>org.onap.ccsdk.cds.error.catalog</groupId> + <artifactId>error-catalog-services</artifactId> + </dependency> </dependencies> </project> diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt index 264cd23ff..1aae8aa1c 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceController.kt @@ -23,7 +23,9 @@ import io.swagger.annotations.ApiParam import kotlinx.coroutines.runBlocking import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolution import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.ResourceResolutionDBService +import org.onap.ccsdk.cds.controllerblueprints.core.httpProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes import org.springframework.http.MediaType import org.springframework.http.ResponseEntity import org.springframework.security.access.prepost.PreAuthorize @@ -83,7 +85,8 @@ open class ResourceController(private var resourceResolutionDBService: ResourceR ResponseEntity<List<ResourceResolution>> = runBlocking { if ((resolutionKey.isNotEmpty() || artifactName.isNotEmpty()) && (resourceId.isNotEmpty() || resourceType.isNotEmpty())) { - throw ResolutionException("Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.") + throw httpProcessorException(ErrorCatalogCodes.REQUEST_NOT_FOUND, ResourceApiDomains.RESOURCE_API, + "Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.") } else if (resolutionKey.isNotEmpty() && artifactName.isNotEmpty()) { ResponseEntity.ok() .body(resourceResolutionDBService.readWithResolutionKey(bpName, bpVersion, artifactName, resolutionKey)) @@ -98,7 +101,8 @@ open class ResourceController(private var resourceResolutionDBService: ResourceR ) ) } else { - throw ResolutionException("Missing param. Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.") + throw httpProcessorException(ErrorCatalogCodes.REQUEST_NOT_FOUND, ResourceApiDomains.RESOURCE_API, + "Missing param. Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.") } } diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceExceptionHandler.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceExceptionHandler.kt index 5d5623d4f..9c09bd819 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceExceptionHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceExceptionHandler.kt @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Bell Canada + * Copyright © 2019 - 2020 IBM, Bell Canada * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,99 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.onap.ccsdk.cds.blueprintsprocessor.resource.api -import com.fasterxml.jackson.annotation.JsonFormat -import com.fasterxml.jackson.annotation.JsonInclude -import com.fasterxml.jackson.annotation.JsonTypeInfo -import com.fasterxml.jackson.annotation.JsonTypeName -import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException -import org.onap.ccsdk.cds.controllerblueprints.core.data.ErrorCode -import org.slf4j.LoggerFactory -import org.springframework.dao.EmptyResultDataAccessException -import org.springframework.dao.IncorrectResultSizeDataAccessException -import org.springframework.http.HttpStatus -import org.springframework.http.ResponseEntity -import org.springframework.orm.jpa.JpaObjectRetrievalFailureException -import org.springframework.web.bind.annotation.ExceptionHandler +import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogExceptionHandler +import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogService import org.springframework.web.bind.annotation.RestControllerAdvice -import org.springframework.web.server.ServerWebInputException -import java.io.Serializable -import java.util.Date /** * Handle exceptions in Resolution API and provide relevant HTTP status codes and messages * * @author Serge Simard - * @version 1.0 + * @version 2.0 */ @RestControllerAdvice("org.onap.ccsdk.cds.blueprintsprocessor.resource.api") -open class ResourceExceptionHandler { - - private val log = LoggerFactory.getLogger(ExceptionHandler::class.toString()) - - private val debugMsg = "Resolution_Service_Error_Message" - - @ExceptionHandler - fun resolutionResultsServiceExceptionHandler(e: BluePrintProcessorException): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.BLUEPRINT_PATH_MISSING - return returnError(e, errorCode) - } - - @ExceptionHandler - fun resolutionResultsServiceExceptionHandler(e: ServerWebInputException): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.INVALID_REQUEST_FORMAT - return returnError(e, errorCode) - } - - @ExceptionHandler - fun resolutionResultsServiceExceptionHandler(e: IncorrectResultSizeDataAccessException): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.DUPLICATE_DATA - return returnError(e, errorCode) - } - - @ExceptionHandler - fun resolutionResultsServiceExceptionHandler(e: EmptyResultDataAccessException): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.RESOURCE_NOT_FOUND - return returnError(e, errorCode) - } - - @ExceptionHandler - fun resolutionResultsServiceExceptionHandler(e: JpaObjectRetrievalFailureException): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.RESOURCE_NOT_FOUND - return returnError(e, errorCode) - } - - @ExceptionHandler - fun resolutionResultsServiceExceptionHandler(e: Exception): ResponseEntity<ErrorMessage> { - val errorCode = ErrorCode.GENERIC_FAILURE - return returnError(e, errorCode) - } - - fun returnError(e: Exception, errorCode: ErrorCode): ResponseEntity<ErrorMessage> { - log.error(e.message, e) - val errorMessage = - ErrorMessage( - errorCode.message(e.message!!), - errorCode.value, - debugMsg - ) - return ResponseEntity(errorMessage, HttpStatus.resolve(errorCode.httpCode)!!) - } - - @ExceptionHandler - fun ResolutionResultsServiceExceptionHandler(e: ResolutionException): ResponseEntity<ErrorMessage> { - log.error(e.message, e) - return ResponseEntity(ErrorMessage(e.message, e.code, debugMsg), HttpStatus.resolve(e.code)) - } -} - -@JsonInclude(JsonInclude.Include.NON_NULL) -@JsonTypeName("errorMessage") -@JsonTypeInfo(include = JsonTypeInfo.As.WRAPPER_OBJECT, use = JsonTypeInfo.Id.NAME) -class ErrorMessage(var message: String?, var code: Int?, var debugMessage: String?) : Serializable { - - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - var timestamp = Date() -} +open class ResourceExceptionHandler(private val errorCatalogService: ErrorCatalogService) : + ErrorCatalogExceptionHandler(errorCatalogService) diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt index 5913bde1d..80000d5fc 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateController.kt @@ -23,7 +23,9 @@ import io.swagger.annotations.ApiParam import kotlinx.coroutines.runBlocking import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.TemplateResolution import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.db.TemplateResolutionService +import org.onap.ccsdk.cds.controllerblueprints.core.httpProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes import org.springframework.http.MediaType import org.springframework.http.ResponseEntity import org.springframework.security.access.prepost.PreAuthorize @@ -99,7 +101,8 @@ open class TemplateController(private val templateResolutionService: TemplateRes var result = "" if ((resolutionKey.isNotEmpty() || artifactName.isNotEmpty()) && (resourceId.isNotEmpty() || resourceType.isNotEmpty())) { - throw ResolutionException("Either retrieve resolved template using artifact name and resolution-key OR using resource-id and resource-type.") + throw httpProcessorException(ErrorCatalogCodes.REQUEST_NOT_FOUND, ResourceApiDomains.RESOURCE_API, + "Either retrieve resolved template using artifact name and resolution-key OR using resource-id and resource-type.") } else if (resolutionKey.isNotEmpty() && artifactName.isNotEmpty()) { result = templateResolutionService.findByResolutionKeyAndBlueprintNameAndBlueprintVersionAndArtifactName( bpName, @@ -117,7 +120,8 @@ open class TemplateController(private val templateResolutionService: TemplateRes resourceType ) } else { - throw ResolutionException("Missing param. Either retrieve resolved template using artifact name and resolution-key OR using resource-id and resource-type.") + throw httpProcessorException(ErrorCatalogCodes.REQUEST_NOT_FOUND, ResourceApiDomains.RESOURCE_API, + "Missing param. Either retrieve resolved template using artifact name and resolution-key OR using resource-id and resource-type.") } var expectedContentType = format diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ErrorCatalogTestConfiguration.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ErrorCatalogTestConfiguration.kt new file mode 100644 index 000000000..5b0d1980b --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ErrorCatalogTestConfiguration.kt @@ -0,0 +1,28 @@ +/* + * Copyright © 2020 IBM, Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.resource.api + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration + +@Configuration +@ComponentScan( + basePackages = ["org.onap.ccsdk.cds.error.catalog"] +) +@EnableAutoConfiguration +open class ErrorCatalogTestConfiguration diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceControllerTest.kt index dab96527d..c5e002f08 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceControllerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResourceControllerTest.kt @@ -27,6 +27,7 @@ import org.onap.ccsdk.cds.controllerblueprints.core.asJsonPrimitive import org.onap.ccsdk.cds.controllerblueprints.core.data.PropertyDefinition import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment +import org.onap.ccsdk.cds.error.catalog.core.ErrorPayload import org.slf4j.LoggerFactory import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest @@ -39,7 +40,7 @@ import org.springframework.test.web.reactive.server.WebTestClient @RunWith(SpringRunner::class) @WebFluxTest @ContextConfiguration( - classes = [TestDatabaseConfiguration::class, + classes = [TestDatabaseConfiguration::class, ErrorCatalogTestConfiguration::class, ResourceController::class, ResourceResolutionDBService::class] ) @ComponentScan( @@ -147,9 +148,11 @@ class ResourceControllerTest { .expectStatus().is4xxClientError .expectBody() .consumeWith { - val r = JacksonUtils.objectMapper.readValue(it.responseBody, ErrorMessage::class.java) + val r = JacksonUtils.objectMapper.readValue(it.responseBody, ErrorPayload::class.java) Assert.assertEquals( - "Missing param. Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.", + "Cause: Missing param. Either retrieve resolved value using artifact name and " + + "resolution-key OR using resource-id and resource-type. \n" + + " Action : Please verify your request.", r.message ) } @@ -166,9 +169,10 @@ class ResourceControllerTest { .expectStatus().is4xxClientError .expectBody() .consumeWith { - val r = JacksonUtils.objectMapper.readValue(it.responseBody, ErrorMessage::class.java) + val r = JacksonUtils.objectMapper.readValue(it.responseBody, ErrorPayload::class.java) Assert.assertEquals( - "Either retrieve resolved value using artifact name and resolution-key OR using resource-id and resource-type.", + "Cause: Either retrieve resolved value using artifact name and resolution-key OR using " + + "resource-id and resource-type. \n Action : Please verify your request.", r.message ) } diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateControllerTest.kt index 09b2c5bf7..098423540 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateControllerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/TemplateControllerTest.kt @@ -38,7 +38,7 @@ import kotlin.test.AfterTest @WebFluxTest @ContextConfiguration( classes = [TestDatabaseConfiguration::class, BluePrintCoreConfiguration::class, - BluePrintCatalogService::class] + BluePrintCatalogService::class, ErrorCatalogTestConfiguration::class] ) @ComponentScan(basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", "org.onap.ccsdk.cds.controllerblueprints"]) @TestPropertySource(locations = ["classpath:application-test.properties"]) @@ -120,7 +120,7 @@ class TemplateControllerTest { webTestClient.get().uri("/api/v1/template?$arguments") .exchange() - .expectStatus().isBadRequest + .expectStatus().isNotFound } } diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/application-test.properties b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/application-test.properties index cb7837ba4..ee7d6e611 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/application-test.properties +++ b/ms/blueprintsprocessor/modules/inbounds/resource-api/src/test/resources/application-test.properties @@ -1,7 +1,7 @@ # -# Copyright � 2017-2018 AT&T Intellectual Property. +# Copyright (c) 2017-2018 AT&T Intellectual Property. # -# Modifications Copyright � 2019 IBM, Bell Canada. +# Modifications Copyright (c) 2019 - 2020 IBM, Bell Canada. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -28,6 +28,11 @@ blueprintsprocessor.blueprintDeployPath=./target/blueprints/deploy blueprintsprocessor.blueprintWorkingPath=./target/blueprints/work blueprintsprocessor.blueprintArchivePath=./target/blueprints/archive +# Error Managements +error.catalog.applicationId=cds +error.catalog.type=properties +error.catalog.errorDefinitionDir=./../../../application/src/test/resources/ + # Python executor blueprints.processor.functions.python.executor.executionPath=./../../../../components/scripts/python/ccsdk_blueprints blueprints.processor.functions.python.executor.modulePaths=./../../../../components/scripts/python/ccsdk_blueprints diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml index 5e3ce2cc9..616b8e144 100755 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/pom.xml @@ -17,13 +17,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>inbounds</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>selfservice-api</artifactId> @@ -41,6 +42,10 @@ <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>blueprint-validation</artifactId> </dependency> + <dependency> + <groupId>org.onap.ccsdk.cds.error.catalog</groupId> + <artifactId>error-catalog-services</artifactId> + </dependency> <!-- For Message libraries --> <dependency> diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandler.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandler.kt index 305437923..46d91e57c 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandler.kt @@ -17,13 +17,19 @@ package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api +import io.grpc.Status import io.grpc.stub.StreamObserver import kotlinx.coroutines.runBlocking import org.onap.ccsdk.cds.blueprintsprocessor.core.BluePrintCoreConfiguration import org.onap.ccsdk.cds.blueprintsprocessor.core.utils.toJava +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.processing.api.BluePrintProcessingServiceGrpc import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput +import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes +import org.onap.ccsdk.cds.error.catalog.core.utils.errorCauseOrDefault +import org.onap.ccsdk.cds.error.catalog.core.utils.errorMessageOrDefault +import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogService import org.slf4j.LoggerFactory import org.springframework.security.access.prepost.PreAuthorize import org.springframework.stereotype.Service @@ -33,7 +39,8 @@ import javax.annotation.PreDestroy @Service open class BluePrintProcessingGRPCHandler( private val bluePrintCoreConfiguration: BluePrintCoreConfiguration, - private val executionServiceHandler: ExecutionServiceHandler + private val executionServiceHandler: ExecutionServiceHandler, + private val errorCatalogService: ErrorCatalogService ) : BluePrintProcessingServiceGrpc.BluePrintProcessingServiceImplBase() { @@ -62,10 +69,29 @@ open class BluePrintProcessingGRPCHandler( override fun onError(error: Throwable) { log.debug("Fail to process message", error) + if (error is BluePrintProcessorException) onErrorCatalog(error) else onError(error) + } + + fun onError(error: Exception) { + responseObserver.onError( + Status.INTERNAL + .withDescription(error.errorMessageOrDefault()) + .withCause(error.errorCauseOrDefault()) + .asException() + ) + } + + fun onErrorCatalog(error: BluePrintProcessorException) { + if (error.protocol == "") { + error.grpc(ErrorCatalogCodes.GENERIC_FAILURE) + } + val errorPayload = errorCatalogService.errorPayload(error) + val grpcCode = Status.fromCodeValue(errorPayload.code) responseObserver.onError( - io.grpc.Status.INTERNAL - .withDescription(error.message) - .asException() + grpcCode + .withDescription(errorPayload.message) + .withCause(error.errorCauseOrDefault()) + .asException() ) } diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingKafkaConsumer.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingKafkaConsumer.kt index 6293f48f4..49f2a50d5 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingKafkaConsumer.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingKafkaConsumer.kt @@ -25,6 +25,7 @@ import org.onap.ccsdk.cds.blueprintsprocessor.message.service.BlueprintMessageCo import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException import org.onap.ccsdk.cds.controllerblueprints.core.jsonAsType import org.onap.ccsdk.cds.controllerblueprints.core.logger +import org.onap.ccsdk.cds.controllerblueprints.core.updateErrorMessage import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty import org.springframework.boot.context.event.ApplicationReadyEvent import org.springframework.context.event.EventListener @@ -50,33 +51,27 @@ open class BluePrintProcessingKafkaConsumer( companion object { const val CONSUMER_SELECTOR = "self-service-api" - const val PRODUCER_SELECTOR = "self-service-api" } @EventListener(ApplicationReadyEvent::class) fun setupMessageListener() = runBlocking { try { log.info( - "Setting up message consumer($CONSUMER_SELECTOR) and " + - "message producer($PRODUCER_SELECTOR)..." + "Setting up message consumer($CONSUMER_SELECTOR)" ) /** Get the Message Consumer Service **/ blueprintMessageConsumerService = try { bluePrintMessageLibPropertyService .blueprintMessageConsumerService(CONSUMER_SELECTOR) + } catch (e: BluePrintProcessorException) { + val errorMsg = "Failed creating Kafka consumer message service." + throw e.updateErrorMessage(SelfServiceApiDomains.SELF_SERVICE_API, errorMsg, + "Wrong Kafka selector provided or internal error in Kafka service.") } catch (e: Exception) { throw BluePrintProcessorException("failed to create consumer service ${e.message}") } - /** Get the Message Producer Service **/ - val blueprintMessageProducerService = try { - bluePrintMessageLibPropertyService - .blueprintMessageProducerService(PRODUCER_SELECTOR) - } catch (e: Exception) { - throw BluePrintProcessorException("failed to create producer service ${e.message}") - } - launch { /** Subscribe to the consumer topics */ val additionalConfig: MutableMap<String, Any> = hashMapOf() @@ -87,10 +82,7 @@ open class BluePrintProcessingKafkaConsumer( ph.register() log.trace("Consumed Message : $message") val executionServiceInput = message.jsonAsType<ExecutionServiceInput>() - val executionServiceOutput = executionServiceHandler.doProcess(executionServiceInput) - // TODO("In future, Message publisher configuration vary with respect to request") - /** Send the response message */ - blueprintMessageProducerService.sendMessage(executionServiceOutput) + executionServiceHandler.doProcess(executionServiceInput) } catch (e: Exception) { log.error("failed in processing the consumed message : $message", e) } finally { @@ -101,8 +93,7 @@ open class BluePrintProcessingKafkaConsumer( } } catch (e: Exception) { log.error( - "failed to start message consumer($CONSUMER_SELECTOR) and " + - "message producer($PRODUCER_SELECTOR) ", e + "failed to start message consumer($CONSUMER_SELECTOR) ", e ) } } @@ -111,8 +102,7 @@ open class BluePrintProcessingKafkaConsumer( fun shutdownMessageListener() = runBlocking { try { log.info( - "Shutting down message consumer($CONSUMER_SELECTOR) and " + - "message producer($PRODUCER_SELECTOR)..." + "Shutting down message consumer($CONSUMER_SELECTOR)" ) blueprintMessageConsumerService.shutDown() ph.arriveAndAwaitAdvance() diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ErrorHandling.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ErrorHandling.kt index b76bc263a..c4baa854c 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ErrorHandling.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ErrorHandling.kt @@ -21,12 +21,6 @@ object SelfServiceApiDomains { const val BLUEPRINT_PROCESSOR = "org.onap.ccsdk.cds.blueprintsprocessor" const val SELF_SERVICE_API = "org.onap.ccsdk.cds.blueprintsprocessor.resource.api" const val SELF_SERVICE_API_VALIDATOR = "org.onap.ccsdk.cds.blueprintsprocessor.resource.api.validator" - const val NETCONF_EXECUTOR = "org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor" - const val RESOURCE_RESOLUTION = "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution" - const val RESTCONF_EXECUTOR = "org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor" - const val CLI_EXECUTOR = "org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor" - const val PYTHON_EXECUTOR = "org.onap.ccsdk.cds.blueprintsprocessor.functions.python.executor" - const val SDC_LISTENER = "org.onap.ccsdk.cds.sdclistener" } object SelfServiceApiHttpErrorCodes { diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceExceptionHandler.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceExceptionHandler.kt new file mode 100644 index 000000000..57c02fe6a --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceExceptionHandler.kt @@ -0,0 +1,32 @@ +/* + * Copyright © 2020 IBM, Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api + +import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogExceptionHandler +import org.onap.ccsdk.cds.error.catalog.services.ErrorCatalogService +import org.springframework.web.bind.annotation.RestControllerAdvice + +/** + * ExecutionServiceExceptionHandler.kt Purpose: Handle exceptions in selfservice API and provide the right + * HTTP code status + * + * @author Steve Siani + * @version 1.0 + */ +@RestControllerAdvice("org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api") +class ExecutionServiceExceptionHandler(private val errorCatalogService: ErrorCatalogService) : + ErrorCatalogExceptionHandler(errorCatalogService) diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandler.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandler.kt index 9524e375e..74c4b00e4 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandler.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandler.kt @@ -44,7 +44,8 @@ class ExecutionServiceHandler( private val bluePrintLoadConfiguration: BluePrintLoadConfiguration, private val blueprintsProcessorCatalogService: BluePrintCatalogService, private val bluePrintWorkflowExecutionService: - BluePrintWorkflowExecutionService<ExecutionServiceInput, ExecutionServiceOutput> + BluePrintWorkflowExecutionService<ExecutionServiceInput, ExecutionServiceOutput>, + private val publishAuditService: PublishAuditService ) { private val log = LoggerFactory.getLogger(ExecutionServiceHandler::class.toString()) @@ -67,33 +68,44 @@ class ExecutionServiceHandler( responseObserver.onNext(executionServiceOutput.toProto()) responseObserver.onCompleted() } - else -> responseObserver.onNext( - response( - executionServiceInput, - "Failed to process request, 'actionIdentifiers.mode' not specified. Valid value are: 'sync' or 'async'.", - true - ).toProto() - ) + else -> { + publishAuditService.publish(executionServiceInput) + val executionServiceOutput = response( + executionServiceInput, + "Failed to process request, 'actionIdentifiers.mode' not specified. Valid value are: 'sync' or 'async'.", + true + ) + publishAuditService.publish(executionServiceOutput) + responseObserver.onNext( + executionServiceOutput.toProto() + ) + } } } suspend fun doProcess(executionServiceInput: ExecutionServiceInput): ExecutionServiceOutput { val requestId = executionServiceInput.commonHeader.requestId - log.info("processing request id $requestId") val actionIdentifiers = executionServiceInput.actionIdentifiers val blueprintName = actionIdentifiers.blueprintName val blueprintVersion = actionIdentifiers.blueprintVersion + + lateinit var executionServiceOutput: ExecutionServiceOutput + + log.info("processing request id $requestId") + try { + publishAuditService.publish(executionServiceInput) + /** Check Blueprint is needed for this request */ if (checkServiceFunction(executionServiceInput)) { - return executeServiceFunction(executionServiceInput) + executionServiceOutput = executeServiceFunction(executionServiceInput) } else { val basePath = blueprintsProcessorCatalogService.getFromDatabase(blueprintName, blueprintVersion) log.info("blueprint base path $basePath") val blueprintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(requestId, basePath.toString()) - val output = bluePrintWorkflowExecutionService.executeBluePrintWorkflow( + executionServiceOutput = bluePrintWorkflowExecutionService.executeBluePrintWorkflow( blueprintRuntimeService, executionServiceInput, hashMapOf() ) @@ -101,14 +113,16 @@ class ExecutionServiceHandler( val errors = blueprintRuntimeService.getBluePrintError().errors if (errors.isNotEmpty()) { val errorMessage = errors.stream().map { it.toString() }.collect(Collectors.joining(", ")) - setErrorStatus(errorMessage, output.status) + setErrorStatus(errorMessage, executionServiceOutput.status) } - return output } } catch (e: Exception) { log.error("fail processing request id $requestId", e) - return response(executionServiceInput, e.localizedMessage ?: e.message ?: e.toString(), true) + executionServiceOutput = response(executionServiceInput, e.localizedMessage ?: e.message ?: e.toString(), true) } + + publishAuditService.publish(executionServiceOutput) + return executionServiceOutput } /** If the blueprint name is default, It means no blueprint is needed for the execution */ diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/KafkaPublishAuditService.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/KafkaPublishAuditService.kt new file mode 100644 index 000000000..129e7a54d --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/KafkaPublishAuditService.kt @@ -0,0 +1,184 @@ +/* + * Copyright © 2020 Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api + +import com.fasterxml.jackson.databind.JsonNode +import com.fasterxml.jackson.databind.node.ObjectNode +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput +import org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution.ResourceResolutionConstants +import org.onap.ccsdk.cds.blueprintsprocessor.message.service.BluePrintMessageLibPropertyService +import org.onap.ccsdk.cds.blueprintsprocessor.message.service.BlueprintMessageProducerService +import org.onap.ccsdk.cds.controllerblueprints.core.BluePrintProcessorException +import org.onap.ccsdk.cds.controllerblueprints.core.common.ApplicationConstants +import org.onap.ccsdk.cds.controllerblueprints.core.interfaces.BluePrintCatalogService +import org.onap.ccsdk.cds.controllerblueprints.core.utils.BluePrintMetadataUtils +import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils +import org.onap.ccsdk.cds.controllerblueprints.core.utils.PropertyDefinitionUtils +import org.onap.ccsdk.cds.controllerblueprints.resource.dict.ResourceAssignment +import org.slf4j.LoggerFactory +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.stereotype.Service +import javax.annotation.PostConstruct + +/** + * Audit service used to produce execution service input and output message + * sent into dedicated kafka topics. + */ +@ConditionalOnProperty( + name = ["blueprintsprocessor.messageproducer.self-service-api.audit.kafkaEnable"], + havingValue = "true" +) +@Service +class KafkaPublishAuditService( + private val bluePrintMessageLibPropertyService: BluePrintMessageLibPropertyService, + private val blueprintsProcessorCatalogService: BluePrintCatalogService +) : PublishAuditService { + + private var inputInstance: BlueprintMessageProducerService? = null + private var outputInstance: BlueprintMessageProducerService? = null + + private lateinit var correlationUUID: String + + private val log = LoggerFactory.getLogger(KafkaPublishAuditService::class.toString()) + + companion object { + const val INPUT_SELECTOR = "self-service-api.audit.request" + const val OUTPUT_SELECTOR = "self-service-api.audit.response" + } + + @PostConstruct + private fun init() { + log.info("Kakfa audit service is enabled") + } + + /** + * Publish execution input into a kafka topic. + * The correlation UUID is used to link the input to its output. + * Sensitive data within the request are hidden. + */ + override suspend fun publish(executionServiceInput: ExecutionServiceInput) { + this.correlationUUID = executionServiceInput.correlationUUID + val secureExecutionServiceInput = hideSensitiveData(executionServiceInput) + this.inputInstance = this.getInputInstance(INPUT_SELECTOR) + this.inputInstance!!.sendMessage(secureExecutionServiceInput) + } + + /** + * Publish execution output into a kafka topic. + * The correlation UUID is used to link the output to its input. + * A correlation UUID is added to link the input to its output. + */ + override fun publish(executionServiceOutput: ExecutionServiceOutput) { + executionServiceOutput.correlationUUID = this.correlationUUID + this.outputInstance = this.getOutputInstance(OUTPUT_SELECTOR) + this.outputInstance!!.sendMessage(executionServiceOutput) + } + + /** + * Return the input kafka producer instance using a selector. + */ + private fun getInputInstance(selector: String): BlueprintMessageProducerService = inputInstance ?: createInstance(selector) + + /** + * Return the output kafka producer instance using a selector. + */ + private fun getOutputInstance(selector: String): BlueprintMessageProducerService = outputInstance ?: createInstance(selector) + + /** + * Create a kafka producer instance. + */ + private fun createInstance(selector: String): BlueprintMessageProducerService { + log.info( + "Setting up message producer($selector)..." + ) + return try { + bluePrintMessageLibPropertyService + .blueprintMessageProducerService(selector) + } catch (e: Exception) { + throw BluePrintProcessorException("failed to create producer service ${e.message}") + } + } + + /** + * Hide sensitive data in the request. + * Sensitive data are declared in the resource resolution mapping using + * the property metadata "log-protect" set to true. + */ + private suspend fun hideSensitiveData( + executionServiceInput: ExecutionServiceInput + ): ExecutionServiceInput { + + var clonedExecutionServiceInput = ExecutionServiceInput().apply { + correlationUUID = executionServiceInput.correlationUUID + commonHeader = executionServiceInput.commonHeader + actionIdentifiers = executionServiceInput.actionIdentifiers + payload = executionServiceInput.payload + } + + val blueprintName = clonedExecutionServiceInput.actionIdentifiers.blueprintName + val workflowName = clonedExecutionServiceInput.actionIdentifiers.actionName + + if (blueprintName == "default") return clonedExecutionServiceInput + + if (clonedExecutionServiceInput.payload + .path("$workflowName-request").has("$workflowName-properties")) { + + /** Retrieving sensitive input parameters */ + val requestId = clonedExecutionServiceInput.commonHeader.requestId + val blueprintVersion = clonedExecutionServiceInput.actionIdentifiers.blueprintVersion + + val basePath = blueprintsProcessorCatalogService.getFromDatabase(blueprintName, blueprintVersion) + + val blueprintRuntimeService = BluePrintMetadataUtils.getBluePrintRuntime(requestId, basePath.toString()) + val blueprintContext = blueprintRuntimeService.bluePrintContext() + + val nodeTemplateName = blueprintContext.workflowFirstStepNodeTemplate(workflowName) + val interfaceName = blueprintContext.nodeTemplateFirstInterfaceName(nodeTemplateName) + val operationName = blueprintContext.nodeTemplateFirstInterfaceFirstOperationName(nodeTemplateName) + + val propertyAssignments: MutableMap<String, JsonNode> = + blueprintContext.nodeTemplateInterfaceOperationInputs(nodeTemplateName, interfaceName, operationName) + ?: hashMapOf() + + val artifactPrefixNamesNode = propertyAssignments[ResourceResolutionConstants.INPUT_ARTIFACT_PREFIX_NAMES] + val artifactPrefixNames = JacksonUtils.getListFromJsonNode(artifactPrefixNamesNode!!, String::class.java) + + /** Storing mapping entries with metadata log-protect set to true */ + val sensitiveParameters: List<String> = artifactPrefixNames + .map { "$it-mapping" } + .map { blueprintRuntimeService.resolveNodeTemplateArtifact(nodeTemplateName, it) } + .flatMap { JacksonUtils.getListFromJson(it, ResourceAssignment::class.java) } + .filter { PropertyDefinitionUtils.hasLogProtect(it.property) } + .map { it.name } + + /** Hiding sensitive input parameters from the request */ + var workflowProperties: ObjectNode = clonedExecutionServiceInput.payload + .path("$workflowName-request") + .path("$workflowName-properties") as ObjectNode + + sensitiveParameters.forEach { sensitiveParameter -> + if (workflowProperties.has(sensitiveParameter)) { + workflowProperties.remove(sensitiveParameter) + workflowProperties.put(sensitiveParameter, ApplicationConstants.LOG_REDACTED) + } + } + } + + return clonedExecutionServiceInput + } +} diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/NoPublishAuditService.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/NoPublishAuditService.kt new file mode 100644 index 000000000..3f782000b --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/NoPublishAuditService.kt @@ -0,0 +1,47 @@ +/* + * Copyright © 2020 Bell Canada + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api + +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput +import org.onap.ccsdk.cds.controllerblueprints.core.logger +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty +import org.springframework.stereotype.Service +import javax.annotation.PostConstruct + +/** + * Default audit service when no audit publisher is defined, message aren't sent + */ +@ConditionalOnProperty( + name = ["blueprintsprocessor.messageproducer.self-service-api.audit.kafkaEnable"], + havingValue = "false" +) +@Service +class NoPublishAuditService : PublishAuditService { + + val log = logger(NoPublishAuditService::class) + + @PostConstruct + fun init() { + log.info("Audit service is disabled") + } + + override suspend fun publish(executionServiceInput: ExecutionServiceInput) { + } + + override fun publish(executionServiceOutput: ExecutionServiceOutput) { + } +} diff --git a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResolutionException.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/PublishAuditService.kt index 62e89e260..535a5eae0 100644 --- a/ms/blueprintsprocessor/modules/inbounds/resource-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/resource/api/ResolutionException.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/PublishAuditService.kt @@ -1,11 +1,11 @@ /* - * Copyright (C) 2019 Bell Canada. + * Copyright © 2020 Bell Canada * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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, @@ -13,8 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onap.ccsdk.cds.blueprintsprocessor.resource.api -class ResolutionException(message: String) : RuntimeException(message) { - var code: Int = 404 +package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api + +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput + +interface PublishAuditService { + suspend fun publish(executionServiceInput: ExecutionServiceInput) + fun publish(executionServiceOutput: ExecutionServiceOutput) } diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandlerTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandlerTest.kt index af23e7902..f33f1149f 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandlerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingGRPCHandlerTest.kt @@ -42,7 +42,8 @@ import kotlin.test.BeforeTest @RunWith(SpringRunner::class) @DirtiesContext @ContextConfiguration( - classes = [SelfServiceApiTestConfiguration::class, TestDatabaseConfiguration::class] + classes = [SelfServiceApiTestConfiguration::class, TestDatabaseConfiguration::class, + ErrorCatalogTestConfiguration::class] ) @TestPropertySource(locations = ["classpath:application-test.properties"]) class BluePrintProcessingGRPCHandlerTest { diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingIntegrationTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingIntegrationTest.kt index b26781ad2..825b0c82a 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingIntegrationTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingIntegrationTest.kt @@ -30,7 +30,11 @@ import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.onap.ccsdk.cds.controllerblueprints.processing.api.BluePrintProcessingServiceGrpc import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceInput import org.onap.ccsdk.cds.controllerblueprints.processing.api.ExecutionServiceOutput +import org.springframework.test.context.ContextConfiguration +@ContextConfiguration( + classes = [SelfServiceApiTestConfiguration::class, ErrorCatalogTestConfiguration::class] +) class BluePrintProcessingIntegrationTest { private val log = logger(BluePrintProcessingIntegrationTest::class) diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingKafkaConsumerTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingKafkaConsumerTest.kt index f71d1b444..ed573d72f 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingKafkaConsumerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/BluePrintProcessingKafkaConsumerTest.kt @@ -35,8 +35,8 @@ import kotlin.test.assertNotNull @RunWith(SpringRunner::class) @ContextConfiguration( - classes = [BluePrintMessageLibConfiguration::class, - BluePrintPropertyConfiguration::class, BluePrintPropertiesService::class] + classes = [BluePrintMessageLibConfiguration::class, SelfServiceApiTestConfiguration::class, + BluePrintPropertyConfiguration::class, BluePrintPropertiesService::class, ErrorCatalogTestConfiguration::class] ) @TestPropertySource(locations = ["classpath:application-test.properties"]) class BluePrintProcessingKafkaConsumerTest { diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ErrorCatalogTestConfiguration.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ErrorCatalogTestConfiguration.kt new file mode 100644 index 000000000..a773b4cc5 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ErrorCatalogTestConfiguration.kt @@ -0,0 +1,28 @@ +/* + * Copyright © 2020 IBM, Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration +import org.springframework.context.annotation.ComponentScan +import org.springframework.context.annotation.Configuration + +@Configuration +@ComponentScan( + basePackages = ["org.onap.ccsdk.cds.error.catalog"] +) +@EnableAutoConfiguration +open class ErrorCatalogTestConfiguration diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceControllerTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceControllerTest.kt index 255220fc5..f2c77d6f8 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceControllerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceControllerTest.kt @@ -29,7 +29,6 @@ import org.onap.ccsdk.cds.controllerblueprints.core.normalizedFile import org.onap.ccsdk.cds.controllerblueprints.core.utils.JacksonUtils import org.springframework.beans.factory.annotation.Autowired import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest -import org.springframework.context.annotation.ComponentScan import org.springframework.test.context.ContextConfiguration import org.springframework.test.context.TestPropertySource import org.springframework.test.context.junit4.SpringRunner @@ -45,11 +44,7 @@ import kotlin.test.assertTrue @WebFluxTest @ContextConfiguration( classes = [ExecutionServiceHandler::class, BluePrintCoreConfiguration::class, - BluePrintCatalogService::class] -) -@ComponentScan( - basePackages = ["org.onap.ccsdk.cds.blueprintsprocessor", - "org.onap.ccsdk.cds.controllerblueprints"] + BluePrintCatalogService::class, SelfServiceApiTestConfiguration::class, ErrorCatalogTestConfiguration::class] ) @TestPropertySource(locations = ["classpath:application-test.properties"]) class ExecutionServiceControllerTest { diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt index 5a44403e1..37f7861be 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/selfservice/api/ExecutionServiceHandlerTest.kt @@ -16,6 +16,11 @@ package org.onap.ccsdk.cds.blueprintsprocessor.selfservice.api +import io.mockk.verify +import io.mockk.coVerify +import io.mockk.Runs +import io.mockk.coEvery +import io.mockk.just import io.mockk.mockk import kotlinx.coroutines.runBlocking import org.junit.Before @@ -23,6 +28,7 @@ import org.junit.runner.RunWith import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ActionIdentifiers import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.CommonHeader import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceInput +import org.onap.ccsdk.cds.blueprintsprocessor.core.api.data.ExecutionServiceOutput import org.onap.ccsdk.cds.blueprintsprocessor.services.execution.AbstractServiceFunction import org.onap.ccsdk.cds.controllerblueprints.core.jsonAsJsonType import org.onap.ccsdk.cds.controllerblueprints.core.service.BluePrintDependencyService @@ -30,13 +36,16 @@ import org.springframework.beans.factory.annotation.Autowired import org.springframework.context.ApplicationContext import org.springframework.stereotype.Service import org.springframework.test.context.ContextConfiguration +import org.springframework.test.context.TestPropertySource import org.springframework.test.context.junit4.SpringRunner import kotlin.test.Test import kotlin.test.assertNotNull import kotlin.test.assertTrue @RunWith(SpringRunner::class) -@ContextConfiguration(classes = [MockServiceAction::class]) +@ContextConfiguration(classes = [MockServiceAction::class, SelfServiceApiTestConfiguration::class, + ErrorCatalogTestConfiguration::class]) +@TestPropertySource(locations = ["classpath:application-test.properties"]) class ExecutionServiceHandlerTest { @Autowired @@ -62,13 +71,52 @@ class ExecutionServiceHandlerTest { } } runBlocking { - val executionServiceHandler = ExecutionServiceHandler(mockk(), mockk(), mockk()) + val executionServiceHandler = ExecutionServiceHandler(mockk(), mockk(), mockk(), mockk()) val isServiceFunction = executionServiceHandler.checkServiceFunction(executionServiceInput) assertTrue(isServiceFunction, "failed to checkServiceFunction") val executionServiceOutput = executionServiceHandler.executeServiceFunction(executionServiceInput) assertNotNull(executionServiceOutput, "failed to get executionServiceOutput") } } + + @Test + fun testPublishAuditFunction() { + val executionServiceInput = ExecutionServiceInput().apply { + commonHeader = CommonHeader().apply { + requestId = "1234" + subRequestId = "1234-12" + originatorId = "cds-test" + } + actionIdentifiers = ActionIdentifiers().apply { + blueprintName = "default" + blueprintVersion = "1.0.0" + actionName = "mock-service-action" + } + } + + val publishAuditService = mockk<KafkaPublishAuditService>(relaxed = true) + val executionServiceHandler = ExecutionServiceHandler( + mockk(), + mockk(), + mockk(), + publishAuditService + ) + + coEvery { publishAuditService.publish(ExecutionServiceInput()) } just Runs + + var executionServiceOutput: ExecutionServiceOutput? = null + runBlocking { + executionServiceOutput = executionServiceHandler.doProcess(executionServiceInput) + } + + coVerify { + publishAuditService.publish(executionServiceInput) + } + + verify { + publishAuditService.publish(executionServiceOutput!!) + } + } } @Service("mock-service-action") diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/application-test.properties b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/application-test.properties index d18b70010..77b61a421 100644 --- a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/application-test.properties +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/application-test.properties @@ -1,7 +1,7 @@ # # Copyright © 2017-2018 AT&T Intellectual Property. # -# Modifications Copyright © 2019 IBM, Bell Canada. +# Modifications Copyright © 2019 - 2020 IBM, Bell Canada. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -28,20 +28,43 @@ blueprintsprocessor.blueprintDeployPath=./target/blueprints/deploy blueprintsprocessor.blueprintWorkingPath=./target/blueprints/work blueprintsprocessor.blueprintArchivePath=./target/blueprints/archive +# Error Managements +error.catalog.applicationId=cds +error.catalog.type=properties +error.catalog.errorDefinitionDir=./../../../application/src/test/resources/ + # Python executor blueprints.processor.functions.python.executor.executionPath=./../../../../components/scripts/python/ccsdk_blueprints blueprints.processor.functions.python.executor.modulePaths=./../../../../components/scripts/python/ccsdk_blueprints -# Kafka-message-lib Configuration +# Kafka-message-lib Configurations blueprintsprocessor.messageconsumer.self-service-api.kafkaEnable=false -blueprintsprocessor.messageconsumer.self-service-api.type=kafka-basic-auth +blueprintsprocessor.messageconsumer.self-service-api.type=kafka-scram-ssl-auth blueprintsprocessor.messageconsumer.self-service-api.bootstrapServers=127.0.0.1:9092 -blueprintsprocessor.messageconsumer.self-service-api.topic=receiver.t blueprintsprocessor.messageconsumer.self-service-api.groupId=receiver-id -blueprintsprocessor.messageconsumer.self-service-api.clientId=default-client-id -blueprintsprocessor.messageconsumer.self-service-api.pollMillSec=10 +blueprintsprocessor.messageconsumer.self-service-api.topic=receiver.t +blueprintsprocessor.messageconsumer.self-service-api.clientId=request-receiver-client-id +blueprintsprocessor.messageconsumer.self-service-api.pollMillSec=1000 +### Security settings +### SSL +blueprintsprocessor.messageconsumer.self-service-api.truststore=src/test/resources/test.truststore.jks +blueprintsprocessor.messageconsumer.self-service-api.truststorePassword=secretpassword +blueprintsprocessor.messageconsumer.self-service-api.keystore=src/test/resources/test.keystore.jks +blueprintsprocessor.messageconsumer.self-service-api.keystorePassword=secretpassword +### SCRAM +blueprintsprocessor.messageconsumer.self-service-api.scramUsername=test-user +blueprintsprocessor.messageconsumer.self-service-api.scramPassword=testUserPassword + +# Kafka audit service Configurations +## Audit request +blueprintsprocessor.messageproducer.self-service-api.audit.kafkaEnable=false +blueprintsprocessor.messageproducer.self-service-api.audit.request.type=kafka-basic-auth +blueprintsprocessor.messageproducer.self-service-api.audit.request.bootstrapServers=127.0.0.1:9092 +blueprintsprocessor.messageproducer.self-service-api.audit.request.clientId=audit-request-producer-client-id +blueprintsprocessor.messageproducer.self-service-api.audit.request.topic=audit-request-producer.t -blueprintsprocessor.messageproducer.self-service-api.type=kafka-basic-auth -blueprintsprocessor.messageproducer.self-service-api.bootstrapServers=127.0.0.1:9092 -blueprintsprocessor.messageproducer.self-service-api.clientId=default-client-id -blueprintsprocessor.messageproducer.self-service-api.topic=producer.t +## Audit response +blueprintsprocessor.messageproducer.self-service-api.audit.response.type=kafka-basic-auth +blueprintsprocessor.messageproducer.self-service-api.audit.response.bootstrapServers=127.0.0.1:9092 +blueprintsprocessor.messageproducer.self-service-api.audit.response.clientId=audit-response-producer-client-id +blueprintsprocessor.messageproducer.self-service-api.audit.response.topic=audit-response-producer.t diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/test.keystore.jks b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/test.keystore.jks Binary files differnew file mode 100644 index 000000000..1a4150952 --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/test.keystore.jks diff --git a/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/test.truststore.jks b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/test.truststore.jks Binary files differnew file mode 100644 index 000000000..b094a1f8a --- /dev/null +++ b/ms/blueprintsprocessor/modules/inbounds/selfservice-api/src/test/resources/test.truststore.jks diff --git a/ms/blueprintsprocessor/modules/outbounds/pom.xml b/ms/blueprintsprocessor/modules/outbounds/pom.xml index e6739571d..49279c926 100644 --- a/ms/blueprintsprocessor/modules/outbounds/pom.xml +++ b/ms/blueprintsprocessor/modules/outbounds/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>modules</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>outbounds</artifactId> diff --git a/ms/blueprintsprocessor/modules/pom.xml b/ms/blueprintsprocessor/modules/pom.xml index 3f6d915bd..fd9a1e7ca 100644 --- a/ms/blueprintsprocessor/modules/pom.xml +++ b/ms/blueprintsprocessor/modules/pom.xml @@ -16,13 +16,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>parent</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <relativePath>../parent</relativePath> </parent> diff --git a/ms/blueprintsprocessor/modules/services/execution-service/pom.xml b/ms/blueprintsprocessor/modules/services/execution-service/pom.xml index 15e715249..a81723663 100644 --- a/ms/blueprintsprocessor/modules/services/execution-service/pom.xml +++ b/ms/blueprintsprocessor/modules/services/execution-service/pom.xml @@ -15,13 +15,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>services</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>execution-service</artifactId> diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt index 3e329d7f5..aa39a1dd0 100644 --- a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/AbstractComponentFunction.kt @@ -134,6 +134,7 @@ abstract class AbstractComponentFunction : BlueprintFunctionNode<ExecutionServic try { prepareRequestNB(executionServiceInput) withTimeout((implementation.timeout * 1000).toLong()) { + log.debug("DEBUG::: AbstractComponentFunction.withTimeout section ${implementation.timeout} seconds") processNB(executionServiceInput) } } catch (runtimeException: RuntimeException) { diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ErrorHandling.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ErrorHandling.kt new file mode 100644 index 000000000..fd7cde4d0 --- /dev/null +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/ErrorHandling.kt @@ -0,0 +1,42 @@ +/* + * Copyright © 2020 IBM, Bell Canada. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.ccsdk.cds.blueprintsprocessor.services.execution + +object ExecutionServiceDomains { + // ExecutionService Domains Constants + const val BLUEPRINT_PROCESSOR = "org.onap.ccsdk.cds.blueprintsprocessor" + const val NETCONF_EXECUTOR = "org.onap.ccsdk.cds.blueprintsprocessor.functions.netconf.executor" + const val RESOURCE_RESOLUTION = "org.onap.ccsdk.cds.blueprintsprocessor.functions.resource.resolution" + const val RESTCONF_EXECUTOR = "org.onap.ccsdk.cds.blueprintsprocessor.functions.restconf.executor" + const val CLI_EXECUTOR = "org.onap.ccsdk.cds.blueprintsprocessor.functions.cli.executor" + const val PYTHON_EXECUTOR = "org.onap.ccsdk.cds.blueprintsprocessor.functions.python.executor" + const val SDC_LISTENER = "org.onap.ccsdk.cds.sdclistener" +} + +object ExecutionServiceHttpErrorCodes { + init { + // Register HttpErrorCodes + // HttpErrorCodes.register("", 200) + } +} + +object ExecutionServiceGrpcErrorCodes { + init { + // Register GrpcErrorCodes + // GrpcErrorCodes.register("", 3) + } +} diff --git a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt index 3b83261e5..861a95507 100644 --- a/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt +++ b/ms/blueprintsprocessor/modules/services/execution-service/src/main/kotlin/org/onap/ccsdk/cds/blueprintsprocessor/services/execution/RemoteScriptExecutionService.kt @@ -41,6 +41,7 @@ import org.springframework.beans.factory.config.ConfigurableBeanFactory import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty import org.springframework.context.annotation.Scope import org.springframework.stereotype.Service +import java.util.concurrent.TimeUnit interface RemoteScriptExecutionService { suspend fun init(selector: Any) @@ -65,12 +66,12 @@ class GrpcRemoteScriptExecutionService(private val bluePrintGrpcLibPropertyServi override suspend fun init(selector: Any) { // Get the GRPC Client Service based on selector - val grpcClientService: BluePrintGrpcClientService - if (selector is JsonNode) { - grpcClientService = bluePrintGrpcLibPropertyService.blueprintGrpcClientService(selector) + val grpcClientService: BluePrintGrpcClientService = if (selector is JsonNode) { + bluePrintGrpcLibPropertyService.blueprintGrpcClientService(selector) } else { - grpcClientService = bluePrintGrpcLibPropertyService.blueprintGrpcClientService(selector.toString()) + bluePrintGrpcLibPropertyService.blueprintGrpcClientService(selector.toString()) } + // Get the GRPC Channel channel = grpcClientService.channel() // Create Non Blocking Stub @@ -81,9 +82,10 @@ class GrpcRemoteScriptExecutionService(private val bluePrintGrpcLibPropertyServi } } - override suspend fun prepareEnv(prepareEnvInput: PrepareRemoteEnvInput): - RemoteScriptExecutionOutput { - val grpResponse = commandExecutorServiceGrpc.prepareEnv(prepareEnvInput.asGrpcData()) + override suspend fun prepareEnv(prepareEnvInput: PrepareRemoteEnvInput): RemoteScriptExecutionOutput { + val grpResponse = commandExecutorServiceGrpc + .withDeadlineAfter(prepareEnvInput.timeOut * 1000, TimeUnit.MILLISECONDS) + .prepareEnv(prepareEnvInput.asGrpcData()) checkNotNull(grpResponse.status) { "failed to get GRPC prepare env response status for requestId(${prepareEnvInput.requestId})" @@ -95,19 +97,18 @@ class GrpcRemoteScriptExecutionService(private val bluePrintGrpcLibPropertyServi return remoteScriptExecutionOutput } - override suspend fun executeCommand(remoteExecutionInput: RemoteScriptExecutionInput): - RemoteScriptExecutionOutput { - - val grpResponse = commandExecutorServiceGrpc.executeCommand(remoteExecutionInput.asGrpcData()) + override suspend fun executeCommand(remoteExecutionInput: RemoteScriptExecutionInput): RemoteScriptExecutionOutput { + val grpResponse = + commandExecutorServiceGrpc + .withDeadlineAfter(remoteExecutionInput.timeOut * 1000, TimeUnit.MILLISECONDS) + .executeCommand(remoteExecutionInput.asGrpcData()) checkNotNull(grpResponse.status) { "failed to get GRPC response status for requestId(${remoteExecutionInput.requestId})" } - val remoteScriptExecutionOutput = grpResponse.asJavaData() log.debug("Received response from command server for requestId(${remoteExecutionInput.requestId})") - - return remoteScriptExecutionOutput + return grpResponse.asJavaData() } override suspend fun close() { diff --git a/ms/blueprintsprocessor/modules/services/pom.xml b/ms/blueprintsprocessor/modules/services/pom.xml index 604cdb19d..da4581fd5 100755 --- a/ms/blueprintsprocessor/modules/services/pom.xml +++ b/ms/blueprintsprocessor/modules/services/pom.xml @@ -17,13 +17,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>modules</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>services</artifactId> diff --git a/ms/blueprintsprocessor/modules/services/workflow-service/pom.xml b/ms/blueprintsprocessor/modules/services/workflow-service/pom.xml index 98bb82397..cfc03e7dc 100644 --- a/ms/blueprintsprocessor/modules/services/workflow-service/pom.xml +++ b/ms/blueprintsprocessor/modules/services/workflow-service/pom.xml @@ -15,13 +15,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>services</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>workflow-service</artifactId> diff --git a/ms/blueprintsprocessor/parent/pom.xml b/ms/blueprintsprocessor/parent/pom.xml index 546156d47..a71392b00 100755 --- a/ms/blueprintsprocessor/parent/pom.xml +++ b/ms/blueprintsprocessor/parent/pom.xml @@ -14,18 +14,19 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds</groupId> <artifactId>blueprintsprocessor</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>parent</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <packaging>pom</packaging> <name>Blueprints Processor Parent</name> diff --git a/ms/blueprintsprocessor/pom.xml b/ms/blueprintsprocessor/pom.xml index 2a6bc75a1..be7a73256 100755 --- a/ms/blueprintsprocessor/pom.xml +++ b/ms/blueprintsprocessor/pom.xml @@ -15,13 +15,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds</groupId> <artifactId>ms</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <relativePath>..</relativePath> </parent> diff --git a/ms/command-executor/pom.xml b/ms/command-executor/pom.xml index 0beb34d5e..ceb4147e0 100755 --- a/ms/command-executor/pom.xml +++ b/ms/command-executor/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds</groupId> <artifactId>ms</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <relativePath>..</relativePath> </parent> diff --git a/ms/command-executor/src/main/docker/Dockerfile b/ms/command-executor/src/main/docker/Dockerfile index 70cf943f6..e91265b56 100644 --- a/ms/command-executor/src/main/docker/Dockerfile +++ b/ms/command-executor/src/main/docker/Dockerfile @@ -5,6 +5,8 @@ RUN python -m pip install --upgrade pip RUN pip install grpcio==${GRPC_PYTHON_VERSION} grpcio-tools==${GRPC_PYTHON_VERSION} RUN pip install virtualenv==16.7.9 +RUN groupadd -r onap && useradd -r -g onap onap + COPY start.sh /opt/app/onap/start.sh RUN chmod u+x /opt/app/onap/start.sh @@ -16,6 +18,9 @@ RUN tar -xzf /source.tar.gz -C /tmp \ && rm -rf /source.tar.gz \ && rm -rf /tmp/@project.build.finalName@ -VOLUME /opt/app/onap/blueprints/deploy/ +RUN mkdir -p /opt/app/onap/blueprints/deploy +RUN chown onap:onap /opt -R +VOLUME /opt/app/onap/blueprints/deploy/ +USER onap ENTRYPOINT /opt/app/onap/start.sh diff --git a/ms/command-executor/src/main/python/command_executor_handler.py b/ms/command-executor/src/main/python/command_executor_handler.py index 3219a974b..1e6f03b81 100644 --- a/ms/command-executor/src/main/python/command_executor_handler.py +++ b/ms/command-executor/src/main/python/command_executor_handler.py @@ -31,7 +31,7 @@ import json REQUIREMENTS_TXT = "requirements.txt" -class CommandExecutorHandler: +class CommandExecutorHandler(): def __init__(self, request): self.request = request @@ -45,51 +45,77 @@ class CommandExecutorHandler: def prepare_env(self, request, results): if not self.is_installed(): - self.create_venv() - if not self.activate_venv(): - return False - - f = open(self.installed, "w+") - if not self.install_packages(request, CommandExecutor_pb2.pip, f, results): - return False - f.write("\r\n") - results.append("\n") - if not self.install_packages(request, CommandExecutor_pb2.ansible_galaxy, f, results): - return False - f.close() + create_venv_status = self.create_venv() + if not create_venv_status["cds_is_successful"]: + err_msg = "ERROR: failed to prepare environment for request {} due to error in creating virtual Python env. Original error {}".format(self.blueprint_id, create_venv_status["err_msg"]) + self.logger.error(err_msg) + return utils.build_ret_data(False, err_msg) + + activate_venv_status = self.activate_venv() + if not activate_venv_status["cds_is_successful"]: + err_msg = "ERROR: failed to prepare environment for request {} due Python venv_activation. Original error {}".format(self.blueprint_id, activate_venv_status["err_msg"]) + self.logger.error(err_msg) + return utils.build_ret_data(False, err_msg) + try: + with open(self.installed, "w+") as f: + if not self.install_packages(request, CommandExecutor_pb2.pip, f, results): + return utils.build_ret_data(False, "ERROR: failed to prepare environment for request {} during pip package install.".format(self.blueprint_id)) + f.write("\r\n") # TODO: is \r needed? + results.append("\n") + if not self.install_packages(request, CommandExecutor_pb2.ansible_galaxy, f, results): + return utils.build_ret_data(False, "ERROR: failed to prepare environment for request {} during Ansible install.".format(self.blueprint_id)) + except Exception as ex: + err_msg = "ERROR: failed to prepare environment for request {} during installing packages. Exception: {}".format(self.blueprint_id, ex) + self.logger.error(err_msg) + return utils.build_ret_data(False, err_msg) else: - f = open(self.installed, "r") - results.append(f.read()) - f.close() + try: + with open(self.installed, "r") as f: + results.append(f.read()) + except Exception as ex: + return utils.build_ret_data(False, "ERROR: failed to prepare environment during reading 'installed' file {}. Exception: {}".format(self.installed, ex)) # deactivate_venv(blueprint_id) - return True + return utils.build_ret_data(True, "") def execute_command(self, request, results): - - if not self.activate_venv(): - return False - - cmd = "cd " + self.venv_home - - if "ansible-playbook" in request.command: - cmd = cmd + "; " + request.command + " -e 'ansible_python_interpreter=" + self.venv_home + "/bin/python'" - else: - cmd = cmd + "; " + request.command + " " + re.escape(MessageToJson(request.properties)) - payload_result = {} - payload_section = [] - is_payload_section = False - - ### extract the original header request into sys-env variables - ### RequestID - request_id = request.requestId - ### Sub-requestID - subrequest_id = request.correlationId - request_id_map = {'CDS_REQUEST_ID':request_id, 'CDS_CORRELATION_ID':subrequest_id} - updated_env = { **os.environ, **request_id_map } - + # workaround for when packages are not specified, we may not want to go through the install step + # can just call create_venv from here. + if not self.is_installed(): + self.create_venv() try: + if not self.is_installed(): + create_venv_status = self.create_venv + if not create_venv_status["cds_is_successful"]: + err_msg = "{} - Failed to execute command during venv creation. Original error: {}".format(self.blueprint_id, create_venv_status["err_msg"]) + results.append(err_msg) + return utils.build_ret_data(False, err_msg) + activate_response = self.activate_venv() + if not activate_response["cds_is_successful"]: + orig_error = activate_response["err_msg"] + err_msg = "{} - Failed to execute command during environment activation. Original error: {}".format(self.blueprint_id, orig_error) + results.append(err_msg) #TODO: get rid of results and just rely on the return data struct. + return utils.build_ret_data(False, err_msg) + + cmd = "cd " + self.venv_home + + ### TODO: replace with os.environ['VIRTUAL_ENV']? + if "ansible-playbook" in request.command: + cmd = cmd + "; " + request.command + " -e 'ansible_python_interpreter=" + self.venv_home + "/bin/python'" + else: + cmd = cmd + "; " + request.command + " " + re.escape(MessageToJson(request.properties)) + payload_section = [] + is_payload_section = False + + ### extract the original header request into sys-env variables + ### RequestID + request_id = request.requestId + ### Sub-requestID + subrequest_id = request.correlationId + request_id_map = {'CDS_REQUEST_ID':request_id, 'CDS_CORRELATION_ID':subrequest_id} + updated_env = { **os.environ, **request_id_map } + with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True, bufsize=1, universal_newlines=True, env=updated_env) as newProcess: while True: @@ -113,14 +139,17 @@ class CommandExecutorHandler: payload_section.append(output.strip()) rc = newProcess.poll() except Exception as e: - self.logger.info("{} - Failed to execute command. Error: {}".format(self.blueprint_id, e)) + err_msg = "{} - Failed to execute command. Error: {}".format(self.blueprint_id, e) + self.logger.info(err_msg) results.append(e) - payload_result["cds_return_code"] = False + payload_result.update(utils.build_ret_data(False, err_msg)) return payload_result # deactivate_venv(blueprint_id) - - payload_result["cds_return_code"] = rc + #Since return code is only used to check if it's zero (success), we can just return success flag instead. + self.logger.debug("python return_code : {}".format(rc)) + is_execution_successful = rc == 0 + payload_result.update(utils.build_ret_data(is_execution_successful, "")) return payload_result def install_packages(self, request, type, f, results): @@ -155,13 +184,16 @@ class CommandExecutorHandler: env = dict(os.environ) if "https_proxy" in os.environ: env['https_proxy'] = os.environ['https_proxy'] + self.logger.info("Using https_proxy: ", env['https_proxy']) try: results.append(subprocess.run(command, check=True, stdout=PIPE, stderr=PIPE, env=env).stdout.decode()) results.append("\n") + self.logger.info("install_python_packages {} succeeded".format(package)) return True except CalledProcessError as e: results.append(e.stderr.decode()) + self.logger.error("install_python_packages {} failed".format(package)) return False def install_ansible_packages(self, package, results): @@ -182,6 +214,10 @@ class CommandExecutorHandler: results.append(e.stderr.decode()) return False + # Returns a map with 'status' and 'err_msg'. + # 'status' True indicates success. + # 'err_msg' indicates an error occurred. The presence of err_msg may not be fatal, + # status should be set to False for fatal errors. def create_venv(self): self.logger.info("{} - Create Python Virtual Environment".format(self.blueprint_id)) try: @@ -189,10 +225,15 @@ class CommandExecutorHandler: # venv doesn't populate the activate_this.py script, hence we use from virtualenv venv.create(self.venv_home, with_pip=True, system_site_packages=True) virtualenv.writefile(os.path.join(bin_dir, "activate_this.py"), virtualenv.ACTIVATE_THIS) + self.logger.info("{} - Creation of Python Virtual Environment finished.".format(self.blueprint_id)) + return utils.build_ret_data(True, "") except Exception as err: - self.logger.info( - "{} - Failed to provision Python Virtual Environment. Error: {}".format(self.blueprint_id, err)) + err_msg = "{} - Failed to provision Python Virtual Environment. Error: {}".format(self.blueprint_id, err) + self.logger.info(err_msg) + return utils.build_ret_data(False, err_msg) + # return map cds_is_successful and err_msg. Status is True on success. err_msg may existence doesn't necessarily indicate fatal condition. + # the 'status' should be set to False to indicate error. def activate_venv(self): self.logger.info("{} - Activate Python Virtual Environment".format(self.blueprint_id)) @@ -203,14 +244,15 @@ class CommandExecutorHandler: path = "%s/bin/activate_this.py" % self.venv_home try: - exec (open(path).read(), {'__file__': path}) + with open(path) as activate_this_script: + exec (activate_this_script.read(), {'__file__': path}) exec (fixpathenvvar) self.logger.info("Running with PATH : {}".format(os.environ['PATH'])) - return True + return utils.build_ret_data(True, "") except Exception as err: - self.logger.info( - "{} - Failed to activate Python Virtual Environment. Error: {}".format(self.blueprint_id, err)) - return False + err_msg ="{} - Failed to activate Python Virtual Environment. Error: {}".format(self.blueprint_id, err) + self.logger.info( err_msg) + return utils.build_ret_data(False, err_msg) def deactivate_venv(self): self.logger.info("{} - Deactivate Python Virtual Environment".format(self.blueprint_id)) diff --git a/ms/command-executor/src/main/python/command_executor_server.py b/ms/command-executor/src/main/python/command_executor_server.py index 39cd1e6da..3435e2272 100644 --- a/ms/command-executor/src/main/python/command_executor_server.py +++ b/ms/command-executor/src/main/python/command_executor_server.py @@ -37,11 +37,12 @@ class CommandExecutorServer(CommandExecutor_pb2_grpc.CommandExecutorServiceServi results = [] handler = CommandExecutorHandler(request) - if not handler.prepare_env(request, results): + prepare_env_response = handler.prepare_env(request, results) + if not prepare_env_response["cds_is_successful"]: self.logger.info("{} - Failed to prepare python environment. {}".format(blueprint_id, results)) - return utils.build_response(request, results, {}, False) + return utils.build_grpc_response(request, results, {}, False) self.logger.info("{} - Package installation logs {}".format(blueprint_id, results)) - return utils.build_response(request, results, {}, True) + return utils.build_grpc_response(request, results, {}, True) def executeCommand(self, request, context): blueprint_id = utils.get_blueprint_id(request) @@ -53,12 +54,12 @@ class CommandExecutorServer(CommandExecutor_pb2_grpc.CommandExecutorServiceServi payload_result = {} handler = CommandExecutorHandler(request) payload_result = handler.execute_command(request, log_results) - if payload_result["cds_return_code"] != 0: + if not payload_result["cds_is_successful"]: self.logger.info("{} - Failed to executeCommand. {}".format(blueprint_id, log_results)) else: self.logger.info("{} - Execution finished successfully.".format(blueprint_id)) - ret = utils.build_response(request, log_results, payload_result, payload_result["cds_return_code"] == 0) + ret = utils.build_grpc_response(request, log_results, payload_result, payload_result["cds_is_successful"]) self.logger.info("Payload returned %s" % payload_result) return ret
\ No newline at end of file diff --git a/ms/command-executor/src/main/python/utils.py b/ms/command-executor/src/main/python/utils.py index a3748eb17..574be51db 100644 --- a/ms/command-executor/src/main/python/utils.py +++ b/ms/command-executor/src/main/python/utils.py @@ -18,23 +18,34 @@ from google.protobuf.timestamp_pb2 import Timestamp import proto.CommandExecutor_pb2 as CommandExecutor_pb2 import json + def get_blueprint_id(request): - blueprint_name = request.identifiers.blueprintName - blueprint_version = request.identifiers.blueprintVersion - return blueprint_name + '/' + blueprint_version + blueprint_name = request.identifiers.blueprintName + blueprint_version = request.identifiers.blueprintVersion + return blueprint_name + '/' + blueprint_version +# Create a response for grpc. Fills in the timestamp as well as removes cds_is_successful element +def build_grpc_response(request, log_results, payload_return, is_success=False): + if is_success: + status = CommandExecutor_pb2.SUCCESS + else: + status = CommandExecutor_pb2.FAILURE -def build_response(request, log_results, payload_return, is_success=False): - if is_success: - status = CommandExecutor_pb2.SUCCESS - else: - status = CommandExecutor_pb2.FAILURE + timestamp = Timestamp() + timestamp.GetCurrentTime() - timestamp = Timestamp() - timestamp.GetCurrentTime() + if "cds_is_successful" in payload_return: + payload_return.pop('cds_is_successful') + payload_str = json.dumps(payload_return) + return CommandExecutor_pb2.ExecutionOutput(requestId=request.requestId, + response=log_results, + status=status, + payload=payload_str, + timestamp=timestamp) - if 'cds_return_code' in payload_return: - payload_return.pop('cds_return_code') - payload_str = json.dumps(payload_return) - return CommandExecutor_pb2.ExecutionOutput(requestId=request.requestId, response=log_results, status=status, - payload=payload_str, timestamp=timestamp) +# build a return data structure which may contain an error message +def build_ret_data(cds_is_successful, err_msg): + ret_data = {"cds_is_successful": cds_is_successful } + if err_msg != "": + ret_data["err_msg"] = err_msg + return ret_data diff --git a/ms/error-catalog/application/pom.xml b/ms/error-catalog/application/pom.xml index c2a09dbdb..e775585ae 100644 --- a/ms/error-catalog/application/pom.xml +++ b/ms/error-catalog/application/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.error.catalog</groupId> <artifactId>error-catalog</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>error-catalog-application</artifactId> @@ -31,4 +32,11 @@ <properties> <sonar.skip>true</sonar.skip> </properties> + + <dependencies> + <dependency> + <groupId>org.onap.ccsdk.cds.error.catalog</groupId> + <artifactId>error-catalog-services</artifactId> + </dependency> + </dependencies> </project> diff --git a/ms/error-catalog/core/pom.xml b/ms/error-catalog/core/pom.xml index 0592112cf..81ad38f00 100644 --- a/ms/error-catalog/core/pom.xml +++ b/ms/error-catalog/core/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.error.catalog</groupId> <artifactId>error-catalog</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>error-catalog-core</artifactId> @@ -31,4 +32,23 @@ <properties> <sonar.skip>true</sonar.skip> </properties> + + <dependencies> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-webflux</artifactId> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.module</groupId> + <artifactId>jackson-module-kotlin</artifactId> + </dependency> + <dependency> + <groupId>org.apache.commons</groupId> + <artifactId>commons-lang3</artifactId> + </dependency> + <dependency> + <groupId>javax.persistence</groupId> + <artifactId>javax.persistence-api</artifactId> + </dependency> + </dependencies> </project> diff --git a/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCatalogException.kt b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCatalogException.kt index 032feb62c..348b60ceb 100644 --- a/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCatalogException.kt +++ b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCatalogException.kt @@ -23,6 +23,8 @@ interface ErrorCatalogExceptionFluent<T> { fun action(action: String): T fun http(type: String): T fun grpc(type: String): T + fun convertToHttp(): T + fun convertToGrpc(): T fun payloadMessage(message: String): T fun addErrorPayloadMessage(message: String): T fun addSubError(errorMessage: ErrorMessage): T @@ -78,12 +80,30 @@ open class ErrorCatalogException : RuntimeException { fun <T : ErrorCatalogException> updateHttp(type: String): T { this.protocol = ErrorMessageLibConstants.ERROR_CATALOG_PROTOCOL_HTTP + this.name = type this.code = HttpErrorCodes.code(type) return this as T } + fun <T : ErrorCatalogException> inverseToHttp(): T { + if (this.protocol != "" && this.protocol == ErrorMessageLibConstants.ERROR_CATALOG_PROTOCOL_GRPC) { + this.protocol = ErrorMessageLibConstants.ERROR_CATALOG_PROTOCOL_HTTP + this.code = HttpErrorCodes.code(this.name) + } + return this as T + } + + fun <T : ErrorCatalogException> inverseToGrpc(): T { + if (this.protocol != "" && this.protocol == ErrorMessageLibConstants.ERROR_CATALOG_PROTOCOL_HTTP) { + this.protocol = ErrorMessageLibConstants.ERROR_CATALOG_PROTOCOL_GRPC + this.code = GrpcErrorCodes.code(this.name) + } + return this as T + } + fun <T : ErrorCatalogException> updateGrpc(type: String): T { this.protocol = ErrorMessageLibConstants.ERROR_CATALOG_PROTOCOL_GRPC + this.name = type this.code = GrpcErrorCodes.code(type) return this as T } diff --git a/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCodes.kt b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCodes.kt index 86483e3e9..8023d97c8 100644 --- a/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCodes.kt +++ b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorCodes.kt @@ -54,8 +54,7 @@ object HttpErrorCodes { } fun code(type: String): Int { - // FIXME("Return Default Error Code , If missing") - return store[type]!! + return store[type] ?: store[ErrorCatalogCodes.GENERIC_FAILURE]!! } } @@ -82,7 +81,6 @@ object GrpcErrorCodes { } fun code(type: String): Int { - // FIXME("Return Default Error Code , If missing") - return store[type]!! + return store[type] ?: store[ErrorCatalogCodes.GENERIC_FAILURE]!! } } diff --git a/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorLibData.kt b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorLibData.kt index 2c0772e31..4158cfaf8 100644 --- a/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorLibData.kt +++ b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/ErrorLibData.kt @@ -20,12 +20,15 @@ import com.fasterxml.jackson.annotation.JsonFormat import org.slf4j.event.Level import org.onap.ccsdk.cds.error.catalog.core.ErrorMessageLibConstants.ERROR_CATALOG_DEFAULT_ERROR_CODE import java.time.LocalDateTime +import java.time.ZoneId +import java.util.Date +import kotlin.collections.ArrayList open class ErrorPayload { var code: Int = ERROR_CATALOG_DEFAULT_ERROR_CODE var status: String = "" @get:JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") - var timestamp: LocalDateTime = LocalDateTime.now() + var timestamp: Date = controllerDate() var message: String = "" var debugMessage: String = "" var logLevel: String = Level.ERROR.name @@ -68,6 +71,11 @@ open class ErrorPayload { this.logLevel == errorPayload.logLevel && this.debugMessage == errorPayload.debugMessage && this.subErrors == errorPayload.subErrors) } + + private fun controllerDate(): Date { + val localDateTime = LocalDateTime.now(ZoneId.systemDefault()) + return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()) + } } /** diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/utils/ErrorCatalogUtils.kt b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/utils/ErrorCatalogUtils.kt index 967d3560c..f13a3604f 100644 --- a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/utils/ErrorCatalogUtils.kt +++ b/ms/error-catalog/core/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/core/utils/ErrorCatalogUtils.kt @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package org.onap.ccsdk.cds.error.catalog.services.utils +package org.onap.ccsdk.cds.error.catalog.core.utils + +import org.apache.commons.lang3.exception.ExceptionUtils object ErrorCatalogUtils { private const val REGEX_PATTERN = "^cause=(.*),action=(.*)" @@ -31,7 +33,7 @@ object ErrorCatalogUtils { } fun Exception.errorCauseOrDefault(): Throwable { - return this.cause ?: Throwable() + return ExceptionUtils.getRootCause(this) } fun Exception.errorMessageOrDefault(): String { diff --git a/ms/error-catalog/pom.xml b/ms/error-catalog/pom.xml index 8b82d7d75..8356e4d38 100644 --- a/ms/error-catalog/pom.xml +++ b/ms/error-catalog/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds</groupId> <artifactId>ms</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <relativePath>..</relativePath> </parent> @@ -37,17 +38,21 @@ <module>services</module> </modules> + <properties> + <error-catalog.version>${project.version}</error-catalog.version> + </properties> + <dependencyManagement> <dependencies> <dependency> <groupId>org.onap.ccsdk.cds.error.catalog</groupId> <artifactId>error-catalog-core</artifactId> - <version>${project.version}</version> + <version>${error-catalog.version}</version> </dependency> <dependency> <groupId>org.onap.ccsdk.cds.error.catalog</groupId> <artifactId>error-catalog-services</artifactId> - <version>${project.version}</version> + <version>${error-catalog.version}</version> </dependency> </dependencies> </dependencyManagement> @@ -55,70 +60,29 @@ <!-- Kotlin Dependencies --> <dependency> <groupId>org.jetbrains.kotlin</groupId> - <artifactId>kotlin-stdlib</artifactId> + <artifactId>kotlin-stdlib-jdk8</artifactId> </dependency> <dependency> <groupId>org.jetbrains.kotlin</groupId> - <artifactId>kotlin-stdlib-common</artifactId> + <artifactId>kotlin-reflect</artifactId> </dependency> <dependency> <groupId>org.jetbrains.kotlin</groupId> - <artifactId>kotlin-script-util</artifactId> + <artifactId>kotlin-stdlib</artifactId> </dependency> <dependency> <groupId>org.jetbrains.kotlin</groupId> - <artifactId>kotlin-stdlib-jdk8</artifactId> - </dependency> - <dependency> - <groupId>org.jetbrains.kotlinx</groupId> - <artifactId>kotlinx-coroutines-core</artifactId> - </dependency> - <dependency> - <groupId>org.jetbrains.kotlinx</groupId> - <artifactId>kotlinx-coroutines-reactor</artifactId> - </dependency> - <dependency> - <groupId>com.fasterxml.jackson.module</groupId> - <artifactId>jackson-module-kotlin</artifactId> + <artifactId>kotlin-stdlib-common</artifactId> </dependency> <dependency> <groupId>org.jetbrains.kotlin</groupId> <artifactId>kotlin-compiler-embeddable</artifactId> </dependency> <dependency> - <groupId>org.jetbrains.kotlin</groupId> - <artifactId>kotlin-scripting-jvm-host</artifactId> - <!--Use kotlin-compiler-embeddable as koltin-compiler wrap--> - <!--guava dependency creating classpath issues at runtime--> - <exclusions> - <exclusion> - <groupId>org.jetbrains.kotlin</groupId> - <artifactId>kotlin-compiler</artifactId> - </exclusion> - </exclusions> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-webflux</artifactId> - </dependency> - <dependency> - <groupId>javax.persistence</groupId> - <artifactId>javax.persistence-api</artifactId> - </dependency> - <dependency> - <groupId>org.springframework.boot</groupId> - <artifactId>spring-boot-starter-data-jpa</artifactId> - </dependency> - <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> - <dependency> - <groupId>io.projectreactor</groupId> - <artifactId>reactor-test</artifactId> - <scope>test</scope> - </dependency> </dependencies> <build> diff --git a/ms/error-catalog/services/pom.xml b/ms/error-catalog/services/pom.xml index a0a1ba9b1..c5e6cb216 100644 --- a/ms/error-catalog/services/pom.xml +++ b/ms/error-catalog/services/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.error.catalog</groupId> <artifactId>error-catalog</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>error-catalog-services</artifactId> @@ -37,5 +38,39 @@ <groupId>org.onap.ccsdk.cds.error.catalog</groupId> <artifactId>error-catalog-core</artifactId> </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-data-jpa</artifactId> + </dependency> + <dependency> + <groupId>org.jetbrains.kotlin</groupId> + <artifactId>kotlin-scripting-jvm-host</artifactId> + <!--Use kotlin-compiler-embeddable as koltin-compiler wrap--> + <!--guava dependency creating classpath issues at runtime--> + <exclusions> + <exclusion> + <groupId>org.jetbrains.kotlin</groupId> + <artifactId>kotlin-compiler</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.jetbrains.kotlinx</groupId> + <artifactId>kotlinx-coroutines-core</artifactId> + </dependency> + <dependency> + <groupId>org.jetbrains.kotlinx</groupId> + <artifactId>kotlinx-coroutines-reactor</artifactId> + </dependency> + <dependency> + <groupId>org.jetbrains.kotlin</groupId> + <artifactId>kotlin-script-util</artifactId> + </dependency> + <!-- Kotlin Dependencies --> + <dependency> + <groupId>io.projectreactor</groupId> + <artifactId>reactor-test</artifactId> + <scope>test</scope> + </dependency> </dependencies> </project> diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogExceptionHandler.kt b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogExceptionHandler.kt index 88e2f4522..258209f71 100644 --- a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogExceptionHandler.kt +++ b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogExceptionHandler.kt @@ -16,10 +16,18 @@ package org.onap.ccsdk.cds.error.catalog.services +import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogCodes import org.onap.ccsdk.cds.error.catalog.core.ErrorCatalogException import org.onap.ccsdk.cds.error.catalog.core.ErrorPayload +import org.onap.ccsdk.cds.error.catalog.core.HttpErrorCodes +import org.onap.ccsdk.cds.error.catalog.core.utils.errorCauseOrDefault +import org.onap.ccsdk.cds.error.catalog.core.utils.errorMessageOrDefault +import org.springframework.dao.EmptyResultDataAccessException +import org.springframework.dao.IncorrectResultSizeDataAccessException import org.springframework.http.ResponseEntity +import org.springframework.orm.jpa.JpaObjectRetrievalFailureException import org.springframework.web.bind.annotation.ExceptionHandler +import org.springframework.web.server.ServerWebInputException abstract class ErrorCatalogExceptionHandler(private val errorCatalogService: ErrorCatalogService) { @@ -28,4 +36,44 @@ abstract class ErrorCatalogExceptionHandler(private val errorCatalogService: Err val errorPayload = errorCatalogService.errorPayload(e) return errorPayload.toResponseEntity() } + + @ExceptionHandler + fun errorCatalogException(e: ServerWebInputException): ResponseEntity<ErrorPayload> { + val error = ErrorCatalogException(HttpErrorCodes.code(ErrorCatalogCodes.REQUEST_NOT_FOUND), + e.errorMessageOrDefault(), e.errorCauseOrDefault()) + val errorPayload = ErrorPayload(error.code, error.name, error.errorMessageOrDefault()) + return errorPayload.toResponseEntity() + } + + @ExceptionHandler + fun errorCatalogException(e: IncorrectResultSizeDataAccessException): ResponseEntity<ErrorPayload> { + val error = ErrorCatalogException(HttpErrorCodes.code(ErrorCatalogCodes.DUPLICATE_DATA), + e.errorMessageOrDefault(), e.errorCauseOrDefault()) + val errorPayload = ErrorPayload(error.code, error.name, error.errorMessageOrDefault()) + return errorPayload.toResponseEntity() + } + + @ExceptionHandler + fun errorCatalogException(e: EmptyResultDataAccessException): ResponseEntity<ErrorPayload> { + val error = ErrorCatalogException(HttpErrorCodes.code(ErrorCatalogCodes.RESOURCE_NOT_FOUND), + e.errorMessageOrDefault(), e.errorCauseOrDefault()) + val errorPayload = ErrorPayload(error.code, error.name, error.errorMessageOrDefault()) + return errorPayload.toResponseEntity() + } + + @ExceptionHandler + fun errorCatalogException(e: JpaObjectRetrievalFailureException): ResponseEntity<ErrorPayload> { + val error = ErrorCatalogException(HttpErrorCodes.code(ErrorCatalogCodes.RESOURCE_NOT_FOUND), + e.errorMessageOrDefault(), e.errorCauseOrDefault()) + val errorPayload = ErrorPayload(error.code, error.name, error.errorMessageOrDefault()) + return errorPayload.toResponseEntity() + } + + @ExceptionHandler + fun errorCatalogException(e: Exception): ResponseEntity<ErrorPayload> { + val error = ErrorCatalogException(HttpErrorCodes.code(ErrorCatalogCodes.GENERIC_FAILURE), + e.errorMessageOrDefault(), e.errorCauseOrDefault()) + val errorPayload = ErrorPayload(error.code, error.name, error.errorMessageOrDefault()) + return errorPayload.toResponseEntity() + } } diff --git a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogService.kt b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogService.kt index 91f817133..21fd51b2f 100644 --- a/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogService.kt +++ b/ms/error-catalog/services/src/main/kotlin/org/onap/ccsdk/cds/error/catalog/services/ErrorCatalogService.kt @@ -24,7 +24,8 @@ import org.onap.ccsdk.cds.error.catalog.core.ErrorMessageLibConstants import org.onap.ccsdk.cds.error.catalog.core.ErrorPayload import org.onap.ccsdk.cds.error.catalog.core.GrpcErrorCodes import org.onap.ccsdk.cds.error.catalog.core.HttpErrorCodes -import org.onap.ccsdk.cds.error.catalog.services.utils.ErrorCatalogUtils +import org.onap.ccsdk.cds.error.catalog.core.utils.ErrorCatalogUtils +import org.apache.commons.lang3.exception.ExceptionUtils import org.springframework.boot.autoconfigure.condition.ConditionalOnBean import org.springframework.stereotype.Service import javax.annotation.PostConstruct @@ -40,10 +41,17 @@ open class ErrorCatalogService(private var errorCatalogLoadService: ErrorCatalog fun errorPayload(errorCatalogException: ErrorCatalogException): ErrorPayload { val errorCatalog = getErrorCatalog(errorCatalogException) - val errorPayload = ErrorPayload(errorCatalog.code, errorCatalog.errorId, errorCatalog.getMessage()) - errorPayload.subErrors.addAll(errorCatalogException.errorPayload!!.subErrors) + val errorPayload: ErrorPayload + if (errorCatalogException.errorPayload == null) { + errorPayload = ErrorPayload(errorCatalog.code, errorCatalog.errorId, errorCatalog.getMessage()) + } else { + errorPayload = errorCatalogException.errorPayload!! + errorPayload.code = errorCatalog.code + errorPayload.message = errorCatalog.getMessage() + errorPayload.status = errorCatalog.errorId + } if (errorCatalogException.cause != null) { - errorPayload.debugMessage = errorCatalogException.cause!!.printStackTrace().toString() + errorPayload.debugMessage = ExceptionUtils.getStackTrace(errorCatalogException.cause) } return errorPayload } diff --git a/ms/pom.xml b/ms/pom.xml index 22f016a2e..92ffa546b 100644 --- a/ms/pom.xml +++ b/ms/pom.xml @@ -14,18 +14,19 @@ * See the License for the specific language governing permissions and * limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds</groupId> <artifactId>parent</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <relativePath>..</relativePath> </parent> <artifactId>ms</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <packaging>pom</packaging> <name>Micro-services Root</name> diff --git a/ms/py-executor/docker/Dockerfile b/ms/py-executor/docker/Dockerfile index 043e15d53..638b09f39 100644 --- a/ms/py-executor/docker/Dockerfile +++ b/ms/py-executor/docker/Dockerfile @@ -1,5 +1,7 @@ FROM python:3.7-slim +RUN groupadd -r onap && useradd -r -g onap onap + RUN mkdir -p /opt/app/onap/logs/ && touch /opt/app/onap/logs/application.log COPY @project.build.finalName@-@assembly.id@.tar.gz /source.tar.gz @@ -10,6 +12,9 @@ RUN tar -xzf /source.tar.gz -C /tmp \ RUN pip install --no-cache-dir -r /opt/app/onap/python/requirements/docker.txt -VOLUME /opt/app/onap/blueprints/deploy/ +RUN mkdir -p /opt/app/onap/blueprints/deploy +RUN chown onap:onap /opt -R +VOLUME /opt/app/onap/blueprints/deploy/ +USER onap ENTRYPOINT /opt/app/onap/python/start.sh diff --git a/ms/py-executor/pom.xml b/ms/py-executor/pom.xml index dee2a3307..e678ea9dc 100644 --- a/ms/py-executor/pom.xml +++ b/ms/py-executor/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds</groupId> <artifactId>ms</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <artifactId>py-executor</artifactId> diff --git a/ms/sdclistener/application/pom.xml b/ms/sdclistener/application/pom.xml index 3825a0809..45c3919e6 100644 --- a/ms/sdclistener/application/pom.xml +++ b/ms/sdclistener/application/pom.xml @@ -14,18 +14,19 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.sdclistener</groupId> <artifactId>parent</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <relativePath>../parent</relativePath> </parent> <artifactId>application</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <packaging>jar</packaging> <name>SDC Listener Application</name> @@ -56,7 +57,7 @@ <dependency> <groupId>org.onap.ccsdk.cds.blueprintsprocessor</groupId> <artifactId>health-api-common</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> diff --git a/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/dto/SdcListenerDtoTest.java b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/dto/SdcListenerDtoTest.java new file mode 100644 index 000000000..1f4ba81f7 --- /dev/null +++ b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/dto/SdcListenerDtoTest.java @@ -0,0 +1,68 @@ +/*- + * ============LICENSE_START========================================== + * ONAP Portal + * =================================================================== + * Copyright (C) 2020 IBM Intellectual Property. All rights reserved. + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software 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. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================ + * + * + */ +package org.onap.ccsdk.cds.sdclistener.dto; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.ccsdk.cds.sdclistener.dto.SdcListenerDto; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import org.onap.ccsdk.cds.sdclistener.client.SdcListenerAuthClientInterceptor; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringRunner.class) +@EnableConfigurationProperties({SdcListenerDto.class,SdcListenerAuthClientInterceptor.class}) +@SpringBootTest(classes = {SdcListenerDtoTest.class}) +public class SdcListenerDtoTest { + + @Autowired + private SdcListenerDto listenerConfiguration; + + @Test + public void testCdsSdcListenerDto() { + listenerConfiguration.setDistributionId("1234"); + listenerConfiguration.setArtifactUrl("/sdc/v1/artifact/"); + assertEquals(listenerConfiguration.getDistributionId(), "1234"); + assertEquals(listenerConfiguration.getArtifactUrl(), "/sdc/v1/artifact/"); + } + + +} diff --git a/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/exceptions/SdcListenerExceptionTest.java b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/exceptions/SdcListenerExceptionTest.java new file mode 100644 index 000000000..72f0ef289 --- /dev/null +++ b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/exceptions/SdcListenerExceptionTest.java @@ -0,0 +1,50 @@ +/*- + * ============LICENSE_START============================================ + * ONAP Portal + * ===================================================================== + * Copyright (C) 2020 IBM Intellectual Property. All rights reserved. + * ===================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software 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. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END================================================ + * + * + */ +package org.onap.ccsdk.cds.sdclistener.exceptions; + +import org.junit.Test; +import static org.junit.Assert.assertEquals; +public class SdcListenerExceptionTest { + + @Test + public void testConstructor() { + final String s1="Exception occured"; + SdcListenerException sle=new SdcListenerException(s1); + assertEquals(sle.getMessage(),"Exception occured"); + } +} diff --git a/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/status/ComponentStatusMessageTest.java b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/status/ComponentStatusMessageTest.java new file mode 100644 index 000000000..898596dfa --- /dev/null +++ b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/status/ComponentStatusMessageTest.java @@ -0,0 +1,30 @@ +package org.onap.ccsdk.cds.sdclistener.status; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.ccsdk.cds.sdclistener.status.ComponentStatusMessage; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.junit.Assert.assertEquals; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {ComponentStatusMessageTest.class}) +public class ComponentStatusMessageTest { + ComponentStatusMessage componentStatusMsg= new ComponentStatusMessage(); + + @Test + public void testComponentStatusMessage() { + componentStatusMsg.setComponentName("Test"); + componentStatusMsg.setArtifactUrl("/sdc/v1/artifact"); + componentStatusMsg.setConsumerID("cds-id-local"); + componentStatusMsg.setDistributionID("1"); + componentStatusMsg.setTimeStamp(01022020); + assertEquals(componentStatusMsg.getComponentName(), "Test"); + assertEquals(componentStatusMsg.getArtifactURL(), "/sdc/v1/artifact"); + assertEquals(componentStatusMsg.getConsumerID(), "cds-id-local"); + assertEquals(componentStatusMsg.getDistributionID(), "1"); + assertEquals(componentStatusMsg.getTimeStamp(), 01022020); + assertEquals(componentStatusMsg.getTimestamp(), 01022020); + } +} diff --git a/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/util/FileUtilTest.java b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/util/FileUtilTest.java new file mode 100644 index 000000000..a43e8c072 --- /dev/null +++ b/ms/sdclistener/application/src/test/java/org/onap/ccsdk/cds/sdclistener/util/FileUtilTest.java @@ -0,0 +1,83 @@ +/*- + * ============LICENSE_START========================================== + * ONAP Portal + * =================================================================== + * Copyright (C) 2020 IBM Intellectual Property. All rights reserved. + * =================================================================== + * + * Unless otherwise specified, all software contained herein is licensed + * under the Apache License, Version 2.0 (the "License"); + * you may not use this software 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. + * + * Unless otherwise specified, all documentation contained herein is licensed + * under the Creative Commons License, Attribution 4.0 Intl. (the "License"); + * you may not use this documentation except in compliance with the License. + * You may obtain a copy of the License at + * + * https://creativecommons.org/licenses/by/4.0/ + * + * Unless required by applicable law or agreed to in writing, documentation + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ============LICENSE_END============================================ + * + * + */ +package org.onap.ccsdk.cds.sdclistener.util; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; +import java.io.File; +import java.io.IOException; +import static org.hamcrest.MatcherAssert.assertThat; +import java.nio.file.Path; +import java.nio.file.Paths; +import org.hamcrest.collection.IsEmptyCollection; + +import java.util.ArrayList; +import java.util.List; +import static org.hamcrest.CoreMatchers.*; + +import static org.junit.Assert.*; + +@RunWith(SpringRunner.class) +@SpringBootTest(classes = {FileUtilTest.class}) +public class FileUtilTest { + + FileUtil fs; + + @Test + public void testDeleteFile() throws IOException { + File tempFile = File.createTempFile("tempFile", ".txt"); +// System.out.println(tempFile.getRoot()); + fs.deleteFile(tempFile,tempFile.getAbsolutePath()); + assertFalse(tempFile.exists()); + + } + + @Test + public void testGetFilesFromDisk() throws IOException{ + + Path resourceDirectory = Paths.get("src","test","resources"); + int totalfile=resourceDirectory.getNameCount(); + List fileList=fs.getFilesFromDisk(resourceDirectory); + assertNotNull(fileList); + assertEquals(fileList.size(),totalfile); + } + + +} diff --git a/ms/sdclistener/distribution/pom.xml b/ms/sdclistener/distribution/pom.xml index 669db4338..ec02cfb5c 100755 --- a/ms/sdclistener/distribution/pom.xml +++ b/ms/sdclistener/distribution/pom.xml @@ -14,13 +14,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds.sdclistener</groupId> <artifactId>parent</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <relativePath>../parent</relativePath> </parent> diff --git a/ms/sdclistener/distribution/src/main/docker/Dockerfile b/ms/sdclistener/distribution/src/main/docker/Dockerfile index 34f6443bf..e9ecb8d66 100755 --- a/ms/sdclistener/distribution/src/main/docker/Dockerfile +++ b/ms/sdclistener/distribution/src/main/docker/Dockerfile @@ -1,7 +1,9 @@ FROM openjdk:8-jdk-alpine +RUN addgroup -S onap && adduser -S onap -G onap # add entrypoint COPY startService.sh /startService.sh +RUN chown onap:onap /startService.sh RUN chmod 751 /startService.sh # add application COPY @project.build.finalName@-@assembly.id@.tar.gz /source.tar.gz @@ -10,4 +12,8 @@ RUN tar -xzf /source.tar.gz -C /tmp \ && rm -rf /source.tar.gz \ && rm -rf /tmp/@project.build.finalName@ +RUN mkdir -p /opt/app/onap/cds-sdc-listener +RUN chown onap:onap /opt -R + +USER onap ENTRYPOINT /startService.sh diff --git a/ms/sdclistener/parent/pom.xml b/ms/sdclistener/parent/pom.xml index 36a96f037..ea67d1b95 100755 --- a/ms/sdclistener/parent/pom.xml +++ b/ms/sdclistener/parent/pom.xml @@ -16,13 +16,14 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds</groupId> <artifactId>sdclistener</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> </parent> <groupId>org.onap.ccsdk.cds.sdclistener</groupId> diff --git a/ms/sdclistener/pom.xml b/ms/sdclistener/pom.xml index 8404f0a81..d89eb14a3 100644 --- a/ms/sdclistener/pom.xml +++ b/ms/sdclistener/pom.xml @@ -14,13 +14,14 @@ * See the License for the specific language governing permissions and * limitations under the License. --> + <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.cds</groupId> <artifactId>ms</artifactId> - <version>0.7.1-SNAPSHOT</version> + <version>1.0.0-SNAPSHOT</version> <relativePath>..</relativePath> </parent> |