aboutsummaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
@media only all and (prefers-color-scheme: dark) { .highlight .hll { background-color: #49483e } .highlight .c { color: #75715e } /* Comment */ .highlight .err { color: #960050; background-color: #1e0010 } /* Error */ .highlight .k { color: #66d9ef } /* Keyword */ .highlight .l { color: #ae81ff } /* Literal */ .highlight .n { color: #f8f8f2 } /* Name */ .highlight .o { color: #f92672 } /* Operator */ .highlight .p { color: #f8f8f2 } /* Punctuation */ .highlight .ch { color: #75715e } /* Comment.Hashbang */ .highlight .cm { color: #75715e } /* Comment.Multiline */ .highlight .cp { color: #75715e } /* Comment.Preproc */ .highlight .cpf { color: #75715e } /* Comment.PreprocFile */ .highlight .c1 { color: #75715e } /* Comment.Single */ .highlight .cs { color: #75715e } /* Comment.Special */ .highlight .gd { color: #f92672 } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gi { color: #a6e22e } /* Generic.Inserted */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #75715e } /* Generic.Subheading */ .highlight .kc { color: #66d9ef } /* Keyword.Constant */ .highlight .kd { color: #66d9ef } /* Keyword.Declaration */ .highlight .kn { color: #f92672 } /* Keyword.Namespace */ .highlight .kp { color: #66d9ef } /* Keyword.Pseudo */ .highlight .kr { color: #66d9ef } /* Keyword.Reserved */ .highlight .kt { color: #66d9ef } /* Keyword.Type */ .highlight .ld { color: #e6db74 } /* Literal.Date */ .highlight .m { color: #ae81ff } /* Literal.Number */ .highlight .s { color: #e6db74 } /* Literal.String */ .highlight .na { color: #a6e22e } /* Name.Attribute */ .highlight .nb { color: #f8f8f2 } /* Name.Builtin */ .highlight .nc { color: #a6e22e } /* Name.Class */ .highlight .no { color: #66d9ef } /* Name.Constant */ .highlight .nd { color: #a6e22e } /* Name.Decorator */ .highlight .ni { color: #f8f8f2 } /* Name.Entity */ .highlight .ne { color: #a6e22e } /* Name.Exception */ .highlight .nf { color: #a6e22e } /* Name.Function */ .highlight .nl { color: #f8f8f2 } /* Name.Label */ .highlight .nn { color: #f8f8f2 } /* Name.Namespace */ .highlight .nx { color: #a6e22e } /* Name.Other */ .highlight .py { color: #f8f8f2 } /* Name.Property */ .highlight .nt { color: #f92672 } /* Name.Tag */ .highlight .nv { color: #f8f8f2 } /* Name.Variable */ .highlight .ow { color: #f92672 } /* Operator.Word */ .highlight .w { color: #f8f8f2 } /* Text.Whitespace */ .highlight .mb { color: #ae81ff } /* Literal.Number.Bin */ .highlight .mf { color: #ae81ff } /* Literal.Number.Float */ .highlight .mh { color: #ae81ff } /* Literal.Number.Hex */ .highlight .mi { color: #ae81ff } /* Literal.Number.Integer */ .highlight .mo { color: #ae81ff } /* Literal.Number.Oct */ .highlight .sa { color: #e6db74 } /* Literal.String.Affix */ .highlight .sb { color: #e6db74 } /* Literal.String.Backtick */ .highlight .sc { color: #e6db74 } /* Literal.String.Char */ .highlight .dl { color: #e6db74 } /* Literal.String.Delimiter */ .highlight .sd { color: #e6db74 } /* Literal.String.Doc */ .highlight .s2 { color: #e6db74 } /* Literal.String.Double */ .highlight .se { color: #ae81ff } /* Literal.String.Escape */ .highlight .sh { color: #e6db74 } /* Literal.String.Heredoc */ .highlight .si { color: #e6db74 } /* Literal.String.Interpol */ .highlight .sx { color: #e6db74 } /* Literal.String.Other */ .highlight .sr { color: #e6db74 } /* Literal.String.Regex */ .highlight .s1 { color: #e6db74 } /* Literal.String.Single */ .highlight .ss { color: #e6db74 } /* Literal.String.Symbol */ .highlight .bp { color: #f8f8f2 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #a6e22e } /* Name.Function.Magic */ .highlight .vc { color: #f8f8f2 } /* Name.Variable.Class */ .highlight .vg { color: #f8f8f2 } /* Name.Variable.Global */ .highlight .vi { color: #f8f8f2 } /* Name.Variable.Instance */ .highlight .vm { color: #f8f8f2 } /* Name.Variable.Magic */ .highlight .il { color: #ae81ff } /* Literal.Number.Integer.Long */ } @media (prefers-color-scheme: light) { .highlight .hll { background-color: #ffffcc } .highlight .c { color: #888888 } /* Comment */ .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */ .highlight .k { color: #008800; font-weight: bold } /* Keyword */ .highlight .ch { color: #888888 } /* Comment.Hashbang */ .highlight .cm { color: #888888 } /* Comment.Multiline */ .highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */ .highlight .cpf { color: #888888 } /* Comment.PreprocFile */ .highlight .c1 { color: #888888 } /* Comment.Single */ .highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */ .highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */ .highlight .ge { font-style: italic } /* Generic.Emph */ .highlight .gr { color: #aa0000 } /* Generic.Error */ .highlight .gh { color: #333333 } /* Generic.Heading */ .highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */ .highlight .go { color: #888888 } /* Generic.Output */ .highlight .gp { color: #555555 } /* Generic.Prompt */ .highlight .gs { font-weight: bold } /* Generic.Strong */ .highlight .gu { color: #666666 } /* Generic.Subheading */ .highlight .gt { color: #aa0000 } /* Generic.Traceback */ .highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */ .highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #008800 } /* Keyword.Pseudo */ .highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */ .highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */ .highlight .na { color: #336699 } /* Name.Attribute */ .highlight .nb { color: #003388 } /* Name.Builtin */ .highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */ .highlight .no { color: #003366; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555555 } /* Name.Decorator */ .highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */ .highlight .nl { color: #336699; font-style: italic } /* Name.Label */ .highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #336699; font-weight: bold } /* Name.Property */ .highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #336699 } /* Name.Variable */ .highlight .ow { color: #008800 } /* Operator.Word */ .highlight .w { color: #bbbbbb } /* Text.Whitespace */ .highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */ .highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */ .highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */ .highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */ .highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */ .highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */ .highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */ .highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */ .highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */ .highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */ .highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */ .highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */ .highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */ .highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #336699 } /* Name.Variable.Class */ .highlight .vg { color: #dd7700 } /* Name.Variable.Global */ .highlight .vi { color: #3333bb } /* Name.Variable.Instance */ .highlight .vm { color: #336699 } /* Name.Variable.Magic */ .highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */ }
<?xml version="1.0" encoding="UTF-8"?>
<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.so</groupId>
        <artifactId>so</artifactId>
        <version>1.2.0-SNAPSHOT</version>
    </parent>

    <artifactId>status-control</artifactId>
    <name>MSO Status Control module</name>
    <description>Contains classes to update and query the MSO status per site</description>

    <dependencies>
        <dependency>
            <groupId>org.onap.so</groupId>
            <artifactId>common</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.onap.so</groupId>
            <artifactId>mso-catalog-db</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>org.onap.so</groupId>
            <artifactId>mso-requests-db</artifactId>
            <version>${project.version}</version>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
</project>
authorSirisha_Manchikanti <sirisha.manchikanti@est.tech>2021-05-07 15:17:52 +0100
committerSirisha_Manchikanti <sirisha.manchikanti@est.tech>2021-05-13 09:00:52 +0100
table summary='file diffstat' width='100%'> -rw-r--r--runtime/src/main/java/org/onap/policy/clamp/authorization/CldsUser.java97
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/authorization/SecureServicePermission.java203
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/authorization/SecureServicePermissionDeserializer.java46
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/authorization/UserService.java43
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/Application.java195
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/ClampInUserAuditorAware.java40
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/ClampServlet.java160
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/TomcatEmbeddedServletContainerFactoryRedirection.java53
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/client/CdsServices.java229
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/client/DcaeInventoryServices.java144
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/config/AafConfiguration.java67
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/config/CamelConfiguration.java166
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/config/ClampProperties.java105
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/config/CldsUserJsonDecoder.java74
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/config/DefaultDictionaryElements.java167
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/config/DefaultUserConfiguration.java140
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/config/SslConfig.java97
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/config/SystemPropertiesLoader.java46
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/config/sdc/SdcControllersConfiguration.java100
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java272
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/config/spring/CldsConfiguration.java55
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/config/spring/SdcControllerConfiguration.java110
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/exception/CldsConfigException.java61
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/exception/CldsUsersException.java61
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/exception/NotAuthorizedException.java61
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/exception/cds/CdsParametersException.java53
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/exception/dcae/DcaeDeploymentException.java61
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/BlueprintParserException.java54
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/CsarHandlerException.java54
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcArtifactInstallerException.java54
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcControllerException.java54
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcDownloadException.java54
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcParametersException.java54
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/filter/ClampCadiFilter.java190
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/model/ClampInformation.java62
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/model/CldsHealthCheck.java60
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java66
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryCache.java62
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryResponse.java102
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeLinks.java60
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeOperationStatusResponse.java88
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/DistributionStatusMessage.java84
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/SdcSingleController.java438
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/SdcSingleControllerStatus.java28
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintArtifact.java70
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintMicroService.java93
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintParser.java220
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/ChainGenerator.java90
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/CsarHandler.java219
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/service/CldsHealthcheckService.java81
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/JsonEditorSchemaConstants.java86
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/ToscaSchemaConstants.java83
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/ToscaConverterWithDictionarySupport.java105
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/UnknownComponentException.java34
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/ArrayField.java72
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/Constraint.java222
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/ToscaElement.java121
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/ToscaElementProperty.java135
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/ToscaMetadataExecutor.java75
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/ToscaMetadataProcess.java43
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/ToscaMetadataTargetProcess.java49
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/cds/ToscaMetadataCdsProcess.java229
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/ToscaConverterToJsonSchema.java353
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/ToscaElementParser.java103
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParser.java32
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParserWithDictionarySupport.java211
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/templates/JsonTemplate.java223
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/templates/JsonTemplateField.java149
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/templates/JsonTemplateManager.java185
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/util/ClampVersioning.java61
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/util/JsonUtils.java53
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/util/LogMessages.java36
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/util/LoggingUtils.java418
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/util/OnapLogConstants.java304
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/clds/util/ResourceFileUtils.java89
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/configuration/ClampGsonDataFormat.java173
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/dao/model/gson/converter/InstantDeserializer.java46
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/dao/model/gson/converter/InstantSerializer.java40
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/dao/model/jsontype/JsonStringSqlTypeDescriptor.java108
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/dao/model/jsontype/JsonTypeDescriptor.java105
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/dao/model/jsontype/StringJsonUserType.java51
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/flow/log/FlowLogOperation.java101
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/CsarInstaller.java209
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/Loop.java389
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/LoopController.java204
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/LoopService.java190
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/LoopState.java28
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/LoopsRepository.java36
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/cds/CdsDataInstaller.java172
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/common/AuditEntity.java146
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/components/external/DcaeComponent.java266
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/components/external/ExternalComponent.java58
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/components/external/ExternalComponentState.java128
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/components/external/PolicyComponent.java128
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/deploy/DcaeDeployParameters.java112
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/log/LogType.java28
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/log/LoopLog.java193
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/log/LoopLogRepository.java32
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/log/LoopLogService.java51
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/service/CsarServiceInstaller.java129
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/service/Service.java169
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/service/ServicesRepository.java31
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopElementModel.java295
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopElementModelsRepository.java31
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplate.java341
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplateLoopElementModel.java192
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplateLoopElementModelId.java100
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplatesRepository.java36
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplatesService.java67
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopType.java42
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTypeConvertor.java52
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModel.java282
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModelId.java92
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModelsRepository.java37
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModelsService.java138
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/Policy.java255
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/PolicyEngineServices.java223
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/PolicyPayload.java91
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/PolicyService.java35
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/downloader/PolicyEngineController.java76
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/microservice/MicroServicePolicy.java276
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/microservice/MicroServicePolicyRepository.java32
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/microservice/MicroServicePolicyService.java112
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicy.java219
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicyRepository.java32
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java348
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicyService.java94
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayload.java141
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayloadException.java54
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupsAnalyzer.java180
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMerger.java104
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/tosca/Dictionary.java219
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryElement.java254
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryElementsRepository.java32
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryRepository.java40
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryService.java141
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/util/PassDecoder.java66
-rw-r--r--runtime/src/main/java/org/onap/policy/clamp/util/SemanticVersioning.java91
-rw-r--r--runtime/src/main/resources/META-INF/resources/swagger.html4508
-rw-r--r--runtime/src/main/resources/META-INF/services/org/apache/camel/dataformat/clamp-gson23
-rw-r--r--runtime/src/main/resources/application-noaaf.properties190
-rw-r--r--runtime/src/main/resources/application.properties203
-rw-r--r--runtime/src/main/resources/asciidoc/swagger.adoc4
-rw-r--r--runtime/src/main/resources/boot-message.txt16
-rw-r--r--runtime/src/main/resources/clds-version.properties24
-rw-r--r--runtime/src/main/resources/clds/aaf/org.onap.clamp.keyfile27
-rw-r--r--runtime/src/main/resources/clds/aaf/ssl/ca-certs.pem32
-rw-r--r--runtime/src/main/resources/clds/aaf/ssl/clamp.key32
-rw-r--r--runtime/src/main/resources/clds/aaf/ssl/clamp.pem33
-rw-r--r--runtime/src/main/resources/clds/aaf/truststoreONAPall.jksbin0 -> 117990 bytes-rw-r--r--runtime/src/main/resources/clds/camel/rest/clamp-api-v2.xml1472
-rw-r--r--runtime/src/main/resources/clds/camel/rest/clds-services.xml24
-rw-r--r--runtime/src/main/resources/clds/camel/routes/cds-flows.xml64
-rw-r--r--runtime/src/main/resources/clds/camel/routes/dcae-flows.xml501
-rw-r--r--runtime/src/main/resources/clds/camel/routes/loop-flows.xml256
-rw-r--r--runtime/src/main/resources/clds/camel/routes/policy-flows.xml654
-rw-r--r--runtime/src/main/resources/clds/camel/routes/utils-flows.xml28
-rw-r--r--runtime/src/main/resources/clds/clds-users.json33
-rw-r--r--runtime/src/main/resources/clds/json-schema/operational_policies/operational_policy.json320
-rw-r--r--runtime/src/main/resources/clds/sdc-controllers-config.json18
-rw-r--r--runtime/src/main/resources/clds/tosca-converter/default-tosca-types.yaml87
-rw-r--r--runtime/src/main/resources/clds/tosca-converter/templates.json398
-rw-r--r--runtime/src/main/resources/logback-default.xml329
-rw-r--r--runtime/src/main/resources/logback-spring.xml19
-rw-r--r--runtime/src/main/resources/logmessages.properties27
-rw-r--r--runtime/src/main/resources/system.properties27
-rw-r--r--runtime/src/main/script/SelectNpmRepo.groovy34
-rw-r--r--runtime/src/main/script/TagVersion.groovy40
-rw-r--r--runtime/src/main/script/checkLibIndex.sh122
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/client/CdsServicesTest.java56
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/config/CldsUserJsonDecoderTest.java99
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/config/sdc/SdcSingleControllerConfigurationTest.java108
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/it/AuthorizationControllerItCase.java137
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/it/CldsHealthcheckServiceItCase.java55
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/it/HttpsItCase.java106
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/it/RobotItCase.java131
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/it/config/CldsReferencePropertiesItCase.java64
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/it/config/SdcControllersConfigurationItCase.java88
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/it/sdc/controller/SdcSingleControllerItCase.java152
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryResponseCacheTestItCase.java127
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryResponseTest.java59
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/model/jsontype/JsonTypeDescriptorTest.java95
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintParserTest.java208
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/sdc/controller/installer/ChainGeneratorTest.java77
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/sdc/controller/installer/CsarHandlerTest.java199
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/tosca/DictionaryRepositoriesTestItCase.java88
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ArrayFieldTest.java55
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ConstraintTest.java106
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/JsonTemplateFieldTest.java69
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/JsonTemplateManagerTest.java203
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/JsonTemplateTest.java69
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ToscaConverterWithDictionarySupportItCase.java147
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ToscaElementPropertyTest.java79
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ToscaElementTest.java52
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/util/JsonUtilsTest.java77
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/util/LoggingUtilsTest.java138
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/util/TestObject.java45
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/clds/util/TestObject2.java44
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/flow/FlowLogOperationTest.java102
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/CsarInstallerItCase.java322
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/DcaeComponentTest.java189
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/DeployFlowTestItCase.java321
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/ExternalComponentStateTest.java82
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/LoopControllerTestItCase.java175
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/LoopLogServiceTestItCase.java96
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/LoopRepositoriesItCase.java258
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/LoopServiceTestItCase.java381
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/LoopTemplateLoopElementModelTest.java105
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/LoopTemplatesServiceItCase.java146
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/LoopToJsonTest.java173
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/PolicyComponentTest.java296
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/PolicyModelServiceItCase.java300
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/ServiceTest.java54
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/loop/deploy/BlueprintInputParametersTest.java125
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/policy/downloader/PolicyEngineControllerTestItCase.java117
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/policy/microservice/MicroServicePayloadTest.java47
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/policy/operational/OperationalPolicyRepresentationBuilderTest.java67
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupAnalyzerTest.java231
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayloadExceptionTest.java33
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayloadTest.java75
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMergerTest.java102
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/tosca/DictionaryServiceItCase.java247
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/util/PassDecoderTest.java55
-rw-r--r--runtime/src/test/java/org/onap/policy/clamp/util/SemanticVersioningTest.java91
-rw-r--r--runtime/src/test/resources/application.properties180
-rw-r--r--runtime/src/test/resources/clds/blueprint-with-microservice-chain.yaml202
-rw-r--r--runtime/src/test/resources/clds/clds-parse-exception.json1
-rw-r--r--runtime/src/test/resources/clds/clds-users-incomplete-permissions.json14
-rw-r--r--runtime/src/test/resources/clds/clds-users-no-permission.json7
-rw-r--r--runtime/src/test/resources/clds/clds-users-two-users.json26
-rw-r--r--runtime/src/test/resources/clds/new-microservice.yaml46
-rw-r--r--runtime/src/test/resources/clds/policy-merger.json215
-rw-r--r--runtime/src/test/resources/clds/sdc-controller-config-NULL.json11
-rw-r--r--runtime/src/test/resources/clds/sdc-controller-config-TLS.json14
-rw-r--r--runtime/src/test/resources/clds/sdc-controller-config-bad.json13
-rw-r--r--runtime/src/test/resources/clds/sdc-controller-config-empty-encrypted.json14
-rw-r--r--runtime/src/test/resources/clds/sdc-controllers-config-bad.json26
-rw-r--r--runtime/src/test/resources/clds/sdc-controllers-config-missing-param.json13
-rw-r--r--runtime/src/test/resources/clds/sdc-controllers-config.json30
-rw-r--r--runtime/src/test/resources/clds/single-microservice-fragment-invalid.yaml25
-rw-r--r--runtime/src/test/resources/clds/single-microservice-fragment-valid-with-version.yaml21
-rw-r--r--runtime/src/test/resources/clds/single-microservice-fragment-without-name.yaml22
-rw-r--r--runtime/src/test/resources/clds/single-microservice-fragment-without-properties.yaml18
-rw-r--r--runtime/src/test/resources/clds/single-microservice-fragment-without-relationships.yaml18
-rw-r--r--runtime/src/test/resources/clds/templates/dcae-deployment-template.json9
-rw-r--r--runtime/src/test/resources/clds/templates/dcae-template.json26
-rw-r--r--runtime/src/test/resources/clds/templates/globalProperties.json104
-rw-r--r--runtime/src/test/resources/clds/templates/sdc-decode-service_ids.json1
-rw-r--r--runtime/src/test/resources/clds/templates/sdc-template.json1
-rw-r--r--runtime/src/test/resources/clds/templates/tca-policy-template.json19
-rw-r--r--runtime/src/test/resources/clds/templates/tca-template.json14
-rw-r--r--runtime/src/test/resources/clds/templates/tca-thresholds-template.json9
-rw-r--r--runtime/src/test/resources/clds/templates/ui-location-default.json5
-rw-r--r--runtime/src/test/resources/clds/util/file.xml6
-rw-r--r--runtime/src/test/resources/example/cds-response/vFW-CDS-modify-config-wf-expected-result.json30
-rw-r--r--runtime/src/test/resources/example/cds-response/vFW-CDS-modify-config-workflow.json78
-rw-r--r--runtime/src/test/resources/example/cds-response/vFW-CDS-resource-assignment-wf-expected-result.json40
-rw-r--r--runtime/src/test/resources/example/cds-response/vFW-CDS-resource-assignment-workflow.json80
-rw-r--r--runtime/src/test/resources/example/dcae/inventory-response.json78
-rw-r--r--runtime/src/test/resources/example/policy/pdp-deployment-testos-1_0_0.json30
-rw-r--r--runtime/src/test/resources/example/policy/pdp-deployment-testos-2_0_0.json204
-rw-r--r--runtime/src/test/resources/example/policy/pdp-group-multi-policies-payload.json74
-rw-r--r--runtime/src/test/resources/example/policy/pdp-group-policy-payload.json54
-rw-r--r--runtime/src/test/resources/example/policy/policy-merger.json269
-rw-r--r--runtime/src/test/resources/example/policy/single-policy-enriched.json47
-rw-r--r--runtime/src/test/resources/example/sdc/blueprint-dcae/tca-bad-policy.yaml141
-rw-r--r--runtime/src/test/resources/example/sdc/blueprint-dcae/tca-guilin.yaml141
-rw-r--r--runtime/src/test/resources/example/sdc/blueprint-dcae/tca.yaml105
-rw-r--r--runtime/src/test/resources/example/sdc/blueprint-dcae/tca_2.yaml174
-rw-r--r--runtime/src/test/resources/example/sdc/blueprint-dcae/tca_3.yaml171
-rw-r--r--runtime/src/test/resources/example/sdc/expected-result/deployment-parameters-multi-blueprints.json43
-rw-r--r--runtime/src/test/resources/example/sdc/expected-result/deployment-parameters-single-blueprint.json9
-rw-r--r--runtime/src/test/resources/example/sdc/expected-result/policy-data.yaml2859
-rw-r--r--runtime/src/test/resources/example/sdc/service-Simsfoimap0112.csarbin0 -> 52568 bytes-rw-r--r--runtime/src/test/resources/example/sdc/service-without-policy.csarbin0 -> 56126 bytes-rw-r--r--runtime/src/test/resources/example/sdc/service_Vloadbalancerms_cds.csarbin0 -> 115771 bytes-rw-r--r--runtime/src/test/resources/example/sdc/service_Vloadbalancerms_no_cds.csarbin0 -> 115690 bytes-rw-r--r--runtime/src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec/.file96
-rw-r--r--runtime/src/test/resources/http-cache/example/api/v1/blueprint-model/workflow-spec/.header1
-rw-r--r--runtime/src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0/.file12
-rw-r--r--runtime/src/test/resources/http-cache/example/api/v1/blueprint-model/workflows/blueprint-name/baseconfiguration/version/1.0.0/.header1
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policies/.file197
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policies/.header1
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/.file53
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/.header1
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.Naming/versions/1.0.0/.file101
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.Naming/versions/1.0.0/.header1
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.Blacklist/versions/1.0.0/.file38
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.Blacklist/versions/1.0.0/.header1
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.FrequencyLimiter/versions/1.0.0/.file47
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.FrequencyLimiter/versions/1.0.0/.header1
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/1.0.0/.file80
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/1.0.0/.header1
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/2.0.0/.file40
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.guard.common.MinMax/versions/2.0.0/.header1
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Apex/versions/1.0.0/.file360
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Apex/versions/1.0.0/.header1
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Drools/versions/1.0.0/.file150
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Drools/versions/1.0.0/.header1
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.monitoring.cdap.tca.hi.lo.app/versions/1.0.0/.file158
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.monitoring.cdap.tca.hi.lo.app/versions/1.0.0/.header1
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.monitoring.tcagen2/versions/1.0.0/.file160
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/api/v1/policytypes/onap.policies.monitoring.tcagen2/versions/1.0.0/.header1
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/pap/v1/pdps/.file104
-rw-r--r--runtime/src/test/resources/http-cache/example/policy/pap/v1/pdps/.header1
-rwxr-xr-xruntime/src/test/resources/http-cache/start_http_cache.sh52
-rw-r--r--runtime/src/test/resources/http-cache/third_party_proxy.py497
-rw-r--r--runtime/src/test/resources/https/https-test.properties135
-rw-r--r--runtime/src/test/resources/https/keystore-test.jksbin0 -> 2244 bytes-rw-r--r--runtime/src/test/resources/logback.xml95
-rw-r--r--runtime/src/test/resources/robotframework/Dockerfile6
-rw-r--r--runtime/src/test/resources/robotframework/requirements.txt6
-rw-r--r--runtime/src/test/resources/robotframework/robotframework-test.properties180
-rw-r--r--runtime/src/test/resources/robotframework/tests/01_healthcheck.robot19
-rw-r--r--runtime/src/test/resources/robotframework/tests/02_policy_queries.robot21
-rw-r--r--runtime/src/test/resources/tosca/micro-service-policy-payload.json42
-rw-r--r--runtime/src/test/resources/tosca/micro-service-policy-properties.json25
-rw-r--r--runtime/src/test/resources/tosca/model-properties-cds.json154
-rw-r--r--runtime/src/test/resources/tosca/model-properties-operational-policy.json353
-rw-r--r--runtime/src/test/resources/tosca/model-properties.json353
-rw-r--r--runtime/src/test/resources/tosca/new-converter/constraints.yaml60
-rw-r--r--runtime/src/test/resources/tosca/new-converter/sampleOperationalPolicies.yaml160
-rw-r--r--runtime/src/test/resources/tosca/new-converter/sampleOperationalPoliciesEXTENTED.yaml174
-rw-r--r--runtime/src/test/resources/tosca/new-converter/tca-with-metadata.json224
-rw-r--r--runtime/src/test/resources/tosca/new-converter/tosca_apex_with_metadata.json577
-rw-r--r--runtime/src/test/resources/tosca/new-converter/tosca_metadata_clamp_possible_values.yaml184
-rw-r--r--runtime/src/test/resources/tosca/operational-policy-cds-payload-with-list.json590
-rw-r--r--runtime/src/test/resources/tosca/operational-policy-json-schema.json936
-rw-r--r--runtime/src/test/resources/tosca/operational-policy-no-guard-properties.json35
-rw-r--r--runtime/src/test/resources/tosca/operational-policy-properties.json132
-rw-r--r--runtime/src/test/resources/tosca/resource-details-cds.json336
-rw-r--r--runtime/src/test/resources/tosca/resource-details.json336
-rw-r--r--runtime/src/test/resources/tosca/service-details.json15
-rw-r--r--runtime/src/test/resources/tosca/tca_hi_lo.json179
-rw-r--r--runtime/src/test/resources/tosca/tosca_example.yaml158
-rw-r--r--runtime/src/test/resources/tosca/tosca_with_date_time_json_schema.json240
-rw-r--r--runtime/src/test/resources/tosca/tosca_with_metadata.yaml162
-rw-r--r--runtime/ui-react-lib/libExportExclusions.dat4
-rwxr-xr-xruntime/ui-react-lib/libIndex.js56
-rwxr-xr-xruntime/ui-react-lib/package.json54
-rwxr-xr-xruntime/ui-react-lib/rollup.config.js48
-rw-r--r--runtime/ui-react/package.json100
-rw-r--r--runtime/ui-react/public/index.html40
-rw-r--r--runtime/ui-react/public/manifest.json15
-rw-r--r--runtime/ui-react/public/onap.icobin0 -> 18046 bytes-rw-r--r--runtime/ui-react/src/LoopUI.js419
-rw-r--r--runtime/ui-react/src/LoopUI.test.js171
-rw-r--r--runtime/ui-react/src/NotFound.js36
-rw-r--r--runtime/ui-react/src/NotFound.test.js36
-rw-r--r--runtime/ui-react/src/OnapClamp.js39
-rw-r--r--runtime/ui-react/src/OnapClamp.test.js36
-rw-r--r--runtime/ui-react/src/__snapshots__/LoopUI.test.js.snap188
-rw-r--r--runtime/ui-react/src/__snapshots__/NotFound.test.js.snap26
-rw-r--r--runtime/ui-react/src/__snapshots__/OnapClamp.test.js.snap216
-rw-r--r--runtime/ui-react/src/api/LoopActionService.js74
-rw-r--r--runtime/ui-react/src/api/LoopCache.js252
-rw-r--r--runtime/ui-react/src/api/LoopCache.test.js305
-rw-r--r--runtime/ui-react/src/api/LoopCacheMockFile.json125
-rw-r--r--runtime/ui-react/src/api/LoopService.js244
-rw-r--r--runtime/ui-react/src/api/PoliciesListCacheMockFile.json215
-rw-r--r--runtime/ui-react/src/api/PolicyService.js148
-rw-r--r--runtime/ui-react/src/api/PolicyToscaService.js80
-rw-r--r--runtime/ui-react/src/api/TemplateService.js197
-rw-r--r--runtime/ui-react/src/api/UserService.js74
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/CreateLoopModal.js190
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/CreateLoopModal.test.js143
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/DeployLoopModal.js173
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/DeployLoopModal.test.js112
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/LoopPropertiesModal.js118
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/LoopPropertiesModal.test.js108
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/ModifyLoopModal.js247
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/ModifyLoopModal.test.js109
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/OpenLoopModal.js137
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/OpenLoopModal.test.js92
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/__snapshots__/CreateLoopModal.test.js.snap167
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/__snapshots__/DeployLoopModal.test.js.snap88
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/__snapshots__/LoopPropertiesModal.test.js.snap61
-rw-r--r--runtime/ui-react/src/components/dialogs/Loop/__snapshots__/OpenLoopModal.test.js.snap137
-rw-r--r--runtime/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.js631
-rw-r--r--runtime/ui-react/src/components/dialogs/ManageDictionaries/ManageDictionaries.test.js462
-rw-r--r--runtime/ui-react/src/components/dialogs/ManageDictionaries/__snapshots__/ManageDictionaries.test.js.snap196
-rw-r--r--runtime/ui-react/src/components/dialogs/PerformActions.js95
-rw-r--r--runtime/ui-react/src/components/dialogs/PerformActions.test.js90
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/PoliciesTreeViewer.js109
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/PolicyDeploymentEditor.js176
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/PolicyEditor.js192
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/PolicyEditor.test.js71
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/PolicyModal.js345
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/PolicyModal.test.js135
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/PolicyToscaFileSelector.js128
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/ToscaViewer.js66
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/ToscaViewer.test.js54
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/ViewAllPolicies.js473
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/__snapshots__/PolicyEditor.test.js.snap788
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/__snapshots__/PolicyModal.test.js.snap159
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/__snapshots__/ToscaViewer.test.js.snap30
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/toscaData.test.json179
-rw-r--r--runtime/ui-react/src/components/dialogs/Policy/toscaData.test.yaml13
-rw-r--r--runtime/ui-react/src/components/dialogs/RefreshStatus.js65
-rw-r--r--runtime/ui-react/src/components/dialogs/RefreshStatus.test.js71
-rw-r--r--runtime/ui-react/src/components/dialogs/Tosca/ViewLoopTemplatesModal.js163
-rw-r--r--runtime/ui-react/src/components/dialogs/Tosca/ViewLoopTemplatesModal.test.js162
-rw-r--r--runtime/ui-react/src/components/dialogs/Tosca/__snapshots__/ViewLoopTemplatesModal.test.js.snap157
-rw-r--r--runtime/ui-react/src/components/dialogs/UserInfoModal.js110
-rw-r--r--runtime/ui-react/src/components/dialogs/UserInfoModal.test.js78
-rw-r--r--runtime/ui-react/src/components/dialogs/__snapshots__/UserInfoModal.test.js.snap119
-rw-r--r--runtime/ui-react/src/components/loop_viewer/logs/LoopLogs.js96
-rw-r--r--runtime/ui-react/src/components/loop_viewer/logs/LoopLogs.test.js70
-rw-r--r--runtime/ui-react/src/components/loop_viewer/logs/__snapshots__/LoopLogs.test.js.snap62
-rw-r--r--runtime/ui-react/src/components/loop_viewer/status/LoopStatus.js106
-rw-r--r--runtime/ui-react/src/components/loop_viewer/status/LoopStatus.test.js78
-rw-r--r--runtime/ui-react/src/components/loop_viewer/status/__snapshots__/LoopStatus.test.js.snap66
-rw-r--r--runtime/ui-react/src/components/loop_viewer/svg/SvgGenerator.js246
-rw-r--r--runtime/ui-react/src/components/menu/MenuBar.js123
-rw-r--r--runtime/ui-react/src/components/menu/MenuBar.test.js46
-rw-r--r--runtime/ui-react/src/components/menu/__snapshots__/MenuBar.test.js.snap1070
-rw-r--r--runtime/ui-react/src/index.js38
-rw-r--r--runtime/ui-react/src/logo.pngbin0 -> 21360 bytes-rw-r--r--runtime/ui-react/src/setupTests.js28
-rw-r--r--runtime/ui-react/src/theme/globalStyle.js98
-rw-r--r--runtime/ui-react/src/utils/CsvToJson.js204
-rw-r--r--runtime/ui-react/src/utils/CsvToJson.test.js268
-rw-r--r--runtime/ui-react/src/utils/OnapConstants.js32
-rw-r--r--runtime/ui-react/src/utils/OnapUtils.js65
449 files changed, 63871 insertions, 0 deletions
diff --git a/runtime/extra/bin-for-dev/start-backend.sh b/runtime/extra/bin-for-dev/start-backend.sh
new file mode 100755
index 000000000..df513d263
--- /dev/null
+++ b/runtime/extra/bin-for-dev/start-backend.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+# Start Clamp backend in DEBUG mode
+mkdir -p /var/log/onap
+java -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=9999 -jar ../../target/policy-clamp-backend.jar --spring.config.name=application-noaaf
diff --git a/runtime/extra/bin-for-dev/start-db.sh b/runtime/extra/bin-for-dev/start-db.sh
new file mode 100755
index 000000000..97f8de1f5
--- /dev/null
+++ b/runtime/extra/bin-for-dev/start-db.sh
@@ -0,0 +1,35 @@
+#!/bin/sh
+
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+docker-compose -f ../docker/clamp/docker-compose.yml up -d db
+
+if [ "$1" = "test" ]; then
+ while ! (docker logs clamp_db_1 2>&1 | grep "socket: '/run/mysqld/mysqld.sock' port: 3306 mariadb.org binary distribution" > /dev/null);
+ do
+ echo "Waiting Mysql to be up with CLDSDB4 db loaded before loading the TEST DATA ..."
+ sleep 3
+ done
+ docker exec -it clamp_db_1 /docker-entrypoint-initdb.d/dump/load-fake-data.sh
+fi;
diff --git a/runtime/extra/bin-for-dev/start-emulator.sh b/runtime/extra/bin-for-dev/start-emulator.sh
new file mode 100755
index 000000000..274d88939
--- /dev/null
+++ b/runtime/extra/bin-for-dev/start-emulator.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+docker-compose -f ../docker/clamp/docker-compose.yml up -d third-party-proxy
diff --git a/runtime/extra/bin-for-dev/start-frontend.sh b/runtime/extra/bin-for-dev/start-frontend.sh
new file mode 100755
index 000000000..d5f4d2414
--- /dev/null
+++ b/runtime/extra/bin-for-dev/start-frontend.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+cd ../../target/ui-react
+node/npm start --scripts-prepend-node-path
diff --git a/runtime/extra/docker/clamp/clamp.env b/runtime/extra/docker/clamp/clamp.env
new file mode 100644
index 000000000..5d31aa42e
--- /dev/null
+++ b/runtime/extra/docker/clamp/clamp.env
@@ -0,0 +1,2 @@
+### Be careful, this must be in one line only ###
+SPRING_APPLICATION_JSON={"spring.datasource.url":"jdbc:mariadb:sequential://db:3306/cldsdb4?autoReconnect=true&connectTimeout=10000&socketTimeout=10000&retriesAllDown=3","spring.profiles.active":"clamp-default,clamp-default-user,clamp-sdc-controller,clamp-ssl-config,clamp-policy-controller,default-dictionary-elements","clamp.config.policy.api.url":"http://third-party-proxy:8085","clamp.config.policy.pap.url":"http://third-party-proxy:8085","clamp.config.dcae.inventory.url":"http://third-party-proxy:8085","clamp.config.dcae.deployment.url":"http://third-party-proxy:8085"}
diff --git a/runtime/extra/docker/clamp/docker-compose.yml b/runtime/extra/docker/clamp/docker-compose.yml
new file mode 100644
index 000000000..c56be0aae
--- /dev/null
+++ b/runtime/extra/docker/clamp/docker-compose.yml
@@ -0,0 +1,38 @@
+version: '3.1'
+
+services:
+ policy-clamp-frontend:
+ image: onap/policy-clamp-frontend
+ depends_on:
+ - policy-clamp-backend
+ ports:
+ - "2443:2443"
+ db:
+ image: mariadb:10.5.4
+ volumes:
+ - "/var/lib/mysql"
+ - "../mariadb/conf1:/etc/mysql/conf.d:ro"
+ - "../../sql/:/docker-entrypoint-initdb.d:rw"
+ environment:
+ - MYSQL_ROOT_PASSWORD=strong_pitchou
+ ports:
+ - "3306:3306"
+
+ policy-clamp-backend:
+ image: onap/policy-clamp-backend
+ depends_on:
+ - db
+ - third-party-proxy
+ env_file:
+ - clamp.env
+ ports:
+ - "10443:8443"
+
+ third-party-proxy:
+ image: python:2-slim
+ volumes:
+ - "../../../src/test/resources/http-cache/example/:/thirdparty:rw"
+ - "../../../src/test/resources/http-cache/:/script/:ro"
+ ports:
+ - "8085:8085"
+ command: /bin/sh -c "pip install --no-cache-dir requests && pip install --no-cache-dir simplejson && python -u /script/third_party_proxy.py -v true --port 8085 --root /thirdparty --proxyaddress third-party-proxy:8085"
diff --git a/runtime/extra/docker/mariadb/conf1/my.cnf b/runtime/extra/docker/mariadb/conf1/my.cnf
new file mode 100644
index 000000000..c6631fb4e
--- /dev/null
+++ b/runtime/extra/docker/mariadb/conf1/my.cnf
@@ -0,0 +1,194 @@
+# Example MySQL config file for medium systems.
+#
+# This is for a system with memory 8G where MySQL plays
+# an important part, or systems up to 128M where MySQL is used together with
+# other programs (such as a web server)
+#
+# In this file, you can use all long options that a program supports.
+# If you want to know which options a program supports, run the program
+# with the "--help" option.
+
+# The following options will be passed to all MySQL clients
+##[client]
+##user = root
+##port = 3306
+##socket = //opt/app/mysql/mysql.sock
+
+# Here follows entries for some specific programs
+
+# The MySQL server
+[mysqld]
+##performance_schema
+
+slow_query_log =ON
+long_query_time =2
+slow_query_log_file =//var/lib/mysql/slow_query.log
+##basedir = //opt/app/mysql/product/mariadb-10.1.11-linux-x86_64
+##datadir = //opt/app/mysql/data
+##port = 3306
+##socket = //opt/app/mysql/mysql.sock
+skip-external-locking
+explicit_defaults_for_timestamp = true
+skip-symbolic-links
+local-infile = 0
+#ignore_db_dir=lost+found
+key_buffer_size = 16M
+max_allowed_packet = 4M
+table_open_cache = 100
+sort_buffer_size = 512K
+net_buffer_length = 8K
+read_buffer_size = 256K
+read_rnd_buffer_size = 512K
+myisam_sort_buffer_size = 8M
+max_connections = 500
+lower_case_table_names = 1
+thread_stack = 256K
+thread_cache_size = 25
+query_cache_size = 8M
+query_cache_type = 0
+query_prealloc_size = 512K
+query_cache_limit = 1M
+
+# Password validation
+##plugin-load-add=simple_password_check.so
+##simple_password_check_other_characters=0
+
+# Audit Log settings
+plugin-load-add=server_audit.so
+server_audit=FORCE_PLUS_PERMANENT
+server_audit_file_path=//var/lib/mysql/audit.log
+server_audit_file_rotate_size=50M
+server_audit_events=CONNECT,QUERY,TABLE
+server_audit_logging=on
+
+# Don't listen on a TCP/IP port at all. This can be a security enhancement,
+# if all processes that need to connect to mysqld run on the same host.
+# All interaction with mysqld must be made via Unix sockets or named pipes.
+# Note that using this option without enabling named pipes on Windows
+# (via the "enable-named-pipe" option) will render mysqld useless!
+#
+#skip-networking
+
+# Replication Master Server (default)
+# binary logging is required for replication
+##log-bin=//var/lib/mysql/mysql-bin
+
+# binary logging format - mixed recommended
+binlog_format=row
+
+# required unique id between 1 and 2^32 - 1
+# defaults to 1 if master-host is not set
+# but will not function as a master if omitted
+
+# Replication Slave (comment out master section to use this)
+#
+# To configure this host as a replication slave, you can choose between
+# two methods :
+#
+# 1) Use the CHANGE MASTER TO command (fully described in our manual) -
+# the syntax is:
+#
+# CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>,
+# MASTER_USER=<user>, MASTER_PASSWORD=<password> ;
+#
+# where you replace <host>, <user>, <password> by quoted strings and
+# <port> by the master's port number (3306 by default).
+#
+# Example:
+#
+# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306,
+# MASTER_USER='joe', MASTER_PASSWORD='secret';
+#
+# OR
+#
+# 2) Set the variables below. However, in case you choose this method, then
+# start replication for the first time (even unsuccessfully, for example
+# if you mistyped the password in master-password and the slave fails to
+# connect), the slave will create a master.info file, and any later
+# change in this file to the variables' values below will be ignored and
+# overridden by the content of the master.info file, unless you shutdown
+# the slave server, delete master.info and restart the slaver server.
+# For that reason, you may want to leave the lines below untouched
+# (commented) and instead use CHANGE MASTER TO (see above)
+#
+# required unique id between 2 and 2^32 - 1
+# (and different from the master)
+# defaults to 2 if master-host is set
+# but will not function as a slave if omitted
+#server-id = 2
+#
+# The replication master for this slave - required
+#master-host = <hostname>
+#
+# The username the slave will use for authentication when connecting
+# to the master - required
+#master-user = <username>
+#
+# The password the slave will authenticate with when connecting to
+# the master - required
+#master-password = <password>
+#
+# The port the master is listening on.
+# optional - defaults to 3306
+#master-port = <port>
+#
+# binary logging - not required for slaves, but recommended
+#log-bin=mysql-bin
+
+# Uncomment the following if you are using InnoDB tables
+##innodb_data_home_dir = //opt/app/mysql/data
+##innodb_data_file_path = ibdata1:20M:autoextend:max:32G
+##innodb_log_group_home_dir = //opt/app/mysql/iblogs
+# You can set .._buffer_pool_size up to 50 - 80 %
+# of RAM but beware of setting memory usage too high
+innodb_buffer_pool_size = 128M
+#innodb_additional_mem_pool_size = 2M
+# Set .._log_file_size to 25 % of buffer pool size
+innodb_log_file_size = 10M
+innodb_log_files_in_group = 3
+innodb_log_buffer_size = 8M
+#innodb_flush_log_at_trx_commit = 1
+innodb_lock_wait_timeout = 50
+innodb_autoextend_increment = 100
+expire_logs_days = 8
+open_files_limit = 2000
+transaction-isolation=READ-COMMITTED
+####### Galera parameters #######
+## Galera Provider configuration
+wsrep_provider=/usr/lib/galera/libgalera_smm.so
+wsrep_provider_options="gcache.size=128M; gcache.page_size=10M"
+## Galera Cluster configuration
+wsrep_cluster_name="MSO-automated-tests-cluster"
+wsrep_cluster_address="gcomm://"
+#wsrep_cluster_address="gcomm://mariadb1,mariadb2,mariadb3"
+##wsrep_cluster_address="gcomm://192.169.3.184,192.169.3.185,192.169.3.186"
+## Galera Synchronization configuration
+wsrep_sst_method=rsync
+#wsrep_sst_method=xtrabackup-v2
+#wsrep_sst_auth="sstuser:Mon#2o!6"
+## Galera Node configuration
+wsrep_node_name="mariadb1"
+##wsrep_node_address="192.169.3.184"
+wsrep_on=OFF
+## Status notification
+#wsrep_notify_cmd=/opt/app/mysql/bin/wsrep_notify
+#######
+
+
+[mysqldump]
+quick
+max_allowed_packet = 16M
+
+[mysql]
+no-auto-rehash
+# Remove the next comment character if you are not familiar with SQL
+#safe-updates
+
+[myisamchk]
+key_buffer_size = 20971520
+
+##[mysqlhotcopy]
+##interactive-timeout
+##[mysqld_safe]
+##malloc-lib=//opt/app/mysql/local/lib/libjemalloc.so.1
+##log-error=//opt/app/mysql/log/mysqld.log \ No newline at end of file
diff --git a/runtime/extra/docker/mariadb/conf2/my.cnf b/runtime/extra/docker/mariadb/conf2/my.cnf
new file mode 100644
index 000000000..bf5f9c177
--- /dev/null
+++ b/runtime/extra/docker/mariadb/conf2/my.cnf
@@ -0,0 +1,193 @@
+# Example MySQL config file for medium systems.
+#
+# This is for a system with memory 8G where MySQL plays
+# an important part, or systems up to 128M where MySQL is used together with
+# other programs (such as a web server)
+#
+# In this file, you can use all long options that a program supports.
+# If you want to know which options a program supports, run the program
+# with the "--help" option.
+
+# The following options will be passed to all MySQL clients
+##[client]
+##user = root
+##port = 3306
+##socket = //opt/app/mysql/mysql.sock
+
+# Here follows entries for some specific programs
+
+# The MySQL server
+[mysqld]
+##performance_schema
+
+slow_query_log =ON
+long_query_time =2
+slow_query_log_file =//var/lib/mysql/slow_query.log
+##basedir = //opt/app/mysql/product/mariadb-10.1.11-linux-x86_64
+##datadir = //opt/app/mysql/data
+##port = 3306
+##socket = //opt/app/mysql/mysql.sock
+skip-external-locking
+explicit_defaults_for_timestamp = true
+skip-symbolic-links
+local-infile = 0
+#ignore_db_dir=lost+found
+key_buffer_size = 16M
+max_allowed_packet = 4M
+table_open_cache = 100
+sort_buffer_size = 512K
+net_buffer_length = 8K
+read_buffer_size = 256K
+read_rnd_buffer_size = 512K
+myisam_sort_buffer_size = 8M
+max_connections = 500
+lower_case_table_names = 1
+thread_stack = 256K
+thread_cache_size = 25
+query_cache_size = 8M
+query_cache_type = 0
+query_prealloc_size = 512K
+query_cache_limit = 1M
+
+# Password validation
+##plugin-load-add=simple_password_check.so
+##simple_password_check_other_characters=0
+
+# Audit Log settings
+plugin-load-add=server_audit.so
+server_audit=FORCE_PLUS_PERMANENT
+server_audit_file_path=//var/lib/mysql/audit.log
+server_audit_file_rotate_size=50M
+server_audit_events=CONNECT,QUERY,TABLE
+server_audit_logging=on
+
+# Don't listen on a TCP/IP port at all. This can be a security enhancement,
+# if all processes that need to connect to mysqld run on the same host.
+# All interaction with mysqld must be made via Unix sockets or named pipes.
+# Note that using this option without enabling named pipes on Windows
+# (via the "enable-named-pipe" option) will render mysqld useless!
+#
+#skip-networking
+
+# Replication Master Server (default)
+# binary logging is required for replication
+##log-bin=//var/lib/mysql/mysql-bin
+
+# binary logging format - mixed recommended
+binlog_format=row
+
+# required unique id between 1 and 2^32 - 1
+# defaults to 1 if master-host is not set
+# but will not function as a master if omitted
+
+# Replication Slave (comment out master section to use this)
+#
+# To configure this host as a replication slave, you can choose between
+# two methods :
+#
+# 1) Use the CHANGE MASTER TO command (fully described in our manual) -
+# the syntax is:
+#
+# CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>,
+# MASTER_USER=<user>, MASTER_PASSWORD=<password> ;
+#
+# where you replace <host>, <user>, <password> by quoted strings and
+# <port> by the master's port number (3306 by default).
+#
+# Example:
+#
+# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306,
+# MASTER_USER='joe', MASTER_PASSWORD='secret';
+#
+# OR
+#
+# 2) Set the variables below. However, in case you choose this method, then
+# start replication for the first time (even unsuccessfully, for example
+# if you mistyped the password in master-password and the slave fails to
+# connect), the slave will create a master.info file, and any later
+# change in this file to the variables' values below will be ignored and
+# overridden by the content of the master.info file, unless you shutdown
+# the slave server, delete master.info and restart the slaver server.
+# For that reason, you may want to leave the lines below untouched
+# (commented) and instead use CHANGE MASTER TO (see above)
+#
+# required unique id between 2 and 2^32 - 1
+# (and different from the master)
+# defaults to 2 if master-host is set
+# but will not function as a slave if omitted
+#server-id = 2
+#
+# The replication master for this slave - required
+#master-host = <hostname>
+#
+# The username the slave will use for authentication when connecting
+# to the master - required
+#master-user = <username>
+#
+# The password the slave will authenticate with when connecting to
+# the master - required
+#master-password = <password>
+#
+# The port the master is listening on.
+# optional - defaults to 3306
+#master-port = <port>
+#
+# binary logging - not required for slaves, but recommended
+#log-bin=mysql-bin
+
+# Uncomment the following if you are using InnoDB tables
+##innodb_data_home_dir = //opt/app/mysql/data
+##innodb_data_file_path = ibdata1:20M:autoextend:max:32G
+##innodb_log_group_home_dir = //opt/app/mysql/iblogs
+# You can set .._buffer_pool_size up to 50 - 80 %
+# of RAM but beware of setting memory usage too high
+innodb_buffer_pool_size = 6380M
+#innodb_additional_mem_pool_size = 2M
+# Set .._log_file_size to 25 % of buffer pool size
+innodb_log_file_size = 150M
+innodb_log_files_in_group = 3
+innodb_log_buffer_size = 8M
+#innodb_flush_log_at_trx_commit = 1
+innodb_lock_wait_timeout = 50
+innodb_autoextend_increment = 100
+expire_logs_days = 8
+open_files_limit = 2000
+transaction-isolation=READ-COMMITTED
+####### Galera parameters #######
+## Galera Provider configuration
+wsrep_provider=/usr/lib/galera/libgalera_smm.so
+wsrep_provider_options="gcache.size=2G; gcache.page_size=1G"
+## Galera Cluster configuration
+wsrep_cluster_name="MSO-automated-tests-cluster"
+wsrep_cluster_address="gcomm://mariadb1,mariadb2,mariadb3"
+##wsrep_cluster_address="gcomm://192.169.3.184,192.169.3.185,192.169.3.186"
+## Galera Synchronization configuration
+wsrep_sst_method=rsync
+#wsrep_sst_method=xtrabackup-v2
+#wsrep_sst_auth="sstuser:Mon#2o!6"
+## Galera Node configuration
+wsrep_node_name="mariadb2"
+##wsrep_node_address="192.169.3.184"
+wsrep_on=ON
+## Status notification
+#wsrep_notify_cmd=/opt/app/mysql/bin/wsrep_notify
+#######
+
+
+[mysqldump]
+quick
+max_allowed_packet = 16M
+
+[mysql]
+no-auto-rehash
+# Remove the next comment character if you are not familiar with SQL
+#safe-updates
+
+[myisamchk]
+key_buffer_size = 20971520
+
+##[mysqlhotcopy]
+##interactive-timeout
+##[mysqld_safe]
+##malloc-lib=//opt/app/mysql/local/lib/libjemalloc.so.1
+##log-error=//opt/app/mysql/log/mysqld.log \ No newline at end of file
diff --git a/runtime/extra/docker/mariadb/conf3/my.cnf b/runtime/extra/docker/mariadb/conf3/my.cnf
new file mode 100644
index 000000000..74f7a31b0
--- /dev/null
+++ b/runtime/extra/docker/mariadb/conf3/my.cnf
@@ -0,0 +1,193 @@
+# Example MySQL config file for medium systems.
+#
+# This is for a system with memory 8G where MySQL plays
+# an important part, or systems up to 128M where MySQL is used together with
+# other programs (such as a web server)
+#
+# In this file, you can use all long options that a program supports.
+# If you want to know which options a program supports, run the program
+# with the "--help" option.
+
+# The following options will be passed to all MySQL clients
+##[client]
+##user = root
+##port = 3306
+##socket = //opt/app/mysql/mysql.sock
+
+# Here follows entries for some specific programs
+
+# The MySQL server
+[mysqld]
+##performance_schema
+
+slow_query_log =ON
+long_query_time =2
+slow_query_log_file =//var/lib/mysql/slow_query.log
+##basedir = //opt/app/mysql/product/mariadb-10.1.11-linux-x86_64
+##datadir = //opt/app/mysql/data
+##port = 3306
+##socket = //opt/app/mysql/mysql.sock
+skip-external-locking
+explicit_defaults_for_timestamp = true
+skip-symbolic-links
+local-infile = 0
+#ignore_db_dir=lost+found
+key_buffer_size = 16M
+max_allowed_packet = 4M
+table_open_cache = 100
+sort_buffer_size = 512K
+net_buffer_length = 8K
+read_buffer_size = 256K
+read_rnd_buffer_size = 512K
+myisam_sort_buffer_size = 8M
+max_connections = 500
+lower_case_table_names = 1
+thread_stack = 256K
+thread_cache_size = 25
+query_cache_size = 8M
+query_cache_type = 0
+query_prealloc_size = 512K
+query_cache_limit = 1M
+
+# Password validation
+##plugin-load-add=simple_password_check.so
+##simple_password_check_other_characters=0
+
+# Audit Log settings
+plugin-load-add=server_audit.so
+server_audit=FORCE_PLUS_PERMANENT
+server_audit_file_path=//var/lib/mysql/audit.log
+server_audit_file_rotate_size=50M
+server_audit_events=CONNECT,QUERY,TABLE
+server_audit_logging=on
+
+# Don't listen on a TCP/IP port at all. This can be a security enhancement,
+# if all processes that need to connect to mysqld run on the same host.
+# All interaction with mysqld must be made via Unix sockets or named pipes.
+# Note that using this option without enabling named pipes on Windows
+# (via the "enable-named-pipe" option) will render mysqld useless!
+#
+#skip-networking
+
+# Replication Master Server (default)
+# binary logging is required for replication
+##log-bin=//var/lib/mysql/mysql-bin
+
+# binary logging format - mixed recommended
+binlog_format=row
+
+# required unique id between 1 and 2^32 - 1
+# defaults to 1 if master-host is not set
+# but will not function as a master if omitted
+
+# Replication Slave (comment out master section to use this)
+#
+# To configure this host as a replication slave, you can choose between
+# two methods :
+#
+# 1) Use the CHANGE MASTER TO command (fully described in our manual) -
+# the syntax is:
+#
+# CHANGE MASTER TO MASTER_HOST=<host>, MASTER_PORT=<port>,
+# MASTER_USER=<user>, MASTER_PASSWORD=<password> ;
+#
+# where you replace <host>, <user>, <password> by quoted strings and
+# <port> by the master's port number (3306 by default).
+#
+# Example:
+#
+# CHANGE MASTER TO MASTER_HOST='125.564.12.1', MASTER_PORT=3306,
+# MASTER_USER='joe', MASTER_PASSWORD='secret';
+#
+# OR
+#
+# 2) Set the variables below. However, in case you choose this method, then
+# start replication for the first time (even unsuccessfully, for example
+# if you mistyped the password in master-password and the slave fails to
+# connect), the slave will create a master.info file, and any later
+# change in this file to the variables' values below will be ignored and
+# overridden by the content of the master.info file, unless you shutdown
+# the slave server, delete master.info and restart the slaver server.
+# For that reason, you may want to leave the lines below untouched
+# (commented) and instead use CHANGE MASTER TO (see above)
+#
+# required unique id between 2 and 2^32 - 1
+# (and different from the master)
+# defaults to 2 if master-host is set
+# but will not function as a slave if omitted
+#server-id = 2
+#
+# The replication master for this slave - required
+#master-host = <hostname>
+#
+# The username the slave will use for authentication when connecting
+# to the master - required
+#master-user = <username>
+#
+# The password the slave will authenticate with when connecting to
+# the master - required
+#master-password = <password>
+#
+# The port the master is listening on.
+# optional - defaults to 3306
+#master-port = <port>
+#
+# binary logging - not required for slaves, but recommended
+#log-bin=mysql-bin
+
+# Uncomment the following if you are using InnoDB tables
+##innodb_data_home_dir = //opt/app/mysql/data
+##innodb_data_file_path = ibdata1:20M:autoextend:max:32G
+##innodb_log_group_home_dir = //opt/app/mysql/iblogs
+# You can set .._buffer_pool_size up to 50 - 80 %
+# of RAM but beware of setting memory usage too high
+innodb_buffer_pool_size = 6380M
+#innodb_additional_mem_pool_size = 2M
+# Set .._log_file_size to 25 % of buffer pool size
+innodb_log_file_size = 150M
+innodb_log_files_in_group = 3
+innodb_log_buffer_size = 8M
+#innodb_flush_log_at_trx_commit = 1
+innodb_lock_wait_timeout = 50
+innodb_autoextend_increment = 100
+expire_logs_days = 8
+open_files_limit = 2000
+transaction-isolation=READ-COMMITTED
+####### Galera parameters #######
+## Galera Provider configuration
+wsrep_provider=/usr/lib/galera/libgalera_smm.so
+wsrep_provider_options="gcache.size=2G; gcache.page_size=1G"
+## Galera Cluster configuration
+wsrep_cluster_name="MSO-automated-tests-cluster"
+wsrep_cluster_address="gcomm://mariadb1,mariadb2,mariadb3"
+##wsrep_cluster_address="gcomm://192.169.3.184,192.169.3.185,192.169.3.186"
+## Galera Synchronization configuration
+wsrep_sst_method=rsync
+#wsrep_sst_method=xtrabackup-v2
+#wsrep_sst_auth="sstuser:Mon#2o!6"
+## Galera Node configuration
+wsrep_node_name="mariadb3"
+##wsrep_node_address="192.169.3.184"
+wsrep_on=ON
+## Status notification
+#wsrep_notify_cmd=/opt/app/mysql/bin/wsrep_notify
+#######
+
+
+[mysqldump]
+quick
+max_allowed_packet = 16M
+
+[mysql]
+no-auto-rehash
+# Remove the next comment character if you are not familiar with SQL
+#safe-updates
+
+[myisamchk]
+key_buffer_size = 20971520
+
+##[mysqlhotcopy]
+##interactive-timeout
+##[mysqld_safe]
+##malloc-lib=//opt/app/mysql/local/lib/libjemalloc.so.1
+##log-error=//opt/app/mysql/log/mysqld.log \ No newline at end of file
diff --git a/runtime/extra/sql/bootstrap-database.sh b/runtime/extra/sql/bootstrap-database.sh
new file mode 100755
index 000000000..224a813db
--- /dev/null
+++ b/runtime/extra/sql/bootstrap-database.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+mysql -uroot -p$MYSQL_ROOT_PASSWORD -f < /docker-entrypoint-initdb.d/bulkload/create-db.sql
+## New model creation
+mysql -uroot -p$MYSQL_ROOT_PASSWORD -f cldsdb4 < /docker-entrypoint-initdb.d/bulkload/create-tables.sql
diff --git a/runtime/extra/sql/bulkload/create-db.sql b/runtime/extra/sql/bulkload/create-db.sql
new file mode 100644
index 000000000..ea4d97c1b
--- /dev/null
+++ b/runtime/extra/sql/bulkload/create-db.sql
@@ -0,0 +1,11 @@
+#
+# Create CLDS database objects (tables, etc.)
+#
+#
+CREATE DATABASE `cldsdb4`;
+USE `cldsdb4`;
+DROP USER 'clds';
+CREATE USER 'clds';
+GRANT ALL on cldsdb4.* to 'clds' identified by 'sidnnd83K' with GRANT OPTION;
+FLUSH PRIVILEGES;
+
diff --git a/runtime/extra/sql/bulkload/create-tables.sql b/runtime/extra/sql/bulkload/create-tables.sql
new file mode 100644
index 000000000..111a4058e
--- /dev/null
+++ b/runtime/extra/sql/bulkload/create-tables.sql
@@ -0,0 +1,255 @@
+
+ create table dictionary (
+ name varchar(255) not null,
+ created_by varchar(255),
+ created_timestamp datetime(6) not null,
+ updated_by varchar(255),
+ updated_timestamp datetime(6) not null,
+ dictionary_second_level integer,
+ dictionary_type varchar(255),
+ primary key (name)
+ ) engine=InnoDB;
+
+ create table dictionary_elements (
+ short_name varchar(255) not null,
+ created_by varchar(255),
+ created_timestamp datetime(6) not null,
+ updated_by varchar(255),
+ updated_timestamp datetime(6) not null,
+ description varchar(255) not null,
+ name varchar(255) not null,
+ subdictionary_name varchar(255),
+ type varchar(255) not null,
+ primary key (short_name)
+ ) engine=InnoDB;
+
+ create table dictionary_to_dictionaryelements (
+ dictionary_name varchar(255) not null,
+ dictionary_element_short_name varchar(255) not null,
+ primary key (dictionary_name, dictionary_element_short_name)
+ ) engine=InnoDB;
+
+ create table hibernate_sequence (
+ next_val bigint
+ ) engine=InnoDB;
+
+ insert into hibernate_sequence values ( 1 );
+
+ create table loop_element_models (
+ name varchar(255) not null,
+ created_by varchar(255),
+ created_timestamp datetime(6) not null,
+ updated_by varchar(255),
+ updated_timestamp datetime(6) not null,
+ blueprint_yaml MEDIUMTEXT,
+ dcae_blueprint_id varchar(255),
+ loop_element_type varchar(255) not null,
+ short_name varchar(255),
+ primary key (name)
+ ) engine=InnoDB;
+
+ create table loop_logs (
+ id bigint not null,
+ log_component varchar(255) not null,
+ log_instant datetime(6) not null,
+ log_type varchar(255) not null,
+ message MEDIUMTEXT not null,
+ loop_id varchar(255) not null,
+ primary key (id)
+ ) engine=InnoDB;
+
+ create table loop_templates (
+ name varchar(255) not null,
+ created_by varchar(255),
+ created_timestamp datetime(6) not null,
+ updated_by varchar(255),
+ updated_timestamp datetime(6) not null,
+ allowed_loop_type varchar(255),
+ blueprint_yaml MEDIUMTEXT,
+ dcae_blueprint_id varchar(255),
+ maximum_instances_allowed integer,
+ unique_blueprint boolean default false,
+ service_uuid varchar(255),
+ primary key (name)
+ ) engine=InnoDB;
+
+ create table loopelementmodels_to_policymodels (
+ loop_element_name varchar(255) not null,
+ policy_model_type varchar(255) not null,
+ policy_model_version varchar(255) not null,
+ primary key (loop_element_name, policy_model_type, policy_model_version)
+ ) engine=InnoDB;
+
+ create table loops (
+ name varchar(255) not null,
+ created_by varchar(255),
+ created_timestamp datetime(6) not null,
+ updated_by varchar(255),
+ updated_timestamp datetime(6) not null,
+ dcae_deployment_id varchar(255),
+ dcae_deployment_status_url varchar(255),
+ global_properties_json json,
+ last_computed_state varchar(255) not null,
+ loop_template_name varchar(255) not null,
+ service_uuid varchar(255),
+ primary key (name)
+ ) engine=InnoDB;
+
+ create table loops_to_microservicepolicies (
+ loop_name varchar(255) not null,
+ microservicepolicy_name varchar(255) not null,
+ primary key (loop_name, microservicepolicy_name)
+ ) engine=InnoDB;
+
+ create table looptemplates_to_loopelementmodels (
+ loop_element_model_name varchar(255) not null,
+ loop_template_name varchar(255) not null,
+ flow_order integer not null,
+ primary key (loop_element_model_name, loop_template_name)
+ ) engine=InnoDB;
+
+ create table micro_service_policies (
+ name varchar(255) not null,
+ created_by varchar(255),
+ created_timestamp datetime(6) not null,
+ updated_by varchar(255),
+ updated_timestamp datetime(6) not null,
+ configurations_json json,
+ json_representation json not null,
+ pdp_group varchar(255),
+ pdp_sub_group varchar(255),
+ context varchar(255),
+ dcae_blueprint_id varchar(255),
+ dcae_deployment_id varchar(255),
+ dcae_deployment_status_url varchar(255),
+ device_type_scope varchar(255),
+ shared bit not null,
+ loop_element_model_id varchar(255),
+ policy_model_type varchar(255),
+ policy_model_version varchar(255),
+ primary key (name)
+ ) engine=InnoDB;
+
+ create table operational_policies (
+ name varchar(255) not null,
+ created_by varchar(255),
+ created_timestamp datetime(6) not null,
+ updated_by varchar(255),
+ updated_timestamp datetime(6) not null,
+ configurations_json json,
+ json_representation json not null,
+ pdp_group varchar(255),
+ pdp_sub_group varchar(255),
+ loop_element_model_id varchar(255),
+ policy_model_type varchar(255),
+ policy_model_version varchar(255),
+ loop_id varchar(255) not null,
+ primary key (name)
+ ) engine=InnoDB;
+
+ create table policy_models (
+ policy_model_type varchar(255) not null,
+ version varchar(255) not null,
+ created_by varchar(255),
+ created_timestamp datetime(6) not null,
+ updated_by varchar(255),
+ updated_timestamp datetime(6) not null,
+ policy_acronym varchar(255),
+ policy_tosca MEDIUMTEXT,
+ policy_pdp_group json,
+ primary key (policy_model_type, version)
+ ) engine=InnoDB;
+
+ create table services (
+ service_uuid varchar(255) not null,
+ name varchar(255) not null,
+ resource_details json,
+ service_details json,
+ version varchar(255),
+ primary key (service_uuid)
+ ) engine=InnoDB;
+
+ alter table dictionary_to_dictionaryelements
+ add constraint FK68hjjinnm8nte2owstd0xwp23
+ foreign key (dictionary_element_short_name)
+ references dictionary_elements (short_name);
+
+ alter table dictionary_to_dictionaryelements
+ add constraint FKtqfxg46gsxwlm2gkl6ne3cxfe
+ foreign key (dictionary_name)
+ references dictionary (name);
+
+ alter table loop_logs
+ add constraint FK1j0cda46aickcaoxqoo34khg2
+ foreign key (loop_id)
+ references loops (name);
+
+ alter table loop_templates
+ add constraint FKn692dk6281wvp1o95074uacn6
+ foreign key (service_uuid)
+ references services (service_uuid);
+
+ alter table loopelementmodels_to_policymodels
+ add constraint FK23j2q74v6kaexefy0tdabsnda
+ foreign key (policy_model_type, policy_model_version)
+ references policy_models (policy_model_type, version);
+
+ alter table loopelementmodels_to_policymodels
+ add constraint FKjag1iu0olojfwryfkvb5o0rk5
+ foreign key (loop_element_name)
+ references loop_element_models (name);
+
+ alter table loops
+ add constraint FK844uwy82wt0l66jljkjqembpj
+ foreign key (loop_template_name)
+ references loop_templates (name);
+
+ alter table loops
+ add constraint FK4b9wnqopxogwek014i1shqw7w
+ foreign key (service_uuid)
+ references services (service_uuid);
+
+ alter table loops_to_microservicepolicies
+ add constraint FKle255jmi7b065fwbvmwbiehtb
+ foreign key (microservicepolicy_name)
+ references micro_service_policies (name);
+
+ alter table loops_to_microservicepolicies
+ add constraint FK8avfqaf7xl71l7sn7a5eri68d
+ foreign key (loop_name)
+ references loops (name);
+
+ alter table looptemplates_to_loopelementmodels
+ add constraint FK1k7nbrbugvqa0xfxkq3cj1yn9
+ foreign key (loop_element_model_name)
+ references loop_element_models (name);
+
+ alter table looptemplates_to_loopelementmodels
+ add constraint FKj29yxyw0x7ue6mwgi6d3qg748
+ foreign key (loop_template_name)
+ references loop_templates (name);
+
+ alter table micro_service_policies
+ add constraint FKqvvdypacbww07fuv8xvlvdjgl
+ foreign key (loop_element_model_id)
+ references loop_element_models (name);
+
+ alter table micro_service_policies
+ add constraint FKn17j9ufmyhqicb6cvr1dbjvkt
+ foreign key (policy_model_type, policy_model_version)
+ references policy_models (policy_model_type, version);
+
+ alter table operational_policies
+ add constraint FKi9kh7my40737xeuaye9xwbnko
+ foreign key (loop_element_model_id)
+ references loop_element_models (name);
+
+ alter table operational_policies
+ add constraint FKlsyhfkoqvkwj78ofepxhoctip
+ foreign key (policy_model_type, policy_model_version)
+ references policy_models (policy_model_type, version);
+
+ alter table operational_policies
+ add constraint FK1ddoggk9ni2bnqighv6ecmuwu
+ foreign key (loop_id)
+ references loops (name);
diff --git a/runtime/extra/sql/dump/backup-data-only.sh b/runtime/extra/sql/dump/backup-data-only.sh
new file mode 100755
index 000000000..8ebebf91d
--- /dev/null
+++ b/runtime/extra/sql/dump/backup-data-only.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+mysqldump -uroot -p$MYSQL_ROOT_PASSWORD -v --extended-insert=FALSE --complete-insert --no-create-db --no-create-info --databases cldsdb4 > /docker-entrypoint-initdb.d/dump/test-data.sql \ No newline at end of file
diff --git a/runtime/extra/sql/dump/backup-database.sh b/runtime/extra/sql/dump/backup-database.sh
new file mode 100755
index 000000000..1ae7ee2b7
--- /dev/null
+++ b/runtime/extra/sql/dump/backup-database.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+mysqldump -uroot -p$MYSQL_ROOT_PASSWORD -v --extended-insert=FALSE --databases cldsdb4 > $1 \ No newline at end of file
diff --git a/runtime/extra/sql/dump/load-fake-data.sh b/runtime/extra/sql/dump/load-fake-data.sh
new file mode 100755
index 000000000..572972683
--- /dev/null
+++ b/runtime/extra/sql/dump/load-fake-data.sh
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+mysql -uroot -p$MYSQL_ROOT_PASSWORD -v -f cldsdb4 < /docker-entrypoint-initdb.d/dump/test-data.sql \ No newline at end of file
diff --git a/runtime/extra/sql/dump/test-data.sql b/runtime/extra/sql/dump/test-data.sql
new file mode 100644
index 000000000..367ddb61d
--- /dev/null
+++ b/runtime/extra/sql/dump/test-data.sql
@@ -0,0 +1,218 @@
+-- MariaDB dump 10.17 Distrib 10.5.4-MariaDB, for debian-linux-gnu (x86_64)
+--
+-- Host: localhost Database: cldsdb4
+-- ------------------------------------------------------
+-- Server version 10.5.4-MariaDB-1:10.5.4+maria~focal-log
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8mb4 */;
+/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
+/*!40103 SET TIME_ZONE='+00:00' */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
+/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
+
+--
+-- Current Database: `cldsdb4`
+--
+
+USE `cldsdb4`;
+
+--
+-- Dumping data for table `dictionary`
+--
+
+LOCK TABLES `dictionary` WRITE;
+/*!40000 ALTER TABLE `dictionary` DISABLE KEYS */;
+INSERT INTO `dictionary` (`name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `dictionary_second_level`, `dictionary_type`) VALUES ('DefaultActors','Not found','2021-03-05 17:10:52.561538','Not found','2021-03-05 17:10:52.561538',0,'');
+INSERT INTO `dictionary` (`name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `dictionary_second_level`, `dictionary_type`) VALUES ('DefaultOperations','Not found','2021-03-05 17:10:52.579372','Not found','2021-03-05 17:10:52.579372',0,'');
+/*!40000 ALTER TABLE `dictionary` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `dictionary_elements`
+--
+
+LOCK TABLES `dictionary_elements` WRITE;
+/*!40000 ALTER TABLE `dictionary_elements` DISABLE KEYS */;
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('APPC','Not found','2021-03-05 17:10:52.570617','Not found','2021-03-05 17:10:52.570617','APPC component','APPC',NULL,'string');
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('BandwidthOnDemand (SDNC operation)','Not found','2021-03-05 17:10:52.580331','Not found','2021-03-05 17:10:52.580331','SDNC operation','BandwidthOnDemand',NULL,'string');
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('Health-Check (APPC operation)','Not found','2021-03-05 17:10:52.587614','Not found','2021-03-05 17:10:52.587614','APPC operation','Health-Check',NULL,'string');
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('Migrate (APPC operation)','Not found','2021-03-05 17:10:52.586285','Not found','2021-03-05 17:10:52.586285','APPC operation','Migrate',NULL,'string');
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('ModifyConfig (APPC/VFC operation)','Not found','2021-03-05 17:10:52.584261','Not found','2021-03-05 17:10:52.584261','APPC/VFC operation','ModifyConfig',NULL,'string');
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('Rebuild (APPC operation)','Not found','2021-03-05 17:10:52.583480','Not found','2021-03-05 17:10:52.583480','APPC operation','Rebuild',NULL,'string');
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('Reroute (SDNC operation)','Not found','2021-03-05 17:10:52.581911','Not found','2021-03-05 17:10:52.581911','SDNC operation','Reroute',NULL,'string');
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('Restart (APPC operation)','Not found','2021-03-05 17:10:52.585115','Not found','2021-03-05 17:10:52.585115','APPC operation','Restart',NULL,'string');
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('SDNC','Not found','2021-03-05 17:10:52.567645','Not found','2021-03-05 17:10:52.567645','SDNC component','SDNC',NULL,'string');
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('SDNR','Not found','2021-03-05 17:10:52.566004','Not found','2021-03-05 17:10:52.566004','SDNR component','SDNR',NULL,'string');
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('SO','Not found','2021-03-05 17:10:52.569719','Not found','2021-03-05 17:10:52.569719','SO component','SO',NULL,'string');
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('VF Module Create (SO operation)','Not found','2021-03-05 17:10:52.582689','Not found','2021-03-05 17:10:52.582689','SO operation','VF Module Create',NULL,'string');
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('VF Module Delete (SO operation)','Not found','2021-03-05 17:10:52.581150','Not found','2021-03-05 17:10:52.581150','SO operation','VF Module Delete',NULL,'string');
+INSERT INTO `dictionary_elements` (`short_name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `description`, `name`, `subdictionary_name`, `type`) VALUES ('VFC','Not found','2021-03-05 17:10:52.568756','Not found','2021-03-05 17:10:52.568756','VFC component','VFC',NULL,'string');
+/*!40000 ALTER TABLE `dictionary_elements` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `dictionary_to_dictionaryelements`
+--
+
+LOCK TABLES `dictionary_to_dictionaryelements` WRITE;
+/*!40000 ALTER TABLE `dictionary_to_dictionaryelements` DISABLE KEYS */;
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultActors','APPC');
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultActors','SDNC');
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultActors','SDNR');
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultActors','SO');
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultActors','VFC');
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultOperations','BandwidthOnDemand (SDNC operation)');
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultOperations','Health-Check (APPC operation)');
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultOperations','Migrate (APPC operation)');
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultOperations','ModifyConfig (APPC/VFC operation)');
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultOperations','Rebuild (APPC operation)');
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultOperations','Reroute (SDNC operation)');
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultOperations','Restart (APPC operation)');
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultOperations','VF Module Create (SO operation)');
+INSERT INTO `dictionary_to_dictionaryelements` (`dictionary_name`, `dictionary_element_short_name`) VALUES ('DefaultOperations','VF Module Delete (SO operation)');
+/*!40000 ALTER TABLE `dictionary_to_dictionaryelements` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `hibernate_sequence`
+--
+
+LOCK TABLES `hibernate_sequence` WRITE;
+/*!40000 ALTER TABLE `hibernate_sequence` DISABLE KEYS */;
+INSERT INTO `hibernate_sequence` (`next_val`) VALUES (11);
+/*!40000 ALTER TABLE `hibernate_sequence` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `loop_element_models`
+--
+
+LOCK TABLES `loop_element_models` WRITE;
+/*!40000 ALTER TABLE `loop_element_models` DISABLE KEYS */;
+INSERT INTO `loop_element_models` (`name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `blueprint_yaml`, `dcae_blueprint_id`, `loop_element_type`, `short_name`) VALUES ('onap.policies.monitoring.cdap.tca.hi.lo.app',NULL,'2021-03-05 17:10:19.722143','Not found','2021-03-05 17:10:19.852676',NULL,NULL,'MICRO_SERVICE_TYPE',NULL);
+INSERT INTO `loop_element_models` (`name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `blueprint_yaml`, `dcae_blueprint_id`, `loop_element_type`, `short_name`) VALUES ('onap.policies.monitoring.tcagen2','Not found','2021-03-05 17:10:19.837051','Not found','2021-03-05 17:10:19.837051',NULL,NULL,'MICRO_SERVICE_TYPE',NULL);
+/*!40000 ALTER TABLE `loop_element_models` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `loop_logs`
+--
+
+LOCK TABLES `loop_logs` WRITE;
+/*!40000 ALTER TABLE `loop_logs` DISABLE KEYS */;
+/*!40000 ALTER TABLE `loop_logs` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `loop_templates`
+--
+
+LOCK TABLES `loop_templates` WRITE;
+/*!40000 ALTER TABLE `loop_templates` DISABLE KEYS */;
+INSERT INTO `loop_templates` (`name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `allowed_loop_type`, `blueprint_yaml`, `dcae_blueprint_id`, `maximum_instances_allowed`, `unique_blueprint`, `service_uuid`) VALUES ('LOOP_TEMPLATE_RzsRR_v1_0_ResourceInstanceName1_tca','Not found','2021-03-05 17:10:19.774034','Not found','2021-03-05 17:10:19.774034','CLOSED','tosca_definitions_version: cloudify_dsl_1_3\nimports:\n- http://www.getcloudify.org/spec/cloudify/3.4/types.yaml\n- https://onap.org:8443/repository/solutioning01-mte2-raw/type_files/docker/2.2.0/node-type.yaml\n- https://onap.org:8443/repository/solutioning01-mte2-raw/type_files/relationship/1.0.0/node-type.yaml\n- http://onap.org:8081/repository/solutioning01-mte2-raw/type_files/dmaap/dmaap_mr.yaml\ninputs:\n location_id:\n type: string\n service_id:\n type: string\n policy_id:\n type: string\nnode_templates:\n policy_0:\n type: dcae.nodes.policy\n properties:\n policy_id: \n get_input: policy_id\n policy_model_id: \"onap.policies.monitoring.cdap.tca.hi.lo.app\"\n cdap_host_host:\n type: dcae.nodes.StreamingAnalytics.SelectedCDAPInfrastructure\n properties:\n location_id:\n get_input: location_id\n scn_override: cdap_broker.solutioning-central.dcae.onap.org\n interfaces:\n cloudify.interfaces.lifecycle: {\n }\n tca_tca:\n type: dcae.nodes.MicroService.cdap\n properties:\n app_config:\n appDescription: DCAE Analytics Threshold Crossing Alert Application\n appName: dcae-tca\n tcaSubscriberOutputStreamName: TCASubscriberOutputStream\n tcaVESAlertsTableName: TCAVESAlertsTable\n tcaVESAlertsTableTTLSeconds: \'1728000\'\n tcaVESMessageStatusTableName: TCAVESMessageStatusTable\n tcaVESMessageStatusTableTTLSeconds: \'86400\'\n thresholdCalculatorFlowletInstances: \'2\'\n app_preferences:\n publisherContentType: application/json\n publisherHostName: mrlocal-mtnjftle01.onap.org\n publisherHostPort: \'3905\'\n publisherMaxBatchSize: \'10\'\n publisherMaxRecoveryQueueSize: \'100000\'\n publisherPollingInterval: \'20000\'\n publisherProtocol: https\n publisherTopicName: org.onap.dcae.dmaap.mtnje2.DcaeTestVESPub\n publisherUserName: test@tca.af.dcae.onap.org\n publisherUserPassword: password\n subscriberConsumerGroup: OpenDCAE-c12\n subscriberConsumerId: c12\n subscriberContentType: application/json\n subscriberHostName: mrlocal-mtnjftle01.onap.org\n subscriberHostPort: \'3905\'\n subscriberMessageLimit: \'-1\'\n subscriberPollingInterval: \'20000\'\n subscriberProtocol: https\n subscriberTimeoutMS: \'-1\'\n subscriberTopicName: org.onap.dcae.dmaap.mtnje2.DcaeTestVESSub\n subscriberUserName: test@tca.af.dcae.onap.org\n subscriberUserPassword: password\n tca_policy: null\n artifact_name: dcae-analytics-tca\n artifact_version: 1.0.0\n connections:\n streams_publishes: [\n ]\n streams_subscribes: [\n ]\n jar_url: http://somejar\n location_id:\n get_input: location_id\n namespace: cdap_tca_hi_lo\n programs:\n - program_id: TCAVESCollectorFlow\n program_type: flows\n - program_id: TCADMaaPMRSubscriberWorker\n program_type: workers\n - program_id: TCADMaaPMRPublisherWorker\n program_type: workers\n service_component_type: cdap_app_tca\n service_id:\n get_input: service_id\n streamname: TCASubscriberOutputStream\n relationships:\n - target: topic0\n type: dcae.relationships.subscribe_to_events\n - target: topic1\n type: dcae.relationships.publish_events\n - target: cdap_host_host\n type: dcae.relationships.component_contained_in\n - target: policy_0\n type: dcae.relationships.depends_on\n topic0:\n type: dcae.nodes.Topic\n properties:\n topic_name: \'\'\n topic1:\n type: dcae.nodes.Topic\n properties:\n topic_name: \'\'\n \n','typeId-7e039b4b-8ab4-47f2-9dd4-2cbe584105a6',0,1,'63cac700-ab9a-4115-a74f-7eac85e3fce0');
+INSERT INTO `loop_templates` (`name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `allowed_loop_type`, `blueprint_yaml`, `dcae_blueprint_id`, `maximum_instances_allowed`, `unique_blueprint`, `service_uuid`) VALUES ('LOOP_TEMPLATE_RzsRR_v1_0_ResourceInstanceName1_tca-guilin','Not found','2021-03-05 17:10:19.833813','Not found','2021-03-05 17:10:19.833813','CLOSED','# ============LICENSE_START====================================================\n# =============================================================================\n# Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.\n# =============================================================================\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============LICENSE_END======================================================\n#k8s-tca-gen2-v3.yaml\n\ntosca_definitions_version: cloudify_dsl_1_3\nimports:\n - https://www.getcloudify.org/spec/cloudify/4.5.5/types.yaml\n - plugin:k8splugin?version=3.4.2\n - plugin:clamppolicyplugin?version=1.1.0\ninputs:\n service_name:\n type: string\n default: \'dcae-tcagen2\'\n log_directory:\n type: string\n default: \"/opt/logs/dcae-analytics-tca\"\n replicas:\n type: integer\n description: number of instances\n default: 1\n spring.data.mongodb.uri:\n type: string\n default: \"mongodb://dcae-mongohost/dcae-tcagen2\"\n tag_version:\n type: string\n default: \"nexus3.onap.org:10001/onap/org.onap.dcaegen2.analytics.tca-gen2.dcae-analytics-tca-web:1.2.1\"\n tca.aai.password:\n type: string\n default: \"DCAE\"\n tca.aai.url:\n type: string\n default: \"http://aai.onap.svc.cluster.local\"\n tca.aai.username:\n type: string\n default: \"DCAE\"\n tca_handle_in_subscribe_url:\n type: string\n default: \"http://message-router.onap.svc.cluster.local:3904/events/unauthenticated.VES_MEASUREMENT_OUTPUT\"\n tca_handle_out_publish_url:\n type: string\n default: \"http://message-router.onap.svc.cluster.local:3904/events/unauthenticated.DCAE_CL_OUTPUT\"\n tca_consumer_group:\n type: string\n default: \"cg1\"\n policy_model_id:\n type: string\n default: \"onap.policies.monitoring.tcagen2\"\n policy_id:\n type: string\n default: \"onap.restart.tca\"\nnode_templates:\n docker.tca:\n type: dcae.nodes.ContainerizedServiceComponent\n relationships:\n - target: tcagen2_policy\n type: cloudify.relationships.depends_on\n interfaces:\n cloudify.interfaces.lifecycle:\n start:\n inputs:\n ports:\n - concat: [\"9091:\", \"0\"]\n properties:\n application_config:\n service_calls: []\n streams_publishes:\n tca_handle_out:\n dmaap_info:\n topic_url:\n get_input: tca_handle_out_publish_url\n type: message_router\n streams_subscribes:\n tca_handle_in:\n dmaap_info:\n topic_url:\n get_input: tca_handle_in_subscribe_url\n type: message_router\n spring.data.mongodb.uri:\n get_input: spring.data.mongodb.uri\n streams_subscribes.tca_handle_in.consumer_group:\n get_input: tca_consumer_group\n streams_subscribes.tca_handle_in.consumer_ids[0]: c0\n streams_subscribes.tca_handle_in.consumer_ids[1]: c1\n streams_subscribes.tca_handle_in.message_limit: 50000\n streams_subscribes.tca_handle_in.polling.auto_adjusting.max: 60000\n streams_subscribes.tca_handle_in.polling.auto_adjusting.min: 30000\n streams_subscribes.tca_handle_in.polling.auto_adjusting.step_down: 30000\n streams_subscribes.tca_handle_in.polling.auto_adjusting.step_up: 10000\n streams_subscribes.tca_handle_in.polling.fixed_rate: 0\n streams_subscribes.tca_handle_in.timeout: -1\n tca.aai.enable_enrichment: true\n tca.aai.generic_vnf_path: aai/v11/network/generic-vnfs/generic-vnf\n tca.aai.node_query_path: aai/v11/search/nodes-query\n tca.aai.password:\n get_input: tca.aai.password\n tca.aai.url:\n get_input: tca.aai.url\n tca.aai.username:\n get_input: tca.aai.username\n tca.policy: \'{\"domain\":\"measurementsForVfScaling\",\"metricsPerEventName\":[{\"eventName\":\"vFirewallBroadcastPackets\",\"controlLoopSchemaType\":\"VM\",\"policyScope\":\"DCAE\",\"policyName\":\"DCAE.Config_tca-hi-lo\",\"policyVersion\":\"v0.0.1\",\"thresholds\":[{\"closedLoopControlName\":\"ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta\",\"thresholdValue\":300,\"direction\":\"LESS_OR_EQUAL\",\"severity\":\"MAJOR\",\"closedLoopEventStatus\":\"ONSET\"},{\"closedLoopControlName\":\"ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta\",\"thresholdValue\":700,\"direction\":\"GREATER_OR_EQUAL\",\"severity\":\"CRITICAL\",\"closedLoopEventStatus\":\"ONSET\"}]},{\"eventName\":\"vLoadBalancer\",\"controlLoopSchemaType\":\"VM\",\"policyScope\":\"DCAE\",\"policyName\":\"DCAE.Config_tca-hi-lo\",\"policyVersion\":\"v0.0.1\",\"thresholds\":[{\"closedLoopControlName\":\"ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta\",\"thresholdValue\":300,\"direction\":\"GREATER_OR_EQUAL\",\"severity\":\"CRITICAL\",\"closedLoopEventStatus\":\"ONSET\"}]},{\"eventName\":\"Measurement_vGMUX\",\"controlLoopSchemaType\":\"VNF\",\"policyScope\":\"DCAE\",\"policyName\":\"DCAE.Config_tca-hi-lo\",\"policyVersion\":\"v0.0.1\",\"thresholds\":[{\"closedLoopControlName\":\"ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value\",\"thresholdValue\":0,\"direction\":\"EQUAL\",\"severity\":\"MAJOR\",\"closedLoopEventStatus\":\"ABATED\"},{\"closedLoopControlName\":\"ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value\",\"thresholdValue\":0,\"direction\":\"GREATER\",\"severity\":\"CRITICAL\",\"closedLoopEventStatus\":\"ONSET\"}]}]}\'\n tca.processing_batch_size: 10000\n tca.enable_abatement: true\n tca.enable_ecomp_logging: true\n docker_config:\n healthcheck:\n endpoint: /actuator/health\n interval: 30s\n timeout: 10s\n type: http\n image:\n get_input: tag_version\n log_info:\n log_directory:\n get_input: log_directory\n tls_info:\n use_tls: true\n cert_directory: \'/etc/tca-gen2/ssl\'\n replicas:\n get_input: replicas\n service_component_type: { get_input: service_name }\n tcagen2_policy:\n type: clamp.nodes.policy\n properties:\n policy_id:\n get_input: policy_id\n policy_model_id:\n get_input: policy_model_id\n','typeId-9355082c-7e22-47aa-963e-3236a0221ac9',0,1,'63cac700-ab9a-4115-a74f-7eac85e3fce0');
+INSERT INTO `loop_templates` (`name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `allowed_loop_type`, `blueprint_yaml`, `dcae_blueprint_id`, `maximum_instances_allowed`, `unique_blueprint`, `service_uuid`) VALUES ('LOOP_TEMPLATE_RzsRR_v1_0_ResourceInstanceName1_tca_3','Not found','2021-03-05 17:10:19.748910','Not found','2021-03-05 17:10:19.748910','CLOSED','#\n# ============LICENSE_START====================================================\n# =============================================================================\n# Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.\n# =============================================================================\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============LICENSE_END======================================================\n\ntosca_definitions_version: cloudify_dsl_1_3\n\ndescription: >\n This blueprint deploys/manages the TCA module as a Docker container\n\nimports:\n - https://www.getcloudify.org/spec/cloudify/4.5.5/types.yaml\n - \"https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R6/k8splugin/1.7.2/k8splugin_types.yaml\"\n - \"https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R6/clamppolicyplugin/1.1.0/clamppolicyplugin_types.yaml\"\ninputs:\n aaiEnrichmentHost:\n type: string\n default: \"aai.onap.svc.cluster.local\"\n aaiEnrichmentPort:\n type: string\n default: \"8443\"\n enableAAIEnrichment:\n type: string\n default: \"true\"\n dmaap_host:\n type: string\n default: \"message-router.onap.svc.cluster.local\"\n dmaap_port:\n type: string\n default: \"3904\"\n enableRedisCaching:\n type: string\n default: \"false\"\n redisHosts:\n type: string\n default: \"dcae-redis.onap.svc.cluster.local:6379\"\n tag_version:\n type: string\n default: \"nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.tca-cdap-container:1.2.2\"\n consul_host:\n type: string\n default: \"consul-server.onap\"\n consul_port:\n type: string\n default: \"8500\"\n cbs_host:\n type: string\n default: \"config-binding-service\"\n cbs_port:\n type: string\n default: \"10000\"\n policy_id:\n type: string\n default: \"onap.restart.tca\"\n external_port:\n type: string\n description: Kubernetes node port on which CDAPgui is exposed\n default: \"32012\"\n policy_model_id:\n type: string\n default: \"onap.policies.monitoring.cdap.tca.hi.lo.app\"\nnode_templates:\n tca_k8s:\n type: dcae.nodes.ContainerizedServiceComponent\n relationships:\n - target: tca_policy\n type: cloudify.relationships.depends_on\n properties:\n service_component_type: \'dcaegen2-analytics-tca\'\n application_config: {}\n docker_config: {}\n image:\n get_input: tag_version\n log_info:\n log_directory: \"/opt/app/TCAnalytics/logs\"\n application_config:\n app_config:\n appDescription: DCAE Analytics Threshold Crossing Alert Application\n appName: dcae-tca\n tcaAlertsAbatementTableName: TCAAlertsAbatementTable\n tcaAlertsAbatementTableTTLSeconds: \'1728000\'\n tcaSubscriberOutputStreamName: TCASubscriberOutputStream\n tcaVESAlertsTableName: TCAVESAlertsTable\n tcaVESAlertsTableTTLSeconds: \'1728000\'\n tcaVESMessageStatusTableName: TCAVESMessageStatusTable\n tcaVESMessageStatusTableTTLSeconds: \'86400\'\n thresholdCalculatorFlowletInstances: \'2\'\n app_preferences:\n aaiEnrichmentHost:\n get_input: aaiEnrichmentHost\n aaiEnrichmentIgnoreSSLCertificateErrors: \'true\'\n aaiEnrichmentPortNumber: \'8443\'\n aaiEnrichmentProtocol: https\n aaiEnrichmentUserName: dcae@dcae.onap.org\n aaiEnrichmentUserPassword: demo123456!\n aaiVMEnrichmentAPIPath: /aai/v11/search/nodes-query\n aaiVNFEnrichmentAPIPath: /aai/v11/network/generic-vnfs/generic-vnf\n enableAAIEnrichment:\n get_input: enableAAIEnrichment\n enableRedisCaching:\n get_input: enableRedisCaching\n redisHosts:\n get_input: redisHosts\n enableAlertCEFFormat: \'false\'\n publisherContentType: application/json\n publisherHostName:\n get_input: dmaap_host\n publisherHostPort:\n get_input: dmaap_port\n publisherMaxBatchSize: \'1\'\n publisherMaxRecoveryQueueSize: \'100000\'\n publisherPollingInterval: \'20000\'\n publisherProtocol: http\n publisherTopicName: unauthenticated.DCAE_CL_OUTPUT\n subscriberConsumerGroup: OpenDCAE-clamp\n subscriberConsumerId: c12\n subscriberContentType: application/json\n subscriberHostName:\n get_input: dmaap_host\n subscriberHostPort:\n get_input: dmaap_port\n subscriberMessageLimit: \'-1\'\n subscriberPollingInterval: \'30000\'\n subscriberProtocol: http\n subscriberTimeoutMS: \'-1\'\n subscriberTopicName: unauthenticated.VES_MEASUREMENT_OUTPUT\n #tca_policy: \'{\"domain\":\"measurementsForVfScaling\",\"metricsPerEventName\":[{\"eventName\":\"vFirewallBroadcastPackets\",\"controlLoopSchemaType\":\"VM\",\"policyScope\":\"DCAE\",\"policyName\":\"DCAE.Config_tca-hi-lo\",\"policyVersion\":\"v0.0.1\",\"thresholds\":[{\"closedLoopControlName\":\"ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta\",\"thresholdValue\":300,\"direction\":\"LESS_OR_EQUAL\",\"severity\":\"MAJOR\",\"closedLoopEventStatus\":\"ONSET\"},{\"closedLoopControlName\":\"ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta\",\"thresholdValue\":700,\"direction\":\"GREATER_OR_EQUAL\",\"severity\":\"CRITICAL\",\"closedLoopEventStatus\":\"ONSET\"}]},{\"eventName\":\"vLoadBalancer\",\"controlLoopSchemaType\":\"VM\",\"policyScope\":\"DCAE\",\"policyName\":\"DCAE.Config_tca-hi-lo\",\"policyVersion\":\"v0.0.1\",\"thresholds\":[{\"closedLoopControlName\":\"ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta\",\"thresholdValue\":300,\"direction\":\"GREATER_OR_EQUAL\",\"severity\":\"CRITICAL\",\"closedLoopEventStatus\":\"ONSET\"}]},{\"eventName\":\"Measurement_vGMUX\",\"controlLoopSchemaType\":\"VNF\",\"policyScope\":\"DCAE\",\"policyName\":\"DCAE.Config_tca-hi-lo\",\"policyVersion\":\"v0.0.1\",\"thresholds\":[{\"closedLoopControlName\":\"ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value\",\"thresholdValue\":0,\"direction\":\"EQUAL\",\"severity\":\"MAJOR\",\"closedLoopEventStatus\":\"ABATED\"},{\"closedLoopControlName\":\"ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value\",\"thresholdValue\":0,\"direction\":\"GREATER\",\"severity\":\"CRITICAL\",\"closedLoopEventStatus\":\"ONSET\"}]}]}\'\n tca_policy: \'\'\n service_component_type: dcaegen2-analytics_tca\n interfaces:\n cloudify.interfaces.lifecycle:\n start:\n inputs:\n envs:\n DMAAPHOST:\n { get_input: dmaap_host }\n DMAAPPORT: \"3904\"\n DMAAPPUBTOPIC: \"unauthenticated.DCAE_CL_OUTPUT\"\n DMAAPSUBTOPIC: \"unauthenticated.VES_MEASUREMENT_OUTPUT\"\n AAIHOST:\n { get_input: aaiEnrichmentHost }\n AAIPORT: \"8443\"\n CONSUL_HOST:\n { get_input: consul_host }\n CONSUL_PORT: \"8500\"\n CBS_HOST:\n { get_input: cbs_host }\n CBS_PORT: \"10000\"\n CONFIG_BINDING_SERVICE: \"config_binding_service\"\n ports:\n - concat: [\"11011:\", { get_input: external_port }]\n tca_policy:\n type: clamp.nodes.policy\n properties:\n policy_id:\n get_input: policy_id\n policy_model_id:\n get_input: policy_model_id\n','typeId-239e94d1-f137-42bf-91d4-659e9a7f928e',0,1,'63cac700-ab9a-4115-a74f-7eac85e3fce0');
+INSERT INTO `loop_templates` (`name`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `allowed_loop_type`, `blueprint_yaml`, `dcae_blueprint_id`, `maximum_instances_allowed`, `unique_blueprint`, `service_uuid`) VALUES ('LOOP_TEMPLATE_RzsRR_v1_0_ResourceInstanceName2_tca_2','Not found','2021-03-05 17:10:19.715327','Not found','2021-03-05 17:10:19.715327','CLOSED','#\n# ============LICENSE_START====================================================\n# =============================================================================\n# Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.\n# =============================================================================\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n# http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n# ============LICENSE_END======================================================\n\ntosca_definitions_version: cloudify_dsl_1_3\n\ndescription: >\n This blueprint deploys/manages the TCA module as a Docker container\n\nimports:\n - http://www.getcloudify.org/spec/cloudify/3.4/types.yaml\n - https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R4/k8splugin/1.4.12/k8splugin_types.yaml\n# - https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R4/dcaepolicyplugin/2.3.0/dcaepolicyplugin_types.yaml\n - https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R4/clamppolicyplugin/1.0.0/clamppolicyplugin_types.yaml\ninputs:\n aaiEnrichmentHost:\n type: string\n default: \"aai.onap.svc.cluster.local\"\n aaiEnrichmentPort:\n type: string\n default: \"8443\"\n enableAAIEnrichment:\n type: string\n default: true\n dmaap_host:\n type: string\n default: message-router.onap\n dmaap_port:\n type: string\n default: \"3904\"\n enableRedisCaching:\n type: string\n default: false\n redisHosts:\n type: string\n default: dcae-redis.onap.svc.cluster.local:6379\n tag_version:\n type: string\n default: \"nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.tca-cdap-container:1.1.1\"\n consul_host:\n type: string\n default: consul-server.onap\n consul_port:\n type: string\n default: \"8500\"\n cbs_host:\n type: string\n default: \"config-binding-servicel\"\n cbs_port:\n type: string\n default: \"10000\"\n policy_id:\n type: string\n default: \"onap.restart.tca\"\n external_port:\n type: string\n description: Kubernetes node port on which CDAPgui is exposed\n default: \"32012\"\n policy_model_id:\n type: string\n default: \"onap.policies.monitoring.cdap.tca.hi.lo.app\"\nnode_templates:\n tca_k8s:\n type: dcae.nodes.ContainerizedServiceComponent\n relationships:\n - target: tca_policy\n type: cloudify.relationships.depends_on\n properties:\n service_component_type: \'dcaegen2-analytics-tca\'\n application_config: {}\n docker_config: {}\n image:\n get_input: tag_version\n log_info:\n log_directory: \"/opt/app/TCAnalytics/logs\"\n application_config:\n app_config:\n appDescription: DCAE Analytics Threshold Crossing Alert Application\n appName: dcae-tca\n tcaAlertsAbatementTableName: TCAAlertsAbatementTable\n tcaAlertsAbatementTableTTLSeconds: \'1728000\'\n tcaSubscriberOutputStreamName: TCASubscriberOutputStream\n tcaVESAlertsTableName: TCAVESAlertsTable\n tcaVESAlertsTableTTLSeconds: \'1728000\'\n tcaVESMessageStatusTableName: TCAVESMessageStatusTable\n tcaVESMessageStatusTableTTLSeconds: \'86400\'\n thresholdCalculatorFlowletInstances: \'2\'\n app_preferences:\n aaiEnrichmentHost:\n get_input: aaiEnrichmentHost\n aaiEnrichmentIgnoreSSLCertificateErrors: \'true\'\n aaiEnrichmentPortNumber: \'8443\'\n aaiEnrichmentProtocol: https\n aaiEnrichmentUserName: dcae@dcae.onap.org\n aaiEnrichmentUserPassword: demo123456!\n aaiVMEnrichmentAPIPath: /aai/v11/search/nodes-query\n aaiVNFEnrichmentAPIPath: /aai/v11/network/generic-vnfs/generic-vnf\n enableAAIEnrichment:\n get_input: enableAAIEnrichment\n enableRedisCaching:\n get_input: enableRedisCaching\n redisHosts:\n get_input: redisHosts\n enableAlertCEFFormat: \'false\'\n publisherContentType: application/json\n publisherHostName:\n get_input: dmaap_host\n publisherHostPort:\n get_input: dmaap_port\n publisherMaxBatchSize: \'1\'\n publisherMaxRecoveryQueueSize: \'100000\'\n publisherPollingInterval: \'20000\'\n publisherProtocol: http\n publisherTopicName: unauthenticated.DCAE_CL_OUTPUT\n subscriberConsumerGroup: OpenDCAE-clamp\n subscriberConsumerId: c12\n subscriberContentType: application/json\n subscriberHostName:\n get_input: dmaap_host\n subscriberHostPort:\n get_input: dmaap_port\n subscriberMessageLimit: \'-1\'\n subscriberPollingInterval: \'30000\'\n subscriberProtocol: http\n subscriberTimeoutMS: \'-1\'\n subscriberTopicName: unauthenticated.VES_MEASUREMENT_OUTPUT\n# tca_policy: \'{\"domain\":\"measurementsForVfScaling\",\"metricsPerEventName\":[{\"eventName\":\"vFirewallBroadcastPackets\",\"controlLoopSchemaType\":\"VNF\",\"policyScope\":\"DCAE\",\"policyName\":\"DCAE.Config_tca-hi-lo\",\"policyVersion\":\"v0.0.1\",\"thresholds\":[{\"closedLoopControlName\":\"ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta\",\"thresholdValue\":300,\"direction\":\"LESS_OR_EQUAL\",\"severity\":\"MAJOR\",\"closedLoopEventStatus\":\"ONSET\"},{\"closedLoopControlName\":\"ControlLoop-vFirewall-d0a1dfc6-94f5-4fd4-a5b5-4630b438850a\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta\",\"thresholdValue\":700,\"direction\":\"GREATER_OR_EQUAL\",\"severity\":\"CRITICAL\",\"closedLoopEventStatus\":\"ONSET\"}]},{\"eventName\":\"vLoadBalancer\",\"controlLoopSchemaType\":\"VM\",\"policyScope\":\"DCAE\",\"policyName\":\"DCAE.Config_tca-hi-lo\",\"policyVersion\":\"v0.0.1\",\"thresholds\":[{\"closedLoopControlName\":\"ControlLoop-vDNS-6f37f56d-a87d-4b85-b6a9-cc953cf779b3\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta\",\"thresholdValue\":300,\"direction\":\"GREATER_OR_EQUAL\",\"severity\":\"CRITICAL\",\"closedLoopEventStatus\":\"ONSET\"}]},{\"eventName\":\"Measurement_vGMUX\",\"controlLoopSchemaType\":\"VNF\",\"policyScope\":\"DCAE\",\"policyName\":\"DCAE.Config_tca-hi-lo\",\"policyVersion\":\"v0.0.1\",\"thresholds\":[{\"closedLoopControlName\":\"ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value\",\"thresholdValue\":0,\"direction\":\"EQUAL\",\"severity\":\"MAJOR\",\"closedLoopEventStatus\":\"ABATED\"},{\"closedLoopControlName\":\"ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value\",\"thresholdValue\":0,\"direction\":\"GREATER\",\"severity\":\"CRITICAL\",\"closedLoopEventStatus\":\"ONSET\"}]}]}\'\n service_component_type: dcaegen2-analytics_tca\n interfaces:\n cloudify.interfaces.lifecycle:\n start:\n inputs:\n envs:\n DMAAPHOST:\n { get_input: dmaap_host }\n DMAAPPORT:\n { get_input: dmaap_port }\n DMAAPPUBTOPIC: \"unauthenticated.DCAE_CL_OUTPUT\"\n DMAAPSUBTOPIC: \"unauthenticated.VES_MEASUREMENT_OUTPUT\"\n AAIHOST:\n { get_input: aaiEnrichmentHost }\n AAIPORT:\n { get_input: aaiEnrichmentPort }\n CONSUL_HOST:\n { get_input: consul_host }\n CONSUL_PORT:\n { get_input: consul_port }\n CBS_HOST:\n { get_input: cbs_host }\n CBS_PORT:\n { get_input: cbs_port }\n CONFIG_BINDING_SERVICE: \"config_binding_service\"\n ports:\n - concat: [\"11011:\", { get_input: external_port }]\n tca_policy:\n type: clamp.nodes.policy\n properties:\n policy_id:\n get_input: policy_id\n policy_model_id: \"onap.policies.monitoring.cdap.tca.hi.lo.app\"\n','typeId-6c349c12-eabd-44a2-9b2d-e9115fb27655',0,1,'63cac700-ab9a-4115-a74f-7eac85e3fce0');
+/*!40000 ALTER TABLE `loop_templates` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `loopelementmodels_to_policymodels`
+--
+
+LOCK TABLES `loopelementmodels_to_policymodels` WRITE;
+/*!40000 ALTER TABLE `loopelementmodels_to_policymodels` DISABLE KEYS */;
+INSERT INTO `loopelementmodels_to_policymodels` (`loop_element_name`, `policy_model_type`, `policy_model_version`) VALUES ('onap.policies.monitoring.cdap.tca.hi.lo.app','onap.policies.monitoring.cdap.tca.hi.lo.app','1.0.0');
+INSERT INTO `loopelementmodels_to_policymodels` (`loop_element_name`, `policy_model_type`, `policy_model_version`) VALUES ('onap.policies.monitoring.tcagen2','onap.policies.monitoring.tcagen2','1.0.0');
+/*!40000 ALTER TABLE `loopelementmodels_to_policymodels` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `loops`
+--
+
+LOCK TABLES `loops` WRITE;
+/*!40000 ALTER TABLE `loops` DISABLE KEYS */;
+/*!40000 ALTER TABLE `loops` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `loops_to_microservicepolicies`
+--
+
+LOCK TABLES `loops_to_microservicepolicies` WRITE;
+/*!40000 ALTER TABLE `loops_to_microservicepolicies` DISABLE KEYS */;
+/*!40000 ALTER TABLE `loops_to_microservicepolicies` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `looptemplates_to_loopelementmodels`
+--
+
+LOCK TABLES `looptemplates_to_loopelementmodels` WRITE;
+/*!40000 ALTER TABLE `looptemplates_to_loopelementmodels` DISABLE KEYS */;
+INSERT INTO `looptemplates_to_loopelementmodels` (`loop_element_model_name`, `loop_template_name`, `flow_order`) VALUES ('onap.policies.monitoring.cdap.tca.hi.lo.app','LOOP_TEMPLATE_RzsRR_v1_0_ResourceInstanceName1_tca',0);
+INSERT INTO `looptemplates_to_loopelementmodels` (`loop_element_model_name`, `loop_template_name`, `flow_order`) VALUES ('onap.policies.monitoring.cdap.tca.hi.lo.app','LOOP_TEMPLATE_RzsRR_v1_0_ResourceInstanceName1_tca_3',0);
+INSERT INTO `looptemplates_to_loopelementmodels` (`loop_element_model_name`, `loop_template_name`, `flow_order`) VALUES ('onap.policies.monitoring.cdap.tca.hi.lo.app','LOOP_TEMPLATE_RzsRR_v1_0_ResourceInstanceName2_tca_2',0);
+INSERT INTO `looptemplates_to_loopelementmodels` (`loop_element_model_name`, `loop_template_name`, `flow_order`) VALUES ('onap.policies.monitoring.tcagen2','LOOP_TEMPLATE_RzsRR_v1_0_ResourceInstanceName1_tca-guilin',0);
+/*!40000 ALTER TABLE `looptemplates_to_loopelementmodels` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `micro_service_policies`
+--
+
+LOCK TABLES `micro_service_policies` WRITE;
+/*!40000 ALTER TABLE `micro_service_policies` DISABLE KEYS */;
+/*!40000 ALTER TABLE `micro_service_policies` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `operational_policies`
+--
+
+LOCK TABLES `operational_policies` WRITE;
+/*!40000 ALTER TABLE `operational_policies` DISABLE KEYS */;
+/*!40000 ALTER TABLE `operational_policies` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `policy_models`
+--
+
+LOCK TABLES `policy_models` WRITE;
+/*!40000 ALTER TABLE `policy_models` DISABLE KEYS */;
+INSERT INTO `policy_models` (`policy_model_type`, `version`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `policy_acronym`, `policy_tosca`, `policy_pdp_group`) VALUES ('onap.policies.controlloop.guard.common.Blacklist','1.0.0','Not found','2021-03-05 17:10:27.333221','Not found','2021-03-05 17:10:27.473020','Blacklist','tosca_definitions_version: tosca_simple_yaml_1_1_0\npolicy_types:\n onap.policies.controlloop.guard.Common:\n derived_from: tosca.policies.Root\n version: 1.0.0\n description: |\n This is the base Policy Type for Guard policies that guard the execution of Operational\n Policies.\n properties:\n actor:\n type: string\n description: Specifies the Actor the guard applies to.\n required: true\n operation:\n type: string\n description: Specified the operation that the actor is performing\n the guard applies to.\n required: true\n timeRange:\n type: tosca.datatypes.TimeInterval\n description: |\n An optional range of time during the day the guard policy is valid for.\n required: false\n id:\n type: string\n description: The Control Loop id this applies to.\n required: false\n onap.policies.controlloop.guard.common.Blacklist:\n derived_from: onap.policies.controlloop.guard.Common\n type_version: 1.0.0\n version: 1.0.0\n description: Supports blacklist of entity id\'s from performing control loop\n actions on.\n properties:\n blacklist:\n type: list\n description: List of entity id\'s\n required: true\n entry_schema:\n type: string\n','{\n \"supportedPdpGroups\": [\n {\n \"controlloop\": [\n \"xacml\"\n ]\n }\n ]\n}');
+INSERT INTO `policy_models` (`policy_model_type`, `version`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `policy_acronym`, `policy_tosca`, `policy_pdp_group`) VALUES ('onap.policies.controlloop.guard.common.FrequencyLimiter','1.0.0','Not found','2021-03-05 17:10:27.311329','Not found','2021-03-05 17:10:27.473520','FrequencyLimiter','tosca_definitions_version: tosca_simple_yaml_1_1_0\npolicy_types:\n onap.policies.controlloop.guard.Common:\n derived_from: tosca.policies.Root\n version: 1.0.0\n description: |\n This is the base Policy Type for Guard policies that guard the execution of Operational\n Policies.\n properties:\n actor:\n type: string\n description: Specifies the Actor the guard applies to.\n required: true\n operation:\n type: string\n description: Specified the operation that the actor is performing\n the guard applies to.\n required: true\n timeRange:\n type: tosca.datatypes.TimeInterval\n description: |\n An optional range of time during the day the guard policy is valid for.\n required: false\n id:\n type: string\n description: The Control Loop id this applies to.\n required: false\n onap.policies.controlloop.guard.common.FrequencyLimiter:\n derived_from: onap.policies.controlloop.guard.Common\n type_version: 1.0.0\n version: 1.0.0\n description: Supports limiting the frequency of actions being taken by a Actor.\n properties:\n timeWindow:\n type: integer\n description: The time window to count the actions against.\n required: true\n timeUnits:\n type: string\n description: The units of time the window is counting.\n constraints:\n - valid_values:\n - second\n - minute\n - hour\n - day\n - week\n - month\n - year\n limit:\n type: integer\n description: The limit\n required: true\n constraints:\n - greater_than: 0\n','{\n \"supportedPdpGroups\": [\n {\n \"controlloop\": [\n \"xacml\"\n ]\n }\n ]\n}');
+INSERT INTO `policy_models` (`policy_model_type`, `version`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `policy_acronym`, `policy_tosca`, `policy_pdp_group`) VALUES ('onap.policies.controlloop.guard.common.MinMax','2.0.0','Not found','2021-03-05 17:10:27.377510','Not found','2021-03-05 17:10:27.377510','MinMax','tosca_definitions_version: tosca_simple_yaml_1_1_0\npolicy_types:\n onap.policies.controlloop.guard.Common:\n derived_from: tosca.policies.Root\n version: 1.0.0\n description: |\n This is the base Policy Type for Guard policies that guard the execution of Operational\n Policies.\n properties:\n actor:\n type: string\n description: Specifies the Actor the guard applies to.\n required: true\n operation:\n type: string\n description: Specified the operation that the actor is performing\n the guard applies to.\n required: true\n timeRange:\n type: tosca.datatypes.TimeInterval\n description: |\n An optional range of time during the day the guard policy is valid for.\n required: false\n id:\n type: string\n description: The Control Loop id this applies to.\n required: false\n onap.policies.controlloop.guard.common.MinMax:\n derived_from: onap.policies.controlloop.guard.Common\n type_version: 1.0.0\n version: 1.0.0\n description: Supports Min/Max number of entity for scaling operations\n properties:\n min:\n type: integer\n required: true\n description: The minimum instances of this entity\n max:\n type: integer\n required: false\n description: The maximum instances of this entity\n',NULL);
+INSERT INTO `policy_models` (`policy_model_type`, `version`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `policy_acronym`, `policy_tosca`, `policy_pdp_group`) VALUES ('onap.policies.controlloop.operational.common.Apex','1.0.0','Not found','2021-03-05 17:10:27.289621','Not found','2021-03-05 17:10:27.473869','Apex','tosca_definitions_version: tosca_simple_yaml_1_1_0\npolicy_types:\n onap.policies.controlloop.operational.Common:\n properties:\n abatement:\n name: abatement\n type: boolean\n typeVersion: 0.0.0\n description: Whether an abatement event message will be expected for\n the control loop from DCAE.\n default: \'false\'\n required: true\n constraints: [\n ]\n metadata: {\n }\n operations:\n name: operations\n type: list\n typeVersion: 0.0.0\n description: List of operations to be performed when Control Loop\n is triggered.\n required: true\n constraints: [\n ]\n entry_schema:\n type: onap.datatype.controlloop.Operation\n typeVersion: 0.0.0\n constraints: [\n ]\n metadata: {\n }\n trigger:\n name: trigger\n type: string\n typeVersion: 0.0.0\n description: Initial operation to execute upon receiving an Onset\n event message for the Control Loop.\n required: true\n constraints: [\n ]\n metadata: {\n }\n timeout:\n name: timeout\n type: integer\n typeVersion: 0.0.0\n description: |\n Overall timeout for executing all the operations. This timeout should equal or exceed the total\n timeout for each operation listed.\n required: true\n constraints: [\n ]\n metadata: {\n }\n id:\n name: id\n type: string\n typeVersion: 0.0.0\n description: The unique control loop id.\n required: true\n constraints: [\n ]\n metadata: {\n }\n name: onap.policies.controlloop.operational.Common\n version: 1.0.0\n derived_from: tosca.policies.Root\n metadata: {\n }\n description: |\n Operational Policy for Control Loop execution. Originated in Frankfurt to support TOSCA Compliant\n Policy Types. This does NOT support the legacy Policy YAML policy type.\n onap.policies.controlloop.operational.common.Apex:\n properties:\n engineServiceParameters:\n name: engineServiceParameters\n type: string\n typeVersion: 0.0.0\n description: The engine parameters like name, instanceCount, policy\n implementation, parameters etc.\n required: true\n constraints: [\n ]\n metadata: {\n }\n eventOutputParameters:\n name: eventOutputParameters\n type: string\n typeVersion: 0.0.0\n description: The event output parameters.\n required: true\n constraints: [\n ]\n metadata: {\n }\n javaProperties:\n name: javaProperties\n type: string\n typeVersion: 0.0.0\n description: Name/value pairs of properties to be set for APEX if\n needed.\n required: false\n constraints: [\n ]\n metadata: {\n }\n eventInputParameters:\n name: eventInputParameters\n type: string\n typeVersion: 0.0.0\n description: The event input parameters.\n required: true\n constraints: [\n ]\n metadata: {\n }\n name: onap.policies.controlloop.operational.common.Apex\n version: 1.0.0\n derived_from: onap.policies.controlloop.operational.Common\n metadata: {\n }\n description: Operational policies for Apex PDP\ndata_types:\n onap.datatype.controlloop.Actor:\n constraints: [\n ]\n properties:\n payload:\n name: payload\n type: map\n typeVersion: 0.0.0\n description: Name/value pairs of payload information passed by Policy\n to the actor\n required: false\n constraints: [\n ]\n entry_schema:\n type: string\n typeVersion: 0.0.0\n constraints: [\n ]\n metadata:\n clamp_possible_values: ClampExecution:CDS/payload\n target:\n name: target\n type: onap.datatype.controlloop.Target\n typeVersion: 0.0.0\n description: The resource the operation should be performed on.\n required: true\n constraints: [\n ]\n metadata: {\n }\n actor:\n name: actor\n type: string\n typeVersion: 0.0.0\n description: The actor performing the operation.\n required: true\n constraints: [\n ]\n metadata:\n clamp_possible_values: Dictionary:DefaultActors,ClampExecution:CDS/actor\n operation:\n name: operation\n type: string\n typeVersion: 0.0.0\n description: The operation the actor is performing.\n required: true\n constraints: [\n ]\n metadata:\n clamp_possible_values: Dictionary:DefaultOperations, ClampExecution:CDS/operation\n name: onap.datatype.controlloop.Actor\n version: 0.0.0\n derived_from: tosca.datatypes.Root\n metadata: {\n }\n description: An actor/operation/target definition\n onap.datatype.controlloop.Operation:\n constraints: [\n ]\n properties:\n failure_retries:\n name: failure_retries\n type: string\n typeVersion: 0.0.0\n description: Points to the operation to invoke when the current operation\n has exceeded its max retries.\n default: final_failure_retries\n required: false\n constraints: [\n ]\n metadata: {\n }\n id:\n name: id\n type: string\n typeVersion: 0.0.0\n description: Unique identifier for the operation\n required: true\n constraints: [\n ]\n metadata: {\n }\n failure_timeout:\n name: failure_timeout\n type: string\n typeVersion: 0.0.0\n description: Points to the operation to invoke when the time out for\n the operation occurs.\n default: final_failure_timeout\n required: false\n constraints: [\n ]\n metadata: {\n }\n failure:\n name: failure\n type: string\n typeVersion: 0.0.0\n description: Points to the operation to invoke on Actor operation\n failure.\n default: final_failure\n required: false\n constraints: [\n ]\n metadata: {\n }\n operation:\n name: operation\n type: onap.datatype.controlloop.Actor\n typeVersion: 0.0.0\n description: The definition of the operation to be performed.\n required: true\n constraints: [\n ]\n metadata: {\n }\n failure_guard:\n name: failure_guard\n type: string\n typeVersion: 0.0.0\n description: Points to the operation to invoke when the current operation\n is blocked due to guard policy enforcement.\n default: final_failure_guard\n required: false\n constraints: [\n ]\n metadata: {\n }\n retries:\n name: retries\n type: integer\n typeVersion: 0.0.0\n description: The number of retries the actor should attempt to perform\n the operation.\n default: \'0\'\n required: true\n constraints: [\n ]\n metadata: {\n }\n timeout:\n name: timeout\n type: integer\n typeVersion: 0.0.0\n description: The amount of time for the actor to perform the operation.\n required: true\n constraints: [\n ]\n metadata: {\n }\n failure_exception:\n name: failure_exception\n type: string\n typeVersion: 0.0.0\n description: Points to the operation to invoke when the current operation\n causes an exception.\n default: final_failure_exception\n required: false\n constraints: [\n ]\n metadata: {\n }\n description:\n name: description\n type: string\n typeVersion: 0.0.0\n description: A user-friendly description of the intent for the operation\n required: false\n constraints: [\n ]\n metadata: {\n }\n success:\n name: success\n type: string\n typeVersion: 0.0.0\n description: Points to the operation to invoke on success. A value\n of \"final_success\" indicates and end to the operation.\n default: final_success\n required: false\n constraints: [\n ]\n metadata: {\n }\n name: onap.datatype.controlloop.Operation\n version: 0.0.0\n derived_from: tosca.datatypes.Root\n metadata: {\n }\n description: An operation supported by an actor\n onap.datatype.controlloop.Target:\n constraints: [\n ]\n properties:\n entityIds:\n name: entityIds\n type: map\n typeVersion: 0.0.0\n description: |\n Map of values that identify the resource. If none are provided, it is assumed that the\n entity that generated the ONSET event will be the target.\n required: false\n constraints: [\n ]\n entry_schema:\n type: string\n typeVersion: 0.0.0\n constraints: [\n ]\n metadata:\n clamp_possible_values: ClampExecution:CSAR_RESOURCES\n targetType:\n name: targetType\n type: string\n typeVersion: 0.0.0\n description: Category for the target type\n required: true\n constraints:\n - valid_values:\n - VNF\n - VM\n - VFMODULE\n - PNF\n metadata: {\n }\n name: onap.datatype.controlloop.Target\n version: 0.0.0\n derived_from: tosca.datatypes.Root\n metadata: {\n }\n description: Definition for a entity in A&AI to perform a control loop operation\n on\nname: ToscaServiceTemplateSimple\nversion: 1.0.0\nmetadata: {\n }\n','{\n \"supportedPdpGroups\": [\n {\n \"controlloop\": [\n \"apex\",\n \"drools\"\n ]\n }\n ]\n}');
+INSERT INTO `policy_models` (`policy_model_type`, `version`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `policy_acronym`, `policy_tosca`, `policy_pdp_group`) VALUES ('onap.policies.controlloop.operational.common.Drools','1.0.0','Not found','2021-03-05 17:10:27.263600','Not found','2021-03-05 17:10:27.476583','Drools','tosca_definitions_version: tosca_simple_yaml_1_1_0\npolicy_types:\n onap.policies.controlloop.operational.common.Drools:\n derived_from: onap.policies.controlloop.operational.Common\n type_version: 1.0.0\n version: 1.0.0\n description: Operational policies for Drools PDP\n properties:\n controllerName:\n type: string\n description: Drools controller properties\n required: false\n onap.policies.controlloop.operational.Common:\n derived_from: tosca.policies.Root\n version: 1.0.0\n description: |\n Operational Policy for Control Loop execution. Originated in Frankfurt to support TOSCA Compliant\n Policy Types. This does NOT support the legacy Policy YAML policy type.\n properties:\n id:\n type: string\n description: The unique control loop id.\n required: true\n timeout:\n type: integer\n description: |\n Overall timeout for executing all the operations. This timeout should equal or exceed the total\n timeout for each operation listed.\n required: true\n abatement:\n type: boolean\n description: Whether an abatement event message will be expected for\n the control loop from DCAE.\n required: true\n default: false\n trigger:\n type: string\n description: Initial operation to execute upon receiving an Onset\n event message for the Control Loop.\n required: true\n operations:\n type: list\n description: List of operations to be performed when Control Loop\n is triggered.\n required: true\n entry_schema:\n type: onap.datatype.controlloop.Operation\ndata_types:\n onap.datatype.controlloop.Target:\n derived_from: tosca.datatypes.Root\n description: Definition for a entity in A&AI to perform a control loop operation\n on\n properties:\n targetType:\n type: string\n description: Category for the target type\n required: true\n constraints:\n - valid_values:\n - VNF\n - VM\n - VFMODULE\n - PNF\n entityIds:\n type: map\n description: |\n Map of values that identify the resource. If none are provided, it is assumed that the\n entity that generated the ONSET event will be the target.\n required: false\n metadata:\n clamp_possible_values: ClampExecution:CSAR_RESOURCES\n entry_schema:\n type: string\n onap.datatype.controlloop.Actor:\n derived_from: tosca.datatypes.Root\n description: An actor/operation/target definition\n properties:\n actor:\n type: string\n description: The actor performing the operation.\n required: true\n metadata:\n clamp_possible_values: Dictionary:DefaultActors,ClampExecution:CDS/actor\n operation:\n type: string\n description: The operation the actor is performing.\n required: true\n metadata:\n clamp_possible_values: Dictionary:DefaultOperations, ClampExecution:CDS/operations\n target:\n type: onap.datatype.controlloop.Target\n description: The resource the operation should be performed on.\n required: true\n payload:\n type: map\n description: Name/value pairs of payload information passed by Policy\n to the actor\n required: false\n metadata:\n clamp_possible_values: ClampExecution:CDS/payload\n entry_schema:\n type: string\n onap.datatype.controlloop.Operation:\n derived_from: tosca.datatypes.Root\n description: An operation supported by an actor\n properties:\n id:\n type: string\n description: Unique identifier for the operation\n required: true\n description:\n type: string\n description: A user-friendly description of the intent for the operation\n required: false\n operation:\n type: onap.datatype.controlloop.Actor\n description: The definition of the operation to be performed.\n required: true\n timeout:\n type: integer\n description: The amount of time for the actor to perform the operation.\n required: true\n retries:\n type: integer\n description: The number of retries the actor should attempt to perform\n the operation.\n required: true\n default: 0\n success:\n type: string\n description: Points to the operation to invoke on success. A value\n of \"final_success\" indicates and end to the operation.\n required: false\n default: final_success\n failure:\n type: string\n description: Points to the operation to invoke on Actor operation\n failure.\n required: false\n default: final_failure\n failure_timeout:\n type: string\n description: Points to the operation to invoke when the time out for\n the operation occurs.\n required: false\n default: final_failure_timeout\n failure_retries:\n type: string\n description: Points to the operation to invoke when the current operation\n has exceeded its max retries.\n required: false\n default: final_failure_retries\n failure_exception:\n type: string\n description: Points to the operation to invoke when the current operation\n causes an exception.\n required: false\n default: final_failure_exception\n failure_guard:\n type: string\n description: Points to the operation to invoke when the current operation\n is blocked due to guard policy enforcement.\n required: false\n default: final_failure_guard\n','{\n \"supportedPdpGroups\": [\n {\n \"controlloop\": [\n \"apex\",\n \"drools\"\n ]\n }\n ]\n}');
+INSERT INTO `policy_models` (`policy_model_type`, `version`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `policy_acronym`, `policy_tosca`, `policy_pdp_group`) VALUES ('onap.policies.monitoring.cdap.tca.hi.lo.app','1.0.0','Not found','2021-03-05 17:10:19.671978','Not found','2021-03-05 17:10:27.477076','app','tosca_definitions_version: tosca_simple_yaml_1_1_0\npolicy_types:\n onap.policies.Monitoring:\n derived_from: tosca.policies.Root\n version: 1.0.0\n description: a base policy type for all policies that govern monitoring provisioning\n onap.policies.monitoring.cdap.tca.hi.lo.app:\n derived_from: onap.policies.Monitoring\n version: 1.0.0\n properties:\n tca_policy:\n type: onap.datatypes.monitoring.tca_policy\n description: TCA Policy JSON\n required: true\ndata_types:\n onap.datatypes.monitoring.metricsPerEventName:\n derived_from: tosca.datatypes.Root\n properties:\n controlLoopSchemaType:\n type: string\n required: true\n description: Specifies Control Loop Schema Type for the event Name\n e.g. VNF, VM\n constraints:\n - valid_values:\n - VM\n - VNF\n eventName:\n type: string\n required: true\n description: Event name to which thresholds need to be applied\n policyName:\n type: string\n required: true\n description: TCA Policy Scope Name\n policyScope:\n type: string\n required: true\n description: TCA Policy Scope\n policyVersion:\n type: string\n required: true\n description: TCA Policy Scope Version\n thresholds:\n type: list\n required: true\n description: Thresholds associated with eventName\n entry_schema:\n type: onap.datatypes.monitoring.thresholds\n onap.datatypes.monitoring.tca_policy:\n derived_from: tosca.datatypes.Root\n properties:\n domain:\n type: string\n required: true\n description: Domain name to which TCA needs to be applied\n default: measurementsForVfScaling\n constraints:\n - equal: measurementsForVfScaling\n metricsPerEventName:\n type: list\n required: true\n description: Contains eventName and threshold details that need to\n be applied to given eventName\n entry_schema:\n type: onap.datatypes.monitoring.metricsPerEventName\n onap.datatypes.monitoring.thresholds:\n derived_from: tosca.datatypes.Root\n properties:\n closedLoopControlName:\n type: string\n required: true\n description: Closed Loop Control Name associated with the threshold\n closedLoopEventStatus:\n type: string\n required: true\n description: Closed Loop Event Status of the threshold\n constraints:\n - valid_values:\n - ONSET\n - ABATED\n direction:\n type: string\n required: true\n description: Direction of the threshold\n constraints:\n - valid_values:\n - LESS\n - LESS_OR_EQUAL\n - GREATER\n - GREATER_OR_EQUAL\n - EQUAL\n fieldPath:\n type: string\n required: true\n description: Json field Path as per CEF message which needs to be\n analyzed for TCA\n constraints:\n - valid_values:\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage\n - $.event.measurementsForVfScalingFields.meanRequestLatency\n - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered\n - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached\n - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured\n - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree\n - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed\n - $.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value\n severity:\n type: string\n required: true\n description: Threshold Event Severity\n constraints:\n - valid_values:\n - CRITICAL\n - MAJOR\n - MINOR\n - WARNING\n - NORMAL\n thresholdValue:\n type: integer\n required: true\n description: Threshold value for the field Path inside CEF message\n version:\n type: string\n required: true\n description: Version number associated with the threshold\n','{\n \"supportedPdpGroups\": [\n {\n \"monitoring\": [\n \"xacml\"\n ]\n }\n ]\n}');
+INSERT INTO `policy_models` (`policy_model_type`, `version`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `policy_acronym`, `policy_tosca`, `policy_pdp_group`) VALUES ('onap.policies.monitoring.tcagen2','1.0.0','Not found','2021-03-05 17:10:19.809945','Not found','2021-03-05 17:10:27.477416','tcagen2','tosca_definitions_version: tosca_simple_yaml_1_1_0\npolicy_types:\n onap.policies.Monitoring:\n derived_from: tosca.policies.Root\n version: 1.0.0\n name: onap.policies.Monitoring\n description: a base policy type for all policies that govern monitoring provisioning\n onap.policies.monitoring.tcagen2:\n derived_from: onap.policies.Monitoring\n version: 1.0.0\n name: onap.policies.monitoring.tcagen2\n properties:\n tca.policy:\n type: onap.datatypes.monitoring.tca_policy\n description: TCA Policy JSON\n required: true\ndata_types:\n onap.datatypes.monitoring.metricsPerEventName:\n derived_from: tosca.datatypes.Root\n properties:\n controlLoopSchemaType:\n type: string\n required: true\n description: Specifies Control Loop Schema Type for the event Name\n e.g. VNF, VM\n constraints:\n - valid_values:\n - VM\n - VNF\n eventName:\n type: string\n required: true\n description: Event name to which thresholds need to be applied\n policyName:\n type: string\n required: true\n description: TCA Policy Scope Name\n policyScope:\n type: string\n required: true\n description: TCA Policy Scope\n policyVersion:\n type: string\n required: true\n description: TCA Policy Scope Version\n thresholds:\n type: list\n required: true\n description: Thresholds associated with eventName\n entry_schema:\n type: onap.datatypes.monitoring.thresholds\n onap.datatypes.monitoring.tca_policy:\n derived_from: tosca.datatypes.Root\n properties:\n domain:\n type: string\n required: true\n description: Domain name to which TCA needs to be applied\n default: measurementsForVfScaling\n constraints:\n - equal: measurementsForVfScaling\n metricsPerEventName:\n type: list\n required: true\n description: Contains eventName and threshold details that need to\n be applied to given eventName\n entry_schema:\n type: onap.datatypes.monitoring.metricsPerEventName\n onap.datatypes.monitoring.thresholds:\n derived_from: tosca.datatypes.Root\n properties:\n closedLoopControlName:\n type: string\n required: true\n description: Closed Loop Control Name associated with the threshold\n closedLoopEventStatus:\n type: string\n required: true\n description: Closed Loop Event Status of the threshold\n constraints:\n - valid_values:\n - ONSET\n - ABATED\n direction:\n type: string\n required: true\n description: Direction of the threshold\n constraints:\n - valid_values:\n - LESS\n - LESS_OR_EQUAL\n - GREATER\n - GREATER_OR_EQUAL\n - EQUAL\n fieldPath:\n type: string\n required: true\n description: Json field Path as per CEF message which needs to be\n analyzed for TCA\n constraints:\n - valid_values:\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedTotalPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedOctetsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedUnicastPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedMulticastPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedDiscardedPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedErrorPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsDelta\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedTotalPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedOctetsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedUnicastPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedMulticastPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedBroadcastPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedDiscardedPacketsAccumulated\n - $.event.measurementsForVfScalingFields.vNicPerformanceArray[*].transmittedErrorPacketsAccumulated\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuIdle\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageInterrupt\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageNice\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSoftIrq\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSteal\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuUsageSystem\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].cpuWait\n - $.event.measurementsForVfScalingFields.cpuUsageArray[*].percentUsage\n - $.event.measurementsForVfScalingFields.meanRequestLatency\n - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryBuffered\n - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryCached\n - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryConfigured\n - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryFree\n - $.event.measurementsForVfScalingFields.memoryUsageArray[*].memoryUsed\n - $.event.measurementsForVfScalingFields.additionalMeasurements[*].arrayOfFields[0].value\n severity:\n type: string\n required: true\n description: Threshold Event Severity\n constraints:\n - valid_values:\n - CRITICAL\n - MAJOR\n - MINOR\n - WARNING\n - NORMAL\n thresholdValue:\n type: integer\n required: true\n description: Threshold value for the field Path inside CEF message\n version:\n type: string\n required: true\n description: Version number associated with the threshold\n','{\n \"supportedPdpGroups\": [\n {\n \"monitoring\": [\n \"xacml\"\n ]\n }\n ]\n}');
+INSERT INTO `policy_models` (`policy_model_type`, `version`, `created_by`, `created_timestamp`, `updated_by`, `updated_timestamp`, `policy_acronym`, `policy_tosca`, `policy_pdp_group`) VALUES ('onap.policies.Naming','1.0.0','Not found','2021-03-05 17:10:27.355402','Not found','2021-03-05 17:10:27.477691','Naming','tosca_definitions_version: tosca_simple_yaml_1_1_0\npolicy_types:\n onap.policies.Naming:\n derived_from: tosca.policies.Root\n version: 1.0.0\n name: onap.policies.Naming\n description: Virtual policy node for naming\n properties:\n policy-instance-name:\n type: string\n naming-models:\n type: list\n entry_schema:\n type: policy.data.naming-model-entity\ndata_types:\n policy.data.naming-model-entity:\n derived_from: tosca.datatypes.Root\n properties:\n nfRole:\n type: string\n required: false\n metadata:\n matchable: true\n naming-type:\n type: string\n required: true\n metadata:\n matchable: true\n naming-recipe:\n type: string\n required: true\n name-operation:\n type: string\n required: false\n naming-properties:\n type: list\n required: true\n entry_schema:\n type: policy.data.naming-property\n policy.data.naming-property:\n derived_from: tosca.datatypes.Root\n properties:\n property-name:\n type: string\n required: true\n metadata:\n matchable: true\n property-value:\n type: string\n required: false\n property-operation:\n type: string\n required: false\n source-system:\n type: string\n required: false\n source-endpoint:\n type: string\n required: false\n increment-sequence:\n type: policy.data.increment-sequence\n required: false\n policy.data.increment-sequence:\n derived_from: tosca.datatypes.Root\n properties:\n scope:\n type: list\n required: true\n entry_schema:\n type: string\n constraints:\n - valid_values:\n - CLOUD_REGION_ID\n - LOCATION_CLLI\n - VNF\n - VM\n - VFMODULE\n - PRECEEDING\n - TRAILING\n - ENTIRETY\n sequence-type:\n type: string\n require: true\n entry_schema:\n type: string\n constraints:\n - valid_values:\n - numeric\n - alpha-numeric\n start-value:\n type: string\n required: true\n max:\n type: string\n required: false\n increment:\n type: string\n required: true\n length:\n type: string\n required: true\n','{\n \"supportedPdpGroups\": [\n {\n \"monitoring\": [\n \"xacml\"\n ]\n }\n ]\n}');
+/*!40000 ALTER TABLE `policy_models` ENABLE KEYS */;
+UNLOCK TABLES;
+
+--
+-- Dumping data for table `services`
+--
+
+LOCK TABLES `services` WRITE;
+/*!40000 ALTER TABLE `services` DISABLE KEYS */;
+INSERT INTO `services` (`service_uuid`, `name`, `resource_details`, `service_details`, `version`) VALUES ('63cac700-ab9a-4115-a74f-7eac85e3fce0','vLoadBalancerMS','{\n \"CP\": {},\n \"VL\": {},\n \"VF\": {\n \"vLoadBalancerMS 0\": {\n \"resourceVendor\": \"Test\",\n \"name\": \"vLoadBalancerMS\",\n \"resourceVendorModelNumber\": \"\",\n \"description\": \"vLBMS\",\n \"invariantUUID\": \"1a31b9f2-e50d-43b7-89b3-a040250cf506\",\n \"UUID\": \"b4c4f3d7-929e-4b6d-a1cd-57e952ddc3e6\",\n \"type\": \"VF\",\n \"category\": \"Application L4+\",\n \"subcategory\": \"Load Balancer\",\n \"version\": \"1.0\",\n \"customizationUUID\": \"465246dc-7748-45f4-a013-308d92922552\",\n \"resourceVendorRelease\": \"1.0\",\n \"controllerProperties\": {\n \"sdnc_model_name\": \"baseconfiguration\",\n \"sdnc_model_version\": \"1.0.0\",\n \"workflows\": {\n \"resource-assignment\": {\n \"inputs\": {\n \"resource-assignment-properties\": {\n \"type\": \"object\",\n \"properties\": {\n \"request-id\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"service-instance-id\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"hostname\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"request-info\": {\n \"type\": \"object\",\n \"properties\": {\n \"prop1\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"prop2\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n }\n }\n }\n }\n }\n }\n },\n \"activate\": {\n \"inputs\": {\n \"resource-assignment-properties\": {\n \"type\": \"object\",\n \"properties\": {\n \"request-id\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"service-instance-id\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"hostname\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"request-info\": {\n \"type\": \"object\",\n \"properties\": {\n \"prop1\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"prop2\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n }\n }\n }\n }\n }\n }\n },\n \"activate-restconf\": {\n \"inputs\": {\n \"resource-assignment-properties\": {\n \"type\": \"object\",\n \"properties\": {\n \"request-id\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"service-instance-id\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"hostname\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"request-info\": {\n \"type\": \"object\",\n \"properties\": {\n \"prop1\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"prop2\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n }\n }\n }\n }\n }\n }\n },\n \"activate-cli\": {\n \"inputs\": {\n \"resource-assignment-properties\": {\n \"type\": \"object\",\n \"properties\": {\n \"request-id\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"service-instance-id\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"hostname\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"request-info\": {\n \"type\": \"object\",\n \"properties\": {\n \"prop1\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"prop2\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n }\n }\n }\n }\n }\n }\n },\n \"assign-activate\": {\n \"inputs\": {\n \"resource-assignment-properties\": {\n \"type\": \"object\",\n \"properties\": {\n \"request-id\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"service-instance-id\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"hostname\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"request-info\": {\n \"type\": \"object\",\n \"properties\": {\n \"prop1\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"prop2\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n }\n }\n }\n }\n }\n }\n },\n \"imperative-test-wf\": {\n \"inputs\": {\n \"resource-assignment-properties\": {\n \"type\": \"object\",\n \"properties\": {\n \"request-id\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"service-instance-id\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"hostname\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"request-info\": {\n \"type\": \"object\",\n \"properties\": {\n \"prop1\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n },\n \"prop2\": {\n \"required\": true,\n \"type\": \"string\",\n \"input-param\": true\n }\n }\n }\n }\n }\n }\n }\n }\n }\n }\n },\n \"CR\": {},\n \"VFC\": {},\n \"PNF\": {},\n \"Service\": {},\n \"CVFC\": {},\n \"Service Proxy\": {},\n \"Configuration\": {},\n \"AllottedResource\": {},\n \"VFModule\": {\n \"Vloadbalancerms..vpkg..module-1\": {\n \"vfModuleModelInvariantUUID\": \"ca052563-eb92-4b5b-ad41-9111768ce043\",\n \"vfModuleModelVersion\": \"1\",\n \"vfModuleModelName\": \"Vloadbalancerms..vpkg..module-1\",\n \"vfModuleModelUUID\": \"1e725ccc-b823-4f67-82b9-4f4367070dbc\",\n \"vfModuleModelCustomizationUUID\": \"1bffdc31-a37d-4dee-b65c-dde623a76e52\",\n \"min_vf_module_instances\": 0,\n \"vf_module_label\": \"vpkg\",\n \"max_vf_module_instances\": 1,\n \"vf_module_type\": \"Expansion\",\n \"isBase\": false,\n \"initial_count\": 0,\n \"volume_group\": false\n },\n \"Vloadbalancerms..vdns..module-3\": {\n \"vfModuleModelInvariantUUID\": \"4c10ba9b-f88f-415e-9de3-5d33336047fa\",\n \"vfModuleModelVersion\": \"1\",\n \"vfModuleModelName\": \"Vloadbalancerms..vdns..module-3\",\n \"vfModuleModelUUID\": \"4fa73b49-8a6c-493e-816b-eb401567b720\",\n \"vfModuleModelCustomizationUUID\": \"bafcdab0-801d-4d81-9ead-f464640a38b1\",\n \"min_vf_module_instances\": 0,\n \"vf_module_label\": \"vdns\",\n \"max_vf_module_instances\": 50,\n \"vf_module_type\": \"Expansion\",\n \"isBase\": false,\n \"initial_count\": 0,\n \"volume_group\": false\n },\n \"Vloadbalancerms..base_template..module-0\": {\n \"vfModuleModelInvariantUUID\": \"921f7c96-ebdd-42e6-81b9-1cfc0c9796f3\",\n \"vfModuleModelVersion\": \"1\",\n \"vfModuleModelName\": \"Vloadbalancerms..base_template..module-0\",\n \"vfModuleModelUUID\": \"63734409-f745-4e4d-a38b-131638a0edce\",\n \"vfModuleModelCustomizationUUID\": \"86baddea-c730-4fb8-9410-cd2e17fd7f27\",\n \"min_vf_module_instances\": 1,\n \"vf_module_label\": \"base_template\",\n \"max_vf_module_instances\": 1,\n \"vf_module_type\": \"Base\",\n \"isBase\": true,\n \"initial_count\": 1,\n \"volume_group\": false\n },\n \"Vloadbalancerms..vlb..module-2\": {\n \"vfModuleModelInvariantUUID\": \"a772a1f4-0064-412c-833d-4749b15828dd\",\n \"vfModuleModelVersion\": \"1\",\n \"vfModuleModelName\": \"Vloadbalancerms..vlb..module-2\",\n \"vfModuleModelUUID\": \"0f5c3f6a-650a-4303-abb6-fff3e573a07a\",\n \"vfModuleModelCustomizationUUID\": \"96a78aad-4ffb-4ef0-9c4f-deb03bf1d806\",\n \"min_vf_module_instances\": 0,\n \"vf_module_label\": \"vlb\",\n \"max_vf_module_instances\": 1,\n \"vf_module_type\": \"Expansion\",\n \"isBase\": false,\n \"initial_count\": 0,\n \"volume_group\": false\n }\n }\n}','{\n \"serviceType\": \"\",\n \"serviceRole\": \"\",\n \"description\": \"vLBMS\",\n \"type\": \"Service\",\n \"instantiationType\": \"A-la-carte\",\n \"namingPolicy\": \"\",\n \"serviceEcompNaming\": \"true\",\n \"environmentContext\": \"General_Revenue-Bearing\",\n \"name\": \"vLoadBalancerMS\",\n \"invariantUUID\": \"30ec5b59-4799-48d8-ac5f-1058a6b0e48f\",\n \"ecompGeneratedNaming\": \"true\",\n \"UUID\": \"63cac700-ab9a-4115-a74f-7eac85e3fce0\",\n \"category\": \"Network L4+\"\n}','1.0');
+/*!40000 ALTER TABLE `services` ENABLE KEYS */;
+UNLOCK TABLES;
+/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
+
+-- Dump completed on 2021-03-05 16:11:22
diff --git a/runtime/pom.xml b/runtime/pom.xml
new file mode 100644
index 000000000..66d555ac7
--- /dev/null
+++ b/runtime/pom.xml
@@ -0,0 +1,1250 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP POLICY-CLAMP
+ ================================================================================
+ Copyright (C) 2017-2021 AT&T Intellectual Property. All rights reserved.
+ Modifications Copyright (C) 2021 Nordix Foundation.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END============================================
+ ===================================================================
+-->
+<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.policy.clamp</groupId>
+ <artifactId>policy-clamp</artifactId>
+ <version>6.1.2-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>policy-clamp-runtime</artifactId>
+ <name>${project.artifactId}</name>
+
+ <description>
+ This is the MAVEN project that builds everything for ONAP POLICY-CLAMP.
+ Docker engine is normally required to perfom all possible tasks (including integration tests)
+
+ It can build:
+ - The ONAP POLICY-CLAMP JAR that contains CLAMP back-end code.
+ - The DOCKER images for:
+ * POLICY-CLAMP backend (Java Spring)
+ * POLICY-CLAMP frontend (Javascript React)
+
+ It can test:
+ - The POLICY-CLAMP backend, JAVA unit testing
+ - The POLICY-CLAMP backend, JAVA integration tests (with Spring + docker mariadb database + docker policy/dcae
+ emulator written in python)
+ - The POLICY-CLAMP frontend, Javascript tests (NodeJS(NPM) + JEST and Enzyme for React)
+
+ The test coverage for dev's can be found after a "clean install" build in:
+ - Clamp backend: target/jacoco-dev.exec (unit tests + integration tests merged)
+ or separately target/coverage-reports/jacoco.exec and target/coverage-reports/jacoco-it.exec
+ - Clamp frontend: target/ui-react/coverage
+
+ Useful mvn commands:
+ - mvn clean install: Build Clamp backend JAR + unit tests + integration tests + NPM tests (+coverage for all)
+ - mvn clean install -DskipITs=true: Build Clamp backend JAR + unit tests + NPM tests (+coverage for all), it
+ does not require a DOCKER engine
+ - mvn clean install -DskipTests -P docker: Build Clamp backend JAR + all docker images
+
+ To start POLICY-CLAMP (Build it before):
+ - Use docker-compose file in ./extra/docker/clamp/docker-compose.yml
+ - Use the script located in ./extra/bin/start-backend.sh + start-frontend.sh
+ - Use your IDE to use the Jar or start NVM/NPM
+
+ </description>
+
+ <properties>
+ <maven.build.timestamp.format>yyyyMMdd'T'HHmmss'Z'</maven.build.timestamp.format>
+ <clamp.project.version>${project.version}</clamp.project.version>
+ <clamp.build.timestamp>${maven.build.timestamp}</clamp.build.timestamp>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+ <eelf.core.version>1.0.0</eelf.core.version>
+ <camel.version>3.7.3</camel.version>
+ <springboot.version>2.4.4</springboot.version>
+
+ <sonar.java.coveragePlugin>jacoco</sonar.java.coveragePlugin>
+ <sonar.surefire.reportsPath>${project.build.directory}/surefire-reports</sonar.surefire.reportsPath>
+ <sonar.coverage.jacoco.xmlReportPaths>${project.build.directory}/jacoco-html-xml-reports/jacoco.xml
+ </sonar.coverage.jacoco.xmlReportPaths>
+ <sonar.projectVersion>${project.version}</sonar.projectVersion>
+ <sonar.log.level>DEBUG</sonar.log.level>
+ <sonar.nodejs.executable>${project.build.directory}/${ui.react.src}/node/node</sonar.nodejs.executable>
+ <sonar.verbose>true</sonar.verbose>
+ <sonar.sources>src/main,${project.build.directory}/${ui.react.src}/src</sonar.sources>
+ <sonar.exclusions>src/main/resources/**</sonar.exclusions>
+ <sonar.scm.exclusions.disabled>true</sonar.scm.exclusions.disabled>
+ <sonar.javascript.lcov.reportPaths>${project.build.directory}/${ui.react.src}/coverage/lcov.info
+ </sonar.javascript.lcov.reportPaths>
+ <sonar.coverage.exclusions>
+ src/main/resources/**,target/ui-react/src/**/*.test.js,target/ui-react/src/setupTests.js
+ </sonar.coverage.exclusions>
+ <docker.push.registry>localhost:5000</docker.push.registry>
+ <docker.pull.registry>nexus3.onap.org:10001</docker.pull.registry>
+ <docker.skip.build>true</docker.skip.build>
+ <docker.skip.push>true</docker.skip.push>
+ <docker.skip.tag>true</docker.skip.tag>
+ <skip.staging.artifacts>false</skip.staging.artifacts>
+ <python.http.proxy.param/>
+ <tomcat.version>9.0.45</tomcat.version>
+ <ui.react.src>ui-react</ui.react.src>
+ <ui.react.lib.src>ui-react-lib</ui.react.lib.src>
+ <npm.publish.url>https://nexus3.onap.org/repository/npm.snapshot/</npm.publish.url>
+ </properties>
+
+ <profiles>
+ <!-- BEGIN: NOT USABLE profiles, those are defined when specific flags are enabled -->
+ <profile>
+ <id>without-test</id>
+ <activation>
+ <property>
+ <name>maven.test.skip</name>
+ <value>true</value>
+ </property>
+ </activation>
+ <properties>
+ <docker.skip.run>true</docker.skip.run>
+ <docker.skip>true</docker.skip>
+ </properties>
+ </profile>
+ <profile>
+ <id>without-IT-only</id>
+ <activation>
+ <property>
+ <name>skipITs</name>
+ <value>true</value>
+ </property>
+ </activation>
+ <properties>
+ <docker.skip.run>true</docker.skip.run>
+ <docker.skip>true</docker.skip>
+ </properties>
+ </profile>
+ <profile>
+ <id>without-IT-only2</id>
+ <activation>
+ <property>
+ <name>skipTests</name>
+ <value>true</value>
+ </property>
+ </activation>
+ <properties>
+ <docker.skip.run>true</docker.skip.run>
+ <docker.skip>true</docker.skip>
+ </properties>
+ </profile>
+ <!-- END: NOT USABLE profiles, those are defined when specific flags are enabled -->
+ <profile>
+ <id>docker</id>
+ <properties>
+ <skip.staging.artifacts>true</skip.staging.artifacts>
+ <docker.skip.build>false</docker.skip.build>
+ <docker.skip.tag>false</docker.skip.tag>
+ <docker.skip.push>false</docker.skip.push>
+ <docker.skip>false</docker.skip>
+ </properties>
+ </profile>
+ </profiles>
+
+ <dependencyManagement>
+ <dependencies>
+ <!-- Spring Boot BOM -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${springboot.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <!-- Camel BOM -->
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-spring-boot-bom</artifactId>
+ <version>${camel.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.att.eelf</groupId>
+ <artifactId>eelf-core</artifactId>
+ <version>${eelf.core.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.janino</groupId>
+ <artifactId>janino</artifactId>
+ <version>3.0.8</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-core</artifactId>
+ <version>${tomcat.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-el</artifactId>
+ <version>${tomcat.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-websocket</artifactId>
+ <version>${tomcat.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat</groupId>
+ <artifactId>tomcat-annotations-api</artifactId>
+ <version>${tomcat.version}</version>
+ </dependency>
+ <!-- For CAMEL -->
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-http-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-spring-boot-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-jaxb-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-servlet-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-gson-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-swagger-java-starter</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>jsr311-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-ext</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <!-- Spring famework -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-json</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-tomcat</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>org.glassfish</groupId>
+ <artifactId>jakarta.el</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-jdbc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-security</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-autoconfigure</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-test</artifactId>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>com.vaadin.external.google</groupId>
+ <artifactId>android-json</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
+ </dependency>
+ <!-- Policy dependencies mainly for the models required -->
+ <dependency>
+ <groupId>org.onap.policy.models</groupId>
+ <artifactId>policy-models-pdp</artifactId>
+ <version>${policy.models.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-reflect</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-stdlib</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.jetbrains.kotlin</groupId>
+ <artifactId>kotlin-stdlib-common</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <!-- Others dependencies -->
+ <!-- Jaxws is required for AAF -->
+ <dependency>
+ <groupId>javax.xml.ws</groupId>
+ <artifactId>jaxws-api</artifactId>
+ <version>2.3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.aaf.authz</groupId>
+ <artifactId>aaf-cadi-aaf</artifactId>
+ <version>2.1.15</version>
+ <exclusions>
+ <exclusion>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <version>1.2.3</version>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>1.2.3</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.8.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-vfs2</artifactId>
+ <version>2.8.0</version>
+ <exclusions>
+ <exclusion>
+ <groupId>com.squareup.okhttp</groupId>
+ <artifactId>okhttp</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.transaction</groupId>
+ <artifactId>jta</artifactId>
+ <version>1.1</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.persistence</groupId>
+ <artifactId>persistence-api</artifactId>
+ <version>1.0.2</version>
+ </dependency>
+ <!-- Other dependencies to fix nexus IQ reported vulnerabilities -->
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ <version>1.15</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-utils</artifactId>
+ <version>3.3.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.spec.javax.ws.rs</groupId>
+ <artifactId>jboss-jaxrs-api_2.0_spec</artifactId>
+ <version>1.0.1.Final</version>
+ </dependency>
+
+
+ <!-- Remove the MYSQL connector and replace it by Mariadb -->
+ <dependency>
+ <groupId>org.mariadb.jdbc</groupId>
+ <artifactId>mariadb-java-client</artifactId>
+ <version>2.7.2</version>
+ </dependency>
+ <!-- For SDC Controller -->
+ <dependency>
+ <groupId>org.onap.sdc.sdc-distribution-client</groupId>
+ <artifactId>sdc-distribution-client</artifactId>
+ <version>1.4.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.sdc.sdc-tosca</groupId>
+ <artifactId>sdc-tosca</artifactId>
+ <version>1.5.1</version>
+ <exclusions>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.yaml</groupId>
+ <artifactId>snakeyaml</artifactId>
+ <version>1.28</version>
+ </dependency>
+ <dependency>
+ <groupId>org.dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ <version>2.1.3</version>
+ </dependency>
+
+ <!-- TESTING -->
+ <dependency>
+ <groupId>org.junit.vintage</groupId>
+ <artifactId>junit-vintage-engine</artifactId>
+ <version>5.7.1</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>3.10.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.docker-java</groupId>
+ <artifactId>docker-java-core</artifactId>
+ <version>3.2.7</version>
+ <scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>com.github.docker-java</groupId>
+ <artifactId>docker-java</artifactId>
+ <version>3.2.7</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.policy.common</groupId>
+ <artifactId>utils-test</artifactId>
+ <version>${policy.common.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>policy-clamp-backend</finalName>
+
+ <testResources>
+ <testResource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ <excludes>
+ <exclude>clds/aaf/**</exclude>
+ </excludes>
+ </testResource>
+ <testResource>
+ <directory>src/main/resources</directory>
+ <filtering>false</filtering>
+ <includes>
+ <include>clds/aaf/**</include>
+ </includes>
+ </testResource>
+ <testResource>
+ <directory>src/test/resources</directory>
+ <excludes>
+ <exclude>**/*.jks</exclude>
+ <exclude>**/*.csar</exclude>
+ </excludes>
+ <filtering>true</filtering>
+ </testResource>
+ <testResource>
+ <directory>src/test/resources/https</directory>
+ <includes>
+ <include>**.jks</include>
+ </includes>
+ <filtering>false</filtering>
+ <targetPath>https</targetPath>
+ </testResource>
+ <testResource>
+ <directory>src/test/resources/example/sdc</directory>
+ <includes>
+ <include>**.csar</include>
+ </includes>
+ <filtering>false</filtering>
+ <targetPath>example/sdc</targetPath>
+ </testResource>
+ </testResources>
+ <resources>
+ <!-- For AAF folder maven should not try to filter Keystores/Truststores ... Otherwise
+ they will be broken and unreadable -->
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>true</filtering>
+ <excludes>
+ <exclude>clds/aaf/**</exclude>
+ </excludes>
+ </resource>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>false</filtering>
+ <includes>
+ <include>clds/aaf/**</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>${ui.react.src}</directory>
+ <excludes>
+ <exclude>node_modules</exclude>
+ </excludes>
+ <includes>
+ <include>src/**</include>
+ <include>public/**</include>
+ <include>package.json</include>
+ <include>package-lock.json</include>
+ </includes>
+ <filtering>true</filtering>
+ <targetPath>${project.build.directory}/${ui.react.src}</targetPath>
+ </resource>
+ <resource>
+ <directory>${ui.react.src}</directory>
+ <includes>
+ <include>src/**</include>
+ </includes>
+ <excludes>
+ <exclude>**/__snapshots__/**</exclude>
+ <exclude>**/**.test.js</exclude>
+ </excludes>
+ <filtering>true</filtering>
+ <targetPath>${project.build.directory}/${ui.react.lib.src}</targetPath>
+ </resource>
+ <resource>
+ <directory>${ui.react.lib.src}</directory>
+ <includes>
+ <include>**</include>
+ </includes>
+ <excludes>
+ <exclude>node_modules/**</exclude>
+ <exclude>package-lock.json</exclude>
+ </excludes>
+ <filtering>true</filtering>
+ <targetPath>${project.build.directory}/${ui.react.lib.src}</targetPath>
+ </resource>
+ </resources>
+
+ <plugins>
+ <plugin>
+ <groupId>de.jpdigital</groupId>
+ <artifactId>hibernate52-ddl-maven-plugin</artifactId>
+ <version>2.2.0</version>
+ <dependencies>
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ <version>2.3.0</version>
+ </dependency>
+ </dependencies>
+ <executions>
+ <execution>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>gen-ddl</goal>
+ </goals>
+ <configuration>
+ <packages>
+ <param>org.onap.policy.clamp</param>
+ </packages>
+ <dialects>
+ <param>MARIADB53</param>
+ </dialects>
+ <outputDirectory>${project.basedir}/extra/sql/bulkload/</outputDirectory>
+ <outputFileNameSuffix>create-tables</outputFileNameSuffix>
+ <!-- <createDropStatements>true</createDropStatements> -->
+ <omitDialectFromFileName>true</omitDialectFromFileName>
+ </configuration>
+ </execution>
+ </executions>
+
+ </plugin>
+ <!-- Read the swagger.json file and the definition from SwaggerConfig.java; generate
+ a list of .adoc files containing the APIs info in more structured way -->
+ <plugin>
+ <groupId>io.github.swagger2markup</groupId>
+ <artifactId>swagger2markup-maven-plugin</artifactId>
+ <version>1.3.3</version>
+ <dependencies>
+ <dependency>
+ <groupId>io.github.swagger2markup</groupId>
+ <artifactId>swagger2markup-import-files-ext</artifactId>
+ <version>1.3.3</version>
+ </dependency>
+ <dependency>
+ <groupId>io.github.swagger2markup</groupId>
+ <artifactId>swagger2markup-spring-restdocs-ext</artifactId>
+ <version>1.3.3</version>
+ </dependency>
+ </dependencies>
+ <configuration>
+ <swaggerInput>${project.basedir}/docs/swagger/swagger.json</swaggerInput>
+ <outputDir>${project.build.directory}/asciidoc/generated</outputDir>
+ <config>
+ <swagger2markup.markupLanguage>ASCIIDOC</swagger2markup.markupLanguage>
+ </config>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>post-integration-test</phase>
+ <goals>
+ <goal>convertSwagger2markup</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- Run the generated asciidoc through Asciidoctor to generate other documentation
+ types, such as PDFs or HTML5 -->
+ <plugin>
+ <groupId>org.asciidoctor</groupId>
+ <artifactId>asciidoctor-maven-plugin</artifactId>
+ <version>1.5.7.1</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.asciidoctor</groupId>
+ <artifactId>asciidoctorj-pdf</artifactId>
+ <version>1.5.0-alpha.10.1</version>
+ </dependency>
+ </dependencies>
+ <configuration>
+ <sourceDirectory>${project.basedir}/src/main/resources/asciidoc</sourceDirectory>
+ <sourceDocumentName>swagger.adoc</sourceDocumentName>
+ <attributes>
+ <doctype>book</doctype>
+ <toc>left</toc>
+ <toclevels>3</toclevels>
+ <numbered/>
+ <hardbreaks/>
+ <sectlinks/>
+ <sectanchors/>
+ <generated>${project.build.directory}/asciidoc/generated</generated>
+ </attributes>
+ </configuration>
+
+ <executions>
+ <execution>
+ <id>output-html</id>
+ <phase>post-integration-test</phase>
+ <goals>
+ <goal>process-asciidoc</goal>
+ </goals>
+ <configuration>
+ <backend>html5</backend>
+ <outputDirectory>${project.basedir}/docs/swagger</outputDirectory>
+ <outputDirectory>${project.basedir}/src/main/resources/META-INF/resources/</outputDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>output-pdf</id>
+ <phase>post-integration-test</phase>
+ <goals>
+ <goal>process-asciidoc</goal>
+ </goals>
+ <configuration>
+ <backend>pdf</backend>
+ <outputDirectory>${project.basedir}/docs/swagger</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.groovy.maven</groupId>
+ <artifactId>gmaven-plugin</artifactId>
+ <version>1.0</version>
+ <executions>
+ <execution>
+ <id>docker-tags</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>execute</goal>
+ </goals>
+ <configuration>
+ <source>${project.basedir}/src/main/script/TagVersion.groovy</source>
+ </configuration>
+ </execution>
+ <execution>
+ <id>npm-repos-selection</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>execute</goal>
+ </goals>
+ <configuration>
+ <source>${project.basedir}/src/main/script/SelectNpmRepo.groovy</source>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>3.2.0</version>
+ <executions>
+ <execution>
+ <id>jar-with-only-classes</id>
+ <phase>package</phase>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ <configuration>
+ <classifier>classes</classifier>
+ <includes>
+ <include>org/**</include>
+ </includes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>3.2.0</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${project.build.directory}/policy-clamp-backend-classes.jar</file>
+ <type>jar</type>
+ <classifier>classes</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ <execution>
+ <id>reserve-port-for-tests</id>
+ <phase>process-resources</phase>
+ <goals>
+ <goal>reserve-network-port</goal>
+ </goals>
+ <configuration>
+ <portNames>
+ <portName>docker.mariadb.port.host</portName>
+ <portName>docker.http-cache.port.host</portName>
+ <portName>clamp.it.tests.http-redirected</portName>
+ <portName>clamp.it.tests.robotframework.http</portName>
+ <portName>clamp.it.tests.https</portName>
+ <portName>clamp.it.tests.http</portName>
+ </portNames>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${springboot.version}</version>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ <phase>package</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.22.2</version>
+ <configuration>
+ <forkCount>1C</forkCount>
+ <reuseForks>true</reuseForks>
+ <useSystemClassLoader>false</useSystemClassLoader>
+ <argLine>${surefireArgLine}</argLine>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <version>2.22.2</version>
+ <executions>
+ <execution>
+ <id>integration-tests</id>
+ <goals>
+ <goal>integration-test</goal>
+ <goal>verify</goal>
+ </goals>
+ <configuration>
+ <additionalClasspathElements>
+ <additionalClasspathElement>${project.build.directory}/classes
+ </additionalClasspathElement>
+ </additionalClasspathElements>
+ <includes>
+ <include>**/*ItCase.java</include>
+ </includes>
+ <forkCount>1C</forkCount>
+ <reuseForks>true</reuseForks>
+ <useSystemClassLoader>false</useSystemClassLoader>
+ <argLine>${failsafeArgLine}</argLine>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>io.fabric8</groupId>
+ <artifactId>docker-maven-plugin</artifactId>
+ <version>0.35.0</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.5</version>
+ </dependency>
+ </dependencies>
+ <configuration>
+ <verbose>true</verbose>
+ <apiVersion>1.35</apiVersion>
+ <images>
+ <image>
+ <name>docker.io/mariadb:10.5.4</name>
+ <alias>mariadb</alias>
+ <run>
+ <env>
+ <MYSQL_ROOT_PASSWORD>strong_pitchou</MYSQL_ROOT_PASSWORD>
+ </env>
+ <hostname>mariadb</hostname>
+ <volumes>
+ <bind>
+ <volume>${project.basedir}/extra/sql/:/docker-entrypoint-initdb.d:rw</volume>
+ <volume>${project.basedir}/extra/docker/mariadb/conf1:/etc/mysql/conf.d</volume>
+ </bind>
+ </volumes>
+ <wait>
+ <log>port: 3306</log>
+ <time>300000</time>
+ <exec>
+ <preStop>/docker-entrypoint-initdb.d/dump/backup-data-only.sh</preStop>
+ </exec>
+ </wait>
+ <ports>
+ <port>${docker.mariadb.port.host}:3306</port>
+ </ports>
+ <network>
+ <mode>bridge</mode>
+ </network>
+ </run>
+ </image>
+ <image>
+ <name>docker.io/python:2-slim</name>
+ <alias>python</alias>
+ <run>
+ <hostname>python</hostname>
+ <volumes>
+ <bind>
+ <volume>
+ ${project.basedir}/src/test/resources/http-cache/:/usr/src/http-cache-app
+ </volume>
+ <volume>
+ ${project.basedir}/src/test/resources/http-cache/example/:/usr/src/http-cache-app/data-cache
+ </volume>
+ </bind>
+ </volumes>
+ <wait>
+ <tcp>
+ <ports>
+ <port>8080</port>
+ </ports>
+ <mode>direct</mode>
+ </tcp>
+ <time>120000</time>
+ </wait>
+ <ports>
+ <port>${docker.http-cache.port.host}:8080</port>
+ </ports>
+ <workingDir>/usr/src/http-cache-app</workingDir>
+ <cmd>
+ <shell>./start_http_cache.sh ${python.http.proxy.param}
+ --python_proxyaddress=localhost:${docker.http-cache.port.host}
+ </shell>
+ </cmd>
+ <network>
+ <mode>bridge</mode>
+ </network>
+ </run>
+ </image>
+ <image>
+ <name>onap/policy-clamp-backend</name>
+ <alias>onap-policy-clamp-backend</alias>
+ <run>
+ <skip>true</skip>
+ </run>
+ <build>
+ <cleanup>true</cleanup>
+ <tags>
+ <tag>latest</tag>
+ <tag>${project.docker.latesttagtimestamp.version}</tag>
+ <tag>${project.docker.latesttag.version}</tag>
+ </tags>
+ <!-- A relative path is looked up in ${project.basedir}/src/main/docker by
+ default -->
+ <dockerFile>backend/Dockerfile</dockerFile>
+ <assembly>
+ <descriptor>backend/backend-files.xml</descriptor>
+ <name>onap-policy-clamp-backend</name>
+ </assembly>
+ </build>
+ </image>
+ <image>
+ <name>onap/policy-clamp-frontend</name>
+ <alias>onap-policy-clamp-frontend</alias>
+ <run>
+ <skip>true</skip>
+ </run>
+ <build>
+ <cleanup>true</cleanup>
+ <tags>
+ <tag>latest</tag>
+ <tag>${project.docker.latesttagtimestamp.version}</tag>
+ <tag>${project.docker.latesttag.version}</tag>
+ </tags>
+ <!-- A relative path is looked up in ${project.basedir}/src/main/docker by
+ default -->
+ <dockerFile>frontend/Dockerfile</dockerFile>
+ <assembly>
+ <descriptor>frontend/frontend-files.xml</descriptor>
+ <name>onap-policy-clamp-frontend</name>
+ </assembly>
+ </build>
+ </image>
+ </images>
+ </configuration>
+
+ <executions>
+ <execution>
+ <id>generate-images</id>
+ <phase>install</phase>
+ <goals>
+ <goal>build</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>push-images</id>
+ <phase>deploy</phase>
+ <goals>
+ <goal>push</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>docker-start-for-it</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>start</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>docker-stop-for-it</id>
+ <phase>post-integration-test</phase>
+ <goals>
+ <goal>stop</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>0.8.5</version>
+ <configuration>
+ <dumpOnExit>true</dumpOnExit>
+ <append>true</append>
+ <includes>
+ <include>org/onap/policy/clamp/**</include>
+ </includes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>pre-unit-test</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ <configuration>
+ <destFile>${project.build.directory}/coverage-reports/jacoco.exec</destFile>
+ <propertyName>surefireArgLine</propertyName>
+ <!-- <append>true</append> -->
+ </configuration>
+ </execution>
+ <execution>
+ <id>pre-integration-test</id>
+ <phase>pre-integration-test</phase>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ <configuration>
+ <destFile>${project.build.directory}/coverage-reports/jacoco-it.exec</destFile>
+ <propertyName>failsafeArgLine</propertyName>
+ <!-- <append>true</append> -->
+ <!-- Need to overwrite the policy integration parent flag -->
+ <skip>false</skip>
+ </configuration>
+ </execution>
+ <execution>
+ <goals>
+ <goal>merge</goal>
+ </goals>
+ <phase>post-integration-test</phase>
+ <configuration>
+ <fileSets>
+ <fileSet
+ implementation="org.apache.maven.shared.model.fileset.FileSet">
+ <directory>${project.build.directory}/coverage-reports</directory>
+ <includes>
+ <include>*.exec</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+ <destFile>${project.build.directory}/jacoco.exec</destFile>
+ </configuration>
+ </execution>
+ <execution>
+ <id>report-xml</id>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ <configuration>
+ <!-- Setting explicit path, so that we remember where it picks them up from -->
+ <dataFile>${project.build.directory}/jacoco.exec</dataFile>
+ <outputDirectory>${project.build.directory}/jacoco-html-xml-reports</outputDirectory>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+
+ <!-- This plugin will be useful when we will have multi-modules project -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>versions-maven-plugin</artifactId>
+ <version>1.3.1</version>
+ </plugin>
+
+ <plugin>
+ <groupId>com.github.eirslett</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.11.3</version>
+ <configuration>
+ <installDirectory>${project.build.directory}/${ui.react.src}</installDirectory>
+ <npmDownloadRoot>${repo.npm}</npmDownloadRoot>
+ </configuration>
+ <executions>
+ <execution>
+ <id>install_node_and_npm</id>
+ <goals>
+ <goal>install-node-and-npm</goal>
+ </goals>
+ <phase>generate-sources</phase>
+ <configuration>
+ <nodeVersion>v14.16.1</nodeVersion>
+ <npmVersion>6.14.13</npmVersion>
+ </configuration>
+ </execution>
+ <execution>
+ <id>npm_install</id>
+ <goals>
+ <goal>npm</goal>
+ </goals>
+ <phase>compile</phase>
+ <configuration>
+ <workingDirectory>${project.build.directory}/${ui.react.src}</workingDirectory>
+ <arguments>install</arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>npm_test</id>
+ <goals>
+ <goal>npm</goal>
+ </goals>
+ <phase>test</phase>
+ <configuration>
+ <skip>${maven.test.skip}</skip>
+ <arguments>run-script test:coverage</arguments>
+ <workingDirectory>${project.build.directory}/${ui.react.src}</workingDirectory>
+ </configuration>
+ </execution>
+ <execution>
+ <id>npm_install_lib</id>
+ <goals>
+ <goal>npm</goal>
+ </goals>
+ <phase>deploy</phase>
+ <configuration>
+ <workingDirectory>${project.build.directory}/${ui.react.lib.src}</workingDirectory>
+ <arguments>install</arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>npm_build_lib</id>
+ <goals>
+ <goal>npm</goal>
+ </goals>
+ <phase>deploy</phase>
+ <configuration>
+ <workingDirectory>${project.build.directory}/${ui.react.lib.src}</workingDirectory>
+ <arguments>run build</arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>npm_publish</id>
+ <goals>
+ <goal>npm</goal>
+ </goals>
+ <phase>deploy</phase>
+ <configuration>
+ <workingDirectory>${project.build.directory}/${ui.react.lib.src}</workingDirectory>
+ <arguments>publish</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.8.1</version>
+ <configuration>
+ <source>11</source>
+ <target>11</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.sonarsource.scanner.maven</groupId>
+ <artifactId>sonar-maven-plugin</artifactId>
+ <version>3.7.0.1746</version>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <version>1.3.2</version>
+ <executions>
+ <execution>
+ <id>libIndexCheck</id>
+ <phase>validate</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <executable>bash</executable>
+ <arguments>
+ <argument>${project.basedir}/src/main/script/checkLibIndex.sh</argument>
+ </arguments>
+ </configuration>
+ </plugin>
+ <!-- Plugin to generate a X509 Certificate for https tests -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>keytool-maven-plugin</artifactId>
+ <version>1.5</version>
+ <executions>
+ <execution>
+ <id>add-certificate-for-dev</id>
+ <configuration>
+ <keystore>${project.build.directory}/classes/clds/aaf/org.onap.clamp.p12</keystore>
+ <storepass>China in the Spring</storepass>
+ <alias>clamptest</alias>
+ <storetype>PKCS12</storetype>
+ <keyalg>RSA</keyalg>
+ <dname>cn=CN, ou=OU, o=O, c=C</dname>
+ <validity>365</validity>
+ </configuration>
+ <goals>
+ <goal>generateKeyPair</goal>
+ </goals>
+ <phase>generate-resources</phase>
+ </execution>
+ <execution>
+ <id>add-certificate-for-test</id>
+ <configuration>
+ <keystore>${project.build.directory}/test-classes/clds/aaf/org.onap.clamp.p12</keystore>
+ <storepass>China in the Spring</storepass>
+ <alias>clamptest</alias>
+ <storetype>PKCS12</storetype>
+ <keyalg>RSA</keyalg>
+ <dname>cn=CN, ou=OU, o=O, c=C</dname>
+ <validity>365</validity>
+ </configuration>
+ <goals>
+ <goal>generateKeyPair</goal>
+ </goals>
+ <phase>generate-test-resources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/runtime/runtime/src/main/resources/META-INF/resources/swagger.html b/runtime/runtime/src/main/resources/META-INF/resources/swagger.html
new file mode 100644
index 000000000..b6f49a78f
--- /dev/null
+++ b/runtime/runtime/src/main/resources/META-INF/resources/swagger.html
@@ -0,0 +1,454 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 1.5.7.1">
+<title>Untitled</title>
+<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
+<style>
+/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
+/* Uncomment @import statement below to use as custom stylesheet */
+/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
+article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
+audio,canvas,video{display:inline-block}
+audio:not([controls]){display:none;height:0}
+script{display:none!important}
+html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
+a{background:transparent}
+a:focus{outline:thin dotted}
+a:active,a:hover{outline:0}
+h1{font-size:2em;margin:.67em 0}
+abbr[title]{border-bottom:1px dotted}
+b,strong{font-weight:bold}
+dfn{font-style:italic}
+hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
+mark{background:#ff0;color:#000}
+code,kbd,pre,samp{font-family:monospace;font-size:1em}
+pre{white-space:pre-wrap}
+q{quotes:"\201C" "\201D" "\2018" "\2019"}
+small{font-size:80%}
+sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
+sup{top:-.5em}
+sub{bottom:-.25em}
+img{border:0}
+svg:not(:root){overflow:hidden}
+figure{margin:0}
+fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
+legend{border:0;padding:0}
+button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
+button,input{line-height:normal}
+button,select{text-transform:none}
+button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
+button[disabled],html input[disabled]{cursor:default}
+input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
+button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
+textarea{overflow:auto;vertical-align:top}
+table{border-collapse:collapse;border-spacing:0}
+*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
+html,body{font-size:100%}
+body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
+a:hover{cursor:pointer}
+img,object,embed{max-width:100%;height:auto}
+object,embed{height:100%}
+img{-ms-interpolation-mode:bicubic}
+.left{float:left!important}
+.right{float:right!important}
+.text-left{text-align:left!important}
+.text-right{text-align:right!important}
+.text-center{text-align:center!important}
+.text-justify{text-align:justify!important}
+.hide{display:none}
+img,object,svg{display:inline-block;vertical-align:middle}
+textarea{height:auto;min-height:50px}
+select{width:100%}
+.center{margin-left:auto;margin-right:auto}
+.stretch{width:100%}
+.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
+div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
+a{color:#2156a5;text-decoration:underline;line-height:inherit}
+a:hover,a:focus{color:#1d4b8f}
+a img{border:none}
+p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
+p aside{font-size:.875em;line-height:1.35;font-style:italic}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
+h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
+h1{font-size:2.125em}
+h2{font-size:1.6875em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
+h4,h5{font-size:1.125em}
+h6{font-size:1em}
+hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
+em,i{font-style:italic;line-height:inherit}
+strong,b{font-weight:bold;line-height:inherit}
+small{font-size:60%;line-height:inherit}
+code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
+ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
+ul,ol{margin-left:1.5em}
+ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
+ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
+ul.square{list-style-type:square}
+ul.circle{list-style-type:circle}
+ul.disc{list-style-type:disc}
+ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
+dl dt{margin-bottom:.3125em;font-weight:bold}
+dl dd{margin-bottom:1.25em}
+abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
+abbr{text-transform:none}
+blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
+blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
+blockquote cite::before{content:"\2014 \0020"}
+blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
+blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
+@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
+h1{font-size:2.75em}
+h2{font-size:2.3125em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
+h4{font-size:1.4375em}}
+table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
+table thead,table tfoot{background:#f7f8f7}
+table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
+table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
+table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
+table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
+h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
+.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
+.clearfix::after,.float-group::after{clear:both}
+*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}
+*:not(pre)>code.nobreak{word-wrap:normal}
+*:not(pre)>code.nowrap{white-space:nowrap}
+pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
+em em{font-style:normal}
+strong strong{font-weight:400}
+.keyseq{color:rgba(51,51,51,.8)}
+kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
+.keyseq kbd:first-child{margin-left:0}
+.keyseq kbd:last-child{margin-right:0}
+.menuseq,.menuref{color:#000}
+.menuseq b:not(.caret),.menuref{font-weight:inherit}
+.menuseq{word-spacing:-.02em}
+.menuseq b.caret{font-size:1.25em;line-height:.8}
+.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
+b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
+b.button::before{content:"[";padding:0 3px 0 2px}
+b.button::after{content:"]";padding:0 2px 0 3px}
+p a>code:hover{color:rgba(0,0,0,.9)}
+#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
+#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
+#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
+#content{margin-top:1.25em}
+#content::before{content:none}
+#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
+#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
+#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
+#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
+#header .details span:first-child{margin-left:-.125em}
+#header .details span.email a{color:rgba(0,0,0,.85)}
+#header .details br{display:none}
+#header .details br+span::before{content:"\00a0\2013\00a0"}
+#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
+#header .details br+span#revremark::before{content:"\00a0|\00a0"}
+#header #revnumber{text-transform:capitalize}
+#header #revnumber::after{content:"\00a0"}
+#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
+#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
+#toc>ul{margin-left:.125em}
+#toc ul.sectlevel0>li>a{font-style:italic}
+#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
+#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
+#toc li{line-height:1.3334;margin-top:.3334em}
+#toc a{text-decoration:none}
+#toc a:active{text-decoration:underline}
+#toctitle{color:#7a2518;font-size:1.2em}
+@media screen and (min-width:768px){#toctitle{font-size:1.375em}
+body.toc2{padding-left:15em;padding-right:0}
+#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
+#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
+#toc.toc2>ul{font-size:.9em;margin-bottom:0}
+#toc.toc2 ul ul{margin-left:0;padding-left:1em}
+#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
+body.toc2.toc-right{padding-left:0;padding-right:15em}
+body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
+@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
+#toc.toc2{width:20em}
+#toc.toc2 #toctitle{font-size:1.375em}
+#toc.toc2>ul{font-size:.95em}
+#toc.toc2 ul ul{padding-left:1.25em}
+body.toc2.toc-right{padding-left:0;padding-right:20em}}
+#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
+#content #toc>:first-child{margin-top:0}
+#content #toc>:last-child{margin-bottom:0}
+#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
+#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
+#content{margin-bottom:.625em}
+.sect1{padding-bottom:.625em}
+@media screen and (min-width:768px){#content{margin-bottom:1.25em}
+.sect1{padding-bottom:1.25em}}
+.sect1:last-child{padding-bottom:0}
+.sect1+.sect1{border-top:1px solid #efefed}
+#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
+#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
+#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
+#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
+#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
+.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
+.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
+table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
+.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
+table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit}
+.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
+.admonitionblock>table td.icon{text-align:center;width:80px}
+.admonitionblock>table td.icon img{max-width:none}
+.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
+.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
+.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
+.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
+.exampleblock>.content>:first-child{margin-top:0}
+.exampleblock>.content>:last-child{margin-bottom:0}
+.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
+.sidebarblock>:first-child{margin-top:0}
+.sidebarblock>:last-child{margin-bottom:0}
+.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
+.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
+.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
+.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
+.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
+.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
+@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
+@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
+.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
+.listingblock pre.highlightjs{padding:0}
+.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
+.listingblock pre.prettyprint{border-width:0}
+.listingblock>.content{position:relative}
+.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
+.listingblock:hover code[data-lang]::before{display:block}
+.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999}
+.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
+table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
+table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
+table.pyhltable td.code{padding-left:.75em;padding-right:0}
+pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
+pre.pygments .lineno{display:inline-block;margin-right:.25em}
+table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
+.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
+.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
+.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
+.quoteblock blockquote{margin:0;padding:0;border:0}
+.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
+.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
+.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
+.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
+.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
+.quoteblock .quoteblock blockquote::before{display:none}
+.verseblock{margin:0 1em 1.25em}
+.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
+.verseblock pre strong{font-weight:400}
+.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
+.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
+.quoteblock .attribution br,.verseblock .attribution br{display:none}
+.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
+.quoteblock.abstract{margin:0 1em 1.25em;display:block}
+.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
+.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{word-spacing:0;line-height:1.6}
+.quoteblock.abstract blockquote::before,.quoteblock.abstract p::before{display:none}
+table.tableblock{max-width:100%;border-collapse:separate}
+p.tableblock:last-child{margin-bottom:0}
+td.tableblock>.content{margin-bottom:-1.25em}
+table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
+table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}
+table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}
+table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}
+table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px}
+table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0}
+table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}
+table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
+table.frame-all{border-width:1px}
+table.frame-sides{border-width:0 1px}
+table.frame-topbot,table.frame-ends{border-width:1px 0}
+table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7}
+table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none}
+th.halign-left,td.halign-left{text-align:left}
+th.halign-right,td.halign-right{text-align:right}
+th.halign-center,td.halign-center{text-align:center}
+th.valign-top,td.valign-top{vertical-align:top}
+th.valign-bottom,td.valign-bottom{vertical-align:bottom}
+th.valign-middle,td.valign-middle{vertical-align:middle}
+table thead th,table tfoot th{font-weight:bold}
+tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
+tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
+p.tableblock>code:only-child{background:none;padding:0}
+p.tableblock{font-size:1em}
+td>div.verse{white-space:pre}
+ol{margin-left:1.75em}
+ul li ol{margin-left:1.5em}
+dl dd{margin-left:1.125em}
+dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
+ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
+ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
+ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
+ul.unstyled,ol.unstyled{margin-left:0}
+ul.checklist{margin-left:.625em}
+ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
+ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}
+ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
+ul.inline>li{margin-left:1.25em}
+.unstyled dl dt{font-weight:400;font-style:normal}
+ol.arabic{list-style-type:decimal}
+ol.decimal{list-style-type:decimal-leading-zero}
+ol.loweralpha{list-style-type:lower-alpha}
+ol.upperalpha{list-style-type:upper-alpha}
+ol.lowerroman{list-style-type:lower-roman}
+ol.upperroman{list-style-type:upper-roman}
+ol.lowergreek{list-style-type:lower-greek}
+.hdlist>table,.colist>table{border:0;background:none}
+.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
+td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
+td.hdlist1{font-weight:bold;padding-bottom:1.25em}
+.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
+.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
+.colist td:not([class]):first-child img{max-width:none}
+.colist td:not([class]):last-child{padding:.25em 0}
+.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
+.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
+.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
+.imageblock>.title{margin-bottom:0}
+.imageblock.thumb,.imageblock.th{border-width:6px}
+.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
+.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
+.image.left{margin-right:.625em}
+.image.right{margin-left:.625em}
+a.image{text-decoration:none;display:inline-block}
+a.image object{pointer-events:none}
+sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
+sup.footnote a,sup.footnoteref a{text-decoration:none}
+sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
+#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
+#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
+#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
+#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
+#footnotes .footnote:last-of-type{margin-bottom:0}
+#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
+.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
+.gist .file-data>table td.line-data{width:99%}
+div.unbreakable{page-break-inside:avoid}
+.big{font-size:larger}
+.small{font-size:smaller}
+.underline{text-decoration:underline}
+.overline{text-decoration:overline}
+.line-through{text-decoration:line-through}
+.aqua{color:#00bfbf}
+.aqua-background{background-color:#00fafa}
+.black{color:#000}
+.black-background{background-color:#000}
+.blue{color:#0000bf}
+.blue-background{background-color:#0000fa}
+.fuchsia{color:#bf00bf}
+.fuchsia-background{background-color:#fa00fa}
+.gray{color:#606060}
+.gray-background{background-color:#7d7d7d}
+.green{color:#006000}
+.green-background{background-color:#007d00}
+.lime{color:#00bf00}
+.lime-background{background-color:#00fa00}
+.maroon{color:#600000}
+.maroon-background{background-color:#7d0000}
+.navy{color:#000060}
+.navy-background{background-color:#00007d}
+.olive{color:#606000}
+.olive-background{background-color:#7d7d00}
+.purple{color:#600060}
+.purple-background{background-color:#7d007d}
+.red{color:#bf0000}
+.red-background{background-color:#fa0000}
+.silver{color:#909090}
+.silver-background{background-color:#bcbcbc}
+.teal{color:#006060}
+.teal-background{background-color:#007d7d}
+.white{color:#bfbfbf}
+.white-background{background-color:#fafafa}
+.yellow{color:#bfbf00}
+.yellow-background{background-color:#fafa00}
+span.icon>.fa{cursor:default}
+a span.icon>.fa{cursor:inherit}
+.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
+.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
+.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
+.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
+.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
+.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
+.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
+.conum[data-value] *{color:#fff!important}
+.conum[data-value]+b{display:none}
+.conum[data-value]::after{content:attr(data-value)}
+pre .conum[data-value]{position:relative;top:-.125em}
+b.conum *{color:inherit!important}
+.conum:not([data-value]):empty{display:none}
+dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
+h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
+p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
+p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
+p{margin-bottom:1.25rem}
+.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
+.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
+.print-only{display:none!important}
+@page{margin:1.25cm .75cm}
+@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
+html{font-size:80%}
+a{color:inherit!important;text-decoration:underline!important}
+a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
+a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
+abbr[title]::after{content:" (" attr(title) ")"}
+pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
+thead{display:table-header-group}
+svg{max-width:100%}
+p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
+h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
+#toc,.sidebarblock,.exampleblock>.content{background:none!important}
+#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
+body.book #header{text-align:center}
+body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
+body.book #header .details{border:0!important;display:block;padding:0!important}
+body.book #header .details span:first-child{margin-left:0!important}
+body.book #header .details br{display:block}
+body.book #header .details br+span::before{content:none!important}
+body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
+body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
+.listingblock code[data-lang]::before{display:block}
+#footer{padding:0 .9375em}
+.hide-on-print{display:none!important}
+.print-only{display:block!important}
+.hide-for-print{display:none!important}
+.show-for-print{display:inherit!important}}
+@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem}
+.sect1{padding:0!important}
+.sect1+.sect1{border:0}
+#footer{background:none}
+#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
+@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
+</style>
+</head>
+<body class="book">
+<div id="header">
+</div>
+<div id="content">
+<div id="preamble">
+<div class="sectionbody">
+<div class="paragraph">
+<p>Unresolved directive in swagger.adoc - include::~\clamp\runtime\target/asciidoc/generated/overview.adoc[]<br>
+Unresolved directive in swagger.adoc - include::~\clamp\runtime\target/asciidoc/generated/paths.adoc[]<br>
+Unresolved directive in swagger.adoc - include::~\clamp\runtime\target/asciidoc/generated/security.adoc[]<br>
+Unresolved directive in swagger.adoc - include::~\clamp\runtime\target/asciidoc/generated/definitions.adoc[]</p>
+</div>
+</div>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2021-05-06 17:18:25 BST
+</div>
+</div>
+</body>
+</html>
diff --git a/runtime/src/main/docker/backend/Dockerfile b/runtime/src/main/docker/backend/Dockerfile
new file mode 100644
index 000000000..bb964158e
--- /dev/null
+++ b/runtime/src/main/docker/backend/Dockerfile
@@ -0,0 +1,53 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2018, 2021 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+FROM onap/integration-java11:8.0.0
+
+MAINTAINER "The Onap Team"
+LABEL Description="This image contains alpine, openjdk 11 and policy clamp"
+
+ARG http_proxy
+ARG https_proxy
+ENV HTTP_PROXY=$http_proxy
+ENV HTTPS_PROXY=$https_proxy
+ENV http_proxy=$HTTP_PROXY
+ENV https_proxy=$HTTPS_PROXY
+
+USER root
+
+RUN mkdir -p /opt/policy/clamp && \
+ chown -R onap:onap /opt/policy/clamp
+
+VOLUME /opt/policy/clamp/config
+
+COPY --chown=onap:onap onap-policy-clamp-backend/policy-clamp-backend.jar /opt/policy/clamp/policy-clamp-backend.jar
+RUN set -x && \
+ apk add --update libintl && \
+ apk add --virtual build_deps gettext && \
+ cp /usr/bin/envsubst /usr/local/bin/envsubst && \
+ apk del build_deps
+
+USER onap
+WORKDIR /opt/policy/clamp/
+ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-XX:MinRAMPercentage=50.0", "-XX:MaxRAMPercentage=75.0","-jar" ,"./policy-clamp-backend.jar"]
+
diff --git a/runtime/src/main/docker/backend/backend-files.xml b/runtime/src/main/docker/backend/backend-files.xml
new file mode 100644
index 000000000..c73c47f64
--- /dev/null
+++ b/runtime/src/main/docker/backend/backend-files.xml
@@ -0,0 +1,43 @@
+<!--
+ ============LICENSE_START=======================================================
+ ECOMP CLAMP
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1 http://maven.apache.org/xsd/assembly-1.1.1.xsd">
+ <id>clamp-files</id>
+
+ <formats>
+ <format>tar.gz</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <!-- include config files -->
+ <fileSet>
+ <includes>
+ <include>${project.build.finalName}.jar</include>
+ </includes>
+ <directory>${project.build.directory}</directory>
+ <outputDirectory></outputDirectory>
+ </fileSet>
+ </fileSets>
+
+</assembly>
diff --git a/runtime/src/main/docker/frontend/Dockerfile b/runtime/src/main/docker/frontend/Dockerfile
new file mode 100644
index 000000000..1d64d2a2d
--- /dev/null
+++ b/runtime/src/main/docker/frontend/Dockerfile
@@ -0,0 +1,71 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+# build environment
+FROM node:12.10.0-alpine as build
+WORKDIR /app
+#ENV PATH /app/node_modules/.bin:$PATH
+COPY onap-policy-clamp-frontend/ /app/
+RUN npm install --silent && \
+ npm run build
+
+FROM nginx:1.17.0-alpine
+
+MAINTAINER "The Onap Team"
+LABEL Description="This image contains Clamp frontend"
+
+ARG http_proxy
+ARG https_proxy
+ENV HTTP_PROXY=$http_proxy
+ENV HTTPS_PROXY=$https_proxy
+ENV http_proxy=$HTTP_PROXY
+ENV https_proxy=$HTTPS_PROXY
+
+RUN addgroup onap && \
+ adduser -D -G onap clamp && \
+ mkdir /var/log/onap && \
+ chmod a+rwx /var/log/onap
+
+COPY --from=build /app/build /usr/share/nginx/html
+COPY --from=build /app/ssl /etc/ssl
+
+RUN rm /etc/nginx/conf.d/default.conf && \
+ ln -sf /dev/stdout /var/log/nginx/access.log && \
+ ln -sf /dev/stderr /var/log/nginx/error.log
+
+COPY nginx/nginx.conf /etc/nginx/nginx.conf
+COPY nginx/default.conf /etc/nginx/conf.d/default.conf
+
+WORKDIR /app
+
+RUN chown -R clamp:onap /app && chmod -R 755 /app && \
+ chown -R clamp:onap /var/cache/nginx && \
+ chown -R clamp:onap /var/log/nginx && \
+ chown -R clamp:onap /etc/nginx/conf.d && \
+ touch /var/run/nginx.pid && \
+ chown -R clamp:onap /var/run/nginx.pid
+
+USER clamp
+EXPOSE 2443
+CMD ["nginx", "-g", "daemon off;"]
+
diff --git a/runtime/src/main/docker/frontend/frontend-files.xml b/runtime/src/main/docker/frontend/frontend-files.xml
new file mode 100644
index 000000000..aaf32be81
--- /dev/null
+++ b/runtime/src/main/docker/frontend/frontend-files.xml
@@ -0,0 +1,48 @@
+<!--
+ ============LICENSE_START=======================================================
+ ECOMP CLAMP
+ ================================================================================
+ Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ ============LICENSE_END=========================================================
+ -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.1 http://maven.apache.org/xsd/assembly-1.1.1.xsd">
+ <id>clamp-files</id>
+
+ <formats>
+ <format>tar.gz</format>
+ </formats>
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <!-- include config files -->
+ <fileSet>
+ <excludes>
+ <exclude>node_modules</exclude>
+ </excludes>
+ <directory>${project.build.directory}/${ui.react.src}</directory>
+ <outputDirectory></outputDirectory>
+ </fileSet>
+ <!-- include ssl certificates files obtain from aaf p12 -->
+ <fileSet>
+ <directory>${project.basedir}/src/main/resources/clds/aaf/ssl</directory>
+ <outputDirectory>ssl</outputDirectory>
+ </fileSet>
+ </fileSets>
+
+</assembly>
diff --git a/runtime/src/main/docker/frontend/nginx/default.conf b/runtime/src/main/docker/frontend/nginx/default.conf
new file mode 100644
index 000000000..570806034
--- /dev/null
+++ b/runtime/src/main/docker/frontend/nginx/default.conf
@@ -0,0 +1,25 @@
+server {
+
+ listen 2443 default ssl;
+ ssl_protocols TLSv1.2;
+ ssl_certificate /etc/ssl/clamp.pem;
+ ssl_certificate_key /etc/ssl/clamp.key;
+ ssl_verify_client optional_no_ca;
+ location /restservices/clds/ {
+ proxy_pass https://policy-clamp-backend:8443;
+ proxy_set_header X-SSL-Cert $ssl_client_escaped_cert;
+ }
+
+ location / {
+ root /usr/share/nginx/html;
+ index index.html index.htm;
+ try_files $uri $uri/ /index.html;
+ }
+
+ error_page 500 502 503 504 /50x.html;
+
+ location = /50x.html {
+ root /usr/share/nginx/html;
+ }
+
+} \ No newline at end of file
diff --git a/runtime/src/main/docker/frontend/nginx/nginx.conf b/runtime/src/main/docker/frontend/nginx/nginx.conf
new file mode 100644
index 000000000..beeb2b1eb
--- /dev/null
+++ b/runtime/src/main/docker/frontend/nginx/nginx.conf
@@ -0,0 +1,18 @@
+worker_processes 1;
+pid /var/run/nginx.pid;
+error_log /dev/stdout info;
+events {
+}
+http {
+ include /etc/nginx/mime.types;
+ default_type application/octet-stream;
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
+ '$status $body_bytes_sent "$http_referer" '
+ '"$http_user_agent" "$http_x_forwarded_for"';
+ access_log /var/log/nginx/access.log main;
+ sendfile on;
+ #tcp_nopush on;
+ keepalive_timeout 65;
+ #gzip on;
+ include /etc/nginx/conf.d/*.conf;
+ } \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/authorization/AuthorizationController.java b/runtime/src/main/java/org/onap/policy/clamp/authorization/AuthorizationController.java
new file mode 100644
index 000000000..89be4fc28
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/authorization/AuthorizationController.java
@@ -0,0 +1,182 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.authorization;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.util.Date;
+import org.apache.camel.Exchange;
+import org.onap.policy.clamp.clds.config.ClampProperties;
+import org.onap.policy.clamp.clds.exception.NotAuthorizedException;
+import org.onap.policy.clamp.clds.model.ClampInformation;
+import org.onap.policy.clamp.clds.util.LoggingUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.stereotype.Component;
+
+/**
+ * Verify user has right permissions.
+ */
+@Component
+public class AuthorizationController {
+
+ protected static final EELFLogger logger =
+ EELFManager.getInstance().getLogger(AuthorizationController.class);
+ protected static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger();
+ protected static final EELFLogger securityLogger = EELFManager.getInstance().getSecurityLogger();
+
+ // By default we'll set it to a default handler
+ @Autowired
+ private ClampProperties refProp;
+
+ public static final String PERM_PREFIX = "security.permission.type.";
+ private static final String PERM_INSTANCE = "security.permission.instance";
+
+ private static String retrieveUserName(SecurityContext securityContext) {
+ if (securityContext == null || securityContext.getAuthentication() == null) {
+ return null;
+ }
+ if ((securityContext.getAuthentication().getPrincipal()) instanceof String) {
+ // anonymous case
+ return ((String) securityContext.getAuthentication().getPrincipal());
+ } else {
+ return ((UserDetails) securityContext.getAuthentication().getPrincipal()).getUsername();
+ }
+ }
+
+ /**
+ * Get the principal name.
+ *
+ * @return The principal name
+ */
+ public static String getPrincipalName(SecurityContext securityContext) {
+ String principal = AuthorizationController.retrieveUserName(securityContext);
+ return principal != null ? principal : "Not found";
+ }
+
+ /**
+ * Insert authorize the api based on the permission.
+ *
+ * @param camelExchange The Camel Exchange object containing the properties
+ * @param typeVar The type of the permissions
+ * @param instanceVar The instance of the permissions. e.g. dev
+ * @param action The action of the permissions. e.g. read
+ */
+ public void authorize(Exchange camelExchange, String typeVar, String instanceVar,
+ String action) {
+ String type = refProp.getStringValue(PERM_PREFIX + typeVar);
+ String instance = refProp.getStringValue(PERM_INSTANCE);
+
+ if (null == type || type.isEmpty()) {
+ // authorization is turned off, since the permission is not defined
+ return;
+ }
+ if (null != instanceVar && !instanceVar.isEmpty()) {
+ instance = instanceVar;
+ }
+ String principalName = AuthorizationController.getPrincipalName(SecurityContextHolder.getContext());
+ SecureServicePermission perm = SecureServicePermission.create(type, instance, action);
+ Date startTime = new Date();
+ LoggingUtils.setTargetContext("Clamp", "authorize");
+ LoggingUtils.setTimeContext(startTime, new Date());
+ securityLogger.debug("checking if {} has permission: {}", principalName, perm);
+
+ if (!isUserPermitted(perm)) {
+ String msg = principalName + " does not have permission: " + perm;
+ LoggingUtils.setErrorContext("100", "Authorization Error");
+ securityLogger.warn(msg);
+ throw new NotAuthorizedException(msg);
+ }
+ }
+
+ /**
+ * Insert authorize the api based on the permission.
+ *
+ * @param inPermission Security permission in input
+ * @return True if user is permitted
+ */
+ public boolean isUserPermitted(SecureServicePermission inPermission) {
+
+ String principalName = AuthorizationController.getPrincipalName(SecurityContextHolder.getContext());
+ // check if the user has the permission key or the permission key with a
+ // combination of all instance and/or all action.
+ if (hasRole(inPermission.getKey()) || hasRole(inPermission.getKeyAllInstance())) {
+ auditLogger.info("{} authorized because user has permission with * for instance: {}",
+ principalName, inPermission.getKey().replace("|", ":"));
+ return true;
+ // the rest of these don't seem to be required - isUserInRole method
+ // appears to take * as a wildcard
+ } else if (hasRole(inPermission.getKeyAllInstanceAction())) {
+ auditLogger.info(
+ "{} authorized because user has permission with * for instance and * for action: {}",
+ principalName, inPermission.getKey().replace("|", ":"));
+ return true;
+ } else if (hasRole(inPermission.getKeyAllAction())) {
+ auditLogger.info("{} authorized because user has permission with * for action: {}",
+ principalName, inPermission.getKey().replace("|", ":"));
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ protected boolean hasRole(String role) {
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (authentication == null) {
+ return false;
+ }
+ for (GrantedAuthority auth : authentication.getAuthorities()) {
+ if (role.equals(auth.getAuthority())) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Gets clds info. CLDS IFO service will return 3 things 1. User Name 2. CLDS
+ * code version that is currently installed from pom.xml file 3. User
+ * permissions
+ *
+ * @return the clds info
+ */
+ public ClampInformation getClampInformation() {
+ ClampInformation clampInfo = new ClampInformation();
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+ if (authentication == null) {
+ return new ClampInformation();
+ }
+ clampInfo.setUserName(AuthorizationController.getPrincipalName(SecurityContextHolder.getContext()));
+ for (GrantedAuthority auth : authentication.getAuthorities()) {
+ clampInfo.getAllPermissions().add(auth.getAuthority());
+ }
+ return clampInfo;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/authorization/CldsUser.java b/runtime/src/main/java/org/onap/policy/clamp/authorization/CldsUser.java
new file mode 100644
index 000000000..8f1e2bf67
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/authorization/CldsUser.java
@@ -0,0 +1,97 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.authorization;
+
+import java.util.Arrays;
+
+/**
+ * The class represents the CldsUser that can be extracted from cldsusers.json.
+ */
+public class CldsUser {
+
+ private String user;
+ private String password;
+ private SecureServicePermission[] permissions;
+
+ /**
+ * Returns the user.
+ *
+ * @return the user
+ */
+ public String getUser() {
+ return user;
+ }
+
+ /**
+ * Sets the user.
+ *
+ * @param user
+ * the user to set
+ */
+ public void setUser(String user) {
+ this.user = user;
+ }
+
+ /**
+ * Returns the password.
+ *
+ * @return the password
+ */
+ public String getPassword() {
+ return password;
+ }
+
+ /**
+ * Sets the password.
+ *
+ * @param password
+ * the password to set
+ */
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ /**
+ * Returns the permissions.
+ *
+ * @return the permissions
+ */
+ public SecureServicePermission[] getPermissions() {
+ return Arrays.copyOf(permissions, permissions.length);
+ }
+
+ public String[] getPermissionsString() {
+ return Arrays.stream(getPermissions()).map(SecureServicePermission::getKey).toArray(String[]::new);
+ }
+
+ /**
+ * Sets the permissions.
+ *
+ * @param permissionsArray
+ * the permissions to set
+ */
+ public void setPermissions(SecureServicePermission[] permissionsArray) {
+ this.permissions = Arrays.copyOf(permissionsArray, permissionsArray.length);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/authorization/SecureServicePermission.java b/runtime/src/main/java/org/onap/policy/clamp/authorization/SecureServicePermission.java
new file mode 100644
index 000000000..41887a315
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/authorization/SecureServicePermission.java
@@ -0,0 +1,203 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.authorization;
+
+/**
+ * Permission class that can be instantiated easily using constructor or factory
+ * methods.
+ */
+public class SecureServicePermission {
+ public static final String ALL = "*";
+
+ private String type;
+ private String instance;
+ private String action;
+
+ /**
+ * Factory method to create permission given type, instance, and action.
+ *
+ * @param type type of the permission
+ * @param instance instance of the permission
+ * @param action action of the permission
+ * @return instance of SecureServicePermission with type, instance and action
+ */
+ public static SecureServicePermission create(String type, String instance, String action) {
+ return new SecureServicePermission(type, instance, action);
+ }
+
+ /**
+ * Factory method to create permission given type and instance. Default
+ * action to ALL/*.
+ *
+ * @param type type of the permission
+ * @param instance instance of the permission
+ * @return instance of SecureServicePermission with type, instance and default action
+ */
+ public static SecureServicePermission create(String type, String instance) {
+ return new SecureServicePermission(type, instance, ALL);
+ }
+
+ /**
+ * Factory method to create permission given type. Default instance and
+ * action to ALL/*.
+ *
+ * @param type type of the permission
+ * @return instance of SecureServicePermission with type and default instance and action
+ */
+ public static SecureServicePermission create(String type) {
+ return new SecureServicePermission(type, ALL, ALL);
+ }
+
+ /**
+ * Instantiate permission given type, instance, and action.
+ *
+ * @param type type of the permission
+ * @param instance instance of the permission
+ * @param action action of the permission
+ */
+ public SecureServicePermission(String type, String instance, String action) {
+ this.type = type;
+ this.instance = instance;
+ this.action = action;
+ }
+
+ /**
+ * Instantiate permission given type from concatenated string.
+ *
+ * @param concatenatedString
+ * the string type|instance|action, less than 3 params can be
+ * provided (e.g. "permission-type-cl", "permission-type-cl|dev",
+ * "permission-type-cl|dev|update" )
+ */
+ public SecureServicePermission(String concatenatedString) {
+ String[] userInfo = concatenatedString.split("[|]");
+ // We should have at least 1 string
+ this.type = userInfo[0];
+ this.instance = (userInfo.length > 1 ? userInfo[1] : ALL);
+ this.action = (userInfo.length > 2 ? userInfo[2] : ALL);
+ }
+
+ /**
+ * Override toString - return permission in key format.
+ */
+ @Override
+ public String toString() {
+ return getKey();
+ }
+
+ /**
+ * Return Permission in Key format = type, instance, and action separate by
+ * pipe character.
+ *
+ * @return permission in key format
+ */
+ public String getKey() {
+ return type + "|" + instance + "|" + action;
+ }
+
+ /**
+ * Return Permission in Key format = type, all instance, and action separate
+ * by pipe character.
+ *
+ * @return permission in key format
+ */
+ public String getKeyAllInstance() {
+ return type + "|" + ALL + "|" + action;
+ }
+
+ /**
+ * Return Permission in Key format = type, all instance, and all action
+ * separate by pipe character.
+ *
+ * @return permission in key format
+ */
+ public String getKeyAllInstanceAction() {
+ return type + "|" + ALL + "|" + ALL;
+ }
+
+ /**
+ * Return Permission in Key format = type, instance, and all action separate
+ * by pipe character.
+ *
+ * @return permission in key format
+ */
+ public String getKeyAllAction() {
+ return type + "|" + instance + "|" + ALL;
+ }
+
+ /**
+ * Returns the permission type.
+ *
+ * @return the type
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * Sets the type of permission.
+ *
+ * @param type the type to set
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * Returns the instance of permission.
+ *
+ * @return the instance
+ */
+ public String getInstance() {
+ return instance;
+ }
+
+ /**
+ * Sets the instance of permission.
+ *
+ * @param instance the instance to set
+ */
+ public void setInstance(String instance) {
+ this.instance = instance;
+ }
+
+ /**
+ * Returns the action of permission.
+ *
+ * @return the action
+ */
+ public String getAction() {
+ return action;
+ }
+
+ /**
+ * Sets the action of permission.
+ *
+ * @param action the action to set
+ */
+ public void setAction(String action) {
+ this.action = action;
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/authorization/SecureServicePermissionDeserializer.java b/runtime/src/main/java/org/onap/policy/clamp/authorization/SecureServicePermissionDeserializer.java
new file mode 100644
index 000000000..0b178c256
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/authorization/SecureServicePermissionDeserializer.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.authorization;
+
+
+import com.google.gson.Gson;
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import java.lang.reflect.Type;
+
+public class SecureServicePermissionDeserializer implements JsonDeserializer<SecureServicePermission> {
+
+ @Override
+ public SecureServicePermission deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
+ throws JsonParseException {
+ if (json.isJsonPrimitive()) {
+ return new SecureServicePermission(json.getAsString());
+ } else {
+ // if not string try default deserialization
+ return new Gson().fromJson(json, SecureServicePermission.class);
+ }
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/authorization/UserService.java b/runtime/src/main/java/org/onap/policy/clamp/authorization/UserService.java
new file mode 100644
index 000000000..96347f82f
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/authorization/UserService.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ */
+
+package org.onap.policy.clamp.authorization;
+
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Controller;
+
+/**
+ * User service used for authorization verification at the login page. Do not
+ * remove this class.
+ */
+@Controller
+public class UserService {
+
+ /**
+ * REST service that returns the username.
+ *
+ * @return the user name
+ */
+ public String getUser() {
+ return AuthorizationController.getPrincipalName(SecurityContextHolder.getContext());
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/Application.java b/runtime/src/main/java/org/onap/policy/clamp/clds/Application.java
new file mode 100644
index 000000000..ba300ac09
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/Application.java
@@ -0,0 +1,195 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+import org.apache.camel.component.servlet.springboot.ServletMappingAutoConfiguration;
+import org.apache.catalina.connector.Connector;
+import org.onap.policy.clamp.clds.util.ClampVersioning;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.util.PassDecoder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.domain.EntityScan;
+import org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration;
+import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration;
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.core.env.Environment;
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
+import org.springframework.scheduling.annotation.EnableAsync;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.transaction.annotation.EnableTransactionManagement;
+
+@ComponentScan(basePackages = {"org.onap.policy.clamp"})
+@SpringBootApplication(exclude = {SecurityAutoConfiguration.class, UserDetailsServiceAutoConfiguration.class,
+ ServletMappingAutoConfiguration.class})
+@EnableJpaRepositories(basePackages = {"org.onap.policy.clamp"})
+@EntityScan(basePackages = {"org.onap.policy.clamp"})
+@EnableTransactionManagement
+@EnableConfigurationProperties
+@EnableAsync
+@EnableScheduling
+@EnableJpaAuditing
+public class Application extends SpringBootServletInitializer {
+
+ protected static final EELFLogger eelfLogger = EELFManager.getInstance().getLogger(Application.class);
+ // This settings is an additional one to Spring config,
+ // only if we want to have an additional port automatically redirected to
+ // HTTPS
+ @Value("${server.http-to-https-redirection.port:#{null}}")
+ private String httpRedirectedPort;
+ /**
+ * This 8080 is the default port used by spring if this parameter is not
+ * specified in application.properties.
+ */
+ @Value("${server.port:8080}")
+ private String springServerPort;
+
+ @Value("${server.ssl.key-store:#{null}}")
+ private String keystoreFile;
+
+ @Value("${server.ssl.key-store-password:#{null}}")
+ private String keyStorePass;
+
+ @Value("${server.ssl.key-store-type:JKS}")
+ private String keyStoreType;
+
+
+ @Value("${clamp.config.keyFile:classpath:/clds/aaf/org.onap.clamp.keyfile}")
+ private String keyFile;
+
+ @Autowired
+ private Environment env;
+
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
+ return application.sources(Application.class);
+ }
+
+ /**
+ * Main method that starts the Clamp backend.
+ *
+ * @param args app params
+ */
+ public static void main(String[] args) {
+ // Start the Spring application
+ SpringApplication.run(Application.class, args);
+ }
+
+ /**
+ * This method is used to declare the camel servlet.
+ *
+ * @return A servlet bean
+ * @throws IOException IO Exception
+ */
+ @Bean
+ public ServletRegistrationBean camelServletRegistrationBean() throws IOException {
+ eelfLogger.info(ResourceFileUtils.getResourceAsString("boot-message.txt") + "(v"
+ + ClampVersioning.getCldsVersionFromProps() + ")" + System.getProperty("line.separator")
+ + getSslExpirationDate());
+ ServletRegistrationBean registration = new ServletRegistrationBean(new ClampServlet(), "/restservices/clds/*");
+ registration.setName("CamelServlet");
+ return registration;
+ }
+
+ /**
+ * This method is used by Spring to create the servlet container factory.
+ *
+ * @return The TomcatEmbeddedServletContainerFactory just created
+ */
+ @Bean
+ public ServletWebServerFactory getEmbeddedServletContainerFactory() {
+ TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
+ if (httpRedirectedPort != null && keystoreFile != null) {
+ // Automatically redirect to HTTPS
+ tomcat = new TomcatEmbeddedServletContainerFactoryRedirection();
+ Connector newConnector = createRedirectConnector(Integer.parseInt(springServerPort));
+ if (newConnector != null) {
+ tomcat.addAdditionalTomcatConnectors(newConnector);
+ }
+ }
+ return tomcat;
+ }
+
+ private Connector createRedirectConnector(int redirectSecuredPort) {
+ if (redirectSecuredPort <= 0) {
+ eelfLogger.warn("HTTP port redirection to HTTPS is disabled because the HTTPS port is 0 (random port) or -1"
+ + " (Connector disabled)");
+ return null;
+ }
+ Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
+ connector.setScheme("http");
+ connector.setSecure(false);
+ connector.setPort(Integer.parseInt(httpRedirectedPort));
+ connector.setRedirectPort(redirectSecuredPort);
+ return connector;
+ }
+
+ private String getSslExpirationDate() throws IOException {
+ StringBuilder result = new StringBuilder(" :: SSL Certificates :: ");
+ try {
+ if (keystoreFile != null) {
+ KeyStore keystore = KeyStore.getInstance(keyStoreType);
+ keystore.load(ResourceFileUtils.getResourceAsStream(keystoreFile.replace("classpath:", "")),
+ PassDecoder.decode(keyStorePass, keyFile).toCharArray());
+
+ Enumeration<String> aliases = keystore.aliases();
+ while (aliases.hasMoreElements()) {
+ String alias = aliases.nextElement();
+ if ("X.509".equals(keystore.getCertificate(alias).getType())) {
+ result.append("* " + alias + " expires "
+ + ((X509Certificate) keystore.getCertificate(alias)).getNotAfter()
+ + System.getProperty("line.separator"));
+ }
+ }
+ } else {
+ result.append("* NONE HAS been configured");
+ }
+ } catch (CertificateException | NoSuchAlgorithmException | KeyStoreException e) {
+ eelfLogger.warn("SSL certificate access error ", e);
+
+ }
+ return result.toString();
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/ClampInUserAuditorAware.java b/runtime/src/main/java/org/onap/policy/clamp/clds/ClampInUserAuditorAware.java
new file mode 100644
index 000000000..939cea49c
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/ClampInUserAuditorAware.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds;
+
+import java.util.Optional;
+import org.onap.policy.clamp.authorization.AuthorizationController;
+import org.springframework.data.domain.AuditorAware;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ClampInUserAuditorAware implements AuditorAware<String> {
+
+ @Override
+ public Optional<String> getCurrentAuditor() {
+ return Optional.of(AuthorizationController.getPrincipalName(SecurityContextHolder.getContext()));
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/ClampServlet.java b/runtime/src/main/java/org/onap/policy/clamp/clds/ClampServlet.java
new file mode 100644
index 000000000..ccde7cf11
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/ClampServlet.java
@@ -0,0 +1,160 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2018, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.IOException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.camel.component.servlet.CamelHttpTransportServlet;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.policy.clamp.authorization.SecureServicePermission;
+import org.springframework.context.ApplicationContext;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.User;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+public class ClampServlet extends CamelHttpTransportServlet {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = -4198841134910211542L;
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(ClampServlet.class);
+ private static final String PERM_INSTANCE = "clamp.config.security.permission.instance";
+ private static final String PERM_CL = "clamp.config.security.permission.type.cl";
+ private static final String PERM_TEMPLATE = "clamp.config.security.permission.type.template";
+ private static final String PERM_VF = "clamp.config.security.permission.type.filter.vf";
+ private static final String PERM_MANAGE = "clamp.config.security.permission.type.cl.manage";
+ private static final String PERM_TOSCA = "clamp.config.security.permission.type.tosca";
+ private static final String PERM_POLICIES = "clamp.config.security.permission.type.policies";
+ private static final String AUTHENTICATION_CLASS = "clamp.config.security.authentication.class";
+ private static final String READ = "read";
+ private static final String UPDATE = "update";
+
+ private static List<SecureServicePermission> permissionList;
+
+ private synchronized List<String> loadDynamicAuthenticationClasses() {
+ WebApplicationContext webAppContext = WebApplicationContextUtils.getWebApplicationContext(getServletContext());
+ if (webAppContext != null) {
+ String authClassProperty = webAppContext.getEnvironment().getProperty(AUTHENTICATION_CLASS);
+ if (!StringUtils.isBlank(authClassProperty)) {
+ return Arrays.stream(authClassProperty.split(",")).map(String::trim)
+ .collect(Collectors.toList());
+ }
+ logger.warn(
+ "No authentication classes defined in Clamp BE config " + AUTHENTICATION_CLASS
+ + " AAF authentication could be broken due to that");
+ } else {
+ logger.error(
+ "WebApplicationContext is NULL, no authentication classes will be loaded in clamp BE"
+ + ", AAF authentication could be broken");
+ }
+ return Collections.emptyList();
+ }
+
+ private synchronized List<SecureServicePermission> getPermissionList() {
+ if (permissionList == null) {
+ permissionList = new ArrayList<>();
+ ApplicationContext applicationContext = WebApplicationContextUtils
+ .getWebApplicationContext(getServletContext());
+ String cldsPermissionInstance = applicationContext.getEnvironment().getProperty(PERM_INSTANCE);
+ permissionList.add(SecureServicePermission.create(applicationContext.getEnvironment().getProperty(PERM_CL),
+ cldsPermissionInstance, READ));
+ permissionList.add(SecureServicePermission.create(applicationContext.getEnvironment().getProperty(PERM_CL),
+ cldsPermissionInstance, UPDATE));
+ permissionList.add(SecureServicePermission.create(
+ applicationContext.getEnvironment().getProperty(PERM_TEMPLATE), cldsPermissionInstance, READ));
+ permissionList.add(SecureServicePermission.create(
+ applicationContext.getEnvironment().getProperty(PERM_TEMPLATE), cldsPermissionInstance, UPDATE));
+ permissionList.add(SecureServicePermission.create(applicationContext.getEnvironment().getProperty(PERM_VF),
+ cldsPermissionInstance, "*"));
+ permissionList.add(SecureServicePermission
+ .create(applicationContext.getEnvironment().getProperty(PERM_MANAGE), cldsPermissionInstance, "*"));
+ permissionList.add(SecureServicePermission
+ .create(applicationContext.getEnvironment().getProperty(PERM_TOSCA), cldsPermissionInstance, READ));
+ permissionList.add(SecureServicePermission
+ .create(applicationContext.getEnvironment().getProperty(PERM_TOSCA), cldsPermissionInstance,
+ UPDATE));
+ permissionList.add(SecureServicePermission
+ .create(applicationContext.getEnvironment().getProperty(PERM_POLICIES), cldsPermissionInstance,
+ READ));
+ permissionList.add(SecureServicePermission
+ .create(applicationContext.getEnvironment().getProperty(PERM_POLICIES), cldsPermissionInstance,
+ UPDATE));
+ }
+ return permissionList;
+ }
+
+ /**
+ * When AAF is enabled, request object will contain a cadi Wrapper, so queries
+ * to isUserInRole will invoke a http call to AAF server.
+ */
+ @Override
+ protected void doService(HttpServletRequest request, HttpServletResponse response) {
+ Principal principal = request.getUserPrincipal();
+ if (principal != null && loadDynamicAuthenticationClasses().stream()
+ .anyMatch(className -> className.equals(principal.getClass().getName()))) {
+ // When AAF is enabled, there is a need to provision the permissions to Spring
+ // system
+ List<GrantedAuthority> grantedAuths = new ArrayList<>();
+ for (SecureServicePermission perm : getPermissionList()) {
+ String permString = perm.toString();
+ if (request.isUserInRole(permString)) {
+ grantedAuths.add(new SimpleGrantedAuthority(permString));
+ }
+ }
+ Authentication auth = new UsernamePasswordAuthenticationToken(new User(principal.getName(), "",
+ grantedAuths), "", grantedAuths);
+ SecurityContextHolder.getContext().setAuthentication(auth);
+ }
+ try {
+ super.doService(request, response);
+ } catch (ServletException | IOException ioe) {
+ logger.error("Exception caught when executing doService in servlet", ioe);
+ try {
+ response.sendError(HttpStatus.INTERNAL_SERVER_ERROR.value());
+ } catch (IOException e) {
+ logger.error("Exception caught when executing HTTP sendError in servlet", e);
+ }
+ }
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/TomcatEmbeddedServletContainerFactoryRedirection.java b/runtime/src/main/java/org/onap/policy/clamp/clds/TomcatEmbeddedServletContainerFactoryRedirection.java
new file mode 100644
index 000000000..f66a09c41
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/TomcatEmbeddedServletContainerFactoryRedirection.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds;
+
+import org.apache.catalina.Context;
+import org.apache.tomcat.util.descriptor.web.SecurityCollection;
+import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+
+/**
+ * This class is a factory that redirects by default all HTTP to HTTPS
+ * connector. It is used by the Application.java class and defined in a Spring
+ * Bean.
+ * In order to do this, the method postProcessContext has been overridden to
+ * provide another behavior.
+ */
+public class TomcatEmbeddedServletContainerFactoryRedirection extends TomcatServletWebServerFactory {
+
+ /**
+ * This method is there to force the automatic redirection of all calls done
+ * on the tomcat server to a Secure connection.
+ */
+ @Override
+ protected void postProcessContext(Context context) {
+ SecurityConstraint securityConstraint = new SecurityConstraint();
+ securityConstraint.setUserConstraint("CONFIDENTIAL");
+ SecurityCollection collection = new SecurityCollection();
+ collection.addPattern("/*");
+ securityConstraint.addCollection(collection);
+ context.addConstraint(securityConstraint);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/client/CdsServices.java b/runtime/src/main/java/org/onap/policy/clamp/clds/client/CdsServices.java
new file mode 100644
index 000000000..cb74ad9e4
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/client/CdsServices.java
@@ -0,0 +1,229 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * Modifications Copyright (C) 2021 AT&T.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ * ================================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.client;
+
+import static java.lang.Boolean.parseBoolean;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import java.io.IOException;
+import java.util.Date;
+import java.util.Map;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.ExchangeBuilder;
+import org.onap.policy.clamp.clds.exception.cds.CdsParametersException;
+import org.onap.policy.clamp.clds.model.cds.CdsBpWorkFlowListResponse;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.LoggingUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+
+/**
+ * This class implements the communication with CDS for the service inventory.
+ */
+@Component
+public class CdsServices {
+
+ @Autowired
+ CamelContext camelContext;
+
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(CdsServices.class);
+
+ private static final String TYPE = "type";
+ private static final String PROPERTIES = "properties";
+ private static final String LIST = "list";
+
+ /**
+ * Query CDS to get blueprint's workflow list.
+ *
+ * @param blueprintName CDS blueprint name
+ * @param blueprintVersion CDS blueprint version
+ * @return CdsBpWorkFlowListResponse CDS blueprint's workflow list
+ */
+ public CdsBpWorkFlowListResponse getBlueprintWorkflowList(String blueprintName, String blueprintVersion) {
+ LoggingUtils.setTargetContext("CDS", "getBlueprintWorkflowList");
+
+ try (ProducerTemplate producerTemplate = camelContext.createProducerTemplate()) {
+ Exchange exchangeResponse =
+ producerTemplate.send("direct:get-blueprint-workflow-list", ExchangeBuilder.anExchange(camelContext)
+ .withProperty("blueprintName", blueprintName)
+ .withProperty("blueprintVersion", blueprintVersion)
+ .withProperty("raiseHttpExceptionFlag", false).build());
+
+ if (HttpStatus.valueOf((Integer) exchangeResponse.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE))
+ .is2xxSuccessful()) {
+ String cdsResponse = (String) exchangeResponse.getIn().getBody();
+ logger.info("getBlueprintWorkflowList, response from CDS:" + cdsResponse);
+ LoggingUtils.setResponseContext("0", "Get Blueprint workflow list", this.getClass().getName());
+ Date startTime = new Date();
+ LoggingUtils.setTimeContext(startTime, new Date());
+ return JsonUtils.GSON_JPA_MODEL.fromJson(cdsResponse, CdsBpWorkFlowListResponse.class);
+ } else {
+ logger.error("CDS getBlueprintWorkflowList FAILED");
+ }
+ } catch (IOException e) {
+ logger.error("IOException caught when trying to execute get-blueprint-workflow-list flow", e);
+ }
+ return null;
+ }
+
+ /**
+ * Query CDS to get input properties of workflow.
+ *
+ * @param blueprintName CDS blueprint name
+ * @param blueprintVersion CDS blueprint name
+ * @param workflow CDS blueprint's workflow
+ * @return input properties in json format
+ */
+ public JsonObject getWorkflowInputProperties(String blueprintName, String blueprintVersion,
+ String workflow) {
+ LoggingUtils.setTargetContext("CDS", "getWorkflowInputProperties");
+
+ try (ProducerTemplate producerTemplate = camelContext.createProducerTemplate()) {
+ Exchange exchangeResponse = producerTemplate
+ .send("direct:get-blueprint-workflow-input-properties", ExchangeBuilder.anExchange(camelContext)
+ .withBody(getCdsPayloadForWorkFlow(blueprintName, blueprintVersion, workflow))
+ .withProperty("raiseHttpExceptionFlag", false).build());
+ if (HttpStatus.valueOf((Integer) exchangeResponse.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE))
+ .is2xxSuccessful()) {
+ String cdsResponse = (String) exchangeResponse.getIn().getBody();
+ logger.info("getWorkflowInputProperties, response from CDS:" + cdsResponse);
+ LoggingUtils
+ .setResponseContext("0", "Get Blueprint workflow input properties", this.getClass().getName());
+ Date startTime = new Date();
+ LoggingUtils.setTimeContext(startTime, new Date());
+ return parseCdsResponse(cdsResponse);
+ } else {
+ logger.error("CDS getWorkflowInputProperties FAILED");
+ }
+ } catch (IOException e) {
+ logger.error("IOException caught when trying to execute get-blueprint-workflow-input-properties flow", e);
+ }
+ return null;
+ }
+
+ protected JsonObject parseCdsResponse(String response) {
+ JsonObject root = JsonParser.parseString(response).getAsJsonObject();
+ JsonObject inputs = root.getAsJsonObject("workFlowData").getAsJsonObject("inputs");
+ JsonObject dataTypes = root.getAsJsonObject("dataTypes");
+
+ JsonObject workFlowProperties = new JsonObject();
+ workFlowProperties.add("inputs", getInputProperties(inputs, dataTypes, new JsonObject()));
+ return workFlowProperties;
+ }
+
+ private JsonObject getInputProperties(JsonObject inputs, JsonObject dataTypes, JsonObject inputObject) {
+ if (inputs == null) {
+ return inputObject;
+ }
+
+ for (Map.Entry<String, JsonElement> entry : inputs.entrySet()) {
+ String key = entry.getKey();
+ JsonObject inputProperty = inputs.getAsJsonObject(key);
+ String type = inputProperty.get(TYPE).getAsString();
+ if (isComplexType(type, dataTypes)) {
+ inputObject.add(key, handleComplexType(type, dataTypes));
+ } else if (LIST.equalsIgnoreCase(type)) {
+ handleListType(key, inputProperty, dataTypes, inputObject);
+ } else if (isInputParam(inputProperty)) {
+ inputObject.add(key, entry.getValue());
+ }
+ }
+ return inputObject;
+ }
+
+ private void handleListType(String propertyName,
+ JsonObject inputProperty,
+ JsonObject dataTypes,
+ JsonObject inputObject) {
+ if (inputProperty.get("entry_schema") == null) {
+ throw new CdsParametersException("Entry schema is null for " + propertyName);
+ }
+
+ String type = inputProperty.get("entry_schema").getAsJsonObject().get(
+ TYPE).getAsString();
+ if (dataTypes != null && dataTypes.get(type) != null) {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty(TYPE, LIST);
+ jsonObject.add(PROPERTIES, getPropertiesObject(type, dataTypes));
+ inputObject.add(propertyName, jsonObject);
+ } else if (isInputParam(inputProperty)) {
+ inputObject.add(propertyName, inputProperty);
+ }
+ }
+
+ private JsonObject handleComplexType(String key, JsonObject dataTypes) {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty(TYPE, "object");
+ jsonObject.add(PROPERTIES, getPropertiesObject(key, dataTypes));
+ return jsonObject;
+ }
+
+ private JsonObject getPropertiesObject(String key, JsonObject dataTypes) {
+ JsonObject properties = dataTypes.get(key).getAsJsonObject().get(PROPERTIES).getAsJsonObject();
+ JsonObject object = new JsonObject();
+ getInputProperties(properties, dataTypes, object);
+ return object;
+ }
+
+ private boolean isComplexType(String type, JsonObject dataTypes) {
+ if (dataTypes == null) {
+ return false;
+ }
+ return dataTypes.get(type) != null;
+ }
+
+ private boolean isInputParam(JsonObject inputProperty) {
+ JsonElement inputParam = inputProperty.get("input-param");
+ if (inputParam == null) {
+ return false;
+ }
+ return parseBoolean(inputParam.getAsString());
+ }
+
+ /**
+ * Creates payload to query CDS to get workflow input properties.
+ *
+ * @param blueprintName CDS blueprint name
+ * @param version CDS blueprint version
+ * @param workflow CDS blueprint workflow
+ * @return returns payload in json format
+ */
+ public String getCdsPayloadForWorkFlow(String blueprintName, String version, String workflow) {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty("blueprintName", blueprintName);
+ jsonObject.addProperty("version", version);
+ jsonObject.addProperty("returnContent", "json");
+ jsonObject.addProperty("workflowName", workflow);
+ jsonObject.addProperty("specType", "TOSCA");
+ return jsonObject.toString();
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/client/DcaeInventoryServices.java b/runtime/src/main/java/org/onap/policy/clamp/clds/client/DcaeInventoryServices.java
new file mode 100644
index 000000000..843107040
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/client/DcaeInventoryServices.java
@@ -0,0 +1,144 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * Modifications copyright (c) 2018 Nokia
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.client;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.IOException;
+import java.util.Date;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.ExchangeBuilder;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.onap.policy.clamp.clds.config.ClampProperties;
+import org.onap.policy.clamp.clds.model.dcae.DcaeInventoryResponse;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.LoggingUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+
+/**
+ * This class implements the communication with DCAE for the service inventory.
+ */
+@Component
+public class DcaeInventoryServices {
+
+ @Autowired
+ CamelContext camelContext;
+
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(DcaeInventoryServices.class);
+ protected static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger();
+ protected static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
+ public static final String DCAE_INVENTORY_URL = "dcae.inventory.url";
+ public static final String DCAE_INVENTORY_RETRY_INTERVAL = "dcae.intentory.retry.interval";
+ public static final String DCAE_INVENTORY_RETRY_LIMIT = "dcae.intentory.retry.limit";
+ private final ClampProperties refProp;
+
+ /**
+ * Constructor.
+ */
+ @Autowired
+ public DcaeInventoryServices(ClampProperties refProp) {
+ this.refProp = refProp;
+ }
+
+ private int getTotalCountFromDcaeInventoryResponse(String responseStr) throws ParseException {
+ JSONParser parser = new JSONParser();
+ Object obj0 = parser.parse(responseStr);
+ JSONObject jsonObj = (JSONObject) obj0;
+ Long totalCount = (Long) jsonObj.get("totalCount");
+ return totalCount.intValue();
+ }
+
+ private DcaeInventoryResponse getItemsFromDcaeInventoryResponse(String responseStr) throws ParseException {
+ JSONParser parser = new JSONParser();
+ Object obj0 = parser.parse(responseStr);
+ JSONObject jsonObj = (JSONObject) obj0;
+ JSONArray itemsArray = (JSONArray) jsonObj.get("items");
+ JSONObject dcaeServiceType0 = (JSONObject) itemsArray.get(0);
+ return JsonUtils.GSON.fromJson(dcaeServiceType0.toString(), DcaeInventoryResponse.class);
+ }
+
+ /**
+ * DO a query to DCAE to get some Information.
+ *
+ * @param artifactName The artifact Name
+ * @param serviceUuid The service UUID
+ * @param resourceUuid The resource UUID
+ * @return The DCAE inventory for the artifact in DcaeInventoryResponse
+ * @throws IOException In case of issues with the stream
+ * @throws ParseException In case of issues with the Json parsing
+ */
+ public DcaeInventoryResponse getDcaeInformation(String artifactName, String serviceUuid, String resourceUuid)
+ throws IOException, ParseException, InterruptedException {
+ LoggingUtils.setTargetContext("DCAE", "getDcaeInformation");
+
+ int retryInterval = 0;
+ int retryLimit = 1;
+ if (refProp.getStringValue(DCAE_INVENTORY_RETRY_LIMIT) != null) {
+ retryLimit = Integer.valueOf(refProp.getStringValue(DCAE_INVENTORY_RETRY_LIMIT));
+ }
+ if (refProp.getStringValue(DCAE_INVENTORY_RETRY_INTERVAL) != null) {
+ retryInterval = Integer.valueOf(refProp.getStringValue(DCAE_INVENTORY_RETRY_INTERVAL));
+ }
+ for (int i = 0; i < retryLimit; i++) {
+ metricsLogger.info("Attempt n°" + i + " to contact DCAE inventory");
+ try (ProducerTemplate producerTemplate = camelContext.createProducerTemplate()) {
+ Exchange exchangeResponse = producerTemplate
+ .send("direct:get-dcae-blueprint-inventory", ExchangeBuilder.anExchange(camelContext)
+ .withProperty("blueprintResourceId", resourceUuid)
+ .withProperty("blueprintServiceId", serviceUuid)
+ .withProperty("blueprintName", artifactName)
+ .withProperty("raiseHttpExceptionFlag", false).build());
+
+ if (HttpStatus.valueOf((Integer) exchangeResponse.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE))
+ .is2xxSuccessful()) {
+ String dcaeResponse = (String) exchangeResponse.getIn().getBody();
+ int totalCount = getTotalCountFromDcaeInventoryResponse(dcaeResponse);
+ metricsLogger.info("getDcaeInformation complete: totalCount returned=" + totalCount);
+ if (totalCount > 0) {
+ logger.info("getDcaeInformation, answer from DCAE inventory:" + dcaeResponse);
+ LoggingUtils.setResponseContext("0", "Get Dcae Information success", this.getClass().getName());
+ Date startTime = new Date();
+ LoggingUtils.setTimeContext(startTime, new Date());
+ return getItemsFromDcaeInventoryResponse(dcaeResponse);
+ } else {
+ logger.info("Dcae inventory totalCount returned is 0, so waiting " + retryInterval
+ + "ms before retrying ...");
+ // wait for a while and try to connect to DCAE again
+ Thread.sleep(retryInterval);
+ }
+ }
+ }
+ }
+ logger.warn("Dcae inventory totalCount returned is still 0, after " + retryLimit + " attempts, returning NULL");
+ return null;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/config/AafConfiguration.java b/runtime/src/main/java/org/onap/policy/clamp/clds/config/AafConfiguration.java
new file mode 100644
index 000000000..9b6338e00
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/config/AafConfiguration.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.config;
+
+import javax.servlet.Filter;
+import org.onap.policy.clamp.clds.filter.ClampCadiFilter;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+@Configuration
+@Profile("clamp-aaf-authentication")
+public class AafConfiguration {
+
+ /**
+ * Method to return clamp cadi filter.
+ *
+ * @return Filter
+ */
+ @Bean(name = "cadiFilter")
+ public Filter cadiFilter() {
+ return new ClampCadiFilter();
+ }
+
+ /**
+ * Method to register cadi filter.
+ *
+ * @return FilterRegistrationBean
+ */
+ @Bean
+ public FilterRegistrationBean cadiFilterRegistration() {
+ FilterRegistrationBean registration = new FilterRegistrationBean();
+ registration.setFilter(cadiFilter());
+ registration.addUrlPatterns("/restservices/clds/v1/user/*");
+ registration.addUrlPatterns("/restservices/clds/v2/dictionary/*");
+ registration.addUrlPatterns("/restservices/clds/v2/templates/*");
+ registration.addUrlPatterns("/restservices/clds/v2/clampInformation/*");
+ registration.addUrlPatterns("/restservices/clds/v2/policyToscaModels/*");
+ registration.addUrlPatterns("/restservices/clds/v2/policies/*");
+ registration.addUrlPatterns("/restservices/clds/v2/loop/*");
+ registration.setName("cadiFilter");
+ registration.setOrder(0);
+ return registration;
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/config/CamelConfiguration.java b/runtime/src/main/java/org/onap/policy/clamp/clds/config/CamelConfiguration.java
new file mode 100644
index 000000000..5f10c0afb
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/config/CamelConfiguration.java
@@ -0,0 +1,166 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2018, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ */
+
+package org.onap.policy.clamp.clds.config;
+
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.util.Objects;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManagerFactory;
+import org.apache.camel.CamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.http.HttpComponent;
+import org.apache.camel.model.rest.RestBindingMode;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.config.Registry;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.conn.socket.ConnectionSocketFactory;
+import org.apache.http.conn.socket.PlainConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
+import org.onap.policy.clamp.clds.util.ClampVersioning;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.util.PassDecoder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CamelConfiguration extends RouteBuilder {
+
+ private static final String HTTP = "http";
+ private static final String HTTPS = "https";
+
+ @Autowired
+ CamelContext camelContext;
+
+ @Value("${server.ssl.key-store:#{null}}")
+ private String keyStore;
+
+ @Value("${server.ssl.key-store-type:JKS}")
+ private String keyStoreType;
+
+ @Value("${server.ssl.key-store-password:#{null}}")
+ private String keyStorePass;
+
+ @Value("${server.ssl.trust-store:#{null}}")
+ private String trustStore;
+
+ @Value("${server.ssl.trust-store-password:#{null}}")
+ private String trustStorePass;
+
+ @Value("${server.ssl.trust-store-type:JKS}")
+ private String trustStoreType;
+
+ @Value("${server.ssl.trust-store-algorithm:PKIX}")
+ private String trustStoreAlgorithm;
+
+ @Value("${clamp.config.httpclient.connectTimeout:-1}")
+ private int connectTimeout;
+
+ @Value("${clamp.config.httpclient.connectRequestTimeout:-1}")
+ private int connectRequestTimeout;
+
+ @Value("${clamp.config.httpclient.socketTimeout:-1}")
+ private int socketTimeout;
+
+ @Value("${clamp.config.keyFile:#{null}}")
+ private String keyFile;
+
+
+ @Autowired
+ private ClampProperties clampProperties;
+
+ private void configureDefaultSslProperties() {
+ if (trustStore != null) {
+ System.setProperty("javax.net.ssl.trustStore", Thread.currentThread().getContextClassLoader()
+ .getResource(trustStore.replaceFirst("classpath:", "")).getPath());
+ System.setProperty("javax.net.ssl.trustStorePassword", Objects.requireNonNull(
+ PassDecoder.decode(trustStorePass, keyFile)));
+ System.setProperty("javax.net.ssl.trustStoreType", trustStoreType);
+ System.setProperty("ssl.TrustManagerFactory.algorithm", trustStoreAlgorithm);
+ }
+ if (keyStore != null) {
+ System.setProperty("javax.net.ssl.keyStore", Thread.currentThread().getContextClassLoader()
+ .getResource(keyStore.replaceFirst("classpath:", "")).getPath());
+ System.setProperty("javax.net.ssl.keyStorePassword", Objects.requireNonNull(
+ PassDecoder.decode(keyStorePass, keyFile)));
+ System.setProperty("javax.net.ssl.keyStoreType", keyStoreType);
+ }
+
+ }
+
+ private void configureCamelHttpComponent()
+ throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException, CertificateException,
+ IOException {
+ RequestConfig requestConfig = RequestConfig.custom()
+ .setConnectTimeout(connectTimeout)
+ .setConnectionRequestTimeout(connectRequestTimeout)
+ .setSocketTimeout(socketTimeout).build();
+
+ if (trustStore != null) {
+ KeyStore truststore = KeyStore.getInstance(trustStoreType);
+ truststore.load(
+ ResourceFileUtils.getResourceAsStream(trustStore),
+ Objects.requireNonNull(PassDecoder.decode(trustStorePass, keyFile)).toCharArray());
+ TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(trustStoreAlgorithm);
+ trustFactory.init(truststore);
+ SSLContext sslcontext = SSLContext.getInstance("TLS");
+ sslcontext.init(null, trustFactory.getTrustManagers(), null);
+ camelContext.getComponent(HTTPS, HttpComponent.class).setHttpClientConfigurer(builder -> {
+ SSLSocketFactory factory = new SSLSocketFactory(sslcontext,
+ SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
+ builder.setSSLSocketFactory(factory);
+ builder.setConnectionManager(new BasicHttpClientConnectionManager(
+ RegistryBuilder.<ConnectionSocketFactory>create().register(HTTPS, factory).build()))
+ .setDefaultRequestConfig(requestConfig);
+ });
+ }
+ camelContext.getComponent(HTTP, HttpComponent.class).setHttpClientConfigurer(builder -> {
+ Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
+ .register(HTTP, PlainConnectionSocketFactory.getSocketFactory()).build();
+ builder.setConnectionManager(new BasicHttpClientConnectionManager(registry))
+ .setDefaultRequestConfig(requestConfig);
+ });
+ }
+
+ @Override
+ public void configure()
+ throws KeyManagementException, KeyStoreException, NoSuchAlgorithmException, CertificateException,
+ IOException {
+ restConfiguration().component("servlet").bindingMode(RestBindingMode.json).jsonDataFormat("clamp-gson")
+ .dataFormatProperty("prettyPrint", "true")// .enableCORS(true)
+ // turn on swagger api-doc
+ .apiContextPath("api-doc").apiVendorExtension(true).apiProperty("api.title", "Clamp Rest API")
+ .apiProperty("api.version", ClampVersioning.getCldsVersionFromProps())
+ .apiProperty("base.path", "/restservices/clds/");
+
+ // Configure httpClient properties for Camel HTTP/HTTPS calls
+ configureDefaultSslProperties();
+ configureCamelHttpComponent();
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/config/ClampProperties.java b/runtime/src/main/java/org/onap/policy/clamp/clds/config/ClampProperties.java
new file mode 100644
index 000000000..f11e16733
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/config/ClampProperties.java
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.config;
+
+import java.io.IOException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import org.apache.commons.io.IOUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationContext;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+
+/**
+ * Holds Clamp properties and add some functionalities.
+ */
+@Component
+public class ClampProperties {
+
+ @Autowired
+ private ApplicationContext appContext;
+ @Autowired
+ private Environment env;
+ public static final String CONFIG_PREFIX = "clamp.config.";
+
+ /**
+ * get property value.
+ *
+ * @param key The first key
+ * @return The string with the value
+ */
+ public String getStringValue(String key) {
+ return env.getProperty(CONFIG_PREFIX + key);
+ }
+
+ /**
+ * get property value for a combo key (key1 + "." + key2). If not found just use
+ * key1.
+ *
+ * @param key1 The first key
+ * @param key2 The second key after a dot
+ * @return The string with the value
+ */
+ public String getStringValue(String key1, String key2) {
+ String value = getStringValue(key1 + "." + key2);
+ if (value == null || value.length() == 0) {
+ value = getStringValue(key1);
+ }
+ return value;
+ }
+
+ /**
+ * Return the file content. The value obtained from the clds-reference file will
+ * be used as a filename.
+ *
+ * @param key The key that will be used to access the clds-reference file
+ * @return File content in String
+ * @throws IOException In case of issues with the JSON parser
+ */
+ public String getFileContent(String key) throws IOException {
+ String fileReference = getStringValue(key);
+ return (fileReference != null) ? getFileContentFromPath(fileReference) : null;
+ }
+
+ /**
+ * Return the file content. First try with combo key (key1 + "." + key2),
+ * otherwise default to just key1. The value obtained from the clds-reference
+ * file will be used as a filename.
+ *
+ * @param key1 The first key
+ * @param key2 The second key after a dot
+ * @return File content in String
+ * @throws IOException In case of issues with the JSON parser
+ */
+ public String getFileContent(String key1, String key2) throws IOException {
+ String fileReference = getStringValue(key1, key2);
+ return (fileReference != null) ? getFileContentFromPath(fileReference) : null;
+ }
+
+ private String getFileContentFromPath(String filepath) throws IOException {
+ URL url = appContext.getResource(filepath).getURL();
+ return IOUtils.toString(url, StandardCharsets.UTF_8);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/config/CldsUserJsonDecoder.java b/runtime/src/main/java/org/onap/policy/clamp/clds/config/CldsUserJsonDecoder.java
new file mode 100644
index 000000000..20d7143fb
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/config/CldsUserJsonDecoder.java
@@ -0,0 +1,74 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.config;
+
+import com.google.gson.JsonParseException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import org.apache.commons.io.IOUtils;
+import org.onap.policy.clamp.authorization.CldsUser;
+import org.onap.policy.clamp.clds.exception.CldsUsersException;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+
+public class CldsUserJsonDecoder {
+
+ private CldsUserJsonDecoder() {
+ }
+
+ /**
+ * This method decodes the JSON file provided to a CldsUser Array. The stream is
+ * closed after this call, this is not possible to reuse it.
+ *
+ * @param cldsUsersFile
+ * The inputStream containing the users json file
+ * @return CldsUser[] Array containing a list of the user defined in the JSON
+ * file
+ */
+ public static CldsUser[] decodeJson(InputStream cldsUsersFile) {
+ try {
+ return decodeJson(IOUtils.toString(cldsUsersFile, StandardCharsets.UTF_8.name()));
+ } catch (IOException e) {
+ throw new CldsUsersException("Exception occurred during the decoding of the clds-users.json", e);
+ }
+ }
+
+ /**
+ * This method decodes the JSON string to a CldsUser Array.
+ *
+ * @param cldsUsersString JSON string
+ * @return CldsUser[] Array containing a list of the user defined in the JSON
+ */
+ public static CldsUser[] decodeJson(String cldsUsersString) {
+ try {
+ // the ObjectMapper readValue method closes the stream no need to do
+ // it
+ return JsonUtils.GSON.fromJson(cldsUsersString, CldsUser[].class);
+ } catch (JsonParseException e) {
+ throw new CldsUsersException("Exception occurred during the decoding of the clds-users.json", e);
+ }
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/config/DefaultDictionaryElements.java b/runtime/src/main/java/org/onap/policy/clamp/clds/config/DefaultDictionaryElements.java
new file mode 100644
index 000000000..27cf0b941
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/config/DefaultDictionaryElements.java
@@ -0,0 +1,167 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.config;
+
+import javax.annotation.PostConstruct;
+import org.onap.policy.clamp.tosca.Dictionary;
+import org.onap.policy.clamp.tosca.DictionaryElement;
+import org.onap.policy.clamp.tosca.DictionaryService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+@Configuration
+@Profile("default-dictionary-elements")
+public class DefaultDictionaryElements {
+
+ @Autowired
+ private DictionaryService dictionaryService;
+
+ /**
+ * Init method.
+ */
+ @PostConstruct
+ public void init() {
+ preProvisionDefaultActors();
+ preProvisionDefaultOperations();
+ }
+
+ private void preProvisionDefaultActors() {
+ // Set up dictionary elements
+ Dictionary actorDictionary = new Dictionary();
+ actorDictionary.setName("DefaultActors");
+ actorDictionary.setSecondLevelDictionary(0);
+ actorDictionary.setSubDictionaryType("");
+
+ DictionaryElement elementSo = new DictionaryElement();
+ elementSo.setName("SO");
+ elementSo.setShortName("SO");
+ elementSo.setType("string");
+ elementSo.setDescription("SO component");
+ actorDictionary.addDictionaryElements(elementSo);
+
+ DictionaryElement elementSdnc = new DictionaryElement();
+ elementSdnc.setName("SDNC");
+ elementSdnc.setShortName("SDNC");
+ elementSdnc.setType("string");
+ elementSdnc.setDescription("SDNC component");
+ actorDictionary.addDictionaryElements(elementSdnc);
+
+ DictionaryElement elementAppc = new DictionaryElement();
+ elementAppc.setName("APPC");
+ elementAppc.setShortName("APPC");
+ elementAppc.setType("string");
+ elementAppc.setDescription("APPC component");
+ actorDictionary.addDictionaryElements(elementAppc);
+
+ DictionaryElement elementVfc = new DictionaryElement();
+ elementVfc.setName("VFC");
+ elementVfc.setShortName("VFC");
+ elementVfc.setType("string");
+ elementVfc.setDescription("VFC component");
+ actorDictionary.addDictionaryElements(elementVfc);
+
+ DictionaryElement elementSdnr = new DictionaryElement();
+ elementSdnr.setName("SDNR");
+ elementSdnr.setShortName("SDNR");
+ elementSdnr.setType("string");
+ elementSdnr.setDescription("SDNR component");
+ actorDictionary.addDictionaryElements(elementSdnr);
+
+ dictionaryService.saveOrUpdateDictionary(actorDictionary);
+ }
+
+ private void preProvisionDefaultOperations() {
+ // Set up dictionary elements
+ Dictionary operationDictionary = new Dictionary();
+ operationDictionary.setName("DefaultOperations");
+ operationDictionary.setSecondLevelDictionary(0);
+ operationDictionary.setSubDictionaryType("");
+
+ DictionaryElement elementRestart = new DictionaryElement();
+ elementRestart.setName("Restart");
+ elementRestart.setShortName("Restart (APPC operation)");
+ elementRestart.setType("string");
+ elementRestart.setDescription("APPC operation");
+ operationDictionary.addDictionaryElements(elementRestart);
+
+ DictionaryElement elementRebuild = new DictionaryElement();
+ elementRebuild.setName("Rebuild");
+ elementRebuild.setShortName("Rebuild (APPC operation)");
+ elementRebuild.setType("string");
+ elementRebuild.setDescription("APPC operation");
+ operationDictionary.addDictionaryElements(elementRebuild);
+
+ DictionaryElement elementMigrate = new DictionaryElement();
+ elementMigrate.setName("Migrate");
+ elementMigrate.setShortName("Migrate (APPC operation)");
+ elementMigrate.setType("string");
+ elementMigrate.setDescription("APPC operation");
+ operationDictionary.addDictionaryElements(elementMigrate);
+
+ DictionaryElement elementHealthCheck = new DictionaryElement();
+ elementHealthCheck.setName("Health-Check");
+ elementHealthCheck.setShortName("Health-Check (APPC operation)");
+ elementHealthCheck.setType("string");
+ elementHealthCheck.setDescription("APPC operation");
+ operationDictionary.addDictionaryElements(elementHealthCheck);
+
+ DictionaryElement elementModifyConfig = new DictionaryElement();
+ elementModifyConfig.setName("ModifyConfig");
+ elementModifyConfig.setShortName("ModifyConfig (APPC/VFC operation)");
+ elementModifyConfig.setType("string");
+ elementModifyConfig.setDescription("APPC/VFC operation");
+ operationDictionary.addDictionaryElements(elementModifyConfig);
+
+ DictionaryElement elementVfModuleCreate = new DictionaryElement();
+ elementVfModuleCreate.setName("VF Module Create");
+ elementVfModuleCreate.setShortName("VF Module Create (SO operation)");
+ elementVfModuleCreate.setType("string");
+ elementVfModuleCreate.setDescription("SO operation");
+ operationDictionary.addDictionaryElements(elementVfModuleCreate);
+
+ DictionaryElement elementVfModuleDelete = new DictionaryElement();
+ elementVfModuleDelete.setName("VF Module Delete");
+ elementVfModuleDelete.setShortName("VF Module Delete (SO operation)");
+ elementVfModuleDelete.setType("string");
+ elementVfModuleDelete.setDescription("SO operation");
+ operationDictionary.addDictionaryElements(elementVfModuleDelete);
+
+ DictionaryElement elementReroute = new DictionaryElement();
+ elementReroute.setName("Reroute");
+ elementReroute.setShortName("Reroute (SDNC operation)");
+ elementReroute.setType("string");
+ elementReroute.setDescription("SDNC operation");
+ operationDictionary.addDictionaryElements(elementReroute);
+
+ DictionaryElement elementBandwidthOnDemand = new DictionaryElement();
+ elementBandwidthOnDemand.setName("BandwidthOnDemand");
+ elementBandwidthOnDemand.setShortName("BandwidthOnDemand (SDNC operation)");
+ elementBandwidthOnDemand.setType("string");
+ elementBandwidthOnDemand.setDescription("SDNC operation");
+ operationDictionary.addDictionaryElements(elementBandwidthOnDemand);
+
+ dictionaryService.saveOrUpdateDictionary(operationDictionary);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/config/DefaultUserConfiguration.java b/runtime/src/main/java/org/onap/policy/clamp/clds/config/DefaultUserConfiguration.java
new file mode 100644
index 000000000..bb7b76af3
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/config/DefaultUserConfiguration.java
@@ -0,0 +1,140 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.config;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.IOException;
+import org.onap.policy.clamp.authorization.CldsUser;
+import org.onap.policy.clamp.clds.exception.CldsConfigException;
+import org.onap.policy.clamp.clds.exception.CldsUsersException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+/**
+ * This class is used to enable the HTTP authentication to login. It requires a
+ * specific JSON file containing the user definition
+ * (classpath:clds/clds-users.json).
+ */
+@Configuration
+@EnableWebSecurity
+@Profile("clamp-default-user")
+public class DefaultUserConfiguration extends WebSecurityConfigurerAdapter {
+
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(DefaultUserConfiguration.class);
+
+ private static final String SETUP_WEB_USERS_EXCEPTION_MSG = "Exception occurred during the "
+ + " setup of the Web users in memory";
+ @Autowired
+ private ClampProperties refProp;
+ @Value("${clamp.config.security.permission.type.cl:permission-type-cl}")
+ private String cldsPersmissionTypeCl;
+ @Value("${CLDS_PERMISSION_INSTANCE:dev}")
+ private String cldsPermissionInstance;
+ @Value("${clamp.config.security.encoder:bcrypt}")
+ private String cldsEncoderMethod;
+ @Value("${clamp.config.security.encoder.bcrypt.strength:10}")
+ private Integer cldsBcryptEncoderStrength;
+
+ /**
+ * This method configures on which URL the authorization will be enabled.
+ */
+ @Override
+ protected void configure(HttpSecurity http) {
+ try {
+ // Do no remove the csrf as recommended by Sonar otherwise Put/post will not work
+ // Moreover this default user class is only used by dev, on prod we use AAF and this code will be disabled
+ http.csrf().disable().httpBasic().and().authorizeRequests().antMatchers("/restservices/clds/v1/user/**")
+ .authenticated().anyRequest().permitAll().and().sessionManagement()
+ .maximumSessions(1);
+
+ } catch (Exception e) {
+ logger.error(SETUP_WEB_USERS_EXCEPTION_MSG, e);
+ throw new CldsUsersException(SETUP_WEB_USERS_EXCEPTION_MSG, e);
+ }
+ }
+
+ /**
+ * This method is called by the framework and is used to load all the users
+ * defined in cldsUsersFile variable (this file path can be configured in the
+ * application.properties).
+ *
+ * @param auth authentication manager builder
+ */
+ @Autowired
+ public void configureGlobal(AuthenticationManagerBuilder auth) {
+ // configure algorithm used for password hashing
+ final PasswordEncoder passwordEncoder = getPasswordEncoder();
+
+ try {
+ CldsUser[] usersList = loadUsers();
+ // no users defined
+ if (null == usersList) {
+ logger.warn("No users defined. Users should be defined under clds-users.json");
+ return;
+ }
+ for (CldsUser user : usersList) {
+ auth.inMemoryAuthentication().withUser(user.getUser()).password(user.getPassword())
+ .authorities(user.getPermissionsString()).and().passwordEncoder(passwordEncoder);
+ }
+ } catch (Exception e) {
+ logger.error(SETUP_WEB_USERS_EXCEPTION_MSG, e);
+ throw new CldsUsersException(SETUP_WEB_USERS_EXCEPTION_MSG, e);
+ }
+ }
+
+ /**
+ * This method loads physically the JSON file and convert it to an Array of
+ * CldsUser.
+ *
+ * @return The array of CldsUser
+ * @throws IOException In case of the file is not found
+ */
+ private CldsUser[] loadUsers() throws IOException {
+ logger.info("Load from clds-users.properties");
+ return CldsUserJsonDecoder.decodeJson(refProp.getFileContent("files.cldsUsers"));
+ }
+
+ /**
+ * This methods returns the chosen encoder for password hashing.
+ */
+ private PasswordEncoder getPasswordEncoder() {
+ if ("bcrypt".equals(cldsEncoderMethod)) {
+ return new BCryptPasswordEncoder(cldsBcryptEncoderStrength);
+ } else {
+ throw new CldsConfigException(
+ "Invalid clamp.config.security.encoder value. 'bcrypt' is the only option at this time.");
+ }
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/config/SslConfig.java b/runtime/src/main/java/org/onap/policy/clamp/clds/config/SslConfig.java
new file mode 100644
index 000000000..a72cffd09
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/config/SslConfig.java
@@ -0,0 +1,97 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.config;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.util.PassDecoder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.web.ServerProperties;
+import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
+import org.springframework.boot.web.server.Ssl;
+import org.springframework.boot.web.server.SslStoreProvider;
+import org.springframework.boot.web.server.WebServerFactoryCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.core.env.Environment;
+import org.springframework.core.io.ResourceLoader;
+
+@Configuration
+@Profile("clamp-ssl-config")
+public class SslConfig {
+ @Autowired
+ private Environment env;
+
+ @Bean
+ WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer(ServerProperties serverProperties,
+ ResourceLoader resourceLoader) {
+ return (tomcat) -> tomcat.setSslStoreProvider(new SslStoreProvider() {
+ @Override
+ public KeyStore getKeyStore() throws KeyStoreException,
+ NoSuchAlgorithmException, CertificateException, IOException {
+ KeyStore keystore = KeyStore.getInstance(env.getProperty("server.ssl.key-store-type"));
+ String password = PassDecoder.decode(env.getProperty("server.ssl.key-store-password"),
+ env.getProperty("clamp.config.keyFile"));
+ keystore.load(ResourceFileUtils.getResourceAsStream(env.getProperty("server.ssl.key-store")),
+ password.toCharArray());
+ return keystore;
+ }
+
+ @Override
+ public KeyStore getTrustStore() throws KeyStoreException,
+ NoSuchAlgorithmException, CertificateException, IOException {
+ KeyStore truststore = KeyStore.getInstance("JKS");
+ String password = PassDecoder.decode(env.getProperty("server.ssl.trust-store-password"),
+ env.getProperty("clamp.config.keyFile"));
+ truststore.load(
+ ResourceFileUtils.getResourceAsStream(env.getProperty("server.ssl.trust-store")),
+ password.toCharArray());
+ return truststore;
+ }
+
+ });
+ }
+
+ @Bean
+ WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatSslCustomizer(ServerProperties serverProperties,
+ ResourceLoader resourceLoader) {
+ return (tomcat) -> tomcat.setSsl(new Ssl() {
+ @Override
+ public String getKeyPassword() {
+ return PassDecoder.decode(env.getProperty("server.ssl.key-password"),
+ env.getProperty("clamp.config.keyFile"));
+ }
+
+ @Override
+ public String getKeyAlias() {
+ return env.getProperty("server.ssl.key-alias");
+ }
+ });
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/config/SystemPropertiesLoader.java b/runtime/src/main/java/org/onap/policy/clamp/clds/config/SystemPropertiesLoader.java
new file mode 100644
index 000000000..3e2e62b66
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/config/SystemPropertiesLoader.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.config;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.util.Properties;
+import javax.annotation.Resource;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextRefreshedEvent;
+import org.springframework.stereotype.Component;
+
+@Component
+public class SystemPropertiesLoader implements ApplicationListener<ContextRefreshedEvent> {
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(SystemPropertiesLoader.class);
+
+ @Resource(name = "mapper")
+ private Properties myTranslator;
+
+ @Override
+ public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {
+ logger.info("Loading additional JVM properties:" + myTranslator.toString());
+ System.getProperties().putAll(myTranslator);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/config/sdc/SdcControllersConfiguration.java b/runtime/src/main/java/org/onap/policy/clamp/clds/config/sdc/SdcControllersConfiguration.java
new file mode 100644
index 000000000..5d8cbb05e
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/config/sdc/SdcControllersConfiguration.java
@@ -0,0 +1,100 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2018, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.config.sdc;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcParametersException;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationContext;
+
+/**
+ * This class maps the SDC config JSON file. This JSON can have multiple
+ * sdc-controller config. So the json is loaded in a static way and the instance
+ * must specify the controller name that it represents.
+ */
+public class SdcControllersConfiguration {
+
+ private static final String CONTROLLER_SUBTREE_KEY = "sdc-connections";
+ @Autowired
+ protected ApplicationContext appContext;
+
+ @Value("${clamp.config.keyFile:classpath:/clds/aaf/org.onap.clamp.keyfile}")
+ private String keyFile;
+
+ /**
+ * The file name that will be loaded by Spring.
+ */
+ @Value("${clamp.config.files.sdcController:classpath:/clds/sdc-controllers-config.json}")
+ protected String sdcControllerFile;
+ /**
+ * The root of the JSON.
+ */
+ private JsonObject jsonRootNode;
+
+ /**
+ * Loads configuration from SDC controller config file.
+ *
+ * @throws IOException IO Exception
+ */
+ @PostConstruct
+ public void loadConfiguration() throws IOException {
+ try (InputStreamReader controllerFile = new InputStreamReader(
+ appContext.getResource(sdcControllerFile).getInputStream(), StandardCharsets.UTF_8)) {
+ jsonRootNode = JsonUtils.GSON.fromJson(controllerFile, JsonObject.class);
+ }
+ }
+
+ public SdcSingleControllerConfiguration getSdcSingleControllerConfiguration(String controllerName) {
+ return getAllDefinedControllers().get(controllerName);
+ }
+
+ /**
+ * This method reads all Controllers configurations and returns them.
+ *
+ * @return A list of controller Names defined in the config
+ */
+ public Map<String, SdcSingleControllerConfiguration> getAllDefinedControllers() {
+ Map<String, SdcSingleControllerConfiguration> result = new HashMap<>();
+ if (jsonRootNode.get(CONTROLLER_SUBTREE_KEY) != null) {
+ jsonRootNode.get(CONTROLLER_SUBTREE_KEY).getAsJsonObject().entrySet().forEach(
+ entry -> result.put(entry.getKey(),
+ new SdcSingleControllerConfiguration(entry.getValue().getAsJsonObject(), entry.getKey(),
+ keyFile)));
+ } else {
+ throw new SdcParametersException(
+ CONTROLLER_SUBTREE_KEY + " key not found in the file: " + sdcControllerFile);
+ }
+ return result;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java b/runtime/src/main/java/org/onap/policy/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java
new file mode 100644
index 000000000..67060d776
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/config/sdc/SdcSingleControllerConfiguration.java
@@ -0,0 +1,272 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2018, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.config.sdc;
+
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcParametersException;
+import org.onap.policy.clamp.util.PassDecoder;
+import org.onap.sdc.api.consumer.IConfiguration;
+
+/**
+ * This class maps the SDC config JSON for one controller.
+ */
+public class SdcSingleControllerConfiguration implements IConfiguration {
+
+ private final String keyFile;
+
+ /**
+ * The sdc Controller name corresponding.
+ */
+ private String sdcControllerName;
+ /**
+ * The root of the JSON.
+ */
+ private JsonObject jsonRootNode;
+ // All keys that can be present in the JSON
+ public static final String CONSUMER_GROUP_ATTRIBUTE_NAME = "consumerGroup";
+ public static final String CONSUMER_ID_ATTRIBUTE_NAME = "consumerId";
+ public static final String ENVIRONMENT_NAME_ATTRIBUTE_NAME = "environmentName";
+ public static final String SDC_KEY_ATTRIBUTE_NAME = "password";
+ public static final String POLLING_INTERVAL_ATTRIBUTE_NAME = "pollingInterval";
+ public static final String RELEVANT_ARTIFACT_TYPES_ATTRIBUTE_NAME = "relevantArtifactTypes";
+ public static final String USER_ATTRIBUTE_NAME = "user";
+ public static final String SDC_ADDRESS_ATTRIBUTE_NAME = "sdcAddress";
+ public static final String POLLING_TIMEOUT_ATTRIBUTE_NAME = "pollingTimeout";
+ public static final String ACTIVATE_SERVER_TLS_AUTH = "activateServerTLSAuth";
+ public static final String KEY_STORE_KEY = "keyStorePassword";
+ public static final String KEY_STORE_PATH = "keyStorePath";
+ public static final String MESSAGE_BUS_ADDRESSES = "messageBusAddresses";
+ private String errorMessageKeyNotFound;
+ /**
+ * Supported artifact types.
+ */
+ public static final String HEAT = "HEAT";
+ public static final String HEAT_ARTIFACT = "HEAT_ARTIFACT";
+ public static final String HEAT_ENV = "HEAT_ENV";
+ public static final String HEAT_NESTED = "HEAT_NESTED";
+ public static final String HEAT_NET = "HEAT_NET";
+ public static final String HEAT_VOL = "HEAT_VOL";
+ public static final String OTHER = "OTHER";
+ public static final String TOSCA_CSAR = "TOSCA_CSAR";
+ public static final String VF_MODULES_METADATA = "VF_MODULES_METADATA";
+ private static final String[] SUPPORTED_ARTIFACT_TYPES = {TOSCA_CSAR, VF_MODULES_METADATA};
+ public static final List<String> SUPPORTED_ARTIFACT_TYPES_LIST = List.of(SUPPORTED_ARTIFACT_TYPES);
+
+ /**
+ * This constructor builds a SdcSingleControllerConfiguration from the
+ * corresponding json.
+ *
+ * @param jsonNode The JSON node
+ * @param controllerName The controller name that must appear in the JSON
+ * @param keyFileLocation The location of the file to decode the password using CADI
+ */
+ public SdcSingleControllerConfiguration(JsonObject jsonNode, String controllerName, String keyFileLocation) {
+ jsonRootNode = jsonNode;
+ keyFile = keyFileLocation;
+ setSdcControllerName(controllerName);
+ testAllRequiredParameters();
+ }
+
+ public String getSdcControllerName() {
+ return sdcControllerName;
+ }
+
+ /**
+ * Sets SDC controller name.
+ *
+ * @param controllerName SDC controller name
+ */
+ public void setSdcControllerName(String controllerName) {
+ this.sdcControllerName = controllerName;
+ errorMessageKeyNotFound = " parameter cannot be found in config file for controller name" + sdcControllerName;
+ testAllRequiredParameters();
+ }
+
+ private String getStringConfig(String key) {
+ if (jsonRootNode != null && jsonRootNode.get(key) != null) {
+ String config = jsonRootNode.get(key).getAsString();
+ return config.isEmpty() ? null : config;
+ }
+ return null;
+ }
+
+ private Integer getIntConfig(String key) {
+ if (jsonRootNode != null && jsonRootNode.get(key) != null) {
+ return jsonRootNode.get(key).getAsInt();
+ } else {
+ return 0;
+ }
+ }
+
+ private String getEncryptedStringConfig(String key) {
+ if (jsonRootNode != null && jsonRootNode.get(key) != null) {
+ return jsonRootNode.get(key).getAsString().isEmpty() ? null
+ : PassDecoder.decode(jsonRootNode.get(key).getAsString(), keyFile);
+ }
+ return null;
+ }
+
+ @Override
+ public java.lang.Boolean isUseHttpsWithDmaap() {
+ return false;
+ }
+
+ @Override
+ public String getConsumerGroup() {
+ if (jsonRootNode != null && jsonRootNode.get(CONSUMER_GROUP_ATTRIBUTE_NAME) != null) {
+ String config = jsonRootNode.get(CONSUMER_GROUP_ATTRIBUTE_NAME).getAsString();
+ return "NULL".equals(config) || config.isEmpty() ? null : config;
+ }
+ return null;
+ }
+
+ @Override
+ public String getConsumerID() {
+ return getStringConfig(CONSUMER_ID_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ public String getEnvironmentName() {
+ return getStringConfig(ENVIRONMENT_NAME_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ public String getPassword() {
+ return getEncryptedStringConfig(SDC_KEY_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ public int getPollingInterval() {
+ return getIntConfig(POLLING_INTERVAL_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ public List<String> getRelevantArtifactTypes() {
+ // DO not return the Static List SUPPORTED_ARTIFACT_TYPES_LIST because
+ // the ASDC Client could try to modify it !!!
+ return Arrays.asList(SUPPORTED_ARTIFACT_TYPES);
+ }
+
+ @Override
+ public String getUser() {
+ return getStringConfig(USER_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ public String getAsdcAddress() {
+ return getStringConfig(SDC_ADDRESS_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ public int getPollingTimeout() {
+ return getIntConfig(POLLING_TIMEOUT_ATTRIBUTE_NAME);
+ }
+
+ @Override
+ public boolean activateServerTLSAuth() {
+ if (jsonRootNode != null && jsonRootNode.get(ACTIVATE_SERVER_TLS_AUTH) != null
+ && jsonRootNode.get(ACTIVATE_SERVER_TLS_AUTH).isJsonPrimitive()) {
+ return jsonRootNode.get(ACTIVATE_SERVER_TLS_AUTH).getAsBoolean();
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public String getKeyStorePassword() {
+ return getEncryptedStringConfig(KEY_STORE_KEY);
+ }
+
+ @Override
+ public String getKeyStorePath() {
+ return getStringConfig(KEY_STORE_PATH);
+ }
+
+ /**
+ * This method can be used to validate all required parameters are well
+ * there.
+ */
+ public void testAllRequiredParameters() {
+ // Special case for this attribute that can be null from
+ // getConsumerGroup
+ if (jsonRootNode == null) {
+ throw new SdcParametersException("Json is null for controller " + this.getSdcControllerName());
+ }
+ if (this.getConsumerGroup() == null && (jsonRootNode.get(CONSUMER_GROUP_ATTRIBUTE_NAME) == null
+ || !"NULL".equals(jsonRootNode.get(CONSUMER_GROUP_ATTRIBUTE_NAME).getAsString()))) {
+ throw new SdcParametersException(CONSUMER_GROUP_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getConsumerID() == null || this.getConsumerID().isEmpty()) {
+ throw new SdcParametersException(CONSUMER_ID_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getEnvironmentName() == null || this.getEnvironmentName().isEmpty()) {
+ throw new SdcParametersException(ENVIRONMENT_NAME_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getAsdcAddress() == null || this.getAsdcAddress().isEmpty()) {
+ throw new SdcParametersException(SDC_ADDRESS_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getMsgBusAddress() == null || this.getMsgBusAddress().isEmpty()) {
+ throw new SdcParametersException(MESSAGE_BUS_ADDRESSES + errorMessageKeyNotFound);
+ }
+ if (this.getPassword() == null || this.getPassword().isEmpty()) {
+ throw new SdcParametersException(SDC_KEY_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getPollingInterval() == 0) {
+ throw new SdcParametersException(POLLING_INTERVAL_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getPollingTimeout() == 0) {
+ throw new SdcParametersException(POLLING_TIMEOUT_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getRelevantArtifactTypes() == null || this.getRelevantArtifactTypes().isEmpty()) {
+ throw new SdcParametersException(RELEVANT_ARTIFACT_TYPES_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ if (this.getUser() == null || this.getUser().isEmpty()) {
+ throw new SdcParametersException(USER_ATTRIBUTE_NAME + errorMessageKeyNotFound);
+ }
+ }
+
+ /**
+ * The flag allows the client to receive metadata for all resources of the
+ * service regardless of the artifacts associated to them. Setting the flag
+ * to false will preserve legacy behavior.
+ */
+ @Override
+ public boolean isFilterInEmptyResources() {
+ return false;
+ }
+
+ @Override
+ public List<String> getMsgBusAddress() {
+ List<String> addressesList = new ArrayList<>();
+ if (jsonRootNode != null && jsonRootNode.get(MESSAGE_BUS_ADDRESSES) != null) {
+ jsonRootNode.get(MESSAGE_BUS_ADDRESSES).getAsJsonArray().forEach(k -> addressesList.add(k.getAsString()));
+ return addressesList;
+ } else {
+ return addressesList;
+ }
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/config/spring/CldsConfiguration.java b/runtime/src/main/java/org/onap/policy/clamp/clds/config/spring/CldsConfiguration.java
new file mode 100644
index 000000000..72f09ce13
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/config/spring/CldsConfiguration.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.config.spring;
+
+import org.onap.policy.clamp.clds.config.ClampProperties;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.PropertiesFactoryBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+@Configuration
+@Profile("clamp-default")
+public class CldsConfiguration {
+
+ @Autowired
+ private ApplicationContext appContext;
+ @Autowired
+ private ClampProperties refProp;
+
+
+ /**
+ * This loads the file system.properties.
+ *
+ * @return The PropertiesFactoryBean
+ */
+ @Bean(name = "mapper")
+ public PropertiesFactoryBean mapper() {
+ PropertiesFactoryBean bean = new PropertiesFactoryBean();
+ bean.setLocation(appContext.getResource(refProp.getStringValue("files.systemProperties")));
+ return bean;
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/config/spring/SdcControllerConfiguration.java b/runtime/src/main/java/org/onap/policy/clamp/clds/config/spring/SdcControllerConfiguration.java
new file mode 100644
index 000000000..6005b0d39
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/config/spring/SdcControllerConfiguration.java
@@ -0,0 +1,110 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.config.spring;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.util.ArrayList;
+import java.util.List;
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import org.onap.policy.clamp.clds.config.ClampProperties;
+import org.onap.policy.clamp.clds.config.sdc.SdcControllersConfiguration;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcControllerException;
+import org.onap.policy.clamp.clds.sdc.controller.SdcSingleController;
+import org.onap.policy.clamp.clds.sdc.controller.SdcSingleControllerStatus;
+import org.onap.policy.clamp.loop.CsarInstaller;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.scheduling.annotation.Scheduled;
+
+@Configuration
+@Profile("clamp-sdc-controller")
+public class SdcControllerConfiguration {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(SdcControllerConfiguration.class);
+ private List<SdcSingleController> sdcControllersList = new ArrayList<>();
+ private final ClampProperties clampProp;
+ private final CsarInstaller csarInstaller;
+
+ @Autowired
+ public SdcControllerConfiguration(ClampProperties clampProp,
+ @Qualifier("csarInstaller") CsarInstaller csarInstaller) {
+ this.clampProp = clampProp;
+ this.csarInstaller = csarInstaller;
+ }
+
+ /**
+ * Loads SDC controller configuration.
+ */
+ @PostConstruct
+ public void loadSdcControllers() {
+ SdcControllersConfiguration sdcControllersConfig = getSdcControllersConfiguration();
+ sdcControllersConfig.getAllDefinedControllers().forEach((key, value) -> {
+ logger.info("Creating controller instance:" + key);
+ SdcSingleController sdcController = new SdcSingleController(clampProp, csarInstaller, value, null);
+ sdcControllersList.add(sdcController);
+ });
+ }
+
+ /**
+ * Checks whether all SDC controllers defined are up and running.
+ */
+ @Scheduled(fixedRate = 120000)
+ public void checkAllSdcControllers() {
+ logger.info("Checking that all SDC Controllers defined are up and running");
+ for (SdcSingleController controller : sdcControllersList) {
+ try {
+ if (SdcSingleControllerStatus.STOPPED.equals(controller.getControllerStatus())) {
+ controller.initSdc();
+ }
+ } catch (SdcControllerException e) {
+ logger.error("Exception caught when booting sdc controller", e);
+ }
+ }
+ logger.info("SDC Controllers check completed");
+ }
+
+ /**
+ * Closes all SDC Controller and the SDC Client.
+ */
+ @PreDestroy
+ public void killSdcControllers() {
+ sdcControllersList.forEach(e -> {
+ try {
+ e.closeSdc();
+ } catch (SdcControllerException e1) {
+ logger.error("Exception caught when stopping sdc controller", e1);
+ }
+ });
+ }
+
+ @Bean(name = "sdcControllersConfiguration")
+ public SdcControllersConfiguration getSdcControllersConfiguration() {
+ return new SdcControllersConfiguration();
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/exception/CldsConfigException.java b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/CldsConfigException.java
new file mode 100644
index 000000000..ef1ced0a3
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/CldsConfigException.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.exception;
+
+/**
+ * New exception to CldsUser errors.
+ *
+ */
+public class CldsConfigException extends RuntimeException {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 5958873136187918505L;
+
+ /**
+ * This constructor can be used to create a new CldsConfigException.
+ *
+ * @param message
+ * A string message detailing the problem
+ * @param ex
+ * The exception sent by the code
+ */
+ public CldsConfigException(String message, Throwable ex) {
+ super(message, ex);
+ }
+
+ /**
+ * This constructor can be used to create a new CldsConfigException. Use
+ * this constructor only if you are creating a new exception stack, not if
+ * an exception was already raised by another code.
+ *
+ * @param message
+ * A string message detailing the problem
+ */
+ public CldsConfigException(String message) {
+ super(message);
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/exception/CldsUsersException.java b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/CldsUsersException.java
new file mode 100644
index 000000000..4d4855b6f
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/CldsUsersException.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.exception;
+
+/**
+ * New exception to CldsUser errors.
+ *
+ */
+public class CldsUsersException extends RuntimeException {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 933535057227505342L;
+
+ /**
+ * This constructor can be used to create a new CldsUsersException.
+ *
+ * @param message
+ * A string message detailing the problem
+ * @param ex
+ * The exception sent by the code
+ */
+ public CldsUsersException(String message, Throwable ex) {
+ super(message, ex);
+ }
+
+ /**
+ * This constructor can be used to create a new CldsUsersException. Use this
+ * constructor only if you are creating a new exception stack, not if an
+ * exception was already raised by another code.
+ *
+ * @param message
+ * A string message detailing the problem
+ */
+ public CldsUsersException(String message) {
+ super(message);
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/exception/NotAuthorizedException.java b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/NotAuthorizedException.java
new file mode 100644
index 000000000..73c117932
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/NotAuthorizedException.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.exception;
+
+/**
+ * New exception to request errors.
+ *
+ */
+public class NotAuthorizedException extends RuntimeException {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = -5738167530541646123L;
+
+ /**
+ * This constructor can be used to create a new CldsConfigException.
+ *
+ * @param message
+ * A string message detailing the problem
+ * @param ex
+ * The exception sent by the code
+ */
+ public NotAuthorizedException(String message, Throwable ex) {
+ super(message, ex);
+ }
+
+ /**
+ * This constructor can be used to create a new CldsConfigException. Use this
+ * constructor only if you are creating a new exception stack, not if an
+ * exception was already raised by another code.
+ *
+ * @param message
+ * A string message detailing the problem
+ */
+ public NotAuthorizedException(String message) {
+ super(message);
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/exception/cds/CdsParametersException.java b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/cds/CdsParametersException.java
new file mode 100644
index 000000000..b4a013eb4
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/cds/CdsParametersException.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ * ================================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.exception.cds;
+
+/**
+ * Exception while parsing CDS response.
+ */
+public class CdsParametersException extends RuntimeException {
+
+ /**
+ * serialization id.
+ */
+ private static final long serialVersionUID = 8425657297510362736L;
+
+ /**
+ * This constructor can be used to create a new CdsParametersException.
+ *
+ * @param message The message to dump
+ */
+ public CdsParametersException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new CdsParametersException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public CdsParametersException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/exception/dcae/DcaeDeploymentException.java b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/dcae/DcaeDeploymentException.java
new file mode 100644
index 000000000..78c2c6331
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/dcae/DcaeDeploymentException.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.exception.dcae;
+
+/**
+ * New exception to capture DCAE communication errors.
+ *
+ */
+public class DcaeDeploymentException extends RuntimeException {
+
+ /**
+ * Generated ID.
+ */
+ private static final long serialVersionUID = 8452294782552680243L;
+
+ /**
+ * This constructor can be used to create a new DcaeDeploymentException.
+ *
+ * @param message
+ * A string message detailing the problem
+ * @param ex
+ * The exception sent by the code
+ */
+ public DcaeDeploymentException(String message, Throwable ex) {
+ super(message, ex);
+ }
+
+ /**
+ * This constructor can be used to create a new DcaeDeploymentException. Use
+ * this constructor only if you are creating a new exception stack, not if
+ * an exception was already raised by another code.
+ *
+ * @param message
+ * A string message detailing the problem
+ */
+ public DcaeDeploymentException(String message) {
+ super(message);
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/BlueprintParserException.java b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/BlueprintParserException.java
new file mode 100644
index 000000000..6939fdf06
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/BlueprintParserException.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.exception.sdc.controller;
+
+/**
+ * Exception during blueprint parsing.
+ */
+public class BlueprintParserException extends Exception {
+
+ /**
+ * Serial ID.
+ */
+ private static final long serialVersionUID = -3044162346353623199L;
+
+ /**
+ * This constructor can be used to create a new SdcDownloadException.
+ *
+ * @param message The message to dump
+ */
+ public BlueprintParserException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new SdcDownloadException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public BlueprintParserException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/CsarHandlerException.java b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/CsarHandlerException.java
new file mode 100644
index 000000000..e3f16f908
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/CsarHandlerException.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.exception.sdc.controller;
+
+/**
+ * Exception during Csar operations.
+ */
+public class CsarHandlerException extends Exception {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = -7628640776124409155L;
+
+ /**
+ * This constructor can be used to create a new CsarHandlerException.
+ *
+ * @param message The message to dump
+ */
+ public CsarHandlerException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new CsarHandlerException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public CsarHandlerException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcArtifactInstallerException.java b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcArtifactInstallerException.java
new file mode 100644
index 000000000..1202ec199
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcArtifactInstallerException.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.exception.sdc.controller;
+
+/**
+ * Exception during SDC artifact installation.
+ */
+public class SdcArtifactInstallerException extends Exception {
+
+ /**
+ * serialization id.
+ */
+ private static final long serialVersionUID = 4095937499475915021L;
+
+ /**
+ * This constructor can be used to create a new SdcArtifactInstallerException.
+ *
+ * @param message The message to dump
+ */
+ public SdcArtifactInstallerException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new SdcArtifactInstallerException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public SdcArtifactInstallerException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcControllerException.java b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcControllerException.java
new file mode 100644
index 000000000..e391ee7e8
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcControllerException.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.exception.sdc.controller;
+
+/**
+ * Exception of the SDC controller.
+ */
+public class SdcControllerException extends Exception {
+
+ /**
+ * serialization id.
+ */
+ private static final long serialVersionUID = -4236006447255525130L;
+
+ /**
+ * This constructor can be used to create a new SdcControllerException.
+ *
+ * @param message The message to dump
+ */
+ public SdcControllerException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new SdcControllerException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public SdcControllerException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcDownloadException.java b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcDownloadException.java
new file mode 100644
index 000000000..3c0240ef3
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcDownloadException.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.exception.sdc.controller;
+
+/**
+ * Exception during download from SDC.
+ */
+public class SdcDownloadException extends Exception {
+
+ /**
+ * serialization id.
+ */
+ private static final long serialVersionUID = -5276848693231134901L;
+
+ /**
+ * This constructor can be used to create a new SdcDownloadException.
+ *
+ * @param message The message to dump
+ */
+ public SdcDownloadException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new SdcDownloadException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public SdcDownloadException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcParametersException.java b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcParametersException.java
new file mode 100644
index 000000000..fe573882f
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/exception/sdc/controller/SdcParametersException.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.exception.sdc.controller;
+
+/**
+ * Exception of the SDC controller.
+ */
+public class SdcParametersException extends RuntimeException {
+
+ /**
+ * serialization id.
+ */
+ private static final long serialVersionUID = 8425657297510362736L;
+
+ /**
+ * This constructor can be used to create a new SdcParametersException.
+ *
+ * @param message The message to dump
+ */
+ public SdcParametersException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new SdcParametersException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public SdcParametersException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/filter/ClampCadiFilter.java b/runtime/src/main/java/org/onap/policy/clamp/clds/filter/ClampCadiFilter.java
new file mode 100644
index 000000000..6fa8ecb2b
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/filter/ClampCadiFilter.java
@@ -0,0 +1,190 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.filter;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLDecoder;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.StandardCopyOption;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import org.onap.aaf.cadi.config.Config;
+import org.onap.aaf.cadi.filter.CadiFilter;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.ApplicationContext;
+
+public class ClampCadiFilter extends CadiFilter {
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(ClampCadiFilter.class);
+
+ @Autowired
+ private ApplicationContext appContext;
+
+ @Value("${server.ssl.key-store:#{null}}")
+ private String keyStore;
+
+ @Value("${server.ssl.key-store-password:#{null}}")
+ private String keyStorePass;
+
+ @Value("${server.ssl.trust-store:#{null}}")
+ private String trustStore;
+
+ @Value("${server.ssl.trust-store-password:#{null}}")
+ private String trustStorePass;
+
+ @Value("${server.ssl.key-alias:clamp@clamp.onap.org}")
+ private String alias;
+
+ @Value("${clamp.config.keyFile:#{null}}")
+ private String keyFile;
+
+ @Value("${clamp.config.cadi.cadiLoglevel:#{null}}")
+ private String cadiLoglevel;
+
+ @Value("${clamp.config.cadi.cadiLatitude:#{null}}")
+ private String cadiLatitude;
+
+ @Value("${clamp.config.cadi.cadiLongitude:#{null}}")
+ private String cadiLongitude;
+
+ @Value("${clamp.config.cadi.aafLocateUrl:#{null}}")
+ private String aafLocateUrl;
+
+ @Value("${clamp.config.cadi.oauthTokenUrl:#{null}}")
+ private String oauthTokenUrl;
+
+ @Value("${clamp.config.cadi.oauthIntrospectUrl:#{null}}")
+ private String oauthIntrospectUrl;
+
+ @Value("${clamp.config.cadi.aafEnv:#{null}}")
+ private String aafEnv;
+
+ @Value("${clamp.config.cadi.aafUrl:#{null}}")
+ private String aafUrl;
+
+ @Value("${clamp.config.cadi.cadiX509Issuers:#{null}}")
+ private String cadiX509Issuers;
+
+ @Value("${clamp.config.caCerts:#{null}}")
+ private String caCertsPath;
+
+ private void checkIfNullProperty(String key, String value) {
+ /*
+ * When value is null, so not defined in application.properties set nothing in
+ * System properties
+ */
+ if (value != null) {
+ /*
+ * Ensure that any properties already defined in System.prop by JVM params won't
+ * be overwritten by Spring application.properties values
+ */
+ System.setProperty(key, System.getProperty(key, value));
+ }
+ }
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ // set some properties in System so that Cadi filter will find its config
+ // The JVM values set will always overwrite the Spring ones.
+ checkIfNullProperty(Config.CADI_KEYFILE, convertSpringToPath(keyFile));
+ checkIfNullProperty(Config.CADI_LOGLEVEL, cadiLoglevel);
+ checkIfNullProperty(Config.CADI_LATITUDE, cadiLatitude);
+ checkIfNullProperty(Config.CADI_LONGITUDE, cadiLongitude);
+
+ checkIfNullProperty(Config.AAF_LOCATE_URL, aafLocateUrl);
+ checkIfNullProperty(Config.AAF_OAUTH2_TOKEN_URL, oauthTokenUrl);
+ checkIfNullProperty(Config.AAF_OAUTH2_INTROSPECT_URL, oauthIntrospectUrl);
+
+ checkIfNullProperty(Config.AAF_ENV, aafEnv);
+ checkIfNullProperty(Config.AAF_URL, aafUrl);
+ checkIfNullProperty(Config.CADI_X509_ISSUERS, cadiX509Issuers);
+ checkIfNullProperty(Config.CADI_KEYSTORE, convertSpringToPath(keyStore));
+ checkIfNullProperty(Config.CADI_TRUSTSTORE, convertSpringToPath(trustStore));
+ checkIfNullProperty(Config.CADI_ALIAS, alias);
+ checkIfNullProperty(Config.CADI_KEYSTORE_PASSWORD, keyStorePass);
+ checkIfNullProperty(Config.CADI_TRUSTSTORE_PASSWORD, trustStorePass);
+
+ super.init(filterConfig);
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ try {
+ String certHeader = ((HttpServletRequest) request).getHeader("X-SSL-Cert");
+ if (certHeader != null) {
+ CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
+ X509Certificate cert = (X509Certificate) certificateFactory
+ .generateCertificate(new ByteArrayInputStream(
+ URLDecoder.decode(certHeader, StandardCharsets.UTF_8.toString()).getBytes()));
+ X509Certificate caCert = (X509Certificate) certificateFactory
+ .generateCertificate(new ByteArrayInputStream(
+ ResourceFileUtils.getResourceAsString(this.caCertsPath).getBytes()));
+
+ X509Certificate[] certifArray = ((X509Certificate[]) request
+ .getAttribute("javax.servlet.request.X509Certificate"));
+ if (certifArray == null) {
+ certifArray = new X509Certificate[] { cert, caCert };
+ request.setAttribute("javax.servlet.request.X509Certificate", certifArray);
+ } else {
+ certifArray[0] = cert;
+ certifArray[1] = caCert;
+ }
+ }
+
+ } catch (CertificateException e) {
+ logger.error("Unable to inject the X.509 certificate", e);
+ }
+ super.doFilter(request, response, chain);
+ }
+
+ private String convertSpringToPath(String fileName) {
+ try (InputStream ioFile = appContext.getResource(fileName).getInputStream()) {
+ if (!fileName.contains("file:")) {
+ File targetFile = new File(appContext.getResource(fileName).getFilename());
+ java.nio.file.Files.copy(ioFile, targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ return targetFile.getPath();
+ } else {
+ return appContext.getResource(fileName).getFile().getPath();
+ }
+ } catch (IOException e) {
+ logger.error("Unable to open and copy the file: " + fileName, e);
+ return null;
+ }
+
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/model/ClampInformation.java b/runtime/src/main/java/org/onap/policy/clamp/clds/model/ClampInformation.java
new file mode 100644
index 000000000..5708cb6ec
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/model/ClampInformation.java
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.model;
+
+import com.google.gson.annotations.Expose;
+import java.util.ArrayList;
+import java.util.List;
+import org.onap.policy.clamp.clds.util.ClampVersioning;
+
+public class ClampInformation {
+ @Expose
+ private String userName;
+ @Expose
+ private String cldsVersion = ClampVersioning.getCldsVersionFromProps();
+ @Expose
+ List<String> allPermissions = new ArrayList<>();
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getCldsVersion() {
+ return cldsVersion;
+ }
+
+ public void setCldsVersion(String cldsVersion) {
+ this.cldsVersion = cldsVersion;
+ }
+
+ public List<String> getAllPermissions() {
+ return allPermissions;
+ }
+
+ public void setAllPermissions(List<String> allPermissions) {
+ this.allPermissions = allPermissions;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/model/CldsHealthCheck.java b/runtime/src/main/java/org/onap/policy/clamp/clds/model/CldsHealthCheck.java
new file mode 100644
index 000000000..c814a628d
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/model/CldsHealthCheck.java
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.model;
+
+import com.google.gson.annotations.Expose;
+
+public class CldsHealthCheck {
+ @Expose
+ private String healthCheckComponent;
+ @Expose
+ private String healthCheckStatus;
+ @Expose
+ private String description;
+
+ public String getHealthCheckComponent() {
+ return healthCheckComponent;
+ }
+
+ public void setHealthCheckComponent(String healthCheckComponent) {
+ this.healthCheckComponent = healthCheckComponent;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getHealthCheckStatus() {
+ return healthCheckStatus;
+ }
+
+ public void setHealthCheckStatus(String healthCheckStatus) {
+ this.healthCheckStatus = healthCheckStatus;
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java b/runtime/src/main/java/org/onap/policy/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java
new file mode 100644
index 000000000..a3b42524e
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/model/cds/CdsBpWorkFlowListResponse.java
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ * ================================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.model.cds;
+
+import com.google.gson.annotations.Expose;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * This class maps the CDS response to a pojo.
+ */
+public class CdsBpWorkFlowListResponse {
+
+ @Expose
+ private String blueprintName;
+
+ @Expose
+ private String version;
+
+ @Expose
+ private List<String> workflows = new LinkedList<String>();
+
+ public String getBlueprintName() {
+ return blueprintName;
+ }
+
+ public void setBlueprintName(String blueprintName) {
+ this.blueprintName = blueprintName;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public List<String> getWorkflows() {
+ return workflows;
+ }
+
+ public void setWorkflows(List<String> workflows) {
+ this.workflows = workflows;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryCache.java b/runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryCache.java
new file mode 100644
index 000000000..a69d1a353
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryCache.java
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.model.dcae;
+
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * This class stores the multiple DcaeInventoryResponse coming back from DCAE.
+ * The structure is a map of list indexed by asdcServiceId. The list is sorted
+ * by asdcResourceId. Therefore it's possible to retrieve all the loops defined
+ * in the DCAE inventory and created by DCAE Mod.
+ */
+public class DcaeInventoryCache {
+
+ private static Map<String, Set<DcaeInventoryResponse>> blueprintsMap = new ConcurrentHashMap<>();
+
+ /**
+ * Add Dcae inventory response.
+ *
+ * @param inventoryResponse the Dcae inventory response
+ */
+ public void addDcaeInventoryResponse(DcaeInventoryResponse inventoryResponse) {
+ Set<DcaeInventoryResponse> responsesSet = blueprintsMap.get(inventoryResponse.getAsdcServiceId());
+ if (responsesSet == null) {
+ responsesSet = new TreeSet<>();
+ blueprintsMap.put(inventoryResponse.getAsdcServiceId(), responsesSet);
+ }
+ responsesSet.add(inventoryResponse);
+ }
+
+ public Set<String> getAllLoopIds() {
+ return this.blueprintsMap.keySet();
+ }
+
+ public Set<DcaeInventoryResponse> getAllBlueprintsPerLoopId(String loopId) {
+ return blueprintsMap.getOrDefault(loopId, new TreeSet<>());
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryResponse.java b/runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryResponse.java
new file mode 100644
index 000000000..72ae61359
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryResponse.java
@@ -0,0 +1,102 @@
+
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.model.dcae;
+
+import com.google.gson.annotations.Expose;
+
+/**
+ * This class maps the DCAE inventory answer to a nice pojo.
+ */
+public class DcaeInventoryResponse implements Comparable<DcaeInventoryResponse> {
+
+ @Expose
+ private String typeName;
+
+ @Expose
+ private String typeId;
+
+ @Expose
+ private String blueprintTemplate;
+
+ /**
+ * This field will be used to know all blueprints associated a loop.
+ */
+ @Expose
+ private String asdcServiceId;
+
+ /**
+ * This field will be used to know to order of each blueprint microservice in a
+ * loop.
+ */
+ @Expose
+ private String asdcResourceId;
+
+ public String getTypeName() {
+ return typeName;
+ }
+
+ public void setTypeName(String typeName) {
+ this.typeName = typeName;
+ }
+
+ public String getTypeId() {
+ return typeId;
+ }
+
+ public void setTypeId(String typeId) {
+ this.typeId = typeId;
+ }
+
+ public String getBlueprintTemplate() {
+ return blueprintTemplate;
+ }
+
+ public void setBlueprintTemplate(String blueprintTemplate) {
+ this.blueprintTemplate = blueprintTemplate;
+ }
+
+ public String getAsdcServiceId() {
+ return asdcServiceId;
+ }
+
+ public void setAsdcServiceId(String asdcServiceId) {
+ this.asdcServiceId = asdcServiceId;
+ }
+
+ public String getAsdcResourceId() {
+ return asdcResourceId;
+ }
+
+ public void setAsdcResourceId(String asdcResourceId) {
+ this.asdcResourceId = asdcResourceId;
+ }
+
+ @Override
+ public int compareTo(DcaeInventoryResponse otherResponse) {
+ int thisResourceId = Integer.parseInt(this.asdcResourceId);
+ int otherResourceId = Integer.parseInt(otherResponse.getAsdcResourceId());
+ return (thisResourceId < otherResourceId ? -1 : (thisResourceId > otherResourceId ? 1 : 0));
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeLinks.java b/runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeLinks.java
new file mode 100644
index 000000000..4d6e544da
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeLinks.java
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.model.dcae;
+
+import com.google.gson.annotations.Expose;
+
+public class DcaeLinks {
+ @Expose
+ private String self;
+ @Expose
+ private String status;
+ @Expose
+ private String uninstall;
+
+ public String getSelf() {
+ return self;
+ }
+
+ public void setSelf(String self) {
+ this.self = self;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public String getUninstall() {
+ return uninstall;
+ }
+
+ public void setUninstall(String uninstall) {
+ this.uninstall = uninstall;
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeOperationStatusResponse.java b/runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeOperationStatusResponse.java
new file mode 100644
index 000000000..9389a51fc
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/model/dcae/DcaeOperationStatusResponse.java
@@ -0,0 +1,88 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.model.dcae;
+
+import com.google.gson.annotations.Expose;
+
+/**
+ * This class maps the DCAE deployment handler response to a nice pojo.
+ */
+public class DcaeOperationStatusResponse {
+
+ @Expose
+ private String operationType;
+
+ @Expose
+ private String status;
+
+ @Expose
+ private String requestId;
+
+ @Expose
+ private String error;
+
+ @Expose
+ private DcaeLinks links;
+
+ public String getOperationType() {
+ return operationType;
+ }
+
+ public void setOperationType(String operationType) {
+ this.operationType = operationType;
+ }
+
+ public String getStatus() {
+ return status;
+ }
+
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public String getRequestId() {
+ return requestId;
+ }
+
+ public void setRequestId(String requestId) {
+ this.requestId = requestId;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public void setError(String error) {
+ this.error = error;
+ }
+
+ public DcaeLinks getLinks() {
+ return links;
+ }
+
+ public void setLinks(DcaeLinks links) {
+ this.links = links;
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/DistributionStatusMessage.java b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/DistributionStatusMessage.java
new file mode 100644
index 000000000..ca46c6d31
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/DistributionStatusMessage.java
@@ -0,0 +1,84 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.sdc.controller;
+
+import org.onap.sdc.api.consumer.IDistributionStatusMessage;
+import org.onap.sdc.utils.DistributionStatusEnum;
+
+public class DistributionStatusMessage implements IDistributionStatusMessage {
+
+ private String artifactUrl;
+ private String consumerId;
+ private String distributionId;
+ private DistributionStatusEnum distributionStatus;
+ private long timestamp;
+
+ /**
+ * Distribution status message constructor.
+ *
+ * @param artifactUrl
+ * Url of specific SDC artifact(resource)
+ * @param consumerId
+ * Unique ID of SDC component instance
+ * @param distributionId
+ * Distribution ID published in the distribution notification.
+ * @param distributionStatusEnum
+ * Status to send in the message
+ * @param timestamp
+ * Timestamp of the message
+ */
+ public DistributionStatusMessage(final String artifactUrl, final String consumerId, final String distributionId,
+ final DistributionStatusEnum distributionStatusEnum, final long timestamp) {
+ this.artifactUrl = artifactUrl;
+ this.consumerId = consumerId;
+ this.distributionId = distributionId;
+ this.distributionStatus = distributionStatusEnum;
+ this.timestamp = timestamp;
+ }
+
+ @Override
+ public String getArtifactURL() {
+ return artifactUrl;
+ }
+
+ @Override
+ public String getConsumerID() {
+ return consumerId;
+ }
+
+ @Override
+ public String getDistributionID() {
+ return distributionId;
+ }
+
+ @Override
+ public DistributionStatusEnum getStatus() {
+ return distributionStatus;
+ }
+
+ @Override
+ public long getTimestamp() {
+ return timestamp;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/SdcSingleController.java b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/SdcSingleController.java
new file mode 100644
index 000000000..39e64e46b
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/SdcSingleController.java
@@ -0,0 +1,438 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2018-2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * Modifications copyright (c) 2018 Nokia
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.sdc.controller;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.security.SecureRandom;
+import java.util.Date;
+import java.util.Map.Entry;
+import org.onap.policy.clamp.clds.config.ClampProperties;
+import org.onap.policy.clamp.clds.config.sdc.SdcSingleControllerConfiguration;
+import org.onap.policy.clamp.clds.exception.sdc.controller.BlueprintParserException;
+import org.onap.policy.clamp.clds.exception.sdc.controller.CsarHandlerException;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcControllerException;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcDownloadException;
+import org.onap.policy.clamp.clds.sdc.controller.installer.BlueprintArtifact;
+import org.onap.policy.clamp.clds.sdc.controller.installer.CsarHandler;
+import org.onap.policy.clamp.clds.util.LoggingUtils;
+import org.onap.policy.clamp.loop.CsarInstaller;
+import org.onap.sdc.api.IDistributionClient;
+import org.onap.sdc.api.consumer.IComponentDoneStatusMessage;
+import org.onap.sdc.api.consumer.IDistributionStatusMessage;
+import org.onap.sdc.api.consumer.INotificationCallback;
+import org.onap.sdc.api.notification.IArtifactInfo;
+import org.onap.sdc.api.notification.INotificationData;
+import org.onap.sdc.api.results.IDistributionClientDownloadResult;
+import org.onap.sdc.api.results.IDistributionClientResult;
+import org.onap.sdc.impl.DistributionClientFactory;
+import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;
+import org.onap.sdc.utils.DistributionActionResultEnum;
+import org.onap.sdc.utils.DistributionStatusEnum;
+
+/**
+ * This class handles one sdc controller defined in the config.
+ */
+public class SdcSingleController {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(SdcSingleController.class);
+ private boolean isSdcClientAutoManaged = false;
+ private CsarInstaller csarInstaller;
+ private ClampProperties refProp;
+ /**
+ * The constant CONFIG_SDC_FOLDER.
+ */
+ public static final String CONFIG_SDC_FOLDER = "sdc.csarFolder";
+ private int nbOfNotificationsOngoing = 0;
+ private SdcSingleControllerStatus controllerStatus = SdcSingleControllerStatus.STOPPED;
+ private SdcSingleControllerConfiguration sdcConfig;
+ private IDistributionClient distributionClient;
+
+ /**
+ * Inner class for Notification callback.
+ */
+ private final class SdcNotificationCallBack implements INotificationCallback {
+
+ private SdcSingleController sdcController;
+
+ /**
+ * Instantiates a new Sdc notification call back.
+ *
+ * @param controller the controller
+ */
+ SdcNotificationCallBack(SdcSingleController controller) {
+ sdcController = controller;
+ }
+
+ /**
+ * This method can be called multiple times at the same moment. The controller
+ * must be thread safe !
+ */
+ @Override
+ public void activateCallback(INotificationData notificationData) {
+ Date startTime = new Date();
+ logger.info("Receive a callback notification in SDC, nb of resources: "
+ + notificationData.getResources().size());
+ sdcController.treatNotification(notificationData);
+ LoggingUtils.setTimeContext(startTime, new Date());
+ LoggingUtils.setResponseContext("0", "SDC Notification received and processed successfully",
+ this.getClass().getName());
+ }
+ }
+
+ /**
+ * Gets nb of notifications ongoing.
+ *
+ * @return the nb of notifications ongoing
+ */
+ public int getNbOfNotificationsOngoing() {
+ return nbOfNotificationsOngoing;
+ }
+
+ private void changeControllerStatusIdle() {
+ if (this.nbOfNotificationsOngoing > 1) {
+ --this.nbOfNotificationsOngoing;
+ } else {
+ this.nbOfNotificationsOngoing = 0;
+ this.controllerStatus = SdcSingleControllerStatus.IDLE;
+ }
+ }
+
+ /**
+ * Change controller status.
+ *
+ * @param newControllerStatus the new controller status
+ */
+ protected final synchronized void changeControllerStatus(SdcSingleControllerStatus newControllerStatus) {
+ switch (newControllerStatus) {
+ case BUSY:
+ ++this.nbOfNotificationsOngoing;
+ this.controllerStatus = newControllerStatus;
+ break;
+ case IDLE:
+ this.changeControllerStatusIdle();
+ break;
+ default:
+ this.controllerStatus = newControllerStatus;
+ break;
+ }
+ }
+
+ /**
+ * Gets controller status.
+ *
+ * @return the controller status
+ */
+ public final synchronized SdcSingleControllerStatus getControllerStatus() {
+ return this.controllerStatus;
+ }
+
+ /**
+ * Instantiates a new Sdc single controller.
+ *
+ * @param clampProp the clamp prop
+ * @param csarInstaller the csar installer
+ * @param sdcSingleConfig the sdc single config
+ * @param distributionClient the distribution client
+ */
+ public SdcSingleController(ClampProperties clampProp, CsarInstaller csarInstaller,
+ SdcSingleControllerConfiguration sdcSingleConfig,
+ IDistributionClient distributionClient) {
+ this.distributionClient = distributionClient;
+ isSdcClientAutoManaged = (distributionClient == null);
+ this.sdcConfig = sdcSingleConfig;
+ this.refProp = clampProp;
+ this.csarInstaller = csarInstaller;
+ }
+
+ /**
+ * This method initializes the SDC Controller and the SDC Client.
+ *
+ * @throws SdcControllerException It throws an exception if the SDC Client
+ * cannot be instantiated or if an init attempt
+ * is done when already initialized
+ */
+ public void initSdc() throws SdcControllerException {
+ logger.info("Attempt to initialize the SDC Controller: " + sdcConfig.getSdcControllerName());
+ if (this.getControllerStatus() != SdcSingleControllerStatus.STOPPED) {
+ throw new SdcControllerException("The controller is already initialized, call the closeSDC method first");
+ }
+ if (distributionClient == null) {
+ distributionClient = DistributionClientFactory.createDistributionClient();
+ }
+ IDistributionClientResult result = distributionClient.init(sdcConfig, new SdcNotificationCallBack(this));
+ if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+ logger.error("SDC distribution client init failed with reason:" + result.getDistributionMessageResult());
+ this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);
+ throw new SdcControllerException("Initialization of the SDC Controller failed with reason: "
+ + result.getDistributionMessageResult());
+ }
+ logger.info("SDC Controller successfully initialized: " + sdcConfig.getSdcControllerName());
+ logger.info("Attempt to start the SDC Controller: " + sdcConfig.getSdcControllerName());
+ result = this.distributionClient.start();
+ if (!result.getDistributionActionResult().equals(DistributionActionResultEnum.SUCCESS)) {
+ logger.error("SDC distribution client start failed with reason:" + result.getDistributionMessageResult());
+ this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);
+ throw new SdcControllerException(
+ "Startup of the SDC Controller failed with reason: " + result.getDistributionMessageResult());
+ }
+ logger.info("SDC Controller successfully started: " + sdcConfig.getSdcControllerName());
+ this.changeControllerStatus(SdcSingleControllerStatus.IDLE);
+ }
+
+ /**
+ * This method closes the SDC Controller and the SDC Client.
+ *
+ * @throws SdcControllerException It throws an exception if the SDC Client
+ * cannot be closed because it's currently BUSY
+ * in processing notifications.
+ */
+ public void closeSdc() throws SdcControllerException {
+ if (this.getControllerStatus() == SdcSingleControllerStatus.BUSY) {
+ throw new SdcControllerException("Cannot close the SDC controller as it's currently in BUSY state");
+ }
+ if (this.distributionClient != null) {
+ this.distributionClient.stop();
+ // If auto managed we can set it to Null, SdcController controls it.
+ // In the other case the client of this class has specified it, so
+ // we can't reset it
+ if (isSdcClientAutoManaged) {
+ // Next init will initialize it with a new SDC Client
+ this.distributionClient = null;
+ }
+ }
+ this.changeControllerStatus(SdcSingleControllerStatus.STOPPED);
+ }
+
+ private void sendAllNotificationForCsarHandler(INotificationData notificationData, CsarHandler csar,
+ NotificationType notificationType,
+ DistributionStatusEnum distributionStatus, String errorMessage) {
+ if (csar != null) {
+ // Notify for the CSAR
+ this.sendSdcNotification(notificationType, csar.getArtifactElement().getArtifactURL(),
+ sdcConfig.getConsumerID(), notificationData.getDistributionID(), distributionStatus, errorMessage,
+ System.currentTimeMillis());
+ // Notify for all VF resources found
+ for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) {
+ // Normally always 1 artifact in resource for Clamp as we
+ // specified
+ // only VF_METADATA type
+ this.sendSdcNotification(notificationType,
+ blueprint.getValue().getResourceAttached().getArtifacts().get(0).getArtifactURL(),
+ sdcConfig.getConsumerID(), notificationData.getDistributionID(), distributionStatus,
+ errorMessage, System.currentTimeMillis());
+ }
+ } else {
+ this.sendSdcNotification(notificationType, null, sdcConfig.getConsumerID(),
+ notificationData.getDistributionID(), distributionStatus, errorMessage, System.currentTimeMillis());
+ }
+ }
+
+ /**
+ * This method processes the notification received from Sdc.
+ *
+ * @param notificationData The INotificationData
+ */
+ public void treatNotification(INotificationData notificationData) {
+ CsarHandler csar = null;
+ try {
+ // wait for a random time, so that 2 running Clamp will not treat
+ // the same Notification at the same time
+ Thread.sleep((new SecureRandom().nextInt(10) + 1) * 1000L);
+ logger.info("Notification received for service UUID:" + notificationData.getServiceUUID());
+ this.changeControllerStatus(SdcSingleControllerStatus.BUSY);
+ csar = new CsarHandler(notificationData, this.sdcConfig.getSdcControllerName(),
+ refProp.getStringValue(CONFIG_SDC_FOLDER));
+ csar.save(downloadTheArtifact(csar.getArtifactElement()));
+ if (csarInstaller.isCsarAlreadyDeployed(csar)) {
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD,
+ DistributionStatusEnum.ALREADY_DOWNLOADED, null);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+ DistributionStatusEnum.ALREADY_DEPLOYED, null);
+ } else {
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD,
+ DistributionStatusEnum.DOWNLOAD_OK, null);
+ csarInstaller.installTheCsar(csar);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+ DistributionStatusEnum.DEPLOY_OK, null);
+ }
+ this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_OK, null);
+ } catch (SdcArtifactInstallerException | SdcToscaParserException e) {
+ logger.error("SdcArtifactInstallerException exception caught during the notification processing", e);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+ DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+ this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+ } catch (SdcDownloadException | CsarHandlerException e) {
+ logger.error("SdcDownloadException exception caught during the notification processing", e);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DOWNLOAD,
+ DistributionStatusEnum.DOWNLOAD_ERROR, e.getMessage());
+ this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+ } catch (InterruptedException e) {
+ logger.error("Interrupt exception caught during the notification processing", e);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+ DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+ this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+ Thread.currentThread().interrupt();
+ } catch (BlueprintParserException e) {
+ logger.error("BlueprintParser exception caught during the notification processing", e);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+ DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+ this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+ } catch (RuntimeException e) {
+ logger.error("Unexpected exception caught during the notification processing", e);
+ sendAllNotificationForCsarHandler(notificationData, csar, NotificationType.DEPLOY,
+ DistributionStatusEnum.DEPLOY_ERROR, e.getMessage());
+ this.sendComponentStatus(notificationData, DistributionStatusEnum.COMPONENT_DONE_ERROR, e.getMessage());
+ } finally {
+ this.changeControllerStatus(SdcSingleControllerStatus.IDLE);
+ }
+ }
+
+ private enum NotificationType {
+ /**
+ * Download notification type.
+ */
+ DOWNLOAD,
+ /**
+ * Deploy notification type.
+ */
+ DEPLOY
+ }
+
+ private IDistributionClientDownloadResult downloadTheArtifact(IArtifactInfo artifact) throws SdcDownloadException {
+ logger.info("Trying to download the artifact : " + artifact.getArtifactURL() + " UUID: "
+ + artifact.getArtifactUUID());
+ IDistributionClientDownloadResult downloadResult;
+ try {
+ downloadResult = distributionClient.download(artifact);
+ if (null == downloadResult) {
+ logger.info("downloadResult is Null for: " + artifact.getArtifactUUID());
+ return null;
+ }
+ } catch (RuntimeException e) {
+ throw new SdcDownloadException("Exception caught when downloading the artifact", e);
+ }
+ if (DistributionActionResultEnum.SUCCESS.equals(downloadResult.getDistributionActionResult())) {
+ logger.info("Successfully downloaded the artifact " + artifact.getArtifactURL() + " UUID "
+ + artifact.getArtifactUUID() + "Size of payload " + downloadResult.getArtifactPayload().length);
+ } else {
+ throw new SdcDownloadException("Artifact " + artifact.getArtifactName()
+ + " could not be downloaded from SDC URL " + artifact.getArtifactURL() + " UUID "
+ + artifact.getArtifactUUID() + ")" + System.lineSeparator() + "Error message is "
+ + downloadResult.getDistributionMessageResult() + System.lineSeparator());
+ }
+ return downloadResult;
+ }
+
+ private void sendSdcNotification(NotificationType notificationType, String artifactUrl, String consumerId,
+ String distributionId, DistributionStatusEnum status, String errorReason,
+ long timestamp) {
+ String event = "Sending " + notificationType.name() + "(" + status.name() + ")"
+ + " notification to SDC for artifact:" + artifactUrl;
+ if (errorReason != null) {
+ event = event + "(" + errorReason + ")";
+ }
+ logger.info(event);
+ String action = "";
+ try {
+ IDistributionStatusMessage message = new DistributionStatusMessage(artifactUrl, consumerId, distributionId,
+ status, timestamp);
+ switch (notificationType) {
+ case DOWNLOAD:
+ this.sendDownloadStatus(message, errorReason);
+ action = "sendDownloadStatus";
+ break;
+ case DEPLOY:
+ this.sendDeploymentStatus(message, errorReason);
+ action = "sendDeploymentdStatus";
+ break;
+ default:
+ break;
+ }
+ } catch (RuntimeException e) {
+ logger.warn("Unable to send the SDC Notification (" + action + ") due to an exception", e);
+ }
+ logger.info("SDC Notification sent successfully(" + action + ")");
+ }
+
+ private void sendComponentStatus(INotificationData notificationData, DistributionStatusEnum status,
+ String errorReason) {
+ try {
+ IComponentDoneStatusMessage message = new IComponentDoneStatusMessage() {
+
+ @Override
+ public String getDistributionID() {
+ return notificationData.getDistributionID();
+ }
+
+ @Override
+ public String getConsumerID() {
+ return sdcConfig.getConsumerID();
+ }
+
+ @Override
+ public long getTimestamp() {
+ return System.currentTimeMillis();
+ }
+
+ @Override
+ public DistributionStatusEnum getStatus() {
+ return status;
+ }
+
+ @Override
+ public String getComponentName() {
+ return sdcConfig.getUser();
+ }
+ };
+
+ if (errorReason != null) {
+ this.distributionClient.sendComponentDoneStatus(message, errorReason);
+ } else {
+ this.distributionClient.sendComponentDoneStatus(message);
+ }
+ } catch (RuntimeException e) {
+ logger.warn("Unable to send the SDC Notification (" + status.name() + ") due to an exception", e);
+ }
+ logger.info("SDC Notification sent successfully(" + status.name() + ")");
+ }
+
+ private void sendDownloadStatus(IDistributionStatusMessage message, String errorReason) {
+ if (errorReason != null) {
+ this.distributionClient.sendDownloadStatus(message, errorReason);
+ } else {
+ this.distributionClient.sendDownloadStatus(message);
+ }
+ }
+
+ private void sendDeploymentStatus(IDistributionStatusMessage message, String errorReason) {
+ if (errorReason != null) {
+ this.distributionClient.sendDeploymentStatus(message, errorReason);
+ } else {
+ this.distributionClient.sendDeploymentStatus(message);
+ }
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/SdcSingleControllerStatus.java b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/SdcSingleControllerStatus.java
new file mode 100644
index 000000000..fe269c486
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/SdcSingleControllerStatus.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.sdc.controller;
+
+public enum SdcSingleControllerStatus {
+ STOPPED, IDLE, BUSY
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintArtifact.java b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintArtifact.java
new file mode 100644
index 000000000..df81cfb0c
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintArtifact.java
@@ -0,0 +1,70 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.sdc.controller.installer;
+
+import org.onap.sdc.api.notification.IResourceInstance;
+
+/**
+ * This class is useful to store the information concerning
+ * blueprint artifact extracted from SDC CSAR.
+ */
+public class BlueprintArtifact {
+
+ private String dcaeBlueprint;
+ private String blueprintArtifactName;
+ private String blueprintInvariantServiceUuid;
+ private IResourceInstance resourceAttached;
+
+ public String getDcaeBlueprint() {
+ return dcaeBlueprint;
+ }
+
+ public void setDcaeBlueprint(String dcaeBlueprint) {
+ this.dcaeBlueprint = dcaeBlueprint;
+ }
+
+ public String getBlueprintArtifactName() {
+ return blueprintArtifactName;
+ }
+
+ public void setBlueprintArtifactName(String blueprintArtifactName) {
+ this.blueprintArtifactName = blueprintArtifactName;
+ }
+
+ public String getBlueprintInvariantServiceUuid() {
+ return blueprintInvariantServiceUuid;
+ }
+
+ public void setBlueprintInvariantServiceUuid(String blueprintInvariantServiceUuid) {
+ this.blueprintInvariantServiceUuid = blueprintInvariantServiceUuid;
+ }
+
+ public IResourceInstance getResourceAttached() {
+ return resourceAttached;
+ }
+
+ public void setResourceAttached(IResourceInstance resourceAttached) {
+ this.resourceAttached = resourceAttached;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintMicroService.java b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintMicroService.java
new file mode 100644
index 000000000..519a24f46
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintMicroService.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * Modifications copyright (c) 2019-2020 AT&T
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.sdc.controller.installer;
+
+import java.util.Objects;
+
+public class BlueprintMicroService {
+ private final String name;
+ private final String modelType;
+ private final String inputFrom;
+ private final String modelVersion;
+
+ /**
+ * The Micro service constructor.
+ *
+ * @param name The name in String
+ * @param modelType The model type
+ * @param inputFrom Comes from (single chained)
+ */
+ public BlueprintMicroService(String name, String modelType, String inputFrom, String modelVersion) {
+ this.name = name;
+ this.inputFrom = inputFrom;
+ this.modelType = modelType;
+ this.modelVersion = modelVersion;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public String getModelType() {
+ return modelType;
+ }
+
+ public String getInputFrom() {
+ return inputFrom;
+ }
+
+ /**
+ * modelVerrsion getter.
+ *
+ * @return the modelVersion
+ */
+ public String getModelVersion() {
+ return modelVersion;
+ }
+
+ @Override
+ public String toString() {
+ return "MicroService {" + "name='" + name + '\'' + ", modelType='" + modelType + '\'' + ", inputFrom='"
+ + inputFrom + '\'' + ", modelVersion='" + modelVersion + '\'' + '}';
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null || getClass() != obj.getClass()) {
+ return false;
+ }
+ BlueprintMicroService that = (BlueprintMicroService) obj;
+ return name.equals(that.name) && modelType.equals(that.modelType) && inputFrom.equals(that.inputFrom)
+ && modelVersion.equals(that.modelVersion);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, modelType, inputFrom, modelVersion);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintParser.java b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintParser.java
new file mode 100644
index 000000000..ada47992a
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintParser.java
@@ -0,0 +1,220 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * Modifications copyright (c) 2019 AT&T
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.sdc.controller.installer;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.util.AbstractMap;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import org.json.JSONObject;
+import org.onap.policy.clamp.clds.exception.sdc.controller.BlueprintParserException;
+import org.yaml.snakeyaml.Yaml;
+
+public class BlueprintParser {
+
+ static final String TCA = "TCA";
+ private static final String NODE_TEMPLATES = "node_templates";
+ private static final String DCAE_NODES = "dcae.nodes.";
+ private static final String DCAE_NODES_POLICY = ".nodes.policy";
+ private static final String TYPE = "type";
+ private static final String PROPERTIES = "properties";
+ private static final String NAME = "name";
+ private static final String INPUT = "inputs";
+ private static final String GET_INPUT = "get_input";
+ private static final String POLICY_MODEL_ID = "policy_model_id";
+ private static final String POLICY_MODEL_VERSION = "policy_model_version";
+ private static final String RELATIONSHIPS = "relationships";
+ private static final String CLAMP_NODE_RELATIONSHIPS_GETS_INPUT_FROM = "clamp_node.relationships.gets_input_from";
+ private static final String TARGET = "target";
+ public static final String DEFAULT_VERSION = "1.0.0";
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(BlueprintParser.class);
+
+ private BlueprintParser() {
+
+ }
+
+ /**
+ * Get all micro services from blueprint.
+ *
+ * @param blueprintString the blueprint in a String
+ * @return A set of MircoService
+ * @throws BlueprintParserException In case of issues with the parsing
+ */
+ public static Set<BlueprintMicroService> getMicroServices(String blueprintString) throws BlueprintParserException {
+ Set<BlueprintMicroService> microServices = new HashSet<>();
+ JsonObject blueprintJson = BlueprintParser.convertToJson(blueprintString);
+ JsonObject nodeTemplateList = blueprintJson.get(NODE_TEMPLATES).getAsJsonObject();
+ JsonObject inputList = blueprintJson.get(INPUT).getAsJsonObject();
+
+ for (Entry<String, JsonElement> entry : nodeTemplateList.entrySet()) {
+ JsonObject nodeTemplate = entry.getValue().getAsJsonObject();
+ if (!nodeTemplate.get(TYPE).getAsString().contains(DCAE_NODES_POLICY)
+ && nodeTemplate.get(TYPE).getAsString().contains(DCAE_NODES)) {
+ BlueprintMicroService microService = getNodeRepresentation(entry, nodeTemplateList, inputList);
+ if (!microService.getModelType().isBlank()) {
+ microServices.add(microService);
+ } else {
+ logger.warn("Microservice " + microService.getName()
+ + " will NOT be used by CLAMP as the model type is not defined or has not been found");
+ }
+ }
+ }
+ logger.debug("Those microservices have been found in the blueprint:" + microServices);
+ return microServices;
+ }
+
+ /**
+ * Does a fallback to TCA.
+ *
+ * @return The list of microservices
+ */
+ public static List<BlueprintMicroService> fallbackToOneMicroService() {
+ return Collections.singletonList(
+ new BlueprintMicroService(TCA, "onap.policies.monitoring.cdap.tca.hi.lo.app", "", DEFAULT_VERSION));
+ }
+
+ static String getName(Entry<String, JsonElement> entry) {
+ String microServiceYamlName = entry.getKey();
+ JsonObject ob = entry.getValue().getAsJsonObject();
+ if (ob.has(PROPERTIES)) {
+ JsonObject properties = ob.get(PROPERTIES).getAsJsonObject();
+ if (properties.has(NAME)) {
+ return properties.get(NAME).getAsString();
+ }
+ }
+ return microServiceYamlName;
+ }
+
+ static String getInput(Entry<String, JsonElement> entry) {
+ JsonObject ob = entry.getValue().getAsJsonObject();
+ if (ob.has(RELATIONSHIPS)) {
+ JsonArray relationships = ob.getAsJsonArray(RELATIONSHIPS);
+ for (JsonElement element : relationships) {
+ String target = getTarget(element.getAsJsonObject());
+ if (!target.isEmpty()) {
+ return target;
+ }
+ }
+ }
+ return "";
+ }
+
+ static String findPropertyInRelationshipsArray(String propertyName, JsonArray relationshipsArray,
+ JsonObject blueprintNodeTemplateList, JsonObject blueprintInputList) throws BlueprintParserException {
+ for (JsonElement elem : relationshipsArray) {
+ if (blueprintNodeTemplateList.get(elem.getAsJsonObject().get(TARGET).getAsString()) == null) {
+ throw new BlueprintParserException(
+ "The Target mentioned in the blueprint is not a known entry in the blueprint: "
+ + elem.getAsJsonObject().get(TARGET).getAsString());
+ } else {
+ String property = getPropertyValue(propertyName,
+ new AbstractMap.SimpleEntry<String, JsonElement>(
+ elem.getAsJsonObject().get(TARGET).getAsString(), blueprintNodeTemplateList
+ .get(elem.getAsJsonObject().get(TARGET).getAsString()).getAsJsonObject()),
+ blueprintNodeTemplateList, blueprintInputList);
+ if (!property.isEmpty()) {
+ return property;
+ }
+ }
+ }
+ return "";
+ }
+
+ static String getDirectOrInputPropertyValue(String propertyName, JsonObject blueprintInputList,
+ JsonObject nodeTemplateContent) {
+ JsonObject properties = nodeTemplateContent.get(PROPERTIES).getAsJsonObject();
+ if (properties.has(propertyName)) {
+ if (properties.get(propertyName).isJsonObject()) {
+ // it's a blueprint parameter
+ return blueprintInputList
+ .get(properties.get(propertyName).getAsJsonObject().get(GET_INPUT).getAsString())
+ .getAsJsonObject().get("default").getAsString();
+ } else {
+ // It's a direct value
+ return properties.get(propertyName).getAsString();
+ }
+ }
+ return "";
+ }
+
+ static String getPropertyValue(String propertyName, Entry<String, JsonElement> nodeTemplateEntry,
+ JsonObject blueprintNodeTemplateList, JsonObject blueprintIputList) throws BlueprintParserException {
+ JsonObject nodeTemplateContent = nodeTemplateEntry.getValue().getAsJsonObject();
+ // Search first in this node template
+ if (nodeTemplateContent.has(PROPERTIES)) {
+ String propValue = getDirectOrInputPropertyValue(propertyName, blueprintIputList, nodeTemplateContent);
+ if (!propValue.isBlank()) {
+ return propValue;
+ }
+ }
+ // Or it's may be defined in a relationship
+ if (nodeTemplateContent.has(RELATIONSHIPS)) {
+ return findPropertyInRelationshipsArray(propertyName,
+ nodeTemplateContent.get(RELATIONSHIPS).getAsJsonArray(), blueprintNodeTemplateList,
+ blueprintIputList);
+ }
+ return "";
+ }
+
+ static BlueprintMicroService getNodeRepresentation(Entry<String, JsonElement> nodeTemplateEntry,
+ JsonObject blueprintNodeTemplateList, JsonObject blueprintInputList) throws BlueprintParserException {
+ String modelIdFound = getPropertyValue(POLICY_MODEL_ID, nodeTemplateEntry, blueprintNodeTemplateList,
+ blueprintInputList);
+ String versionFound = getPropertyValue(POLICY_MODEL_VERSION, nodeTemplateEntry, blueprintNodeTemplateList,
+ blueprintInputList);
+ if (modelIdFound.isBlank()) {
+ logger.warn("policy_model_id is not defined for the node template:" + nodeTemplateEntry.getKey());
+ }
+ if (versionFound.isBlank()) {
+ logger.warn("policy_model_version is not defined (setting it to a default value) for the node template:"
+ + nodeTemplateEntry.getKey());
+ }
+ return new BlueprintMicroService(getName(nodeTemplateEntry), modelIdFound, getInput(nodeTemplateEntry),
+ !versionFound.isBlank() ? versionFound : DEFAULT_VERSION);
+ }
+
+ private static String getTarget(JsonObject elementObject) {
+ if (elementObject.has(TYPE) && elementObject.has(TARGET)
+ && elementObject.get(TYPE).getAsString().equals(CLAMP_NODE_RELATIONSHIPS_GETS_INPUT_FROM)) {
+ return elementObject.get(TARGET).getAsString();
+ }
+ return "";
+ }
+
+ private static JsonObject convertToJson(String yamlString) {
+ Map<String, Object> map = new Yaml().load(yamlString);
+ return new Gson().fromJson(new JSONObject(map).toString(), JsonObject.class);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/ChainGenerator.java b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/ChainGenerator.java
new file mode 100644
index 000000000..10e7a56a4
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/ChainGenerator.java
@@ -0,0 +1,90 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.sdc.controller.installer;
+
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ChainGenerator {
+
+ ChainGenerator() {
+ }
+
+ /**
+ * Get list of microservices chain.
+ *
+ * @param input A set of microservices
+ * @return The list of microservice chained
+ */
+ public List<BlueprintMicroService> getChainOfMicroServices(Set<BlueprintMicroService> input) {
+ LinkedList<BlueprintMicroService> returnList = new LinkedList<>();
+ if (preValidate(input)) {
+ LinkedList<BlueprintMicroService> theList = new LinkedList<>();
+ for (BlueprintMicroService ms : input) {
+ insertNodeTemplateIntoChain(ms, theList);
+ }
+ if (postValidate(theList)) {
+ returnList = theList;
+ }
+ }
+ return returnList;
+ }
+
+ private boolean preValidate(Set<BlueprintMicroService> input) {
+ List<BlueprintMicroService> noInputs = input.stream().filter(ms -> "".equals(ms.getInputFrom()))
+ .collect(Collectors.toList());
+ return noInputs.size() == 1;
+ }
+
+ private boolean postValidate(LinkedList<BlueprintMicroService> microServices) {
+ for (int i = 1; i < microServices.size() - 1; i++) {
+ BlueprintMicroService prev = microServices.get(i - 1);
+ BlueprintMicroService current = microServices.get(i);
+ if (!current.getInputFrom().equals(prev.getName())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void insertNodeTemplateIntoChain(BlueprintMicroService microServicetoInsert,
+ LinkedList<BlueprintMicroService> chainOfMicroServices) {
+ int insertIndex = 0;
+ for (int i = 0; i < chainOfMicroServices.size(); i++) {
+ BlueprintMicroService current = chainOfMicroServices.get(i);
+ if (microServicetoInsert.getName().equals(current.getInputFrom())) {
+ insertIndex = i;
+ break;
+ } else if (current.getName().equals(microServicetoInsert.getInputFrom())) {
+ insertIndex = i + 1;
+ break;
+ }
+ }
+ chainOfMicroServices.add(insertIndex, microServicetoInsert);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/CsarHandler.java b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/CsarHandler.java
new file mode 100644
index 000000000..436e594ce
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/sdc/controller/installer/CsarHandler.java
@@ -0,0 +1,219 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.sdc.controller.installer;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import org.apache.commons.io.IOUtils;
+import org.codehaus.plexus.util.StringUtils;
+import org.onap.policy.clamp.clds.exception.sdc.controller.CsarHandlerException;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.sdc.api.notification.IArtifactInfo;
+import org.onap.sdc.api.notification.INotificationData;
+import org.onap.sdc.api.notification.IResourceInstance;
+import org.onap.sdc.api.results.IDistributionClientDownloadResult;
+import org.onap.sdc.tosca.parser.api.ISdcCsarHelper;
+import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;
+import org.onap.sdc.tosca.parser.impl.SdcToscaParserFactory;
+
+/**
+ * CsarDescriptor that will be used to deploy file in CLAMP file system. Some
+ * methods can also be used to get some data from it.
+ */
+public class CsarHandler {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(CsarHandler.class);
+ private IArtifactInfo artifactElement;
+ private String csarFilePath;
+ private String controllerName;
+ private SdcToscaParserFactory factory = SdcToscaParserFactory.getInstance();
+ private ISdcCsarHelper sdcCsarHelper;
+ private Map<String, BlueprintArtifact> mapOfBlueprints = new HashMap<>();
+ public static final String CSAR_TYPE = "TOSCA_CSAR";
+ public static final String BLUEPRINT_TYPE = "DCAE_INVENTORY_BLUEPRINT";
+ private INotificationData sdcNotification;
+ public static final String RESOURCE_INSTANCE_NAME_PREFIX = "/Artifacts/Resources/";
+ public static final String RESOURCE_INSTANCE_NAME_SUFFIX = "/Deployment/";
+ public static final String POLICY_DEFINITION_NAME_SUFFIX = "Definitions/policies.yml";
+ public static final String DATA_DEFINITION_NAME_SUFFIX = "Definitions/data.yml";
+ public static final String DATA_DEFINITION_KEY = "data_types:";
+
+ /**
+ * Constructor for CsarHandler taking sdc notification in input.
+ */
+ public CsarHandler(INotificationData data, String controller, String clampCsarPath) throws CsarHandlerException {
+ this.sdcNotification = data;
+ this.controllerName = controller;
+ this.artifactElement = searchForUniqueCsar(data);
+ this.csarFilePath = buildFilePathForCsar(artifactElement, clampCsarPath);
+ }
+
+ private String buildFilePathForCsar(IArtifactInfo artifactElement, String clampCsarPath) {
+ return clampCsarPath + "/" + controllerName + "/" + artifactElement.getArtifactName();
+ }
+
+ private IArtifactInfo searchForUniqueCsar(INotificationData notificationData) throws CsarHandlerException {
+ List<IArtifactInfo> serviceArtifacts = notificationData.getServiceArtifacts();
+ for (IArtifactInfo artifact : serviceArtifacts) {
+ if (artifact.getArtifactType().equals(CSAR_TYPE)) {
+ return artifact;
+ }
+ }
+ throw new CsarHandlerException("Unable to find a CSAR in the Sdc Notification");
+ }
+
+ /**
+ * This saves the notification to disk and database.
+ *
+ * @param resultArtifact The artifact to install
+ * @throws SdcArtifactInstallerException In case of issues with the installation
+ * @throws SdcToscaParserException In case of issues with the parsing of
+ * the CSAR
+ */
+ public synchronized void save(IDistributionClientDownloadResult resultArtifact)
+ throws SdcArtifactInstallerException, SdcToscaParserException {
+ try {
+ logger.info("Writing CSAR file to: " + csarFilePath + " UUID " + artifactElement.getArtifactUUID() + ")");
+ Path path = Paths.get(csarFilePath);
+ Files.createDirectories(path.getParent());
+ // Create or replace the file
+ try (OutputStream out = Files.newOutputStream(path)) {
+ out.write(resultArtifact.getArtifactPayload(), 0, resultArtifact.getArtifactPayload().length);
+ }
+ sdcCsarHelper = factory.getSdcCsarHelper(csarFilePath);
+ this.loadDcaeBlueprint();
+ } catch (IOException e) {
+ throw new SdcArtifactInstallerException(
+ "Exception caught when trying to write the CSAR on the file system to " + csarFilePath, e);
+ }
+ }
+
+ private IResourceInstance searchForResourceByInstanceName(String blueprintResourceInstanceName)
+ throws SdcArtifactInstallerException {
+ for (IResourceInstance resource : this.sdcNotification.getResources()) {
+ String filteredString = resource.getResourceInstanceName().replaceAll("-", "");
+ filteredString = filteredString.replaceAll(" ", "");
+ if (filteredString.equalsIgnoreCase(blueprintResourceInstanceName)) {
+ return resource;
+ }
+ }
+ throw new SdcArtifactInstallerException("Error when searching for " + blueprintResourceInstanceName
+ + " as ResourceInstanceName in Sdc notification and did not find it");
+ }
+
+ private void loadDcaeBlueprint() throws IOException, SdcArtifactInstallerException {
+ try (ZipFile zipFile = new ZipFile(csarFilePath)) {
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ if (!entry.isDirectory() && entry.getName().contains(BLUEPRINT_TYPE)) {
+ BlueprintArtifact blueprintArtifact = new BlueprintArtifact();
+ blueprintArtifact.setBlueprintArtifactName(
+ entry.getName().substring(entry.getName().lastIndexOf('/') + 1, entry.getName().length()));
+ blueprintArtifact
+ .setBlueprintInvariantServiceUuid(this.getSdcNotification().getServiceInvariantUUID());
+ try (InputStream stream = zipFile.getInputStream(entry)) {
+ blueprintArtifact.setDcaeBlueprint(IOUtils.toString(stream, StandardCharsets.UTF_8));
+ }
+ blueprintArtifact.setResourceAttached(searchForResourceByInstanceName(entry.getName().substring(
+ entry.getName().indexOf(RESOURCE_INSTANCE_NAME_PREFIX)
+ + RESOURCE_INSTANCE_NAME_PREFIX.length(),
+ entry.getName().indexOf(RESOURCE_INSTANCE_NAME_SUFFIX))));
+ this.mapOfBlueprints.put(blueprintArtifact.getBlueprintArtifactName(), blueprintArtifact);
+ logger.info("Found a blueprint entry in the CSAR " + blueprintArtifact.getBlueprintArtifactName()
+ + " for resource instance Name "
+ + blueprintArtifact.getResourceAttached().getResourceInstanceName());
+ }
+ }
+ logger.info(this.mapOfBlueprints.size() + " blueprint(s) will be converted to closed loop");
+ }
+ }
+
+ public IArtifactInfo getArtifactElement() {
+ return artifactElement;
+ }
+
+ public String getFilePath() {
+ return csarFilePath;
+ }
+
+ public String setFilePath(String newPath) {
+ return csarFilePath = newPath;
+ }
+
+ public synchronized ISdcCsarHelper getSdcCsarHelper() {
+ return sdcCsarHelper;
+ }
+
+ public INotificationData getSdcNotification() {
+ return sdcNotification;
+ }
+
+ public Map<String, BlueprintArtifact> getMapOfBlueprints() {
+ return mapOfBlueprints;
+ }
+
+ /**
+ * Get the whole policy model Yaml. It combines the content of policies.yaml and
+ * data.yaml.
+ *
+ * @return The whole policy model yaml
+ * @throws IOException The IO Exception
+ */
+ public Optional<String> getPolicyModelYaml() throws IOException {
+ String result = null;
+ try (ZipFile zipFile = new ZipFile(csarFilePath)) {
+ ZipEntry entry = zipFile.getEntry(POLICY_DEFINITION_NAME_SUFFIX);
+ if (entry != null) {
+ ZipEntry data = zipFile.getEntry(DATA_DEFINITION_NAME_SUFFIX);
+ if (data != null) {
+ String dataStr = IOUtils.toString(zipFile.getInputStream(data), StandardCharsets.UTF_8);
+ String dataStrWithoutHeader = dataStr.substring(dataStr.indexOf(DATA_DEFINITION_KEY));
+ String policyStr = IOUtils.toString(zipFile.getInputStream(entry), StandardCharsets.UTF_8);
+ StringUtils.chomp(policyStr);
+ result = policyStr.concat(dataStrWithoutHeader);
+ } else {
+ result = IOUtils.toString(zipFile.getInputStream(entry), StandardCharsets.UTF_8);
+ }
+ } else {
+ logger.info("Policy model not found inside the CSAR file: " + csarFilePath);
+ }
+ return Optional.ofNullable(result);
+ }
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/service/CldsHealthcheckService.java b/runtime/src/main/java/org/onap/policy/clamp/clds/service/CldsHealthcheckService.java
new file mode 100644
index 000000000..02481494a
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/service/CldsHealthcheckService.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ */
+
+package org.onap.policy.clamp.clds.service;
+
+import java.util.Date;
+import org.onap.policy.clamp.clds.model.CldsHealthCheck;
+import org.onap.policy.clamp.clds.util.LoggingUtils;
+import org.onap.policy.clamp.clds.util.OnapLogConstants;
+import org.onap.policy.clamp.loop.LoopController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.event.Level;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+
+/**
+ * Service to retrieve the Health Check of the clds application.
+ *
+ */
+@Component
+public class CldsHealthcheckService {
+
+ @Autowired
+ private LoopController loopController;
+
+ protected static final Logger logger = LoggerFactory.getLogger(CldsHealthcheckService.class);
+
+ /**
+ * REST service that retrieves clds healthcheck information.
+ *
+ * @return CldsHealthCheck class containing healthcheck info
+ */
+ public CldsHealthCheck gethealthcheck() {
+ CldsHealthCheck cldsHealthCheck = new CldsHealthCheck();
+ Date startTime = new Date();
+ LoggingUtils util = new LoggingUtils(logger);
+ LoggingUtils.setRequestContext("CldsService: GET healthcheck", "Clamp-Health-Check");
+ LoggingUtils.setTimeContext(startTime, new Date());
+ try {
+ loopController.getLoopNames();
+ cldsHealthCheck.setHealthCheckComponent("CLDS-APP");
+ cldsHealthCheck.setHealthCheckStatus("UP");
+ cldsHealthCheck.setDescription("OK");
+ LoggingUtils.setResponseContext("0", "Get healthcheck success",
+ this.getClass().getName());
+ util.exiting(HttpStatus.OK.value(), "Healthcheck success", Level.INFO,
+ OnapLogConstants.ResponseStatus.COMPLETE);
+ } catch (Exception e) {
+ logger.error("CLAMP application Heath check failed", e);
+ LoggingUtils.setResponseContext("999", "Get healthcheck failed",
+ this.getClass().getName());
+ cldsHealthCheck.setHealthCheckComponent("CLDS-APP");
+ cldsHealthCheck.setHealthCheckStatus("DOWN");
+ cldsHealthCheck.setDescription("NOT-OK");
+ util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Healthcheck failed", Level.INFO,
+ OnapLogConstants.ResponseStatus.ERROR);
+ }
+ return cldsHealthCheck;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/JsonEditorSchemaConstants.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/JsonEditorSchemaConstants.java
new file mode 100644
index 000000000..32f328079
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/JsonEditorSchemaConstants.java
@@ -0,0 +1,86 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca;
+
+public class JsonEditorSchemaConstants {
+
+ //Data types in JSON Schema
+ public static final String TYPE_OBJECT = "object";
+ public static final String TYPE_ARRAY = "array";
+ public static final String TYPE_MAP = "map";
+ public static final String TYPE_STRING = "string";
+ public static final String TYPE_INTEGER = "integer";
+ public static final String TYPE_DATE_TIME = "datetime";
+
+ //Key elements in JSON Schema
+ public static final String TYPE = "type";
+ public static final String TITLE = "title";
+ public static final String REQUIRED = "required";
+ public static final String DEFAULT = "default";
+ public static final String ENUM = "enum";
+ public static final String ENUM_TITLES = "enum_titles";
+ public static final String OPTIONS = "options";
+ public static final String FORMAT = "format";
+ public static final String ITEMS = "items";
+ public static final String PROPERTIES = "properties";
+ public static final String PROPERTY_ORDER = "propertyOrder";
+ public static final String VALUES = "values";
+ public static final String HEADER_TEMPLATE = "headerTemplate";
+ public static final String HEADER_TEMPLATE_VALUE = "{{self.name}}";
+
+ public static final String MINIMUM = "minimum";
+ public static final String MAXIMUM = "maximum";
+ public static final String MIN_LENGTH = "minLength";
+ public static final String MAX_LENGTH = "maxLength";
+ public static final String EXCLUSIVE_MINIMUM = "exclusiveMinimum";
+ public static final String EXCLUSIVE_MAXIMUM = "exclusiveMaximum";
+ public static final String MINITEMS = "minItems";
+ public static final String MAXITEMS = "maxItems";
+
+ public static final String CUSTOM_KEY_FORMAT = "format";
+ public static final String CUSTOM_KEY_FORMAT_TABS_TOP = "tabs-top";
+ public static final String CUSTOM_KEY_FORMAT_TABS = "tabs";
+ public static final String CUSTOM_KEY_FORMAT_INPUT = "input";
+ public static final String FORMAT_SELECT = "select";
+ public static final String UNIQUE_ITEMS = "uniqueItems";
+ public static final String TRUE = "true";
+ public static final String QSSCHEMA = "qschema";
+ public static final String TYPE_QBLDR = "qbldr";
+
+ public static final String ID = "id";
+ public static final String LABEL = "label";
+ public static final String OPERATORS = "operators";
+ public static final String FILTERS = "filters";
+
+ public static final String SCHEMA = "schema";
+ public static final String CURRENT_VALUES = "currentValues";
+
+ public static final String PLUGIN = "plugin";
+ public static final String DATE_TIME_PICKER = "datetimepicker";
+ public static final String VALIDATION = "validation";
+ public static final String DATE_TIME_FORMAT = "YYYY/MM/DD HH:mm:ss";
+ public static final String INPUT_EVENT = "input_event";
+ public static final String DP_CHANGE = "dp.change";
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/ToscaSchemaConstants.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/ToscaSchemaConstants.java
new file mode 100644
index 000000000..c2b5d5963
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/ToscaSchemaConstants.java
@@ -0,0 +1,83 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca;
+
+public class ToscaSchemaConstants {
+
+ // Data types in TOSCA Schema
+ public static final String TYPE_LIST = "list";
+ public static final String TYPE_MAP = "map";
+ public static final String TYPE_STRING = "string";
+ public static final String TYPE_INTEGER = "integer";
+ public static final String TYPE_NUMBER = "number";
+ public static final String TYPE_DATE_TIME = "datetime";
+ public static final String TYPE_FLOAT = "float";
+ public static final String TYPE_BOOLEAN = "boolean";
+ public static final String TYPE_USER_DEFINED = "userDefined";
+
+ // Key elements in Tosca
+ public static final String NODE_TYPES = "policy_types";
+ public static final String DATA_TYPES = "data_types";
+ public static final String TYPE = "type";
+ public static final String DESCRIPTION = "description";
+ public static final String DEFAULT = "default";
+ public static final String PROPERTIES = "properties";
+ public static final String REQUIRED = "required";
+ public static final String ENTRY_SCHEMA = "entry_schema";
+
+ public static final String METADATA = "metadata";
+ public static final String METADATA_POLICY_MODEL_TYPE = "policy_model_type";
+ public static final String METADATA_ACRONYM = "acronym";
+ public static final String METADATA_ELEMENT_NAME = "element_name";
+ public static final String METADATA_HEADER_TEMPLATE = "header_template";
+ public static final String METADATA_CLAMP_POSSIBLE_VALUES = "clamp_possible_values";
+
+ // Constraints
+ public static final String CONSTRAINTS = "constraints";
+ public static final String VALID_VALUES = "valid_values";
+ public static final String EQUAL = "equal";
+ public static final String GREATER_THAN = "greater_than";
+ public static final String GREATER_OR_EQUAL = "greater_or_equal";
+ public static final String LESS_THAN = "less_than";
+ public static final String LESS_OR_EQUAL = "less_or_equal";
+ public static final String IN_RANGE = "in_range";
+ public static final String LENGTH = "length";
+ public static final String MIN_LENGTH = "min_length";
+ public static final String MAX_LENGTH = "max_length";
+ public static final String PATTERN = "pattern";
+
+ // Prefix for policy nodes
+ public static final String POLICY_NODE = "onap.policies.";
+
+ // Prefix for data nodes
+ public static final String POLICY_DATA = "onap.datatypes.";
+
+ // Prefix for dictionary elements
+ public static final String DICTIONARY = "Dictionary:";
+
+ // Custom Elements that must exist in the Tosca models
+ public static final String NAME = "name";
+ public static final String CONTEXT = "context";
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/ToscaConverterWithDictionarySupport.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/ToscaConverterWithDictionarySupport.java
new file mode 100644
index 000000000..6702a6200
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/ToscaConverterWithDictionarySupport.java
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import org.onap.policy.clamp.clds.config.ClampProperties;
+import org.onap.policy.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParser;
+import org.onap.policy.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParserWithDictionarySupport;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplateManager;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.loop.service.Service;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * This is the main class that must be used to convert a tosca to a json schema.
+ * This class adds feature to support the dictionary mechanism that enables json possible values extracted
+ * from the dictionary DB table.
+ *
+ * @see org.onap.policy.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport#convertToscaToJsonSchemaObject
+ */
+@Component
+public class ToscaConverterWithDictionarySupport {
+
+ private static final EELFLogger logger =
+ EELFManager.getInstance().getLogger(ToscaConverterWithDictionarySupport.class);
+
+ private ClampProperties clampProperties;
+ private ToscaMetadataParser metadataParser;
+
+ /**
+ * Constructor with Spring support.
+ *
+ * @param clampProperties Clamp Spring properties
+ * @param metadataParser Metadata parser
+ */
+ @Autowired
+ public ToscaConverterWithDictionarySupport(ClampProperties clampProperties,
+ ToscaMetadataParserWithDictionarySupport metadataParser) {
+ this.clampProperties = clampProperties;
+ this.metadataParser = metadataParser;
+ }
+
+ /**
+ * This method converts a tosca file to a json schema.
+ * It uses some parameters specified in the application.properties.
+ *
+ * @param toscaFile The tosca file as String
+ * @param policyTypeToDecode The policy type to decode
+ * @param serviceModel The service model associated so that the clamp enrichment could be done if required by
+ * the tosca model
+ * @return A json object being a json schema
+ */
+ public JsonObject convertToscaToJsonSchemaObject(String toscaFile, String policyTypeToDecode,
+ Service serviceModel) {
+ try {
+ return new JsonTemplateManager(toscaFile,
+ clampProperties.getFileContent("tosca.converter.default.datatypes"),
+ clampProperties.getFileContent("tosca.converter.json.schema.templates"))
+ .getJsonSchemaForPolicyType(policyTypeToDecode, Boolean.parseBoolean(clampProperties.getStringValue(
+ "tosca.converter.dictionary.support.enabled")) ? metadataParser : null, serviceModel);
+ } catch (IOException | UnknownComponentException e) {
+ logger.error("Unable to convert the tosca properly, exception caught during the decoding",
+ e);
+ return new JsonObject();
+ }
+ }
+
+ /**
+ * This method converts a tosca file to a json schema.
+ * It uses some parameters specified in the application.properties.
+ *
+ * @param toscaFile The tosca file as String
+ * @param policyTypeToDecode The policy type to decode
+ * @param serviceModel The service Model so that clamp enrichment could be done if required by tosca model
+ * @return A String containing the json schema
+ */
+ public String convertToscaToJsonSchemaString(String toscaFile, String policyTypeToDecode, Service serviceModel) {
+ return JsonUtils.GSON.toJson(this.convertToscaToJsonSchemaObject(toscaFile, policyTypeToDecode, serviceModel));
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/UnknownComponentException.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/UnknownComponentException.java
new file mode 100644
index 000000000..fb684b57b
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/UnknownComponentException.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update;
+
+public class UnknownComponentException extends Exception {
+ public UnknownComponentException(String nameEntry) {
+ this.getWrongName(nameEntry);
+ }
+
+ public String getWrongName(String nameEntry) {
+ return "Unknown Component: " + nameEntry;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/ArrayField.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/ArrayField.java
new file mode 100644
index 000000000..fb9d66752
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/ArrayField.java
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.elements;
+
+import com.google.gson.JsonArray;
+import java.util.ArrayList;
+
+public class ArrayField {
+
+ private ArrayList<Object> complexFields;
+
+ /**
+ * Constructor from arraryList.
+ *
+ * @param arrayProperties the array properties
+ */
+ public ArrayField(ArrayList<Object> arrayProperties) {
+ this.complexFields = arrayProperties;
+ }
+
+ /**
+ * Each LinkedHashMap is parsed to extract the Array and each of its value. They are casted for the JsonObject.
+ *
+ * @return JsonArray
+ */
+ public JsonArray deploy() {
+
+ JsonArray subPropertyValuesArray = new JsonArray();
+ for (Object arrayElement : complexFields) {
+ //Cast for each Primitive Type
+ String typeValue = arrayElement.getClass().getSimpleName();
+ switch (typeValue) {
+ case "String":
+ subPropertyValuesArray.add((String) arrayElement);
+ break;
+ case "Boolean":
+ subPropertyValuesArray.add((Boolean) arrayElement);
+ break;
+ case "Double":
+ subPropertyValuesArray.add((Number) arrayElement);
+ break;
+ case "Integer":
+ subPropertyValuesArray.add((Number) arrayElement);
+ break;
+ default:
+ break;
+ }
+ }
+ return subPropertyValuesArray;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/Constraint.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/Constraint.java
new file mode 100644
index 000000000..651456ca6
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/Constraint.java
@@ -0,0 +1,222 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.elements;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplate;
+
+public class Constraint {
+
+ private LinkedHashMap<String, Object> constraints;
+ private JsonTemplate jsonTemplate;
+
+ public Constraint(LinkedHashMap<String, Object> constraints, JsonTemplate jsonTemplate) {
+ this.jsonTemplate = jsonTemplate;
+ this.constraints = constraints;
+ }
+
+ /**
+ * Deploy the linkedhashmap which contains the constraints, to extract them one to one.
+ *
+ * @param jsonSchema The json Schema
+ * @param typeProperty The ype property
+ * @return the json object
+ */
+ public JsonObject deployConstraints(JsonObject jsonSchema, String typeProperty) {
+ for (Entry<String, Object> constraint : constraints.entrySet()) {
+ this.parseConstraint(jsonSchema, constraint.getKey(), constraint.getValue(), typeProperty);
+ }
+ return jsonSchema;
+ }
+
+ /**
+ * Each case of Tosca constraints below parse specifically the field in the JsonObject.
+ *
+ * @param jsonSchema Json Schema
+ * @param nameConstraint Name constraint
+ * @param valueConstraint value constraint
+ * @param typeProperty Type Property
+ */
+ @SuppressWarnings("unchecked")
+ public void parseConstraint(JsonObject jsonSchema, String nameConstraint, Object valueConstraint,
+ String typeProperty) {
+ switch (nameConstraint) {
+ case "equal":
+ checkTemplateField("const", jsonSchema, valueConstraint);
+ break;
+ case "greater_than":
+ checkTemplateField("exclusiveMinimum", jsonSchema, valueConstraint);
+ break;
+ case "greater_or_equal":
+ checkTemplateField("minimum", jsonSchema, valueConstraint);
+ break;
+ case "less_than":
+ checkTemplateField("exclusiveMaximum", jsonSchema, valueConstraint);
+ break;
+ case "less_or_equal":
+ checkTemplateField("maximum", jsonSchema, valueConstraint);
+ break;
+ case "in_range":
+ ArrayList<Integer> limitValues = (ArrayList<Integer>) valueConstraint;
+ checkTemplateField("minimum", jsonSchema, limitValues.get(0));
+ checkTemplateField("maximum", jsonSchema, limitValues.get(1));
+ break;
+ case "pattern":
+ jsonSchema.addProperty(nameConstraint, (String) valueConstraint);
+ break;
+ case "length":
+ this.getSpecificLength(jsonSchema, valueConstraint, typeProperty);
+ break;
+ case "min_length":
+ String[] prefixValues = nameConstraint.split("_");
+ this.getLimitValue(jsonSchema, valueConstraint, typeProperty, prefixValues[0]);
+ break;
+ case "max_length":
+ String[] maxtab = nameConstraint.split("_");
+ this.getLimitValue(jsonSchema, valueConstraint, typeProperty, maxtab[0]);
+ break;
+ default://valid_value
+ this.getValueArray(jsonSchema, valueConstraint, typeProperty);
+ break;
+ }
+
+ }
+
+ /**
+ * To be done.
+ *
+ * @param jsonSchema json schema
+ * @param fieldValue field value
+ * @param typeProperty For the complex components, get a specific number of items/properties
+ */
+ public void getSpecificLength(JsonObject jsonSchema, Object fieldValue, String typeProperty) {
+ switch (typeProperty.toLowerCase()) {
+ case "string":
+ checkTemplateField("minLength", jsonSchema, fieldValue);
+ checkTemplateField("maxLength", jsonSchema, fieldValue);
+ break;
+ case "array":
+ if (fieldValue.equals(1) && jsonTemplate.hasFields("uniqueItems")) {
+ jsonSchema.addProperty("uniqueItems", true);
+ } else {
+ checkTemplateField("minItems", jsonSchema, fieldValue);
+ checkTemplateField("maxItems", jsonSchema, fieldValue);
+ }
+ break;
+ default:// Map && List
+ checkTemplateField("minProperties", jsonSchema, fieldValue);
+ checkTemplateField("maxProperties", jsonSchema, fieldValue);
+ break;
+ }
+
+ }
+
+ /**
+ * To be done.
+ *
+ * @param jsonSchema json schema
+ * @param fieldValue field value
+ * @param typeProperty type property
+ * @param side Get the limits fieldValue for the properties : depend of the type of the component
+ */
+ public void getLimitValue(JsonObject jsonSchema, Object fieldValue, String typeProperty, String side) {
+ switch (typeProperty) {
+ case "string":
+ if (side.equals("min")) {
+ checkTemplateField("minLength", jsonSchema, fieldValue);
+ } else {
+ checkTemplateField("maxLength", jsonSchema, fieldValue);
+ }
+ break;
+ default:// Array
+ if (side.equals("min")) {
+ checkTemplateField("minItems", jsonSchema, fieldValue);
+ } else {
+ checkTemplateField("maxItems", jsonSchema, fieldValue);
+ }
+ break;
+ }
+
+ }
+
+ /**
+ * To be done.
+ *
+ * @param jsonSchema Json schema
+ * @param fieldValue field value
+ * @param typeProperty Get as Enum the valid values for the property
+ */
+ public void getValueArray(JsonObject jsonSchema, Object fieldValue, String typeProperty) {
+ if (jsonTemplate.hasFields("enum")) {
+ JsonArray enumeration = new JsonArray();
+ if (typeProperty.equals("string") || typeProperty.equals("String")) {
+ ArrayList<String> arrayValues = (ArrayList<String>) fieldValue;
+ for (String arrayItem : arrayValues) {
+ enumeration.add(arrayItem);
+ }
+ jsonSchema.add("enum", enumeration);
+ } else {
+ ArrayList<Number> arrayValues = (ArrayList<Number>) fieldValue;
+ for (Number arrayItem : arrayValues) {
+ enumeration.add(arrayItem);
+ }
+ jsonSchema.add("enum", enumeration);
+ }
+ }
+ }
+
+ /**
+ * To be done.
+ *
+ * @param field Field
+ * @param jsonSchema Json schema
+ * @param fieldValue Simple way to avoid code duplication
+ */
+ public void checkTemplateField(String field, JsonObject jsonSchema, Object fieldValue) {
+ if (jsonTemplate.hasFields(field)) {
+ String typeField = fieldValue.getClass().getSimpleName();
+ switch (typeField) {
+ case "String":
+ jsonSchema.addProperty(field, (String) fieldValue);
+ break;
+ case "Integer":
+ jsonSchema.addProperty(field, (Integer) fieldValue);
+ break;
+ case "Number":
+ jsonSchema.addProperty(field, (Number) fieldValue);
+ break;
+ case "Boolean":
+ jsonSchema.addProperty(field, (Boolean) fieldValue);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/ToscaElement.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/ToscaElement.java
new file mode 100644
index 000000000..0c531e9d0
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/ToscaElement.java
@@ -0,0 +1,121 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.elements;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+
+public class ToscaElement {
+
+ /**
+ * name parameter is used as "key", in the LinkedHashMap of Components.
+ */
+ private String name;
+ private String derivedFrom;
+ private String version;
+ private String typeVersion;
+ private String description;
+ private LinkedHashMap<String, ToscaElementProperty> properties;
+
+ public ToscaElement() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name name
+ * @param derivedFrom derivedFrom
+ * @param description description
+ */
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public ToscaElement(String name, String derivedFrom, String description) {
+ super();
+ this.name = name;
+ this.derivedFrom = derivedFrom;
+ this.description = description;
+ this.properties = new LinkedHashMap();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDerivedFrom() {
+ return derivedFrom;
+ }
+
+ public void setDerivedFrom(String derivedFrom) {
+ this.derivedFrom = derivedFrom;
+ }
+
+ public String getVersion() {
+ return version;
+ }
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+ public String getTypeVersion() {
+ return typeVersion;
+ }
+
+ public void setTypeVersion(String typeVersion) {
+ this.typeVersion = typeVersion;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public LinkedHashMap<String, ToscaElementProperty> getProperties() {
+ return properties;
+ }
+
+ public void setProperties(LinkedHashMap<String, ToscaElementProperty> properties) {
+ this.properties = properties;
+ }
+
+ public void addProperties(ToscaElementProperty toscaElementProperty) {
+ this.properties.put(toscaElementProperty.getName(), toscaElementProperty);
+ }
+
+ public ArrayList<String> propertiesNames() {
+ return new ArrayList<>(properties.keySet());
+ }
+
+ @Override
+ public String toString() {
+ return name + ": " + description + ", version: " + version + ", nb de properties: " + properties.size()
+ + System.getProperty("line.separator") + propertiesNames();
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/ToscaElementProperty.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/ToscaElementProperty.java
new file mode 100644
index 000000000..4db8b0356
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/elements/ToscaElementProperty.java
@@ -0,0 +1,135 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.elements;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplate;
+
+public class ToscaElementProperty {
+
+ /**
+ * name parameter is used as "key", in the LinkedHashMap of Components.
+ */
+ private String name;
+ private LinkedHashMap<String, Object> items;
+
+ /**
+ * Constructor.
+ *
+ * @param name the name
+ * @param items the items
+ */
+ public ToscaElementProperty(String name, LinkedHashMap<String, Object> items) {
+ super();
+ this.name = name;
+ this.items = items;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public LinkedHashMap<String, Object> getItems() {
+ return items;
+ }
+
+ public void setItems(LinkedHashMap<String, Object> items) {
+ this.items = items;
+ }
+
+ /**
+ * For each primitive value, requires to get each field Value and cast it and add it in a Json.
+ *
+ * @param fieldsContent field
+ * @param fieldName field
+ * @param value value
+ */
+ public void addFieldToJson(JsonObject fieldsContent, String fieldName, Object value) {
+ if (value != null) {
+ String typeValue = value.getClass().getSimpleName();
+ switch (typeValue) {
+ case "String":
+ fieldsContent.addProperty(fieldName, (String) value);
+ break;
+ case "Boolean":
+ fieldsContent.addProperty(fieldName, (Boolean) value);
+ break;
+ case "Double":
+ fieldsContent.addProperty(fieldName, (Number) value);
+ break;
+ case "Integer":
+ fieldsContent.addProperty(fieldName, (Integer) value);
+ break;
+ default:
+ fieldsContent.add(fieldName, parseArray((ArrayList) value));
+ break;
+ }
+ }
+ }
+
+ /**
+ * If a field value is an Array, create an Instance of ArrayField to insert if in the JsonObject.
+ *
+ * @param arrayProperties array pro
+ * @return a json array
+ */
+ public JsonArray parseArray(ArrayList<Object> arrayProperties) {
+ JsonArray arrayContent = new JsonArray();
+ ArrayList<Object> arrayComponent = new ArrayList<>();
+ for (Object itemArray : arrayProperties) {
+ arrayComponent.add(itemArray);
+ }
+ ArrayField af = new ArrayField(arrayComponent);
+ arrayContent = af.deploy();
+ return arrayContent;
+ }
+
+ /**
+ * Create an instance of Constraint, to extract the values and add it to the Json (according to the type
+ * * of the current property).
+ *
+ * @param json a json
+ * @param constraints constraints
+ * @param jsonTemplate template
+ */
+ @SuppressWarnings("unchecked")
+ public void addConstraintsAsJson(JsonObject json, ArrayList<Object> constraints, JsonTemplate jsonTemplate) {
+ for (Object constraint : constraints) {
+ if (constraint instanceof LinkedHashMap) {
+ LinkedHashMap<String, Object> valueConstraint = (LinkedHashMap<String, Object>) constraint;
+ Constraint constraintParser = new Constraint(valueConstraint, jsonTemplate);
+ constraintParser.deployConstraints(json, (String) getItems().get("type"));
+ }
+ }
+
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/ToscaMetadataExecutor.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/ToscaMetadataExecutor.java
new file mode 100644
index 000000000..5fac9a213
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/ToscaMetadataExecutor.java
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.execution;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.PostConstruct;
+import org.onap.policy.clamp.clds.tosca.update.execution.cds.ToscaMetadataCdsProcess;
+import org.onap.policy.clamp.loop.service.Service;
+import org.onap.policy.clamp.tosca.DictionaryService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * This class is used to execute a code based on a key found in the metadata section.
+ */
+@Component
+public class ToscaMetadataExecutor {
+
+ private static final EELFLogger logger =
+ EELFManager.getInstance().getLogger(ToscaMetadataExecutor.class);
+
+ @Autowired
+ private DictionaryService dictionaryService;
+
+ private Map<String, ToscaMetadataProcess> mapOfProcesses = new HashMap<>();
+
+ /**
+ * This method executes the required process specified in processInfo.
+ *
+ * @param processInfo A String containing the process to execute, like "cds/param1:value1/param2:value2"
+ * @param childObject The jsonObject
+ * @param serviceModel The service model associated to do clamp enrichment
+ */
+ public void executeTheProcess(String processInfo, JsonObject childObject, Service serviceModel) {
+ String[] processParameters = (processInfo + "/ ").split("/");
+ logger.info("Executing the Tosca clamp process " + processParameters[0] + " with parameters "
+ + processParameters[1].trim());
+ mapOfProcesses.get(processParameters[0].trim())
+ .executeProcess(processParameters[1].trim(), childObject, serviceModel);
+ }
+
+ /**
+ * Init method.
+ */
+ @PostConstruct
+ public void init() {
+ mapOfProcesses.put("CDS", new ToscaMetadataCdsProcess());
+ mapOfProcesses.put("CSAR_RESOURCES", new ToscaMetadataTargetProcess());
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/ToscaMetadataProcess.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/ToscaMetadataProcess.java
new file mode 100644
index 000000000..a1275229d
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/ToscaMetadataProcess.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.execution;
+
+import com.google.gson.JsonObject;
+import org.onap.policy.clamp.loop.service.Service;
+
+/**
+ * This code is the interface that must be implemented to have a tosca process.
+ */
+public abstract class ToscaMetadataProcess {
+
+ /**
+ * This method add some elements to the JsonObject childObject passed in argument.
+ * The process can take multiple parameters in arguments.
+ *
+ * @param parameters The parameters required by the process
+ * @param childObject The Json Object modified by the current process
+ * @param serviceModel The service model associated to do clamp enrichment
+ */
+ public abstract void executeProcess(String parameters, JsonObject childObject, Service serviceModel);
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/ToscaMetadataTargetProcess.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/ToscaMetadataTargetProcess.java
new file mode 100644
index 000000000..0ffd86f47
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/ToscaMetadataTargetProcess.java
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.execution;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import org.onap.policy.clamp.loop.service.Service;
+import org.onap.policy.clamp.policy.operational.OperationalPolicyRepresentationBuilder;
+
+/**
+ * This class is there to add the JsonObject for CDS in the json Schema according to what is found in the Tosca model.
+ */
+public class ToscaMetadataTargetProcess extends ToscaMetadataProcess {
+
+
+ private static final EELFLogger logger =
+ EELFManager.getInstance().getLogger(ToscaMetadataTargetProcess.class);
+
+ @Override
+ public void executeProcess(String parameters, JsonObject childObject, Service serviceModel) {
+ if (serviceModel == null) {
+ logger.info("serviceModel is null, therefore the ToscaMetadataTargetProcess is skipped");
+ return;
+ }
+ childObject.add("anyOf", OperationalPolicyRepresentationBuilder.createAnyOfArray(serviceModel, false));
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/cds/ToscaMetadataCdsProcess.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/cds/ToscaMetadataCdsProcess.java
new file mode 100644
index 000000000..c80c91170
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/execution/cds/ToscaMetadataCdsProcess.java
@@ -0,0 +1,229 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.execution.cds;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.util.Map;
+import java.util.Set;
+import org.onap.policy.clamp.clds.tosca.ToscaSchemaConstants;
+import org.onap.policy.clamp.clds.tosca.update.execution.ToscaMetadataProcess;
+import org.onap.policy.clamp.loop.service.Service;
+
+
+/**
+ * This class is there to add the JsonObject for CDS in the json Schema according to what is found in the Tosca model.
+ */
+public class ToscaMetadataCdsProcess extends ToscaMetadataProcess {
+
+ private static final EELFLogger logger =
+ EELFManager.getInstance().getLogger(ToscaMetadataCdsProcess.class);
+
+ @Override
+ public void executeProcess(String parameters, JsonObject childObject, Service serviceModel) {
+ if (serviceModel == null) {
+ logger.info("serviceModel is null, therefore the ToscaMetadataCdsProcess is skipped");
+ return;
+ }
+ switch (parameters) {
+ case "actor":
+ JsonArray jsonArray = new JsonArray();
+ jsonArray.add("CDS");
+ addToJsonArray(childObject, "enum", jsonArray);
+ break;
+ case "payload":
+ generatePayload(childObject, serviceModel);
+ break;
+ case "operation":
+ generateOperation(childObject, serviceModel);
+ break;
+ default:
+ }
+ }
+
+ private static void generatePayload(JsonObject childObject, Service serviceModel) {
+ JsonArray schemaAnyOf = new JsonArray();
+ schemaAnyOf.addAll(createBlankEntry());
+ schemaAnyOf.addAll(generatePayloadPerResource("VF", serviceModel));
+ schemaAnyOf.addAll(generatePayloadPerResource("PNF", serviceModel));
+ addToJsonArray(childObject, "anyOf", schemaAnyOf);
+ }
+
+ private static void generateOperation(JsonObject childObject, Service serviceModel) {
+ generateOperationPerResource(childObject, "VF", serviceModel);
+ generateOperationPerResource(childObject, "PNF", serviceModel);
+ }
+
+ private static void generateOperationPerResource(JsonObject childObject, String resourceName,
+ Service serviceModel) {
+ JsonArray schemaEnum = new JsonArray();
+ JsonArray schemaTitle = new JsonArray();
+ for (Map.Entry<String, JsonElement> entry : serviceModel.getResourceDetails().getAsJsonObject(resourceName)
+ .entrySet()) {
+ JsonObject controllerProperties = entry.getValue().getAsJsonObject()
+ .getAsJsonObject("controllerProperties");
+ if (controllerProperties != null && controllerProperties.getAsJsonObject("workflows") != null) {
+ for (String workflowsEntry : controllerProperties.getAsJsonObject("workflows").keySet()) {
+ schemaEnum.add(workflowsEntry);
+ schemaTitle.add(workflowsEntry + " (CDS operation)");
+ }
+ }
+ }
+ addToJsonArray(childObject, "enum", schemaEnum);
+ if (childObject.get("options") == null) {
+ JsonObject optionsSection = new JsonObject();
+ childObject.add("options", optionsSection);
+ }
+ addToJsonArray(childObject.getAsJsonObject("options"), "enum_titles", schemaTitle);
+
+ }
+
+ private static JsonArray generatePayloadPerResource(String resourceName,
+ Service serviceModel) {
+ JsonArray schemaAnyOf = new JsonArray();
+
+ for (Map.Entry<String, JsonElement> entry : serviceModel.getResourceDetails().getAsJsonObject(resourceName)
+ .entrySet()) {
+ JsonObject controllerProperties = entry.getValue().getAsJsonObject()
+ .getAsJsonObject("controllerProperties");
+ if (controllerProperties != null && controllerProperties.getAsJsonObject("workflows") != null) {
+ for (Map.Entry<String, JsonElement> workflowsEntry : controllerProperties.getAsJsonObject("workflows")
+ .entrySet()) {
+ JsonObject obj = new JsonObject();
+ obj.addProperty("title", workflowsEntry.getKey());
+ obj.add("properties",
+ createInputPropertiesForPayload(workflowsEntry.getValue().getAsJsonObject(),
+ controllerProperties,
+ workflowsEntry.getKey()));
+ schemaAnyOf.add(obj);
+ }
+ }
+ }
+ return schemaAnyOf;
+ }
+
+ private static JsonArray createBlankEntry() {
+ JsonArray result = new JsonArray();
+ JsonObject blankObject = new JsonObject();
+ blankObject.addProperty("title", "User defined");
+ blankObject.add("properties", new JsonObject());
+ result.add(blankObject);
+ return result;
+ }
+
+ private static JsonObject createAnyOfJsonProperty(String name,
+ String defaultValue,
+ boolean readOnlyFlag) {
+ JsonObject result = new JsonObject();
+ result.addProperty("title", name);
+ result.addProperty("type", "string");
+ result.addProperty("default", defaultValue);
+ result.addProperty("readOnly", readOnlyFlag);
+ return result;
+ }
+
+ private static void addToJsonArray(JsonObject childObject, String section, JsonArray value) {
+ if (childObject.getAsJsonArray(section) != null) {
+ childObject.getAsJsonArray(section).addAll(value);
+ } else {
+ childObject.add(section, value);
+ }
+ }
+
+ /**
+ * Returns the properties of payload based on the cds work flows.
+ *
+ * @param workFlow cds work flows to update payload
+ * @param controllerProperties cds properties to get blueprint name and
+ * version
+ * @param workFlowName work flow name
+ * @return returns the properties of payload
+ */
+ public static JsonObject createInputPropertiesForPayload(JsonObject workFlow,
+ JsonObject controllerProperties,
+ String workFlowName) {
+ String artifactName = controllerProperties.get("sdnc_model_name").getAsString();
+ String artifactVersion = controllerProperties.get("sdnc_model_version").getAsString();
+ JsonObject inputs = workFlow.getAsJsonObject("inputs");
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.add("artifact_name", createAnyOfJsonProperty(
+ "artifact name", artifactName, true));
+ jsonObject.add("artifact_version", createAnyOfJsonProperty(
+ "artifact version", artifactVersion, true));
+ jsonObject.add("mode", createAnyOfJsonProperty(
+ "mode", "async", false));
+ jsonObject.add("data", createDataProperty(inputs, workFlowName));
+ return jsonObject;
+ }
+
+ private static JsonObject createDataProperty(JsonObject inputs, String workFlowName) {
+ JsonObject data = new JsonObject();
+ data.addProperty("title", "data");
+ data.addProperty("type", "string");
+ data.addProperty("format", "textarea");
+ JsonObject defaultValue = new JsonObject();
+ addDefaultValueForData(inputs, defaultValue, workFlowName);
+ data.addProperty("default", defaultValue.toString());
+ return data;
+ }
+
+ private static void addDefaultValueForData(JsonObject inputs,
+ JsonObject defaultValue,
+ String workFlowName) {
+ Set<Map.Entry<String, JsonElement>> entrySet = inputs.entrySet();
+ for (Map.Entry<String, JsonElement> entry : entrySet) {
+ String key = entry.getKey();
+ JsonObject inputProperty = inputs.getAsJsonObject(key);
+ if (key.equalsIgnoreCase(workFlowName + "-properties")) {
+ addDefaultValueForData(entry.getValue().getAsJsonObject().get("properties")
+ .getAsJsonObject(), defaultValue, workFlowName);
+ } else if ("object".equalsIgnoreCase(inputProperty.get(ToscaSchemaConstants.TYPE).getAsString())) {
+ JsonObject object = new JsonObject();
+ addDefaultValueForData(entry.getValue().getAsJsonObject().get("properties")
+ .getAsJsonObject(), object, workFlowName);
+ defaultValue.add(entry.getKey(), object);
+ } else if (ToscaSchemaConstants.TYPE_LIST.equalsIgnoreCase(inputProperty.get(ToscaSchemaConstants.TYPE)
+ .getAsString())) {
+ defaultValue.add(entry.getKey(), handleListType(entry.getValue().getAsJsonObject(), workFlowName));
+ } else {
+ defaultValue.addProperty(entry.getKey(), "");
+ }
+ }
+ }
+
+ private static JsonArray handleListType(JsonObject inputs,
+ String workFlowName) {
+
+ JsonObject object = new JsonObject();
+ if (inputs.get("properties") != null) {
+ addDefaultValueForData(inputs.get("properties").getAsJsonObject(), object, workFlowName);
+ }
+ JsonArray arr = new JsonArray();
+ arr.add(object);
+ return arr;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/ToscaConverterToJsonSchema.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/ToscaConverterToJsonSchema.java
new file mode 100644
index 000000000..74fd8e5fd
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/ToscaConverterToJsonSchema.java
@@ -0,0 +1,353 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.parser;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElement;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElementProperty;
+import org.onap.policy.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParser;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplate;
+import org.onap.policy.clamp.loop.service.Service;
+
+/**
+ * This class can be used to convert a tosca to a json schema.
+ * This class is not supposed to be used directly because it requires the json Schema templates
+ * (template conversion tosca type to json schema entry) but also the supported Tosca main type file.
+ * The class ToscaConverterWithDictionarySupport is more complete for the end user to be used (in the clamp context).
+ *
+ * @see org.onap.policy.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport#convertToscaToJsonSchemaObject
+ * @see org.onap.policy.clamp.clds.tosca.update.parser.ToscaConverterToJsonSchema#getJsonSchemaOfToscaElement
+ */
+public class ToscaConverterToJsonSchema {
+ private LinkedHashMap<String, ToscaElement> components;
+ private LinkedHashMap<String, JsonTemplate> templates;
+
+ private ToscaMetadataParser metadataParser;
+
+ private Service serviceModel;
+
+ /**
+ * Constructor.
+ *
+ * @param toscaElementsMap All the tosca elements found (policy type + data types + native tosca datatypes)
+ * @param jsonSchemaTemplates All Json schema templates to use
+ * @param metadataParser The metadata parser to use for metadata section
+ * @param serviceModel The service model for clamp enrichment
+ */
+ public ToscaConverterToJsonSchema(LinkedHashMap<String, ToscaElement> toscaElementsMap,
+ LinkedHashMap<String, JsonTemplate> jsonSchemaTemplates,
+ ToscaMetadataParser metadataParser, Service serviceModel) {
+ this.components = toscaElementsMap;
+ this.templates = jsonSchemaTemplates;
+ this.metadataParser = metadataParser;
+ this.serviceModel = serviceModel;
+ }
+
+ /**
+ * For a given component, launch process to parse it in Json.
+ *
+ * @param toscaElementKey name components
+ * @return return
+ */
+ public JsonObject getJsonSchemaOfToscaElement(String toscaElementKey) {
+ return this.getFieldAsObject(getToscaElement(toscaElementKey));
+ }
+
+ /**
+ * Return the classical/general fields of the component, & launch the properties deployment.
+ *
+ * @param toscaElement the compo
+ * @return a json object
+ */
+ public JsonObject getFieldAsObject(ToscaElement toscaElement) {
+
+ JsonObject globalFields = new JsonObject();
+ if (templates.get("object").hasFields("title")) {
+ globalFields.addProperty("title", toscaElement.getName());
+ }
+ if (templates.get("object").hasFields("type")) {
+ globalFields.addProperty("type", "object");
+ }
+ if (templates.get("object").hasFields("description")) {
+ if (toscaElement.getDescription() != null) {
+ globalFields.addProperty("description", toscaElement.getDescription());
+ }
+ }
+ if (templates.get("object").hasFields("required")) {
+ globalFields.add("required", this.getRequirements(toscaElement.getName()));
+ }
+ if (templates.get("object").hasFields("properties")) {
+ globalFields.add("properties", this.deploy(toscaElement.getName()));
+ }
+ return globalFields;
+ }
+
+ /**
+ * Get the required properties of the Component, including the parents properties requirements.
+ *
+ * @param nameComponent name component
+ * @return a json array
+ */
+ public JsonArray getRequirements(String nameComponent) {
+ JsonArray requirements = new JsonArray();
+ ToscaElement toParse = components.get(nameComponent);
+ //Check for a father component, and launch the same process
+ if (!"tosca.datatypes.Root".equals(toParse.getDerivedFrom())
+ && !"tosca.policies.Root".equals(toParse.getDerivedFrom())) {
+ requirements.addAll(getRequirements(toParse.getDerivedFrom()));
+ }
+ //Each property is checked, and add to the requirement array if it's required
+ Collection<ToscaElementProperty> properties = toParse.getProperties().values();
+ for (ToscaElementProperty toscaElementProperty : properties) {
+ if (toscaElementProperty.getItems().containsKey("required")
+ && toscaElementProperty.getItems().get("required").equals(true)) {
+ requirements.add(toscaElementProperty.getName());
+ }
+ }
+ return requirements;
+ }
+
+ /**
+ * The beginning of the recursive process. Get the parents (or not) to launch the same process, and otherwise
+ * deploy and parse the properties.
+ *
+ * @param nameComponent name component
+ * @return a json object
+ */
+ public JsonObject deploy(String nameComponent) {
+ JsonObject jsonSchema = new JsonObject();
+ ToscaElement toParse = components.get(nameComponent);
+ //Check for a father component, and launch the same process
+ if (!toParse.getDerivedFrom().equals("tosca.datatypes.Root")
+ && !toParse.getDerivedFrom().equals("tosca.policies.Root")) {
+ jsonSchema = this.getParent(toParse.getDerivedFrom());
+ }
+ //For each component property, check if its a complex properties (a component) or not. In that case,
+ //launch the analyse of the property.
+ for (Entry<String, ToscaElementProperty> property : toParse.getProperties().entrySet()) {
+ if (getToscaElement((String) property.getValue().getItems().get("type")) != null) {
+ jsonSchema.add(property.getValue().getName(),
+ this.getJsonSchemaOfToscaElement((String) property.getValue().getItems().get("type")));
+ } else {
+ jsonSchema.add(property.getValue().getName(), this.complexParse(property.getValue()));
+ }
+ }
+ return jsonSchema;
+ }
+
+ /**
+ * If a component has a parent, it is deploy in the same way.
+ *
+ * @param nameComponent name component
+ * @return a json object
+ */
+ public JsonObject getParent(String nameComponent) {
+ return deploy(nameComponent);
+ }
+
+ /**
+ * to be done.
+ *
+ * @param toscaElementProperty property
+ * @return a json object
+ */
+ @SuppressWarnings("unchecked")
+ public JsonObject complexParse(ToscaElementProperty toscaElementProperty) {
+ JsonObject propertiesInJson = new JsonObject();
+ JsonTemplate currentPropertyJsonTemplate;
+ String typeProperty = (String) toscaElementProperty.getItems().get("type");
+ if (typeProperty.toLowerCase().equals("list") || typeProperty.toLowerCase().equals("map")) {
+ currentPropertyJsonTemplate = templates.get("object");
+ } else {
+ String propertyType = (String) toscaElementProperty.getItems().get("type");
+ currentPropertyJsonTemplate = templates.get(propertyType.toLowerCase());
+ }
+ //Each "special" field is analysed, and has a specific treatment
+ for (String propertyField : toscaElementProperty.getItems().keySet()) {
+ switch (propertyField) {
+ case "type":
+ if (currentPropertyJsonTemplate.hasFields(propertyField)) {
+ String fieldtype = (String) toscaElementProperty.getItems().get(propertyField);
+ switch (fieldtype.toLowerCase()) {
+ case "list":
+ propertiesInJson.addProperty("type", "array");
+ break;
+ case "map":
+ propertiesInJson.addProperty("type", "object");
+ break;
+ case "scalar-unit.time":
+ case "scalar-unit.frequency":
+ case "scalar-unit.size":
+ propertiesInJson.addProperty("type", "string");
+ break;
+ case "timestamp":
+ propertiesInJson.addProperty("type", "string");
+ propertiesInJson.addProperty("format", "date-time");
+ break;
+ case "float":
+ propertiesInJson.addProperty("type", "number");
+ break;
+ case "range":
+ propertiesInJson.addProperty("type", "integer");
+ if (!checkConstraintPresence(toscaElementProperty, "greater_than")
+ && currentPropertyJsonTemplate.hasFields("exclusiveMinimum")) {
+ propertiesInJson.addProperty("exclusiveMinimum", false);
+ }
+ if (!checkConstraintPresence(toscaElementProperty, "less_than")
+ && currentPropertyJsonTemplate.hasFields("exclusiveMaximum")) {
+ propertiesInJson.addProperty("exclusiveMaximum", false);
+ }
+ break;
+ default:
+ propertiesInJson.addProperty("type", currentPropertyJsonTemplate.getName());
+ break;
+ }
+ }
+ break;
+ case "metadata":
+ if (metadataParser != null) {
+ metadataParser.processAllMetadataElement(toscaElementProperty, serviceModel).entrySet()
+ .forEach((jsonEntry) -> {
+ propertiesInJson.add(jsonEntry.getKey(),
+ jsonEntry.getValue());
+
+ });
+ }
+ break;
+ case "constraints":
+ toscaElementProperty.addConstraintsAsJson(propertiesInJson,
+ (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"),
+ currentPropertyJsonTemplate);
+ break;
+ case "entry_schema":
+ //Here, a way to check if entry is a component (datatype) or a simple string
+ if (getToscaElement(this.extractSpecificFieldFromMap(toscaElementProperty, "entry_schema"))
+ != null) {
+ String nameComponent = this.extractSpecificFieldFromMap(toscaElementProperty, "entry_schema");
+ ToscaConverterToJsonSchema child = new ToscaConverterToJsonSchema(components, templates,
+ metadataParser, serviceModel);
+ JsonObject propertiesContainer = new JsonObject();
+
+ switch ((String) toscaElementProperty.getItems().get("type")) {
+ case "map": // Get it as an object
+ JsonObject componentAsProperty = child.getJsonSchemaOfToscaElement(nameComponent);
+ propertiesContainer.add(nameComponent, componentAsProperty);
+ if (currentPropertyJsonTemplate.hasFields("properties")) {
+ propertiesInJson.add("properties", propertiesContainer);
+ }
+ break;
+ default://list : get it as an Array
+ JsonObject componentAsItem = child.getJsonSchemaOfToscaElement(nameComponent);
+ if (currentPropertyJsonTemplate.hasFields("properties")) {
+ propertiesInJson.add("items", componentAsItem);
+ propertiesInJson.addProperty("format", "tabs-top");
+ }
+ break;
+ }
+
+ } else if (toscaElementProperty.getItems().get("type").equals("list")) {
+ // Native cases
+ JsonObject itemContainer = new JsonObject();
+ String valueInEntrySchema =
+ this.extractSpecificFieldFromMap(toscaElementProperty, "entry_schema");
+ itemContainer.addProperty("type", valueInEntrySchema);
+ propertiesInJson.add("items", itemContainer);
+ propertiesInJson.addProperty("format", "tabs-top");
+ }
+
+ // MAP Case, for now nothing
+
+ break;
+ default:
+ //Each classical field : type, description, default..
+ if (currentPropertyJsonTemplate.hasFields(propertyField) && !propertyField.equals("required")) {
+ toscaElementProperty.addFieldToJson(propertiesInJson, propertyField,
+ toscaElementProperty.getItems().get(propertyField));
+ }
+ break;
+ }
+ }
+ return propertiesInJson;
+ }
+
+ /**
+ * Look for a matching Component for the name parameter, in the components list.
+ *
+ * @param name the tosca element name to search for
+ * @return a tosca element
+ */
+ public ToscaElement getToscaElement(String name) {
+ ToscaElement correspondingToscaElement = null;
+ if (components == null) {
+ return null;
+ }
+ for (ToscaElement toscaElement : components.values()) {
+ if (toscaElement.getName().equals(name)) {
+ correspondingToscaElement = toscaElement;
+ }
+ }
+ return correspondingToscaElement;
+ }
+
+ /**
+ * Simple method to extract quickly a type field from particular property item.
+ *
+ * @param toscaElementProperty the property
+ * @param fieldName the fieldname
+ * @return a string
+ */
+ @SuppressWarnings("unchecked")
+ public String extractSpecificFieldFromMap(ToscaElementProperty toscaElementProperty, String fieldName) {
+ LinkedHashMap<String, String> entrySchemaFields =
+ (LinkedHashMap<String, String>) toscaElementProperty.getItems().get(fieldName);
+ return entrySchemaFields.get("type");
+ }
+
+ /**
+ * Check if a constraint, for a specific property, is there.
+ *
+ * @param toscaElementProperty property
+ * @param nameConstraint name constraint
+ * @return a flag boolean
+ */
+ public boolean checkConstraintPresence(ToscaElementProperty toscaElementProperty, String nameConstraint) {
+ boolean presentConstraint = false;
+ if (toscaElementProperty.getItems().containsKey("constraints")) {
+ ArrayList<Object> constraints = (ArrayList) toscaElementProperty.getItems().get("constraints");
+ for (Object constraint : constraints) {
+ if (constraint instanceof LinkedHashMap) {
+ if (((LinkedHashMap) constraint).containsKey(nameConstraint)) {
+ presentConstraint = true;
+ }
+ }
+ }
+ }
+ return presentConstraint;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/ToscaElementParser.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/ToscaElementParser.java
new file mode 100644
index 000000000..a3dd9c3e1
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/ToscaElementParser.java
@@ -0,0 +1,103 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.parser;
+
+import java.util.LinkedHashMap;
+import java.util.Map.Entry;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElement;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElementProperty;
+import org.yaml.snakeyaml.Yaml;
+
+public class ToscaElementParser {
+ /**
+ * Constructor.
+ */
+ private ToscaElementParser() {
+ }
+
+ private static LinkedHashMap<String, Object> searchAllDataTypesAndPolicyTypes(String toscaYaml) {
+ LinkedHashMap<String, LinkedHashMap<String, Object>> file =
+ (LinkedHashMap<String, LinkedHashMap<String, Object>>) new Yaml().load(toscaYaml);
+ LinkedHashMap<String, Object> allDataTypesFound = file.get("data_types");
+ LinkedHashMap<String, Object> allPolicyTypesFound = file.get("policy_types");
+ LinkedHashMap<String, Object> allItemsFound = new LinkedHashMap<>();
+ // Put the policies and datatypes in the same collection
+ allItemsFound = (allDataTypesFound == null) ? (new LinkedHashMap<>()) : allDataTypesFound;
+ allItemsFound.putAll(allPolicyTypesFound == null ? new LinkedHashMap<>() : allPolicyTypesFound);
+ return allItemsFound;
+ }
+
+ private static LinkedHashMap<String, Object> searchAllNativeToscaDataTypes(String toscaNativeYaml) {
+ return ((LinkedHashMap<String, LinkedHashMap<String, Object>>) new Yaml().load(toscaNativeYaml))
+ .get("data_types");
+ }
+
+ /**
+ * Yaml Parse gets raw policies and datatypes, in different sections : necessary to extract
+ * all entities and put them at the same level.
+ *
+ * @param toscaYaml the tosca model content
+ * @param nativeToscaYaml the tosca native datatype content
+ * @return a map of Tosca Element containing all tosca elements found (policy types and datatypes)
+ */
+ public static LinkedHashMap<String, ToscaElement> searchAllToscaElements(String toscaYaml,
+ String nativeToscaYaml) {
+ LinkedHashMap<String, Object> allItemsFound = searchAllDataTypesAndPolicyTypes(toscaYaml);
+ allItemsFound.putAll(searchAllNativeToscaDataTypes(nativeToscaYaml));
+ return parseAllItemsFound(allItemsFound);
+ }
+
+ /**
+ * With all the component, get as Map, Components and Components properties are created.
+ *
+ * @param allMaps maps
+ */
+ private static LinkedHashMap<String, ToscaElement> parseAllItemsFound(LinkedHashMap<String, Object> allMaps) {
+ LinkedHashMap<String, ToscaElement> allItemsFound = new LinkedHashMap<String, ToscaElement>();
+ //Component creations, from the file maps
+ for (Entry<String, Object> itemToParse : allMaps.entrySet()) {
+ LinkedHashMap<String, Object> componentBody = (LinkedHashMap<String, Object>) itemToParse.getValue();
+ ToscaElement toscaElement =
+ new ToscaElement(itemToParse.getKey(), (String) componentBody.get("derived_from"),
+ (String) componentBody.get("description"));
+ //If policy, version and type_version :
+ if (componentBody.get("type_version") != null) {
+ toscaElement.setVersion((String) componentBody.get("type_version"));
+ toscaElement.setTypeVersion((String) componentBody.get("type_version"));
+ }
+ //Properties creation, from the map
+ if (componentBody.get("properties") != null) {
+ LinkedHashMap<String, Object> properties =
+ (LinkedHashMap<String, Object>) componentBody.get("properties");
+ for (Entry<String, Object> itemToProperty : properties.entrySet()) {
+ ToscaElementProperty toscaElementProperty = new ToscaElementProperty(itemToProperty.getKey(),
+ (LinkedHashMap<String, Object>) itemToProperty.getValue());
+ toscaElement.addProperties(toscaElementProperty);
+ }
+ }
+ allItemsFound.put(toscaElement.getName(), toscaElement);
+ }
+ return allItemsFound;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParser.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParser.java
new file mode 100644
index 000000000..b2568b79f
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParser.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.parser.metadata;
+
+import com.google.gson.JsonObject;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElementProperty;
+import org.onap.policy.clamp.loop.service.Service;
+
+public interface ToscaMetadataParser {
+ JsonObject processAllMetadataElement(ToscaElementProperty toscaElementProperty, Service serviceModel);
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParserWithDictionarySupport.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParserWithDictionarySupport.java
new file mode 100644
index 000000000..4e55263fb
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/parser/metadata/ToscaMetadataParserWithDictionarySupport.java
@@ -0,0 +1,211 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.parser.metadata;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Optional;
+import org.onap.policy.clamp.clds.tosca.JsonEditorSchemaConstants;
+import org.onap.policy.clamp.clds.tosca.ToscaSchemaConstants;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElementProperty;
+import org.onap.policy.clamp.clds.tosca.update.execution.ToscaMetadataExecutor;
+import org.onap.policy.clamp.loop.service.Service;
+import org.onap.policy.clamp.tosca.DictionaryElement;
+import org.onap.policy.clamp.tosca.DictionaryService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+@Component
+public class ToscaMetadataParserWithDictionarySupport implements ToscaMetadataParser {
+
+ @Autowired
+ private ToscaMetadataExecutor toscaMetadataExecutor;
+
+ @Autowired
+ private DictionaryService dictionaryService;
+
+ /**
+ * This method is used to start the processing of the metadata field.
+ *
+ * @param toscaElementProperty The property metadata as Json Object
+ * @return The jsonObject structure that must be added to the json schema
+ */
+ public JsonObject processAllMetadataElement(ToscaElementProperty toscaElementProperty, Service serviceModel) {
+ if (dictionaryService != null) {
+ return parseMetadataPossibleValues(toscaElementProperty.getItems(), dictionaryService, serviceModel,
+ toscaMetadataExecutor);
+ } else {
+ return null;
+ }
+ }
+
+ private static JsonObject parseMetadataPossibleValues(LinkedHashMap<String, Object> childNodeMap,
+ DictionaryService dictionaryService, Service serviceModel,
+ ToscaMetadataExecutor toscaMetadataExecutor) {
+ JsonObject childObject = new JsonObject();
+ if (childNodeMap.containsKey(ToscaSchemaConstants.METADATA)
+ && childNodeMap.get(ToscaSchemaConstants.METADATA) != null) {
+ ((LinkedHashMap<String, Object>) childNodeMap.get(ToscaSchemaConstants.METADATA)).forEach((key,
+ value) -> {
+ if (key.equalsIgnoreCase(ToscaSchemaConstants.METADATA_CLAMP_POSSIBLE_VALUES)) {
+ String[] multipleValues = ((String) value).split(",");
+ for (String multipleValue : multipleValues) {
+ if (multipleValue.contains(ToscaSchemaConstants.DICTIONARY)) {
+ processDictionaryElements(multipleValue, childObject, dictionaryService);
+ }
+ if (multipleValue.contains("ClampExecution:")) {
+ executeClampProcess(multipleValue.replaceFirst("ClampExecution:", ""), childObject,
+ serviceModel, toscaMetadataExecutor);
+ }
+ }
+
+ }
+ });
+ }
+ return childObject;
+ }
+
+ private static void executeClampProcess(String processInfo, JsonObject childObject, Service serviceModel,
+ ToscaMetadataExecutor toscaMetadataExecutor) {
+ toscaMetadataExecutor.executeTheProcess(processInfo, childObject, serviceModel);
+ }
+
+ /**
+ * For dictionary with multiple levels (defined by #).
+ *
+ * @param dictionaryKeyArray the array containing the different elements
+ * @param childObject the structure getting the new entries
+ * @param dictionaryService the dictionary service bean
+ */
+ private static void processComplexDictionaryElements(String[] dictionaryKeyArray, JsonObject childObject,
+ DictionaryService dictionaryService) {
+ // We support only one # as of now.
+ List<DictionaryElement> dictionaryElements = null;
+ if (dictionaryKeyArray.length == 2) {
+ dictionaryElements = new ArrayList<>(dictionaryService.getDictionary(dictionaryKeyArray[0])
+ .getDictionaryElements());
+ JsonArray subDictionaryNames = new JsonArray();
+ new ArrayList<DictionaryElement>(dictionaryService.getDictionary(dictionaryKeyArray[1])
+ .getDictionaryElements()).forEach(elem -> subDictionaryNames.add(elem.getShortName()));
+
+ JsonArray jsonArray = new JsonArray();
+
+ Optional.of(dictionaryElements).get().forEach(c -> {
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.addProperty(JsonEditorSchemaConstants.TYPE, getJsonType(c.getType()));
+ if (c.getType() != null
+ && c.getType().equalsIgnoreCase(ToscaSchemaConstants.TYPE_STRING)) {
+ jsonObject.addProperty(JsonEditorSchemaConstants.MIN_LENGTH, 1);
+
+ }
+ jsonObject.addProperty(JsonEditorSchemaConstants.ID, c.getName());
+ jsonObject.addProperty(JsonEditorSchemaConstants.LABEL, c.getShortName());
+ jsonObject.add(JsonEditorSchemaConstants.OPERATORS, subDictionaryNames);
+ jsonArray.add(jsonObject);
+ });
+
+ JsonObject filterObject = new JsonObject();
+ filterObject.add(JsonEditorSchemaConstants.FILTERS, jsonArray);
+
+ childObject.addProperty(JsonEditorSchemaConstants.TYPE,
+ JsonEditorSchemaConstants.TYPE_QBLDR);
+ // TO invoke validation on such parameters
+ childObject.addProperty(JsonEditorSchemaConstants.MIN_LENGTH, 1);
+ childObject.add(JsonEditorSchemaConstants.QSSCHEMA, filterObject);
+
+ }
+ }
+
+ /**
+ * For dictionary with single entry.
+ *
+ * @param dictionaryKeyArray the array containing the different elements
+ * @param childObject the structure getting the new entries
+ * @param dictionaryService the dictionary service bean
+ */
+ private static void processSimpleDictionaryElements(String[] dictionaryKeyArray, JsonObject childObject,
+ DictionaryService dictionaryService) {
+ JsonArray dictionaryNames = new JsonArray();
+ JsonArray dictionaryFullNames = new JsonArray();
+ dictionaryService.getDictionary(dictionaryKeyArray[0]).getDictionaryElements().forEach(c -> {
+ // Json type will be translated before Policy creation
+ if (c.getType() != null && !c.getType().equalsIgnoreCase("json")) {
+ dictionaryFullNames.add(c.getName());
+ }
+ dictionaryNames.add(c.getShortName());
+ });
+
+ if (dictionaryFullNames.size() > 0) {
+ if (childObject.get(JsonEditorSchemaConstants.ENUM) != null) {
+ childObject.get(JsonEditorSchemaConstants.ENUM).getAsJsonArray().add(dictionaryFullNames);
+ } else {
+ childObject.add(JsonEditorSchemaConstants.ENUM, dictionaryFullNames);
+ }
+ // Add Enum titles for generated translated values during JSON instance
+ // generation
+ JsonObject enumTitles = new JsonObject();
+ enumTitles.add(JsonEditorSchemaConstants.ENUM_TITLES, dictionaryNames);
+ if (childObject.get(JsonEditorSchemaConstants.OPTIONS) != null) {
+ childObject.get(JsonEditorSchemaConstants.OPTIONS).getAsJsonArray().add(enumTitles);
+ } else {
+ childObject.add(JsonEditorSchemaConstants.OPTIONS, enumTitles);
+ }
+
+ } else {
+ if (childObject.get(JsonEditorSchemaConstants.ENUM) != null) {
+ childObject.get(JsonEditorSchemaConstants.ENUM).getAsJsonArray().add(dictionaryNames);
+ } else {
+ childObject.add(JsonEditorSchemaConstants.ENUM, dictionaryNames);
+ }
+ }
+ }
+
+ private static void processDictionaryElements(String dictionaryReference, JsonObject childObject,
+ DictionaryService dictionaryService) {
+ String[] dictionaryKeyArray =
+ dictionaryReference.substring(dictionaryReference.indexOf(ToscaSchemaConstants.DICTIONARY) + 11,
+ dictionaryReference.length()).split("#");
+ if (dictionaryKeyArray.length > 1) {
+ processComplexDictionaryElements(dictionaryKeyArray, childObject, dictionaryService);
+ } else {
+ processSimpleDictionaryElements(dictionaryKeyArray, childObject, dictionaryService);
+ }
+ }
+
+ private static String getJsonType(String toscaType) {
+ String jsonType = null;
+ if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_INTEGER)) {
+ jsonType = JsonEditorSchemaConstants.TYPE_INTEGER;
+ } else if (toscaType.equalsIgnoreCase(ToscaSchemaConstants.TYPE_LIST)) {
+ jsonType = JsonEditorSchemaConstants.TYPE_ARRAY;
+ } else {
+ jsonType = JsonEditorSchemaConstants.TYPE_STRING;
+ }
+ return jsonType;
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/templates/JsonTemplate.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/templates/JsonTemplate.java
new file mode 100644
index 000000000..5c96f2c4a
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/templates/JsonTemplate.java
@@ -0,0 +1,223 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.templates;
+
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.List;
+
+public class JsonTemplate {
+
+ /**
+ * name parameter is used as "key", in the LinkedHashMap of Templates.
+ */
+ private String name;
+ private List<JsonTemplateField> jsonTemplateFields;
+
+ public JsonTemplate(String name) {
+ this.name = name;
+ this.jsonTemplateFields = new ArrayList<>();
+ }
+
+ public JsonTemplate(String name, List<JsonTemplateField> jsonTemplateFields) {
+ this.name = name;
+ this.jsonTemplateFields = jsonTemplateFields;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public List<JsonTemplateField> getJsonTemplateFields() {
+ return jsonTemplateFields;
+ }
+
+ public void setJsonTemplateFields(List<JsonTemplateField> jsonTemplateFields) {
+ this.jsonTemplateFields = jsonTemplateFields;
+ }
+
+ /**
+ * Search in fields if fieldName exists.
+ *
+ * @param fieldName The field name
+ * @return Ture if it exists, false otherwise
+ */
+ public boolean hasFields(String fieldName) {
+ for (JsonTemplateField jsonTemplateField : this.getJsonTemplateFields()) {
+ if (jsonTemplateField.getTitle().equals(fieldName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get a specific Field.
+ *
+ * @param fieldName The field name
+ * @return THe Field found
+ */
+ public JsonTemplateField getSpecificField(String fieldName) {
+ for (JsonTemplateField jsonTemplateField : this.getJsonTemplateFields()) {
+ if (jsonTemplateField.getTitle().equals(fieldName)) {
+ return jsonTemplateField;
+ }
+ }
+ return null;
+ }
+
+ public void addField(JsonTemplateField jsonTemplateField) {
+ jsonTemplateFields.add(jsonTemplateField);
+ }
+
+ public void removeField(JsonTemplateField jsonTemplateField) {
+ jsonTemplateFields.remove(jsonTemplateField);
+ }
+
+ /**
+ * Enable or disable the visibility.
+ *
+ * @param nameField THe field name
+ * @param state True or false
+ */
+ public void setVisibility(String nameField, boolean state) {
+ for (JsonTemplateField jsonTemplateField : this.jsonTemplateFields) {
+ if (jsonTemplateField.getTitle().equals(nameField)) {
+ jsonTemplateField.setVisible(state);
+ }
+ }
+ }
+
+ /**
+ * This method defines if a field is static or not.
+ *
+ * @param nameField The name of the field
+ * @param state true or false
+ */
+ public void setStatic(String nameField, boolean state) {
+ for (JsonTemplateField jsonTemplateField : this.jsonTemplateFields) {
+ if (jsonTemplateField.getTitle().equals(nameField)) {
+ jsonTemplateField.setStaticValue(state);
+ }
+ }
+ }
+
+ /**
+ * This method updates the value of a specfic field.
+ *
+ * @param nameField The name of the field
+ * @param newValue The new value as Object
+ */
+ public void updateValueField(String nameField, Object newValue) {
+ for (JsonTemplateField jsonTemplateField : this.jsonTemplateFields) {
+ if (jsonTemplateField.getTitle().equals(nameField)) {
+ jsonTemplateField.setValue(newValue);
+ }
+ }
+ }
+
+ /**
+ * Compare two templates : size and their contents.
+ *
+ * @param jsonTemplate the template
+ * @return a boolean
+ */
+ public boolean checkFields(JsonTemplate jsonTemplate) {
+ boolean duplicateFields = false;
+ if (jsonTemplate.getJsonTemplateFields().size() == this.getJsonTemplateFields().size()) {
+ int countMatchingFields = 0;
+ //loop each component of first
+ for (JsonTemplateField jsonTemplateFieldToCheck : jsonTemplate.getJsonTemplateFields()) {
+ for (JsonTemplateField jsonTemplateField : this.getJsonTemplateFields()) {
+ if (jsonTemplateFieldToCheck.compareWithField(jsonTemplateField)) {
+ countMatchingFields++;
+ }
+ }
+ }
+
+ if (jsonTemplate.getJsonTemplateFields().size() == countMatchingFields) {
+ duplicateFields = true;
+ }
+ }
+ return duplicateFields;
+ }
+
+ /**
+ * This method gets the specific field status.
+ *
+ * @param field The field name
+ * @return true or false
+ */
+ public boolean fieldStaticStatus(String field) {
+ if (this.hasFields(field) && this.getSpecificField(field).getStaticValue().equals(true)
+ && this.getSpecificField(field).getValue() != null) {
+ return true;
+ }
+ return false;
+ }
+
+ public boolean isVisible(String field) {
+ return this.getSpecificField(field).getVisible();
+ }
+
+ /**
+ * Set the value of a property of the Field in the json.
+ *
+ * @param jsonSchema The Json schema
+ * @param fieldName The Field name
+ * @param value The value
+ */
+ public void setValue(JsonObject jsonSchema, String fieldName, String value) {
+ if (isVisible(fieldName)) {
+ if (fieldStaticStatus(fieldName)) {
+ String defaultValue = (String) this.getSpecificField(fieldName).getValue();
+ jsonSchema.addProperty(fieldName, defaultValue);
+ } else {
+ jsonSchema.addProperty(fieldName, value);
+ }
+ }
+ }
+
+ /**
+ * Inject a static value in the json.
+ *
+ * @param jsonSchema The json schema object
+ * @param fieldName The field name
+ */
+ public void injectStaticValue(JsonObject jsonSchema, String fieldName) {
+ if (isVisible(fieldName)) {
+ JsonTemplateField toInject = this.getSpecificField(fieldName);
+ jsonSchema.addProperty(fieldName, (String) toInject.getValue());
+ }
+ }
+
+ @Override
+ public String toString() {
+ return " templateFields : " + jsonTemplateFields;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/templates/JsonTemplateField.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/templates/JsonTemplateField.java
new file mode 100644
index 000000000..d9fd11de2
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/templates/JsonTemplateField.java
@@ -0,0 +1,149 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.templates;
+
+public class JsonTemplateField {
+ private String title;
+ private Object value;
+ private Boolean visible;
+ private Boolean staticValue;
+
+ public JsonTemplateField(String title) {
+ this.title = title;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param title The title
+ * @param value The value
+ * @param visible visible or not
+ * @param staticValue The static value
+ */
+ public JsonTemplateField(String title, Object value, Boolean visible, Boolean staticValue) {
+ this.title = title;
+ this.value = value;
+ this.visible = visible;
+ this.staticValue = staticValue;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public void setValue(Object value) {
+ this.value = value;
+ }
+
+ public Boolean getVisible() {
+ return visible;
+ }
+
+ public void setVisible(Boolean visible) {
+ this.visible = visible;
+ }
+
+ public Boolean getStaticValue() {
+ return staticValue;
+ }
+
+ public void setStaticValue(Boolean staticValue) {
+ this.staticValue = staticValue;
+ }
+
+ public String toString() {
+ return title + " " + value + " " + visible + " " + staticValue;
+ }
+
+ /**
+ * This method compares two fields.
+ *
+ * @param otherField Compare the current object with the one specified
+ * @return true if they are totally equals, false otherwise
+ */
+ public boolean compareWithField(Object otherField) {
+ if (this == otherField) {
+ return true;
+ }
+ if (otherField == null || getClass() != otherField.getClass()) {
+ return false;
+ }
+
+ JsonTemplateField jsonTemplateField = (JsonTemplateField) otherField;
+
+ if (title != null ? !title.equals(jsonTemplateField.title) : jsonTemplateField.title != null) {
+ return false;
+ }
+ if (value != null ? !value.equals(jsonTemplateField.value) : jsonTemplateField.value != null) {
+ return false;
+ }
+ if (visible != null ? !visible.equals(jsonTemplateField.visible) : jsonTemplateField.visible != null) {
+ return false;
+ }
+ return staticValue != null ? staticValue.equals(jsonTemplateField.staticValue) :
+ jsonTemplateField.staticValue == null;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object == null || getClass() != object.getClass()) {
+ return false;
+ }
+
+ JsonTemplateField jsonTemplateField = (JsonTemplateField) object;
+
+ return title != null ? title.equals(jsonTemplateField.title) : jsonTemplateField.title == null;
+ }
+
+ @Override
+ public int hashCode() {
+ return title != null ? title.hashCode() : 0;
+ }
+
+ /**
+ * This method test the entire equality.
+ *
+ * @param jsonTemplateField1 object one
+ * @param jsonTemplateField2 object two
+ * @return true if they are totally equals (all attributes, false otherwise
+ */
+ public static boolean fieldsEquals(JsonTemplateField jsonTemplateField1, JsonTemplateField jsonTemplateField2) {
+ return (jsonTemplateField2.getTitle().equals(jsonTemplateField1.getTitle())
+ && jsonTemplateField2.getValue().equals(jsonTemplateField1.getValue())
+ && jsonTemplateField2.getVisible().equals(jsonTemplateField1.getVisible())
+ && jsonTemplateField2.getStaticValue().equals(jsonTemplateField1.getStaticValue()));
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/templates/JsonTemplateManager.java b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/templates/JsonTemplateManager.java
new file mode 100644
index 000000000..1813d0786
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/tosca/update/templates/JsonTemplateManager.java
@@ -0,0 +1,185 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update.templates;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.onap.policy.clamp.clds.tosca.update.UnknownComponentException;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElement;
+import org.onap.policy.clamp.clds.tosca.update.parser.ToscaConverterToJsonSchema;
+import org.onap.policy.clamp.clds.tosca.update.parser.ToscaElementParser;
+import org.onap.policy.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParser;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.loop.service.Service;
+
+public class JsonTemplateManager {
+ private LinkedHashMap<String, JsonTemplate> jsonSchemaTemplates;
+ private LinkedHashMap<String, ToscaElement> toscaElements;
+
+ /**
+ * Constructor.
+ *
+ * @param toscaYamlContent Policy Tosca Yaml content as string
+ * @param nativeToscaDatatypes The tosca yaml with tosca native datatypes
+ * @param jsonSchemaTemplates template properties as string
+ */
+ public JsonTemplateManager(String toscaYamlContent, String nativeToscaDatatypes, String jsonSchemaTemplates) {
+ if (toscaYamlContent != null && !toscaYamlContent.isEmpty()) {
+ this.toscaElements = ToscaElementParser.searchAllToscaElements(toscaYamlContent, nativeToscaDatatypes);
+ this.jsonSchemaTemplates = initializeTemplates(jsonSchemaTemplates);
+ } else {
+ toscaElements = null;
+ }
+ }
+
+ //GETTERS & SETTERS
+ public LinkedHashMap<String, ToscaElement> getToscaElements() {
+ return toscaElements;
+ }
+
+ public void setToscaElements(LinkedHashMap<String, ToscaElement> toscaElements) {
+ this.toscaElements = toscaElements;
+ }
+
+ public LinkedHashMap<String, JsonTemplate> getJsonSchemaTemplates() {
+ return jsonSchemaTemplates;
+ }
+
+ public void setJsonSchemaTemplates(LinkedHashMap<String, JsonTemplate> jsonSchemaTemplates) {
+ this.jsonSchemaTemplates = jsonSchemaTemplates;
+ }
+
+ /**
+ * Add a template.
+ *
+ * @param name name
+ * @param jsonTemplateFields fields
+ */
+ public void addTemplate(String name, List<JsonTemplateField> jsonTemplateFields) {
+ JsonTemplate jsonTemplate = new JsonTemplate(name, jsonTemplateFields);
+ //If it is true, the operation does not have any interest :
+ // replace OR put two different object with the same body
+ if (!jsonSchemaTemplates.containsKey(jsonTemplate.getName()) || !this.hasTemplate(jsonTemplate)) {
+ this.jsonSchemaTemplates.put(jsonTemplate.getName(), jsonTemplate);
+ }
+ }
+
+ /**
+ * By name, find and remove a given template.
+ *
+ * @param nameTemplate name template
+ */
+ public void removeTemplate(String nameTemplate) {
+ this.jsonSchemaTemplates.remove(nameTemplate);
+ }
+
+ /**
+ * Update Template : adding with true flag, removing with false.
+ *
+ * @param nameTemplate name template
+ * @param jsonTemplateField field name
+ * @param operation operation
+ */
+ public void updateTemplate(String nameTemplate, JsonTemplateField jsonTemplateField, Boolean operation) {
+ // Operation = true && field is not present => add Field
+ if (operation
+ && !this.jsonSchemaTemplates.get(nameTemplate).getJsonTemplateFields().contains(jsonTemplateField)) {
+ this.jsonSchemaTemplates.get(nameTemplate).addField(jsonTemplateField);
+ } else if (!operation
+ && this.jsonSchemaTemplates.get(nameTemplate).getJsonTemplateFields().contains(jsonTemplateField)) {
+ // Operation = false && field is present => remove Field
+ this.jsonSchemaTemplates.get(nameTemplate).removeField(jsonTemplateField);
+ }
+ }
+
+ /**
+ * Check if the JSONTemplates have the same bodies.
+ *
+ * @param jsonTemplate template
+ * @return a boolean
+ */
+ public boolean hasTemplate(JsonTemplate jsonTemplate) {
+ boolean duplicateTemplate = false;
+ Collection<String> templatesName = jsonSchemaTemplates.keySet();
+ if (templatesName.contains(jsonTemplate.getName())) {
+ JsonTemplate existingJsonTemplate = jsonSchemaTemplates.get(jsonTemplate.getName());
+ duplicateTemplate = existingJsonTemplate.checkFields(jsonTemplate);
+ }
+ return duplicateTemplate;
+ }
+
+ /**
+ * For a given policy type, get a corresponding JsonObject from the tosca model.
+ *
+ * @param policyType The policy type in the tosca
+ * @param toscaMetadataParser The MetadataParser class that must be used if metadata section are encountered,
+ * if null they will be skipped
+ * @return an json object defining the equivalent json schema from the tosca for a given policy type
+ */
+ public JsonObject getJsonSchemaForPolicyType(String policyType, ToscaMetadataParser toscaMetadataParser,
+ Service serviceModel)
+ throws UnknownComponentException {
+ ToscaConverterToJsonSchema
+ toscaConverterToJsonSchema = new ToscaConverterToJsonSchema(toscaElements, jsonSchemaTemplates,
+ toscaMetadataParser, serviceModel);
+ if (toscaConverterToJsonSchema.getToscaElement(policyType) == null) {
+ throw new UnknownComponentException(policyType);
+ }
+ return toscaConverterToJsonSchema.getJsonSchemaOfToscaElement(policyType);
+ }
+
+ /**
+ * Create and complete several Templates from file.properties.
+ *
+ * @param jsonTemplates The template properties as String
+ * @return a map
+ */
+ @SuppressWarnings("unused")
+ private LinkedHashMap<String, JsonTemplate> initializeTemplates(String jsonTemplates) {
+
+ LinkedHashMap<String, JsonTemplate> generatedTemplates = new LinkedHashMap<>();
+ JsonObject templates = JsonUtils.GSON.fromJson(jsonTemplates, JsonObject.class);
+
+ for (Map.Entry<String, JsonElement> templateAsJson : templates.entrySet()) {
+ JsonTemplate jsonTemplate = new JsonTemplate(templateAsJson.getKey());
+ JsonObject templateBody = (JsonObject) templateAsJson.getValue();
+ for (Map.Entry<String, JsonElement> field : templateBody.entrySet()) {
+ String fieldName = field.getKey();
+ JsonObject bodyFieldAsJson = (JsonObject) field.getValue();
+ Object fieldValue = bodyFieldAsJson.get("defaultValue").getAsString();
+ Boolean fieldVisible = bodyFieldAsJson.get("visible").getAsBoolean();
+ Boolean fieldStatic = bodyFieldAsJson.get("static").getAsBoolean();
+ JsonTemplateField
+ bodyJsonTemplateField = new JsonTemplateField(fieldName, fieldValue, fieldVisible, fieldStatic);
+ jsonTemplate.getJsonTemplateFields().add(bodyJsonTemplateField);
+ }
+ generatedTemplates.put(jsonTemplate.getName(), jsonTemplate);
+ }
+ return generatedTemplates;
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/util/ClampVersioning.java b/runtime/src/main/java/org/onap/policy/clamp/clds/util/ClampVersioning.java
new file mode 100644
index 000000000..0890615d9
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/util/ClampVersioning.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * Modifications copyright (c) 2018 Nokia
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.util;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.InputStream;
+import java.util.Properties;
+
+/**
+ * This class give a way to know the Clamp version easily, the version in that
+ * file is set by maven at build time.
+ *
+ */
+public class ClampVersioning {
+ private static final String RESOURCE_NAME = "clds-version.properties";
+ private static final String CLDS_VERSION_PROPERTY = "clds.version";
+ private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(ClampVersioning.class);
+
+ private ClampVersioning() {
+ }
+
+ /**
+ * Returns Clds version from properties.
+ *
+ * @return Clds version from properties
+ */
+ public static String getCldsVersionFromProps() {
+ String cldsVersion = "";
+ Properties props = new Properties();
+ try (InputStream resourceStream = ResourceFileUtils.getResourceAsStream(RESOURCE_NAME)) {
+ props.load(resourceStream);
+ cldsVersion = props.getProperty(CLDS_VERSION_PROPERTY);
+ } catch (Exception ex) {
+ LOGGER.error("Exception caught during the " + CLDS_VERSION_PROPERTY + " property reading", ex);
+ }
+ return cldsVersion;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/util/JsonUtils.java b/runtime/src/main/java/org/onap/policy/clamp/clds/util/JsonUtils.java
new file mode 100644
index 000000000..fd5079c47
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/util/JsonUtils.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018-2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.util;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import java.time.Instant;
+import org.onap.policy.clamp.authorization.SecureServicePermission;
+import org.onap.policy.clamp.authorization.SecureServicePermissionDeserializer;
+import org.onap.policy.clamp.dao.model.gson.converter.InstantDeserializer;
+import org.onap.policy.clamp.dao.model.gson.converter.InstantSerializer;
+
+/**
+ * This class is used to access the GSON with restricted type access.
+ */
+public class JsonUtils {
+
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(JsonUtils.class);
+
+ public static final Gson GSON = new GsonBuilder().setPrettyPrinting()
+ .registerTypeAdapter(SecureServicePermission.class, new SecureServicePermissionDeserializer()).create();
+
+ public static final Gson GSON_JPA_MODEL = new GsonBuilder().setPrettyPrinting()
+ .registerTypeAdapter(Instant.class, new InstantSerializer())
+ .registerTypeAdapter(Instant.class, new InstantDeserializer()).setPrettyPrinting()
+ .excludeFieldsWithoutExposeAnnotation().create();
+
+ private JsonUtils() {
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/util/LogMessages.java b/runtime/src/main/java/org/onap/policy/clamp/clds/util/LogMessages.java
new file mode 100644
index 000000000..676206e0f
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/util/LogMessages.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.util;
+
+import com.att.eelf.i18n.EELFResolvableErrorEnum;
+import com.att.eelf.i18n.EELFResourceManager;
+
+public enum LogMessages implements EELFResolvableErrorEnum {
+ LOGSERVICE_HELLO_MESSAGE, LOGSERVICE_EMAIL_ERROR, LOGSERVICE_EMAIL_CLASS, LOGSERVICE_EMAIL_CLASS_NULL,
+ PROCESS_INSTANCE_ID;
+
+ static {
+ EELFResourceManager.loadMessageBundle("logmessages");
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/util/LoggingUtils.java b/runtime/src/main/java/org/onap/policy/clamp/clds/util/LoggingUtils.java
new file mode 100644
index 000000000..4145844a2
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/util/LoggingUtils.java
@@ -0,0 +1,418 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.util;
+
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.URLConnection;
+import java.net.UnknownHostException;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.Date;
+import java.util.TimeZone;
+import java.util.UUID;
+import javax.net.ssl.HttpsURLConnection;
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.constraints.NotNull;
+import org.onap.policy.clamp.authorization.AuthorizationController;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.slf4j.event.Level;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+/**
+ * This class handles the special info that appear in the log, like RequestID,
+ * time context, ...
+ */
+public class LoggingUtils {
+
+ protected static final Logger logger = LoggerFactory.getLogger(LoggingUtils.class);
+
+ private static final DateFormat DATE_FORMAT = createDateFormat();
+
+ private static final String DATE_FORMATTER_ISO = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX";
+
+ /**
+ * String constant for messages <tt>ENTERING</tt>, <tt>EXITING</tt>, etc.
+ */
+ private static final String EMPTY_MESSAGE = "";
+
+ /**
+ * Logger delegate.
+ */
+ private final Logger mlogger;
+
+ /**
+ * Automatic UUID, overrideable per adapter or per invocation.
+ */
+ private static final UUID sInstanceUUID = UUID.randomUUID();
+
+ /**
+ * Constructor.
+ */
+ public LoggingUtils(final Logger loggerP) {
+ this.mlogger = checkNotNull(loggerP);
+ }
+
+ /**
+ * Set request related logging variables in thread local data via MDC.
+ *
+ * @param service Service Name of API (ex. "PUT template")
+ * @param partner Partner name (client or user invoking API)
+ */
+ public static void setRequestContext(String service, String partner) {
+ MDC.put("RequestId", UUID.randomUUID().toString());
+ MDC.put("ServiceName", service);
+ MDC.put("PartnerName", partner);
+ // Defaulting to HTTP/1.1 protocol
+ MDC.put("Protocol", "HTTP/1.1");
+ try {
+ MDC.put("ServerFQDN", InetAddress.getLocalHost().getCanonicalHostName());
+ MDC.put("ServerIPAddress", InetAddress.getLocalHost().getHostAddress());
+ } catch (UnknownHostException e) {
+ logger.error("Failed to initiate setRequestContext", e);
+ }
+ }
+
+ /**
+ * Set time related logging variables in thread local data via MDC.
+ *
+ * @param beginTimeStamp Start time
+ * @param endTimeStamp End time
+ */
+ public static void setTimeContext(@NotNull Date beginTimeStamp, @NotNull Date endTimeStamp) {
+ MDC.put("EntryTimestamp", generateTimestampStr(beginTimeStamp));
+ MDC.put("EndTimestamp", generateTimestampStr(endTimeStamp));
+ MDC.put("ElapsedTime", String.valueOf(endTimeStamp.getTime() - beginTimeStamp.getTime()));
+ }
+
+ /**
+ * Set response related logging variables in thread local data via MDC.
+ *
+ * @param code Response code ("0" indicates success)
+ * @param description Response description
+ * @param className class name of invoking class
+ */
+ public static void setResponseContext(String code, String description, String className) {
+ MDC.put("ResponseCode", code);
+ MDC.put("StatusCode", "0".equals(code) ? "COMPLETE" : "ERROR");
+ MDC.put("ResponseDescription", description != null ? description : "");
+ MDC.put("ClassName", className != null ? className : "");
+ }
+
+ /**
+ * Set target related logging variables in thread local data via MDC.
+ *
+ * @param targetEntity Target entity (an external/sub component, for ex. "sdc")
+ * @param targetServiceName Target service name (name of API invoked on target)
+ */
+ public static void setTargetContext(String targetEntity, String targetServiceName) {
+ MDC.put("TargetEntity", targetEntity != null ? targetEntity : "");
+ MDC.put("TargetServiceName", targetServiceName != null ? targetServiceName : "");
+ }
+
+ /**
+ * Set error related logging variables in thread local data via MDC.
+ *
+ * @param code Error code
+ * @param description Error description
+ */
+ public static void setErrorContext(String code, String description) {
+ MDC.put("ErrorCode", code);
+ MDC.put("ErrorDescription", description != null ? description : "");
+ }
+
+ private static String generateTimestampStr(Date timeStamp) {
+ return DATE_FORMAT.format(timeStamp);
+ }
+
+ /**
+ * Get a previously stored RequestID for the thread local data via MDC. If
+ * one was not previously stored, generate one, store it, and return that
+ * one.
+ *
+ * @return A string with the request ID
+ */
+ public static String getRequestId() {
+ String requestId = MDC.get(OnapLogConstants.Mdcs.REQUEST_ID);
+ if (requestId == null || requestId.isEmpty()) {
+ requestId = UUID.randomUUID().toString();
+ MDC.put(OnapLogConstants.Mdcs.REQUEST_ID, requestId);
+ }
+ return requestId;
+ }
+
+ private static DateFormat createDateFormat() {
+ DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+ return dateFormat;
+ }
+
+ /* *******************************************************************************************
+ * Method for ONAP Application Logging Specification v1.2
+ * *******************************************************************************************/
+
+ /**
+ * Report <tt>ENTERING</tt> marker.
+ *
+ * @param request non-null incoming request (wrapper)
+ * @param serviceName service name
+ */
+ public void entering(HttpServletRequest request, String serviceName) {
+ // MDC.clear();
+ checkNotNull(request);
+ // Extract MDC values from standard HTTP headers.
+ final String requestId =
+ defaultToUuid(request.getHeader(OnapLogConstants.Headers.REQUEST_ID));
+ final String invocationId =
+ defaultToUuid(request.getHeader(OnapLogConstants.Headers.INVOCATION_ID));
+ final String partnerName =
+ defaultToEmpty(request.getHeader(OnapLogConstants.Headers.PARTNER_NAME));
+
+ // Default the partner name to the user name used to login to clamp
+ if (partnerName.equalsIgnoreCase(EMPTY_MESSAGE)) {
+ MDC.put(OnapLogConstants.Mdcs.PARTNER_NAME,
+ AuthorizationController.getPrincipalName(SecurityContextHolder.getContext()));
+ }
+
+ // Set standard MDCs. Override this entire method if you want to set
+ // others, OR set them BEFORE or AFTER the invocation of #entering,
+ // depending on where you need them to appear, OR extend the
+ // ServiceDescriptor to add them.
+ MDC.put(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP, ZonedDateTime.now(ZoneOffset.UTC)
+ .format(DateTimeFormatter.ofPattern(DATE_FORMATTER_ISO)));
+ MDC.put(OnapLogConstants.Mdcs.REQUEST_ID, requestId);
+ MDC.put(OnapLogConstants.Mdcs.INVOCATION_ID, invocationId);
+ MDC.put(OnapLogConstants.Mdcs.CLIENT_IP_ADDRESS, defaultToEmpty(request.getRemoteAddr()));
+ MDC.put(OnapLogConstants.Mdcs.SERVER_FQDN, defaultToEmpty(request.getServerName()));
+ MDC.put(OnapLogConstants.Mdcs.INSTANCE_UUID, defaultToEmpty(sInstanceUUID));
+
+ // Default the service name to the requestURI, in the event that
+ // no value has been provided.
+ if (serviceName == null || serviceName.equalsIgnoreCase(EMPTY_MESSAGE)) {
+ MDC.put(OnapLogConstants.Mdcs.SERVICE_NAME, request.getRequestURI());
+ } else {
+ MDC.put(OnapLogConstants.Mdcs.SERVICE_NAME, serviceName);
+ }
+
+ // Set the Response Status code to in progress
+ MDC.put(OnapLogConstants.Mdcs.RESPONSE_STATUS_CODE,
+ OnapLogConstants.ResponseStatus.INPROGRESS.toString());
+ setElapsedTime();
+
+ this.mlogger.info(OnapLogConstants.Markers.ENTRY, "Entering");
+ }
+
+ /**
+ * Report <tt>EXITING</tt> marker.
+ *
+ * @param code response code
+ * @param description response description
+ * @param severity response severity
+ * @param status response status code
+ */
+ public void exiting(int code, String description, Level severity,
+ OnapLogConstants.ResponseStatus status) {
+ try {
+
+ MDC.put(OnapLogConstants.Mdcs.RESPONSE_CODE, defaultToEmpty(code));
+ MDC.put(OnapLogConstants.Mdcs.RESPONSE_DESCRIPTION, defaultToEmpty(description));
+ MDC.put(OnapLogConstants.Mdcs.RESPONSE_SEVERITY, defaultToEmpty(severity));
+ MDC.put(OnapLogConstants.Mdcs.RESPONSE_STATUS_CODE, defaultToEmpty(status));
+
+ setElapsedTime();
+ this.mlogger.info(OnapLogConstants.Markers.EXIT, "Exiting");
+ } finally {
+ MDC.clear();
+ }
+ }
+
+ private void setElapsedTime() {
+ String entryTimestamp = MDC.get(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP);
+ MDC.put(OnapLogConstants.Mdcs.ELAPSED_TIME, String.valueOf(ChronoUnit.MILLIS
+ .between(ZonedDateTime.parse(entryTimestamp != null ? entryTimestamp : ZonedDateTime.now(ZoneOffset.UTC)
+ .format(DateTimeFormatter.ofPattern(DATE_FORMATTER_ISO)),
+ DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneOffset.UTC)), ZonedDateTime.now(ZoneOffset.UTC))));
+ }
+
+ /**
+ * Get the property value.
+ *
+ * @param name The name of the property
+ * @return The value of the property
+ */
+ public String getProperties(String name) {
+ return MDC.get(name);
+ }
+
+ /**
+ * Report pending invocation with <tt>INVOKE</tt> marker,
+ * setting standard ONAP logging headers automatically.
+ *
+ * @param con The HTTP url connection
+ * @param targetEntity The target entity
+ * @param targetServiceName The target service name
+ * @return The HTTP url connection
+ */
+ public HttpURLConnection invoke(final HttpURLConnection con, String targetEntity,
+ String targetServiceName) {
+ return this.invokeGeneric(con, targetEntity, targetServiceName);
+ }
+
+ /**
+ * Report pending invocation with <tt>INVOKE</tt> marker,
+ * setting standard ONAP logging headers automatically.
+ *
+ * @param targetEntity The target entity
+ * @param targetServiceName The target service name
+ */
+ public void invoke(String targetEntity, String targetServiceName) {
+ final String invocationId = UUID.randomUUID().toString();
+
+ invokeContext(targetEntity, targetServiceName, invocationId);
+
+ // Log INVOKE*, with the invocationID as the message body.
+ // (We didn't really want this kind of behavior in the standard,
+ // but is it worse than new, single-message MDC?)
+ this.mlogger.info(OnapLogConstants.Markers.INVOKE, "INVOKE");
+ this.mlogger.info(OnapLogConstants.Markers.INVOKE_SYNCHRONOUS + "{" + invocationId + "}");
+ }
+
+ /**
+ * Report pending invocation with <tt>INVOKE</tt> marker,
+ * setting standard ONAP logging headers automatically.
+ *
+ * @param con The HTTPS url connection
+ * @param targetEntity The target entity
+ * @param targetServiceName The target service name
+ * @return The HTTPS url connection
+ */
+ public HttpsURLConnection invokeHttps(final HttpsURLConnection con, String targetEntity,
+ String targetServiceName) {
+ return this.invokeGeneric(con, targetEntity, targetServiceName);
+ }
+
+ /**
+ * Report pending invocation with <tt>INVOKE-RETURN</tt> marker.
+ */
+ public void invokeReturn() {
+ MDC.put(OnapLogConstants.Mdcs.RESPONSE_STATUS_CODE,
+ OnapLogConstants.ResponseStatus.COMPLETE.toString());
+ // Add the Invoke-return marker and clear the needed MDC
+ this.mlogger.info(OnapLogConstants.Markers.INVOKE_RETURN, "INVOKE-RETURN");
+ invokeReturnContext();
+ }
+
+ /**
+ * Dependency-free nullcheck.
+ *
+ * @param in to be checked
+ * @param <T> argument (and return) type
+ * @return input arg
+ */
+ private static <T> T checkNotNull(final T in) {
+ if (in == null) {
+ throw new NullPointerException();
+ }
+ return in;
+ }
+
+ /**
+ * Dependency-free string default.
+ *
+ * @param in to be filtered
+ * @return input string or null
+ */
+ private static String defaultToEmpty(final Object in) {
+ if (in == null) {
+ return "";
+ }
+ return in.toString();
+ }
+
+ /**
+ * Dependency-free string default.
+ *
+ * @param in to be filtered
+ * @return input string or null
+ */
+ private static String defaultToUuid(final String in) {
+ if (in == null) {
+ return UUID.randomUUID().toString();
+ }
+ return in;
+ }
+
+ /**
+ * Set target related logging variables in thread local data via MDC.
+ *
+ * @param targetEntity Target entity (an external/sub component, for ex. "sdc")
+ * @param targetServiceName Target service name (name of API invoked on target)
+ * @param invocationId The invocation ID
+ */
+ private void invokeContext(String targetEntity, String targetServiceName, String invocationId) {
+ MDC.put(OnapLogConstants.Mdcs.TARGET_ENTITY, defaultToEmpty(targetEntity));
+ MDC.put(OnapLogConstants.Mdcs.TARGET_SERVICE_NAME, defaultToEmpty(targetServiceName));
+ MDC.put(OnapLogConstants.Mdcs.INVOCATIONID_OUT, invocationId);
+ MDC.put(OnapLogConstants.Mdcs.INVOKE_TIMESTAMP, ZonedDateTime.now(ZoneOffset.UTC)
+ .format(DateTimeFormatter.ofPattern(DATE_FORMATTER_ISO)));
+ }
+
+ /**
+ * Clear target related logging variables in thread local data via MDC.
+ */
+ private void invokeReturnContext() {
+ MDC.remove(OnapLogConstants.Mdcs.TARGET_ENTITY);
+ MDC.remove(OnapLogConstants.Mdcs.TARGET_SERVICE_NAME);
+ MDC.remove(OnapLogConstants.Mdcs.INVOCATIONID_OUT);
+ MDC.remove(OnapLogConstants.Mdcs.INVOKE_TIMESTAMP);
+ MDC.remove(OnapLogConstants.Mdcs.RESPONSE_STATUS_CODE);
+ }
+
+ private <T extends URLConnection> T invokeGeneric(final T con, String targetEntity,
+ String targetServiceName) {
+ final String invocationId = UUID.randomUUID().toString();
+
+ // Set standard HTTP headers on (southbound request) builder.
+ con.setRequestProperty(OnapLogConstants.Headers.REQUEST_ID,
+ defaultToEmpty(MDC.get(OnapLogConstants.Mdcs.REQUEST_ID)));
+ con.setRequestProperty(OnapLogConstants.Headers.INVOCATION_ID, invocationId);
+ con.setRequestProperty(OnapLogConstants.Headers.PARTNER_NAME,
+ defaultToEmpty(MDC.get(OnapLogConstants.Mdcs.PARTNER_NAME)));
+
+ invokeContext(targetEntity, targetServiceName, invocationId);
+
+ // Log INVOKE*, with the invocationID as the message body.
+ // (We didn't really want this kind of behavior in the standard,
+ // but is it worse than new, single-message MDC?)
+ this.mlogger.info(OnapLogConstants.Markers.INVOKE, "");
+ this.mlogger.info(OnapLogConstants.Markers.INVOKE_SYNCHRONOUS + "{" + invocationId + "}");
+ return con;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/util/OnapLogConstants.java b/runtime/src/main/java/org/onap/policy/clamp/clds/util/OnapLogConstants.java
new file mode 100644
index 000000000..78b16f1a0
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/util/OnapLogConstants.java
@@ -0,0 +1,304 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.util;
+
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+
+/**
+ * Constants for standard ONAP headers, MDCs, etc.
+ */
+public final class OnapLogConstants {
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Constructors.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Hide and forbid construction.
+ */
+ private OnapLogConstants() {
+ throw new UnsupportedOperationException();
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Inner classes.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Marker constants.
+ */
+ public static final class Markers {
+
+ /** Marker reporting invocation. */
+ public static final Marker INVOKE = MarkerFactory.getMarker("INVOKE");
+
+ /** Marker reporting invocation return. */
+ public static final Marker INVOKE_RETURN = MarkerFactory.getMarker("INVOKE-RETURN");
+
+ /** Marker reporting synchronous invocation. */
+ public static final Marker INVOKE_SYNCHRONOUS = build("INVOKE", "SYNCHRONOUS");
+
+ /** Marker reporting asynchronous invocation. */
+ public static final Marker INVOKE_ASYNCHRONOUS = build("INVOKE", "ASYNCHRONOUS");
+
+ /** Marker reporting entry into a component. */
+ public static final Marker ENTRY = MarkerFactory.getMarker("ENTRY");
+
+ /** Marker reporting exit from a component. */
+ public static final Marker EXIT = MarkerFactory.getMarker("EXIT");
+
+ /**
+ * Build nested, detached marker.
+ *
+ * @param m1 top token.
+ * @param m2 sub-token.
+ * @return detached Marker.
+ */
+ private static Marker build(final String m1, final String m2) {
+ final Marker marker = MarkerFactory.getDetachedMarker(m1);
+ marker.add(MarkerFactory.getDetachedMarker(m2));
+ return marker;
+ }
+
+ /**
+ * Hide and forbid construction.
+ */
+ private Markers() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * MDC name constants.
+ */
+ public static final class Mdcs {
+
+ // Tracing. ////////////////////////////////////////////////////////////
+
+ /** MDC correlating messages for an invocation. */
+ public static final String INVOCATION_ID = "InvocationID";
+
+ public static final String SERVER_INVOCATION_ID = "ServerInvocationId";
+
+ public static final String CLIENT_INVOCATION_ID = "ClientInvocationId";
+
+ /** MDC correlating messages for a logical transaction. */
+ public static final String REQUEST_ID = "RequestID";
+
+ /** MDC recording calling partner name. */
+ public static final String PARTNER_NAME = "PartnerName";
+
+ /** MDC recording current service. */
+ public static final String SERVICE_NAME = "ServiceName";
+
+ /** MDC recording target service. */
+ public static final String TARGET_SERVICE_NAME = "TargetServiceName";
+
+ /** MDC recording InvocationID Out. */
+ public static final String INVOCATIONID_OUT = "InvocationIDOut";
+
+ /** MDC recording target entity. */
+ public static final String TARGET_ENTITY = "TargetEntity";
+
+ /** MDC recording target element. */
+ public static final String TARGET_ELEMENT = "TargetElement";
+
+ /** MDC recording current service instance id. */
+ public static final String SERVICE_INSTANCE_ID = "ServiceInstanceID";
+
+ /** MDC recording current instance id. */
+ public static final String INSTANCE_UUID = "InstanceID";
+
+ // Network. ////////////////////////////////////////////////////////////
+
+ /** MDC recording caller address. */
+ public static final String CLIENT_IP_ADDRESS = "ClientIPAddress";
+
+ /** MDC recording server IP address. */
+ public static final String SERVER_IP_ADDRESS = "ServerIPAddress";
+
+ /** MDC recording server FQDN. */
+ public static final String SERVER_FQDN = "ServerFQDN";
+
+ /** MDC recording virtual server name. */
+ public static final String VIRTUAL_SERVER_NAME = "VirtualServerName";
+
+ /** MDC recording context name. */
+ public static final String CONTEXT_NAME = "ContextName";
+
+ /**
+ * MDC recording timestamp at the start of the current request,
+ * with the same scope as {@link #REQUEST_ID}.
+ *
+ * <p>
+ * Open issues:
+ * <ul>
+ * <ul>
+ * Easily confused with {@link #INVOKE_TIMESTAMP}.
+ * </ul>
+ * <ul>
+ * No mechanism for propagation between components, e.g. via HTTP headers.
+ * </ul>
+ * <ul>
+ * Whatever mechanism we define, it's going to be costly.
+ * </ul>
+ * </ul>
+ * </p>
+ */
+ public static final String ENTRY_TIMESTAMP = "EntryTimestamp";
+
+ /** MDC recording timestamp at the start of the current invocation. */
+ public static final String INVOKE_TIMESTAMP = "InvokeTimestamp";
+
+ /** MDC recording elapsed time. */
+ public static final String ELAPSED_TIME = "ElapsedTime";
+
+ /** MDC recording log timestamp. */
+ public static final String LOG_TIMESTAMP = "LogTimestamp";
+
+ // Outcomes. ///////////////////////////////////////////////////////////
+
+ /** MDC reporting outcome code. */
+ public static final String RESPONSE_CODE = "ResponseCode";
+
+ /** MDC reporting outcome description. */
+ public static final String RESPONSE_DESCRIPTION = "ResponseDesc";
+
+ /** MDC reporting severity. */
+ public static final String RESPONSE_SEVERITY = "Severity";
+
+ /** MDC reporting response status code. */
+ public static final String RESPONSE_STATUS_CODE = "StatusCode";
+
+ /** MDC recording error code. */
+ public static final String ERROR_CODE = "ErrorCode";
+
+ /** MDC recording error description. */
+ public static final String ERROR_DESC = "ErrorDesc";
+
+ // Unsorted. ///////////////////////////////////////////////////////////
+
+ /**
+ * Hide and forbid construction.
+ */
+ private Mdcs() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ /**
+ * Header name constants.
+ */
+ public static final class Headers {
+
+ /** HTTP <tt>X-ONAP-RequestID</tt> header. */
+ public static final String REQUEST_ID = "X-ONAP-RequestID";
+
+ /** HTTP <tt>X-InvocationID</tt> header. */
+ public static final String INVOCATION_ID = "X-ONAP-InvocationID";
+
+ /** HTTP <tt>X-ONAP-PartnerName</tt> header. */
+ public static final String PARTNER_NAME = "X-ONAP-PartnerName";
+
+ /**
+ * Hide and forbid construction.
+ */
+ private Headers() {
+ throw new UnsupportedOperationException();
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ //
+ // Enums.
+ //
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Response success or not, for setting <tt>StatusCode</tt>.
+ */
+ public enum ResponseStatus {
+
+ /** Success. */
+ COMPLETE,
+
+ /** Not. */
+ ERROR,
+
+ /** In Progress. */
+ INPROGRESS
+ }
+
+ /**
+ * Synchronous or asynchronous execution, for setting invocation marker.
+ */
+ public enum InvocationMode {
+
+ /** Synchronous, blocking. */
+ SYNCHRONOUS("SYNCHRONOUS", Markers.INVOKE_SYNCHRONOUS),
+
+ /** Asynchronous, non-blocking. */
+ ASYNCHRONOUS("ASYNCHRONOUS", Markers.INVOKE_ASYNCHRONOUS);
+
+ /** Enum value. */
+ private String enumValue;
+
+ /** Corresponding marker. */
+ private Marker marker;
+
+ /**
+ * Construct enum.
+ *
+ * @param enumValue enum value.
+ * @param marker corresponding Marker.
+ */
+ InvocationMode(final String enumValue, final Marker marker) {
+ this.enumValue = enumValue;
+ this.marker = marker;
+ }
+
+ /**
+ * Get Marker for enum.
+ *
+ * @return Marker.
+ */
+ public Marker getMarker() {
+ return this.marker;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ return this.enumValue;
+ }
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/clds/util/ResourceFileUtils.java b/runtime/src/main/java/org/onap/policy/clamp/clds/util/ResourceFileUtils.java
new file mode 100644
index 000000000..d6184c656
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/clds/util/ResourceFileUtils.java
@@ -0,0 +1,89 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2017, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Scanner;
+
+/**
+ * Utility methods supporting resources accesses.
+ */
+public final class ResourceFileUtils {
+
+ /**
+ * getResourceAsStram supports the "file:" prefix as they use URL.
+ * So here we want to eliminate classpath: prefix, so that this class can get
+ * files from jar resource or file system.
+ */
+
+ private static final String CLASSPATH_PREFIX = "classpath:";
+
+ /**
+ * Private constructor to avoid creating instances of util class.
+ */
+ private ResourceFileUtils() {
+ }
+
+ /**
+ * Method to access a file from the jar resource folder or file system.
+ * Give the prefix "classpath:" so that it accesses the jar resource folder (default case)
+ * or the prefix "file:" so that it accesses the file system.
+ *
+ * @param fileName The path of the resource (no prefix it will be a classpath access,
+ * "classpath:/myfilename" or "file:/myfilename")
+ * @return The file as inputStream
+ */
+ public static InputStream getResourceAsStream(String fileName) {
+ InputStream is = Thread.currentThread().getContextClassLoader()
+ .getResourceAsStream(fileName.replaceFirst("^" + CLASSPATH_PREFIX, ""));
+ if (is == null) {
+ throw new IllegalArgumentException("Unable to find resource: " + fileName);
+ }
+ return is;
+ }
+
+ /**
+ * Method to access a resource file as a string.
+ * Give the prefix "classpath:" so that it accesses the jar resource folder (default case)
+ * or the prefix "file:" so that it accesses the file system.
+ *
+ * @param fileName The path of the resource (no prefix it will be a classpath access,
+ * "classpath:/myfilename" or "file:/myfilename")
+ * @return The file as String
+ * @throws IOException In case of failure to find the file.
+ */
+ public static String getResourceAsString(String fileName) throws IOException {
+ try (InputStream is = getResourceAsStream(fileName)) {
+ return streamToString(is);
+ }
+ }
+
+ private static String streamToString(InputStream inputStream) {
+ try (Scanner scanner = new Scanner(inputStream)) {
+ Scanner delimitedScanner = scanner.useDelimiter("\\A");
+ return delimitedScanner.hasNext() ? delimitedScanner.next() : "";
+ }
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/configuration/ClampGsonDataFormat.java b/runtime/src/main/java/org/onap/policy/clamp/configuration/ClampGsonDataFormat.java
new file mode 100644
index 000000000..6479cf767
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/configuration/ClampGsonDataFormat.java
@@ -0,0 +1,173 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ */
+
+package org.onap.policy.clamp.configuration;
+
+import com.google.gson.Gson;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.lang.reflect.Type;
+import java.nio.charset.StandardCharsets;
+import org.apache.camel.Exchange;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spi.DataFormatName;
+import org.apache.camel.support.service.ServiceSupport;
+import org.apache.camel.util.IOHelper;
+import org.apache.commons.io.IOUtils;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+
+public class ClampGsonDataFormat extends ServiceSupport implements DataFormat, DataFormatName {
+ private Gson gson;
+ private Class<?> unmarshalType;
+ private Type unmarshalGenericType;
+ private boolean contentTypeHeader = true;
+
+ public ClampGsonDataFormat() {
+ this(Object.class);
+ }
+
+ /**
+ * Use the default Gson {@link Gson} and with a custom unmarshal type.
+ *
+ * @param unmarshalType the custom unmarshal type
+ */
+ public ClampGsonDataFormat(Class<?> unmarshalType) {
+ this(null, unmarshalType);
+ }
+
+ /**
+ * Use a custom Gson mapper and and unmarshal type.
+ *
+ * @param gson the custom mapper
+ * @param unmarshalType the custom unmarshal type
+ */
+ public ClampGsonDataFormat(Gson gson, Class<?> unmarshalType) {
+ this.gson = gson;
+ this.unmarshalType = unmarshalType;
+ }
+
+ /**
+ * Use the default Gson {@link Gson} and with a custom unmarshal generic type.
+ *
+ * @param unmarshalGenericType the custom unmarshal generic type
+ */
+ public ClampGsonDataFormat(Type unmarshalGenericType) {
+ this(null, unmarshalGenericType);
+ }
+
+ /**
+ * Use a custom Gson mapper and and unmarshal token type.
+ *
+ * @param gson the custom mapper
+ * @param unmarshalGenericType the custom unmarshal generic type
+ */
+ public ClampGsonDataFormat(Gson gson, Type unmarshalGenericType) {
+ this.gson = gson;
+ this.unmarshalGenericType = unmarshalGenericType;
+ }
+
+ @Override
+ public String getDataFormatName() {
+ return "clamp-gson";
+ }
+
+ @Override
+ public void marshal(final Exchange exchange, final Object graph, final OutputStream stream) throws Exception {
+ try (final OutputStreamWriter osw = new OutputStreamWriter(stream, StandardCharsets.UTF_8);
+ final BufferedWriter writer = IOHelper.buffered(osw)) {
+ gson.toJson(graph, writer);
+ }
+
+ if (contentTypeHeader) {
+ if (exchange.hasOut()) {
+ exchange.getOut().setHeader(Exchange.CONTENT_TYPE, "application/json");
+ } else {
+ exchange.getIn().setHeader(Exchange.CONTENT_TYPE, "application/json");
+ }
+ }
+ }
+
+ @Override
+ public Object unmarshal(final Exchange exchange, final InputStream stream) throws Exception {
+ try (final InputStreamReader isr = new InputStreamReader(stream, StandardCharsets.UTF_8);
+ final BufferedReader reader = IOHelper.buffered(isr)) {
+ if (unmarshalType.equals(String.class)) {
+ return IOUtils.toString(reader);
+ } else if (unmarshalGenericType == null) {
+ return gson.fromJson(reader, unmarshalType);
+ } else {
+ return gson.fromJson(reader, unmarshalGenericType);
+ }
+ }
+ }
+
+ @Override
+ protected void doStart() throws Exception {
+ if (gson == null) {
+ gson = JsonUtils.GSON_JPA_MODEL;
+ }
+ }
+
+ @Override
+ protected void doStop() throws Exception {
+ // noop
+ }
+
+ // Properties
+ // -------------------------------------------------------------------------
+
+ public Class<?> getUnmarshalType() {
+ return this.unmarshalType;
+ }
+
+ public void setUnmarshalType(Class<?> unmarshalType) {
+ this.unmarshalType = unmarshalType;
+ }
+
+ public Type getUnmarshalGenericType() {
+ return this.unmarshalGenericType;
+ }
+
+ public void setUnmarshalGenericType(Type unmarshalGenericType) {
+ this.unmarshalGenericType = unmarshalGenericType;
+ }
+
+ public boolean isContentTypeHeader() {
+ return contentTypeHeader;
+ }
+
+ /**
+ * If enabled then Gson will set the Content-Type header to
+ * <tt>application/json</tt> when marshalling.
+ */
+ public void setContentTypeHeader(boolean contentTypeHeader) {
+ this.contentTypeHeader = contentTypeHeader;
+ }
+
+ public Gson getGson() {
+ return this.gson;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/dao/model/gson/converter/InstantDeserializer.java b/runtime/src/main/java/org/onap/policy/clamp/dao/model/gson/converter/InstantDeserializer.java
new file mode 100644
index 000000000..db024e07a
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/dao/model/gson/converter/InstantDeserializer.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.dao.model.gson.converter;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import java.lang.reflect.Type;
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.format.FormatStyle;
+import java.util.Locale;
+
+public class InstantDeserializer implements JsonDeserializer<Instant> {
+
+ DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(Locale.US)
+ .withZone(ZoneId.systemDefault());
+
+ @Override
+ public Instant deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) {
+ return Instant.parse(json.getAsString());
+
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/dao/model/gson/converter/InstantSerializer.java b/runtime/src/main/java/org/onap/policy/clamp/dao/model/gson/converter/InstantSerializer.java
new file mode 100644
index 000000000..7208a472c
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/dao/model/gson/converter/InstantSerializer.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.dao.model.gson.converter;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import java.lang.reflect.Type;
+import java.time.Instant;
+import java.time.format.DateTimeFormatter;
+
+public class InstantSerializer implements JsonSerializer<Instant> {
+
+ @Override
+ public JsonElement serialize(Instant src, Type typeOfSrc, JsonSerializationContext context) {
+ return new JsonPrimitive(DateTimeFormatter.ISO_INSTANT.format(src));
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/dao/model/jsontype/JsonStringSqlTypeDescriptor.java b/runtime/src/main/java/org/onap/policy/clamp/dao/model/jsontype/JsonStringSqlTypeDescriptor.java
new file mode 100644
index 000000000..d3aaa32a9
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/dao/model/jsontype/JsonStringSqlTypeDescriptor.java
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.dao.model.jsontype;
+
+import java.sql.CallableStatement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+import org.hibernate.type.descriptor.ValueBinder;
+import org.hibernate.type.descriptor.ValueExtractor;
+import org.hibernate.type.descriptor.WrapperOptions;
+import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
+import org.hibernate.type.descriptor.sql.BasicBinder;
+import org.hibernate.type.descriptor.sql.BasicExtractor;
+import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
+
+public class JsonStringSqlTypeDescriptor implements SqlTypeDescriptor {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 1103168570216921981L;
+
+ public static final JsonStringSqlTypeDescriptor INSTANCE = new JsonStringSqlTypeDescriptor();
+
+ @Override
+ public int getSqlType() {
+ return Types.OTHER;
+ }
+
+ @Override
+ public boolean canBeRemapped() {
+ return true;
+ }
+
+ @Override
+ public <X> ValueBinder<X> getBinder(JavaTypeDescriptor<X> javaTypeDescriptor) {
+ return new BasicBinder<X>(javaTypeDescriptor, this) {
+ @Override
+ protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options)
+ throws SQLException {
+ st.setString(index, javaTypeDescriptor.unwrap(value, String.class, options));
+ }
+
+ @Override
+ protected void doBind(CallableStatement st, X value, String name, WrapperOptions options)
+ throws SQLException {
+ st.setString(name, javaTypeDescriptor.unwrap(value, String.class, options));
+ }
+ };
+ }
+
+ @Override
+ public <X> ValueExtractor<X> getExtractor(JavaTypeDescriptor<X> javaTypeDescriptor) {
+ return new BasicExtractor<X>(javaTypeDescriptor, this) {
+ @Override
+ protected X doExtract(ResultSet rs, String name, WrapperOptions options) throws SQLException {
+ return javaTypeDescriptor.wrap(extractJson(rs, name), options);
+ }
+
+ @Override
+ protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
+ return javaTypeDescriptor.wrap(extractJson(statement, index), options);
+ }
+
+ @Override
+ protected X doExtract(CallableStatement statement, String name, WrapperOptions options)
+ throws SQLException {
+ return javaTypeDescriptor.wrap(extractJson(statement, name), options);
+ }
+ };
+ }
+
+ protected Object extractJson(ResultSet rs, String name) throws SQLException {
+ return rs.getObject(name);
+ }
+
+ protected Object extractJson(CallableStatement statement, int index) throws SQLException {
+ return statement.getObject(index);
+ }
+
+ protected Object extractJson(CallableStatement statement, String name) throws SQLException {
+ return statement.getObject(name);
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/dao/model/jsontype/JsonTypeDescriptor.java b/runtime/src/main/java/org/onap/policy/clamp/dao/model/jsontype/JsonTypeDescriptor.java
new file mode 100644
index 000000000..ed8464b14
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/dao/model/jsontype/JsonTypeDescriptor.java
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.dao.model.jsontype;
+
+import com.google.gson.JsonObject;
+import java.io.Serializable;
+import org.hibernate.type.descriptor.WrapperOptions;
+import org.hibernate.type.descriptor.java.AbstractTypeDescriptor;
+import org.hibernate.type.descriptor.java.ImmutableMutabilityPlan;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+
+public class JsonTypeDescriptor extends AbstractTypeDescriptor<JsonObject> {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = -3439698221196089003L;
+
+ public static final JsonTypeDescriptor INSTANCE = new JsonTypeDescriptor();
+
+ /**
+ * Creates an instance of JsonTypeDescriptor.
+ */
+ public JsonTypeDescriptor() {
+ super(JsonObject.class, new ImmutableMutabilityPlan<JsonObject>() {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 1169396106518110214L;
+
+ @Override
+ public Serializable disassemble(JsonObject value) {
+ return JsonUtils.GSON_JPA_MODEL.toJson(value);
+ }
+
+ @Override
+ public JsonObject assemble(Serializable cached) {
+ return JsonUtils.GSON_JPA_MODEL.fromJson((String) cached, JsonObject.class);
+ }
+
+ });
+ }
+
+ @Override
+ public String toString(JsonObject value) {
+ return JsonUtils.GSON_JPA_MODEL.toJson(value);
+ }
+
+ @Override
+ public JsonObject fromString(String string) {
+ return JsonUtils.GSON_JPA_MODEL.fromJson(string, JsonObject.class);
+ }
+
+ @Override
+ public <X> X unwrap(JsonObject value, Class<X> type, WrapperOptions options) {
+ if (value == null) {
+ return null;
+ }
+
+ if (String.class.isAssignableFrom(type)) {
+ return (X) toString(value);
+ }
+
+ if (JsonObject.class.isAssignableFrom(type)) {
+ return (X) JsonUtils.GSON_JPA_MODEL.toJson(toString(value));
+ }
+ throw unknownUnwrap(type);
+ }
+
+ @Override
+ public <X> JsonObject wrap(X value, WrapperOptions options) {
+ if (value == null) {
+ return null;
+ }
+
+ if (String.class.isInstance(value)) {
+ return JsonUtils.GSON_JPA_MODEL.fromJson((String) value, JsonObject.class);
+ }
+
+ throw unknownWrap(value.getClass());
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/dao/model/jsontype/StringJsonUserType.java b/runtime/src/main/java/org/onap/policy/clamp/dao/model/jsontype/StringJsonUserType.java
new file mode 100644
index 000000000..4a7b65bb4
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/dao/model/jsontype/StringJsonUserType.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.dao.model.jsontype;
+
+import com.google.gson.JsonObject;
+import org.hibernate.type.AbstractSingleColumnStandardBasicType;
+import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
+import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
+
+public class StringJsonUserType extends AbstractSingleColumnStandardBasicType<JsonObject> {
+
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = -7929809808079327767L;
+
+ public StringJsonUserType() {
+ super(JsonStringSqlTypeDescriptor.INSTANCE, JsonTypeDescriptor.INSTANCE);
+ }
+
+ public StringJsonUserType(SqlTypeDescriptor sqlTypeDescriptor, JavaTypeDescriptor<JsonObject> javaTypeDescriptor) {
+ super(sqlTypeDescriptor, javaTypeDescriptor);
+ }
+
+ @Override
+ public String getName() {
+ return "json";
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/flow/log/FlowLogOperation.java b/runtime/src/main/java/org/onap/policy/clamp/flow/log/FlowLogOperation.java
new file mode 100644
index 000000000..d54b23b21
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/flow/log/FlowLogOperation.java
@@ -0,0 +1,101 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.flow.log;
+
+import javax.servlet.http.HttpServletRequest;
+import org.apache.camel.Exchange;
+import org.onap.policy.clamp.clds.util.LoggingUtils;
+import org.onap.policy.clamp.clds.util.OnapLogConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.event.Level;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+
+/**
+ * The Flow log operations.
+ */
+@Component
+public class FlowLogOperation {
+
+ protected static final Logger logger = LoggerFactory.getLogger(FlowLogOperation.class);
+ private LoggingUtils util = new LoggingUtils(logger);
+
+ @Autowired
+ private HttpServletRequest request;
+
+ /**
+ * Generate the entry log.
+ *
+ * @param serviceDesc
+ * The service description the loop name
+ */
+ public void startLog(Exchange exchange, String serviceDesc) {
+ util.entering(request, serviceDesc);
+ exchange.setProperty(OnapLogConstants.Headers.REQUEST_ID,
+ util.getProperties(OnapLogConstants.Mdcs.REQUEST_ID));
+ exchange.setProperty(OnapLogConstants.Headers.INVOCATION_ID,
+ util.getProperties(OnapLogConstants.Mdcs.INVOCATION_ID));
+ exchange.setProperty(OnapLogConstants.Headers.PARTNER_NAME,
+ util.getProperties(OnapLogConstants.Mdcs.PARTNER_NAME));
+ }
+
+ /**
+ * Generate the exiting log.
+ */
+ public void endLog() {
+ util.exiting(HttpStatus.OK.value(), "Successful", Level.INFO,
+ OnapLogConstants.ResponseStatus.COMPLETE);
+ }
+
+ /**
+ * Generate the error exiting log.
+ */
+ public void errorLog() {
+ util.exiting(HttpStatus.INTERNAL_SERVER_ERROR.value(), "Failed", Level.INFO,
+ OnapLogConstants.ResponseStatus.ERROR);
+ }
+
+ /**
+ * Generate the error exiting log.
+ */
+ public void httpErrorLog() {
+
+ }
+
+ /**
+ * Generate the invoke log.
+ */
+ public void invokeLog(String targetEntity, String targetServiceName) {
+ util.invoke(targetEntity, targetServiceName);
+ }
+
+ /**
+ * Generate the invoke return marker.
+ */
+ public void invokeReturnLog() {
+ util.invokeReturn();
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/CsarInstaller.java b/runtime/src/main/java/org/onap/policy/clamp/loop/CsarInstaller.java
new file mode 100644
index 000000000..f46f4227b
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/CsarInstaller.java
@@ -0,0 +1,209 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map.Entry;
+import org.json.simple.parser.ParseException;
+import org.onap.policy.clamp.clds.client.DcaeInventoryServices;
+import org.onap.policy.clamp.clds.exception.sdc.controller.BlueprintParserException;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.policy.clamp.clds.model.dcae.DcaeInventoryResponse;
+import org.onap.policy.clamp.clds.sdc.controller.installer.BlueprintArtifact;
+import org.onap.policy.clamp.clds.sdc.controller.installer.BlueprintMicroService;
+import org.onap.policy.clamp.clds.sdc.controller.installer.BlueprintParser;
+import org.onap.policy.clamp.clds.sdc.controller.installer.ChainGenerator;
+import org.onap.policy.clamp.clds.sdc.controller.installer.CsarHandler;
+import org.onap.policy.clamp.loop.cds.CdsDataInstaller;
+import org.onap.policy.clamp.loop.service.CsarServiceInstaller;
+import org.onap.policy.clamp.loop.service.Service;
+import org.onap.policy.clamp.loop.template.LoopElementModel;
+import org.onap.policy.clamp.loop.template.LoopTemplate;
+import org.onap.policy.clamp.loop.template.LoopTemplatesRepository;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.loop.template.PolicyModelsRepository;
+import org.onap.policy.clamp.policy.PolicyEngineServices;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+
+/**
+ * This class will be instantiated by spring config, and used by Sdc Controller.
+ * There is no state kept by the bean. It's used to deploy the csar/notification
+ * received from SDC in DB.
+ */
+@Component
+@Qualifier("csarInstaller")
+public class CsarInstaller {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(CsarInstaller.class);
+
+ @Autowired
+ private PolicyModelsRepository policyModelsRepository;
+
+ @Autowired
+ private LoopTemplatesRepository loopTemplatesRepository;
+
+ @Autowired
+ private ChainGenerator chainGenerator;
+
+ @Autowired
+ private DcaeInventoryServices dcaeInventoryService;
+
+ @Autowired
+ private CsarServiceInstaller csarServiceInstaller;
+
+ @Autowired
+ private CdsDataInstaller cdsDataInstaller;
+
+ @Autowired
+ private PolicyEngineServices policyEngineServices;
+
+ /**
+ * Verify whether Csar is deployed.
+ *
+ * @param csar The Csar Handler
+ * @return The flag indicating whether Csar is deployed
+ * @throws SdcArtifactInstallerException The SdcArtifactInstallerException
+ */
+ public boolean isCsarAlreadyDeployed(CsarHandler csar) throws SdcArtifactInstallerException {
+ boolean alreadyInstalled = csarServiceInstaller.isServiceAlreadyDeployed(csar);
+
+ for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) {
+ alreadyInstalled = alreadyInstalled
+ && loopTemplatesRepository.existsById(LoopTemplate.generateLoopTemplateName(
+ csar.getSdcNotification().getServiceName(), csar.getSdcNotification().getServiceVersion(),
+ blueprint.getValue().getResourceAttached().getResourceInstanceName(),
+ blueprint.getValue().getBlueprintArtifactName()));
+ }
+ return alreadyInstalled;
+ }
+
+ /**
+ * Install the service and loop templates from the csar.
+ *
+ * @param csar The Csar Handler
+ * @throws SdcArtifactInstallerException The SdcArtifactInstallerException
+ * @throws InterruptedException The InterruptedException
+ * @throws BlueprintParserException In case of issues with the blueprint
+ * parsing
+ */
+ public void installTheCsar(CsarHandler csar)
+ throws SdcArtifactInstallerException, InterruptedException, BlueprintParserException {
+ logger.info("Installing the CSAR " + csar.getFilePath());
+ Service associatedService = csarServiceInstaller.installTheService(csar);
+ cdsDataInstaller.installCdsServiceProperties(csar, associatedService);
+
+ installTheLoopTemplates(csar, associatedService);
+ logger.info("Successfully installed the CSAR " + csar.getFilePath());
+ }
+
+ /**
+ * Install the loop templates from the csar.
+ *
+ * @param csar The Csar Handler
+ * @param service The service object that is related to the loop
+ * @throws SdcArtifactInstallerException The SdcArtifactInstallerException
+ * @throws InterruptedException The InterruptedException
+ * @throws BlueprintParserException In case of issues with the blueprint
+ * parsing
+ */
+ public void installTheLoopTemplates(CsarHandler csar, Service service)
+ throws SdcArtifactInstallerException, InterruptedException, BlueprintParserException {
+ try {
+ logger.info("Installing the Loops");
+ for (Entry<String, BlueprintArtifact> blueprint : csar.getMapOfBlueprints().entrySet()) {
+ logger.info("Processing blueprint " + blueprint.getValue().getBlueprintArtifactName());
+ loopTemplatesRepository.save(createLoopTemplateFromBlueprint(csar, blueprint.getValue(), service));
+ }
+ logger.info("Successfully installed the Loops ");
+ } catch (IOException e) {
+ throw new SdcArtifactInstallerException("Exception caught during the Loop installation in database", e);
+ } catch (ParseException e) {
+ throw new SdcArtifactInstallerException("Exception caught during the Dcae query to get ServiceTypeId", e);
+ }
+ }
+
+ private LoopTemplate createLoopTemplateFromBlueprint(CsarHandler csar, BlueprintArtifact blueprintArtifact,
+ Service service)
+ throws IOException, ParseException, InterruptedException, BlueprintParserException,
+ SdcArtifactInstallerException {
+ LoopTemplate newLoopTemplate = new LoopTemplate();
+ newLoopTemplate.setBlueprint(blueprintArtifact.getDcaeBlueprint());
+ newLoopTemplate.setName(LoopTemplate.generateLoopTemplateName(csar.getSdcNotification().getServiceName(),
+ csar.getSdcNotification().getServiceVersion(),
+ blueprintArtifact.getResourceAttached().getResourceInstanceName(),
+ blueprintArtifact.getBlueprintArtifactName()));
+ List<BlueprintMicroService> microServicesChain = chainGenerator
+ .getChainOfMicroServices(BlueprintParser.getMicroServices(blueprintArtifact.getDcaeBlueprint()));
+ if (microServicesChain.isEmpty()) {
+ microServicesChain = BlueprintParser.fallbackToOneMicroService();
+ }
+ newLoopTemplate.setModelService(service);
+ newLoopTemplate.addLoopElementModels(createMicroServiceModels(blueprintArtifact, microServicesChain));
+ newLoopTemplate.setMaximumInstancesAllowed(0);
+ DcaeInventoryResponse dcaeResponse = queryDcaeToGetServiceTypeId(blueprintArtifact);
+ newLoopTemplate.setDcaeBlueprintId(dcaeResponse.getTypeId());
+ return newLoopTemplate;
+ }
+
+ private HashSet<LoopElementModel> createMicroServiceModels(BlueprintArtifact blueprintArtifact,
+ List<BlueprintMicroService> microServicesChain)
+ throws SdcArtifactInstallerException {
+ HashSet<LoopElementModel> newSet = new HashSet<>();
+ for (BlueprintMicroService microService : microServicesChain) {
+ LoopElementModel loopElementModel =
+ new LoopElementModel(microService.getModelType(), LoopElementModel.MICRO_SERVICE_TYPE,
+ null);
+ newSet.add(loopElementModel);
+ PolicyModel newPolicyModel = policyEngineServices.createPolicyModelFromPolicyEngine(microService);
+ if (newPolicyModel != null) {
+ loopElementModel.addPolicyModel(newPolicyModel);
+ } else {
+ throw new SdcArtifactInstallerException(
+ "Unable to find the policy specified in the blueprint " + blueprintArtifact
+ .getBlueprintArtifactName() + ") on the Policy Engine:"
+ + microService.getModelType() + "/" + microService.getModelVersion());
+ }
+ }
+ return newSet;
+ }
+
+ /**
+ * Get the service blueprint Id in the Dcae inventory using the SDC UUID.
+ *
+ * @return The DcaeInventoryResponse object containing the dcae values
+ */
+ private DcaeInventoryResponse queryDcaeToGetServiceTypeId(BlueprintArtifact blueprintArtifact)
+ throws IOException, ParseException, InterruptedException {
+ return dcaeInventoryService.getDcaeInformation(blueprintArtifact.getBlueprintArtifactName(),
+ blueprintArtifact.getBlueprintInvariantServiceUuid(),
+ blueprintArtifact.getResourceAttached().getResourceInvariantUUID());
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/Loop.java b/runtime/src/main/java/org/onap/policy/clamp/loop/Loop.java
new file mode 100644
index 000000000..99d8d1e69
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/Loop.java
@@ -0,0 +1,389 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import org.hibernate.annotations.SortNatural;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
+import org.onap.policy.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.policy.clamp.dao.model.jsontype.StringJsonUserType;
+import org.onap.policy.clamp.loop.common.AuditEntity;
+import org.onap.policy.clamp.loop.components.external.DcaeComponent;
+import org.onap.policy.clamp.loop.components.external.ExternalComponent;
+import org.onap.policy.clamp.loop.components.external.PolicyComponent;
+import org.onap.policy.clamp.loop.deploy.DcaeDeployParameters;
+import org.onap.policy.clamp.loop.log.LoopLog;
+import org.onap.policy.clamp.loop.service.Service;
+import org.onap.policy.clamp.loop.template.LoopElementModel;
+import org.onap.policy.clamp.loop.template.LoopTemplate;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.policy.clamp.policy.operational.OperationalPolicy;
+
+@Entity
+@Table(name = "loops")
+@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)})
+public class Loop extends AuditEntity implements Serializable {
+
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = -286522707701388642L;
+
+ @Id
+ @Expose
+ @Column(nullable = false, name = "name", unique = true)
+ private String name;
+
+ @Expose
+ @Column(name = "dcae_deployment_id")
+ private String dcaeDeploymentId;
+
+ @Expose
+ @Column(name = "dcae_deployment_status_url")
+ private String dcaeDeploymentStatusUrl;
+
+ @Expose
+ @Type(type = "json")
+ @Column(columnDefinition = "json", name = "global_properties_json")
+ private JsonObject globalPropertiesJson;
+
+ @Expose
+ @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
+ @JoinColumn(name = "service_uuid")
+ private Service modelService;
+
+ @Expose
+ @Column(nullable = false, name = "last_computed_state")
+ @Enumerated(EnumType.STRING)
+ private LoopState lastComputedState;
+
+ @Expose
+ @Transient
+ private final Map<String, ExternalComponent> components = new HashMap<>();
+
+ @Expose
+ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "loop", orphanRemoval = true)
+ private Set<OperationalPolicy> operationalPolicies = new HashSet<>();
+
+ @Expose
+ @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER)
+ @JoinTable(name = "loops_to_microservicepolicies", joinColumns = @JoinColumn(name = "loop_name"),
+ inverseJoinColumns = @JoinColumn(name = "microservicepolicy_name"))
+ private Set<MicroServicePolicy> microServicePolicies = new HashSet<>();
+
+ @Expose
+ @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "loop", orphanRemoval = true)
+ @SortNatural
+ private SortedSet<LoopLog> loopLogs = new TreeSet<>();
+
+ @Expose
+ @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH}, fetch = FetchType.EAGER)
+ @JoinColumn(name = "loop_template_name", nullable = false)
+ private LoopTemplate loopTemplate;
+
+ private void initializeExternalComponents() {
+ this.addComponent(new PolicyComponent());
+ this.addComponent(new DcaeComponent());
+ }
+
+ /**
+ * Public constructor.
+ */
+ public Loop() {
+ initializeExternalComponents();
+ }
+
+ /**
+ * Constructor.
+ */
+ public Loop(String name) {
+ this.name = name;
+ this.lastComputedState = LoopState.DESIGN;
+ this.globalPropertiesJson = new JsonObject();
+ initializeExternalComponents();
+ }
+
+ /**
+ * This constructor creates a loop from a loop template.
+ *
+ * @param name The loop name
+ * @param loopTemplate The loop template from which a new loop instance must be created
+ */
+ public Loop(String name, LoopTemplate loopTemplate, ToscaConverterWithDictionarySupport toscaConverter) {
+ this(name);
+ this.setLoopTemplate(loopTemplate);
+ this.setModelService(loopTemplate.getModelService());
+ loopTemplate.getLoopElementModelsUsed().forEach(element -> {
+ if (LoopElementModel.MICRO_SERVICE_TYPE.equals(element.getLoopElementModel().getLoopElementType())) {
+ this.addMicroServicePolicy((MicroServicePolicy) element.getLoopElementModel()
+ .createPolicyInstance(this, toscaConverter));
+ } else if (LoopElementModel.OPERATIONAL_POLICY_TYPE
+ .equals(element.getLoopElementModel().getLoopElementType())) {
+ this.addOperationalPolicy((OperationalPolicy) element.getLoopElementModel()
+ .createPolicyInstance(this, toscaConverter));
+ }
+ });
+ this.setGlobalPropertiesJson(DcaeDeployParameters.getDcaeDeploymentParametersInJson(this));
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ void setName(String name) {
+ this.name = name;
+ }
+
+ public String getDcaeDeploymentId() {
+ return dcaeDeploymentId;
+ }
+
+ void setDcaeDeploymentId(String dcaeDeploymentId) {
+ this.dcaeDeploymentId = dcaeDeploymentId;
+ }
+
+ public String getDcaeDeploymentStatusUrl() {
+ return dcaeDeploymentStatusUrl;
+ }
+
+ void setDcaeDeploymentStatusUrl(String dcaeDeploymentStatusUrl) {
+ this.dcaeDeploymentStatusUrl = dcaeDeploymentStatusUrl;
+ }
+
+ public LoopState getLastComputedState() {
+ return lastComputedState;
+ }
+
+ void setLastComputedState(LoopState lastComputedState) {
+ this.lastComputedState = lastComputedState;
+ }
+
+ public Set<OperationalPolicy> getOperationalPolicies() {
+ return operationalPolicies;
+ }
+
+ void setOperationalPolicies(Set<OperationalPolicy> operationalPolicies) {
+ this.operationalPolicies = operationalPolicies;
+ }
+
+ public Set<MicroServicePolicy> getMicroServicePolicies() {
+ return microServicePolicies;
+ }
+
+ void setMicroServicePolicies(Set<MicroServicePolicy> microServicePolicies) {
+ this.microServicePolicies = microServicePolicies;
+ }
+
+ public JsonObject getGlobalPropertiesJson() {
+ return globalPropertiesJson;
+ }
+
+ void setGlobalPropertiesJson(JsonObject globalPropertiesJson) {
+ this.globalPropertiesJson = globalPropertiesJson;
+ }
+
+ public Set<LoopLog> getLoopLogs() {
+ return loopLogs;
+ }
+
+ void setLoopLogs(SortedSet<LoopLog> loopLogs) {
+ this.loopLogs = loopLogs;
+ }
+
+ /**
+ * This method adds an operational policy to the loop.
+ *
+ * @param opPolicy the operationalPolicy to add
+ */
+ public void addOperationalPolicy(OperationalPolicy opPolicy) {
+ operationalPolicies.add(opPolicy);
+ opPolicy.setLoop(this);
+ }
+
+ /**
+ * This method removes an operational policy to the loop.
+ *
+ * @param opPolicy the operationalPolicy to add
+ */
+ public void removeOperationalPolicy(OperationalPolicy opPolicy) {
+ operationalPolicies.remove(opPolicy);
+ }
+
+ /**
+ * This method adds an micro service policy to the loop.
+ *
+ * @param microServicePolicy the micro service to add
+ */
+ public void addMicroServicePolicy(MicroServicePolicy microServicePolicy) {
+ microServicePolicies.add(microServicePolicy);
+ microServicePolicy.getUsedByLoops().add(this);
+ }
+
+ public void addLog(LoopLog log) {
+ log.setLoop(this);
+ this.loopLogs.add(log);
+ }
+
+ public Service getModelService() {
+ return modelService;
+ }
+
+ void setModelService(Service modelService) {
+ this.modelService = modelService;
+ }
+
+ public Map<String, ExternalComponent> getComponents() {
+ refreshDcaeComponents();
+ return components;
+ }
+
+ public ExternalComponent getComponent(String componentName) {
+ refreshDcaeComponents();
+ return this.components.get(componentName);
+ }
+
+ public void addComponent(ExternalComponent component) {
+ this.components.put(component.getComponentName(), component);
+ }
+
+ public LoopTemplate getLoopTemplate() {
+ return loopTemplate;
+ }
+
+ public void setLoopTemplate(LoopTemplate loopTemplate) {
+ this.loopTemplate = loopTemplate;
+ }
+
+ private void refreshDcaeComponents() {
+ if (!this.loopTemplate.getUniqueBlueprint()) {
+ this.components.remove("DCAE");
+ for (MicroServicePolicy policy : this.microServicePolicies) {
+ if (!this.components.containsKey("DCAE_" + policy.getName())) {
+ this.addComponent(new DcaeComponent(policy.getName()));
+ }
+ }
+ }
+ }
+
+ /**
+ * Return the operationalPolicy object with the opPolicyName.
+ *
+ * @param opPolicyName The operationalPolicy name
+ * @return The OperationalPolicy object found in loop object
+ */
+ public OperationalPolicy getOperationalPolicy(String opPolicyName) {
+ for (OperationalPolicy operationalPolicy : this.getOperationalPolicies()) {
+ if (operationalPolicy.getName().equals(opPolicyName)) {
+ return operationalPolicy;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Return the microServicePolicy object with the msPolicyName.
+ *
+ * @param msPolicyName The microServicePolicy name
+ * @return The MicroServicePolicy object found in loop object
+ */
+ public MicroServicePolicy getMicroServicePolicy(String msPolicyName) {
+ for (MicroServicePolicy microServicePolicy : this.getMicroServicePolicies()) {
+ if (microServicePolicy.getName().equals(msPolicyName)) {
+ return microServicePolicy;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Generate the loop name.
+ *
+ * @param serviceName The service name
+ * @param serviceVersion The service version
+ * @param resourceName The resource name
+ * @param blueprintFileName The blueprint file name
+ * @return The generated loop name
+ */
+ public static String generateLoopName(String serviceName, String serviceVersion, String resourceName,
+ String blueprintFileName) {
+ StringBuilder buffer = new StringBuilder("LOOP_").append(serviceName).append("_v").append(serviceVersion)
+ .append("_").append(resourceName).append("_").append(blueprintFileName.replaceAll(".yaml", ""));
+ return buffer.toString().replace('.', '_').replaceAll(" ", "");
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Loop other = (Loop) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/LoopController.java b/runtime/src/main/java/org/onap/policy/clamp/loop/LoopController.java
new file mode 100644
index 000000000..98459c909
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/LoopController.java
@@ -0,0 +1,204 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.reflect.TypeToken;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.util.List;
+import org.onap.policy.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicyService;
+import org.onap.policy.clamp.policy.operational.OperationalPolicy;
+import org.onap.policy.clamp.policy.operational.OperationalPolicyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+
+@Controller
+public class LoopController {
+
+ private final LoopService loopService;
+
+ private final ToscaConverterWithDictionarySupport toscaConverter;
+
+ private final OperationalPolicyService operationalPolicyService;
+
+ private final MicroServicePolicyService microServicePolicyService;
+
+ private static final Type OPERATIONAL_POLICY_TYPE = new TypeToken<List<OperationalPolicy>>() {
+ }.getType();
+
+ private static final Type MICROSERVICE_POLICY_TYPE = new TypeToken<List<MicroServicePolicy>>() {
+ }.getType();
+
+
+ /**
+ * Constructor.
+ *
+ * @param loopService loopService
+ * @param operationalPolicyService operationalPolicyService
+ * @param microServicePolicyService microServicePolicyService
+ * @param toscaConverter toscaConverter
+ */
+ @Autowired
+ public LoopController(LoopService loopService, OperationalPolicyService operationalPolicyService,
+ MicroServicePolicyService microServicePolicyService,
+ ToscaConverterWithDictionarySupport toscaConverter) {
+ this.loopService = loopService;
+ this.toscaConverter = toscaConverter;
+ this.operationalPolicyService = operationalPolicyService;
+ this.microServicePolicyService = microServicePolicyService;
+ }
+
+ public Loop createLoop(String loopName, String templateName) {
+ return loopService.createLoopFromTemplate(loopName, templateName);
+ }
+
+ public List<String> getLoopNames() {
+ return loopService.getClosedLoopNames();
+ }
+
+ public Loop getLoop(String loopName) {
+ return loopService.getLoop(loopName);
+ }
+
+ /**
+ * Update the Operational Policy properties.
+ *
+ * @param loopName The loop name
+ * @param operationalPoliciesJson The new Operational Policy properties
+ * @return The updated loop
+ */
+ public Loop updateOperationalPolicies(String loopName, JsonArray operationalPoliciesJson) {
+ List<OperationalPolicy> operationalPolicies = JsonUtils.GSON_JPA_MODEL.fromJson(operationalPoliciesJson,
+ OPERATIONAL_POLICY_TYPE);
+ return loopService.updateAndSaveOperationalPolicies(loopName, operationalPolicies);
+ }
+
+ /**
+ * Update the whole array of MicroService policies properties.
+ *
+ * @param loopName The loop name
+ * @param microServicePoliciesJson The array of all MicroService policies
+ * properties
+ * @return The updated loop
+ */
+ public Loop updateMicroservicePolicies(String loopName, JsonArray microServicePoliciesJson) {
+ List<MicroServicePolicy> microservicePolicies = JsonUtils.GSON_JPA_MODEL.fromJson(microServicePoliciesJson,
+ MICROSERVICE_POLICY_TYPE);
+ return loopService.updateAndSaveMicroservicePolicies(loopName, microservicePolicies);
+ }
+
+ /**
+ * Update the global properties.
+ *
+ * @param loopName The loop name
+ * @param globalProperties The updated global properties
+ * @return The updated loop
+ */
+ public Loop updateGlobalPropertiesJson(String loopName, JsonObject globalProperties) {
+ return loopService.updateAndSaveGlobalPropertiesJson(loopName, globalProperties);
+ }
+
+ /**
+ * This method add an operational policy to a loop instance.
+ *
+ * @param loopName The loop name
+ * @param policyType The policy model type
+ * @param policyVersion The policy model version
+ * @return The loop modified
+ */
+ public Loop addOperationalPolicy(String loopName, String policyType, String policyVersion) throws IOException {
+ return loopService.addOperationalPolicy(loopName, policyType, policyVersion);
+ }
+
+ /**
+ * This method removes an operational policy from a loop instance.
+ *
+ * @param loopName The loop name
+ * @param policyType The policy model type
+ * @param policyVersion The policy model version
+ * @return The loop modified
+ */
+ public Loop removeOperationalPolicy(String loopName, String policyType, String policyVersion) {
+ return loopService.removeOperationalPolicy(loopName, policyType, policyVersion);
+ }
+
+ /**
+ * This method deletes the loop.
+ *
+ * @param loopName The loop Name
+ */
+ public void deleteLoop(String loopName) {
+ loopService.deleteLoop(loopName);
+ }
+
+ /**
+ * Update one MicroService policy properties.
+ *
+ * @param loopName The loop name
+ * @param newMicroservicePolicy The new MicroService policy properties
+ * @return The updated MicroService policy
+ */
+ public MicroServicePolicy updateMicroservicePolicy(String loopName, MicroServicePolicy newMicroservicePolicy) {
+ return loopService.updateMicroservicePolicy(loopName, newMicroservicePolicy);
+ }
+
+ /**
+ * Refresh the Operational Policy Json representation of the loop.
+ *
+ * @param loop The loop
+ * @param operationalPolicyName The operational policy name that needs a refresh
+ * @return The loop object
+ */
+ public Loop refreshOperationalPolicyJsonRepresentation(Loop loop, String operationalPolicyName) {
+ for (OperationalPolicy operationalPolicy : loop.getOperationalPolicies()) {
+ if (operationalPolicy.getName().equals(operationalPolicyName)) {
+ this.operationalPolicyService
+ .refreshOperationalPolicyJsonRepresentation(operationalPolicy, toscaConverter);
+ }
+ }
+ return loop;
+ }
+
+ /**
+ * Refresh the Config Policy Json representation of the loop.
+ *
+ * @param loop The loop
+ * @param microServicePolicyName The microservice policy name that needs a refresh
+ * @return The loop object
+ */
+ public Loop refreshMicroServicePolicyJsonRepresentation(Loop loop, String microServicePolicyName) {
+ for (MicroServicePolicy microServicePolicy : loop.getMicroServicePolicies()) {
+ if (microServicePolicy.getName().equals(microServicePolicyName)) {
+ this.microServicePolicyService
+ .refreshMicroServicePolicyJsonRepresentation(microServicePolicy, toscaConverter, loop);
+ }
+ }
+ return loop;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/LoopService.java b/runtime/src/main/java/org/onap/policy/clamp/loop/LoopService.java
new file mode 100644
index 000000000..975011669
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/LoopService.java
@@ -0,0 +1,190 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+import javax.persistence.EntityNotFoundException;
+import org.onap.policy.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.policy.clamp.loop.template.LoopTemplatesService;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.loop.template.PolicyModelsService;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicyService;
+import org.onap.policy.clamp.policy.operational.OperationalPolicy;
+import org.onap.policy.clamp.policy.operational.OperationalPolicyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class LoopService {
+
+ @Autowired
+ private LoopsRepository loopsRepository;
+
+ @Autowired
+ private MicroServicePolicyService microservicePolicyService;
+
+ @Autowired
+ private OperationalPolicyService operationalPolicyService;
+
+ @Autowired
+ private PolicyModelsService policyModelsService;
+
+ @Autowired
+ private LoopTemplatesService loopTemplateService;
+
+ @Autowired
+ private ToscaConverterWithDictionarySupport toscaConverter;
+
+ Loop saveOrUpdateLoop(Loop loop) {
+ return loopsRepository.save(loop);
+ }
+
+ List<String> getClosedLoopNames() {
+ return loopsRepository.getAllLoopNames();
+ }
+
+ public Loop getLoop(String loopName) {
+ return loopsRepository.findById(loopName).orElse(null);
+ }
+
+ public void deleteLoop(String loopName) {
+ loopsRepository.deleteById(loopName);
+ }
+
+ /**
+ * Creates a Loop Instance from Loop Template Name.
+ *
+ * @param loopName Name of the Loop to be created
+ * @param templateName Loop Template to used for Loop
+ * @return Loop Instance
+ */
+ public Loop createLoopFromTemplate(String loopName, String templateName) {
+ return loopsRepository
+ .save(new Loop(loopName, loopTemplateService.getLoopTemplate(templateName), toscaConverter));
+ }
+
+ /**
+ * This method is used to refresh the DCAE deployment status fields.
+ *
+ * @param loop The loop instance to be modified
+ * @param deploymentId The deployment ID as returned by DCAE
+ * @param deploymentUrl The Deployment URL as returned by DCAE
+ */
+ public void updateDcaeDeploymentFields(Loop loop, String deploymentId, String deploymentUrl) {
+ loop.setDcaeDeploymentId(deploymentId);
+ loop.setDcaeDeploymentStatusUrl(deploymentUrl);
+ loopsRepository.saveAndFlush(loop);
+ }
+
+ public void updateLoopState(Loop loop, String newState) {
+ loop.setLastComputedState(LoopState.valueOf(newState));
+ loopsRepository.save(loop);
+ }
+
+ /**
+ * This method add an operational policy to a loop instance.
+ * This creates an operational policy from the policy model info and not the loop element model
+ *
+ * @param loopName The loop name
+ * @param policyType The policy model type
+ * @param policyVersion The policy model version
+ * @return The loop modified
+ */
+ Loop addOperationalPolicy(String loopName, String policyType, String policyVersion) throws IOException {
+ Loop loop = getLoop(loopName);
+ PolicyModel policyModel = policyModelsService.getPolicyModel(policyType, policyVersion);
+ Set<OperationalPolicy> opPolicySet = loop.getOperationalPolicies();
+ for (OperationalPolicy opPolicy : opPolicySet) {
+ if (opPolicy.getPolicyModel().equals(policyModel)) {
+ throw new IllegalArgumentException(
+ "This type of Operational Policy is already added to the loop. Please choose another one.");
+ }
+ }
+ if (policyModel == null) {
+ return null;
+ }
+ loop.addOperationalPolicy(
+ new OperationalPolicy(loop, loop.getModelService(), policyModel, toscaConverter));
+ return loopsRepository.saveAndFlush(loop);
+ }
+
+ /**
+ * This method remove an operational policy to a loop instance.
+ *
+ * @param loopName The loop name
+ * @param policyType The policy model type
+ * @param policyVersion The policy model version
+ * @return The loop modified
+ */
+ Loop removeOperationalPolicy(String loopName, String policyType, String policyVersion) {
+ Loop loop = getLoop(loopName);
+ PolicyModel policyModel = policyModelsService.getPolicyModel(policyType, policyVersion);
+ if (policyModel == null) {
+ return null;
+ }
+ for (OperationalPolicy opPolicy : loop.getOperationalPolicies()) {
+ if (opPolicy.getPolicyModel().getPolicyModelType().equals(policyType)
+ && opPolicy.getPolicyModel().getVersion().equals(policyVersion)) {
+ loop.removeOperationalPolicy(opPolicy);
+ break;
+ }
+ }
+ return loopsRepository.saveAndFlush(loop);
+ }
+
+ Loop updateAndSaveOperationalPolicies(String loopName, List<OperationalPolicy> newOperationalPolicies) {
+ Loop loop = findClosedLoopByName(loopName);
+ Set<OperationalPolicy> newPolicies = operationalPolicyService.updatePolicies(loop, newOperationalPolicies);
+ loop.setOperationalPolicies(newPolicies);
+ return loopsRepository.save(loop);
+ }
+
+ Loop updateAndSaveMicroservicePolicies(String loopName, List<MicroServicePolicy> newMicroservicePolicies) {
+ Loop loop = findClosedLoopByName(loopName);
+ Set<MicroServicePolicy> newPolicies = microservicePolicyService.updatePolicies(loop, newMicroservicePolicies);
+ loop.setMicroServicePolicies(newPolicies);
+ return loopsRepository.save(loop);
+ }
+
+ Loop updateAndSaveGlobalPropertiesJson(String loopName, JsonObject newGlobalPropertiesJson) {
+ Loop loop = findClosedLoopByName(loopName);
+ loop.setGlobalPropertiesJson(newGlobalPropertiesJson);
+ return loopsRepository.save(loop);
+ }
+
+ MicroServicePolicy updateMicroservicePolicy(String loopName, MicroServicePolicy newMicroservicePolicy) {
+ Loop loop = findClosedLoopByName(loopName);
+ return microservicePolicyService.getAndUpdateMicroServicePolicy(loop, newMicroservicePolicy);
+ }
+
+ private Loop findClosedLoopByName(String loopName) {
+ return loopsRepository.findById(loopName)
+ .orElseThrow(() -> new EntityNotFoundException("Couldn't find closed loop named: " + loopName));
+ }
+}
+
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/LoopState.java b/runtime/src/main/java/org/onap/policy/clamp/loop/LoopState.java
new file mode 100644
index 000000000..48d4487f0
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/LoopState.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+public enum LoopState {
+ DESIGN, SUBMITTED, DEPLOYED, RUNNING, STOPPED, IN_ERROR, WAITING;
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/LoopsRepository.java b/runtime/src/main/java/org/onap/policy/clamp/loop/LoopsRepository.java
new file mode 100644
index 000000000..7b92ed584
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/LoopsRepository.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import java.util.List;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface LoopsRepository extends JpaRepository<Loop, String> {
+
+ @Query("SELECT loop.name FROM Loop as loop")
+ List<String> getAllLoopNames();
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/cds/CdsDataInstaller.java b/runtime/src/main/java/org/onap/policy/clamp/loop/cds/CdsDataInstaller.java
new file mode 100644
index 000000000..68adb3887
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/cds/CdsDataInstaller.java
@@ -0,0 +1,172 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.cds;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import org.onap.policy.clamp.clds.client.CdsServices;
+import org.onap.policy.clamp.clds.model.cds.CdsBpWorkFlowListResponse;
+import org.onap.policy.clamp.clds.sdc.controller.installer.CsarHandler;
+import org.onap.policy.clamp.loop.service.Service;
+import org.onap.policy.clamp.loop.service.ServicesRepository;
+import org.onap.sdc.tosca.parser.enums.SdcTypes;
+import org.onap.sdc.toscaparser.api.NodeTemplate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * This class installs the cds data in the service model properties.
+ * This can be refreshed later on by clicking on the button refresh, when recomputing the json schema.
+ */
+@Component
+public class CdsDataInstaller {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(CdsDataInstaller.class);
+
+ @Autowired
+ CdsServices cdsServices;
+
+ @Autowired
+ ServicesRepository serviceRepository;
+
+ public static final String CONTROLLER_PROPERTIES = "controllerProperties";
+ public static final String SDNC_MODEL_NAME = "sdnc_model_name";
+ public static final String SDNC_MODEL_VERSION = "sdnc_model_version";
+
+ /**
+ * This method installs the service model properties for CDS in the service object given in input.
+ *
+ * @param csar The csar from sdc
+ * @param service the service object already provisioned with csar data
+ */
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public Service installCdsServiceProperties(CsarHandler csar, Service service) {
+ // Iterate on all types defined in the tosca lib
+ for (SdcTypes type : SdcTypes.values()) {
+ JsonObject resourcesPropByType = service.getResourceByType(type.getValue());
+ // For each type, get the metadata of each nodetemplate
+ for (NodeTemplate nodeTemplate : csar.getSdcCsarHelper().getServiceNodeTemplateBySdcType(type)) {
+ // get cds artifact information and save in resources Prop
+ if (SdcTypes.PNF == type || SdcTypes.VF == type) {
+ JsonObject controllerProperties = createCdsArtifactProperties(
+ String.valueOf(nodeTemplate.getPropertyValue(SDNC_MODEL_NAME)),
+ String.valueOf(nodeTemplate.getPropertyValue(SDNC_MODEL_VERSION)));
+ if (controllerProperties != null) {
+ resourcesPropByType.getAsJsonObject(nodeTemplate.getName())
+ .add(CONTROLLER_PROPERTIES, controllerProperties);
+ logger.info("Successfully installed the CDS data in Service");
+ } else {
+ logger.warn("Skipping CDS data installation in Service, as sdnc_model_name and "
+ + "sdnc_model_version are not provided in the CSAR");
+ }
+ }
+ }
+ }
+ serviceRepository.save(service);
+
+ return service;
+ }
+
+ /**
+ * This method updates the service model properties for CDS in the service object given in input.
+ *
+ * @param service the service object already provisioned with csar data
+ */
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public Service updateCdsServiceProperties(Service service) {
+ // Iterate on all types defined in the tosca lib
+ for (SdcTypes type : SdcTypes.values()) {
+ JsonObject resourcesPropByType = service.getResourceByType(type.getValue());
+ for (String resourceName : resourcesPropByType.keySet()) {
+ // get cds artifact information and save in resources Prop
+ if ((SdcTypes.PNF == type || SdcTypes.VF == type) && resourcesPropByType.getAsJsonObject(resourceName)
+ .getAsJsonObject(CONTROLLER_PROPERTIES) != null) {
+ JsonObject controllerProperties =
+ createCdsArtifactProperties(resourcesPropByType.getAsJsonObject(resourceName)
+ .getAsJsonObject(CONTROLLER_PROPERTIES).get(SDNC_MODEL_NAME)
+ .getAsString(),
+ resourcesPropByType.getAsJsonObject(resourceName)
+ .getAsJsonObject(CONTROLLER_PROPERTIES).get(SDNC_MODEL_VERSION)
+ .getAsString());
+ if (controllerProperties != null) {
+ resourcesPropByType.getAsJsonObject(resourceName)
+ .add(CONTROLLER_PROPERTIES, controllerProperties);
+ }
+ }
+ }
+ }
+ serviceRepository.save(service);
+ logger.info("Successfully updated the CDS data in Service");
+ return service;
+ }
+
+ /**
+ * Retrieve CDS artifacts information from node template and save in resource object.
+ *
+ * @param sdncModelName sdnc model name
+ * @param sdncModelVersion sdnc model version
+ * @return Returns CDS artifacts information
+ */
+ private JsonObject createCdsArtifactProperties(String sdncModelName, String sdncModelVersion) {
+ if (sdncModelName != null && !"null".equals(sdncModelName)
+ && sdncModelVersion != null && !"null".equals(sdncModelVersion)) {
+ JsonObject controllerProperties = new JsonObject();
+ controllerProperties.addProperty(SDNC_MODEL_NAME, sdncModelName);
+ controllerProperties.addProperty(SDNC_MODEL_VERSION, sdncModelVersion);
+
+ CdsBpWorkFlowListResponse response =
+ queryCdsToGetWorkFlowList(sdncModelName, sdncModelVersion);
+ if (response == null) {
+ return controllerProperties;
+ }
+
+ JsonObject workFlowProps = new JsonObject();
+ for (String workFlow : response.getWorkflows()) {
+ logger.info("Found CDS workflow " + workFlow + " for model name " + sdncModelName + " and version "
+ + sdncModelVersion);
+ JsonObject inputs = queryCdsToGetWorkFlowInputProperties(response.getBlueprintName(),
+ response.getVersion(), workFlow);
+ workFlowProps.add(workFlow, inputs);
+ }
+
+ controllerProperties.add("workflows", workFlowProps);
+ return controllerProperties;
+ }
+ return null;
+ }
+
+
+ private CdsBpWorkFlowListResponse queryCdsToGetWorkFlowList(String artifactName, String artifactVersion) {
+ return cdsServices.getBlueprintWorkflowList(artifactName, artifactVersion);
+ }
+
+ private JsonObject queryCdsToGetWorkFlowInputProperties(String artifactName, String artifactVersion,
+ String workFlow) {
+ return cdsServices.getWorkflowInputProperties(artifactName, artifactVersion, workFlow);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/common/AuditEntity.java b/runtime/src/main/java/org/onap/policy/clamp/loop/common/AuditEntity.java
new file mode 100644
index 000000000..92c795e90
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/common/AuditEntity.java
@@ -0,0 +1,146 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.common;
+
+import com.google.gson.annotations.Expose;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import javax.persistence.Column;
+import javax.persistence.EntityListeners;
+import javax.persistence.MappedSuperclass;
+import org.springframework.data.annotation.CreatedBy;
+import org.springframework.data.annotation.CreatedDate;
+import org.springframework.data.annotation.LastModifiedBy;
+import org.springframework.data.annotation.LastModifiedDate;
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
+
+/**
+ * This class is the parent of the hibernate entities requiring to be audited.
+ */
+@MappedSuperclass
+@EntityListeners(AuditingEntityListener.class)
+public class AuditEntity {
+
+ @Expose
+ @CreatedDate
+ @Column(name = "created_timestamp", nullable = false, updatable = false)
+ private Instant createdDate;
+
+ @Expose
+ @LastModifiedDate
+ @Column(name = "updated_timestamp", nullable = false)
+ private Instant updatedDate;
+
+ @Expose
+ @LastModifiedBy
+ @Column(name = "updated_by")
+ private String updatedBy;
+
+ @Expose
+ @CreatedBy
+ @Column(name = "created_by")
+ private String createdBy;
+
+ public Instant getCreatedDate() {
+ return createdDate;
+ }
+
+ /**
+ * createdDate setter.
+ *
+ * @param createdDate The created Date object
+ */
+ public void setCreatedDate(Instant createdDate) {
+ if (createdDate != null) {
+ this.createdDate = createdDate.truncatedTo(ChronoUnit.SECONDS);
+ } else {
+ this.createdDate = null;
+ }
+ }
+
+ /**
+ * updatedDate getter.
+ *
+ * @return the updatedDate
+ */
+ public Instant getUpdatedDate() {
+ return updatedDate;
+ }
+
+ /**
+ * updatedDate setter.
+ *
+ * @param updatedDate updatedDate to set
+ */
+ public void setUpdatedDate(Instant updatedDate) {
+ if (updatedDate != null) {
+ this.updatedDate = updatedDate.truncatedTo(ChronoUnit.SECONDS);
+ } else {
+ this.updatedDate = null;
+ }
+ }
+
+ /**
+ * updatedBy getter.
+ *
+ * @return the updatedBy
+ */
+ public String getUpdatedBy() {
+ return updatedBy;
+ }
+
+ /**
+ * updatedBy setter.
+ *
+ * @param updatedBy the updatedBy
+ */
+ public void setUpdatedBy(String updatedBy) {
+ this.updatedBy = updatedBy;
+ }
+
+ /**
+ * createdBy getter.
+ *
+ * @return the createdBy
+ */
+ public String getCreatedBy() {
+ return createdBy;
+ }
+
+ /**
+ * createdBy setter.
+ *
+ * @param createdBy the createdBy to set
+ */
+ public void setCreatedBy(String createdBy) {
+ this.createdBy = createdBy;
+ }
+
+ /**
+ * Empty constructor.
+ */
+ public AuditEntity() {
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/components/external/DcaeComponent.java b/runtime/src/main/java/org/onap/policy/clamp/loop/components/external/DcaeComponent.java
new file mode 100644
index 000000000..6a935d011
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/components/external/DcaeComponent.java
@@ -0,0 +1,266 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.components.external;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.UUID;
+import javax.persistence.Transient;
+import org.apache.camel.Exchange;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.json.simple.parser.ParseException;
+import org.onap.policy.clamp.clds.model.dcae.DcaeInventoryResponse;
+import org.onap.policy.clamp.clds.model.dcae.DcaeOperationStatusResponse;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.loop.Loop;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+
+public class DcaeComponent extends ExternalComponent {
+
+ @Transient
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(DcaeComponent.class);
+
+ private static final String DCAE_DEPLOYMENT_PREFIX = "CLAMP_";
+ private static final String DEPLOYMENT_PARAMETER = "dcaeDeployParameters";
+ private static final String DCAE_SERVICETYPE_ID = "serviceTypeId";
+ private static final String DCAE_INPUTS = "inputs";
+ public static final String UNIQUE_BLUEPRINT_PARAMETERS = "uniqueBlueprintParameters";
+
+ private String name;
+
+ public static final ExternalComponentState BLUEPRINT_DEPLOYED = new ExternalComponentState("BLUEPRINT_DEPLOYED",
+ "The DCAE blueprint has been found in the DCAE inventory but not yet instancianted for this loop");
+ public static final ExternalComponentState PROCESSING_MICROSERVICE_INSTALLATION = new ExternalComponentState(
+ "PROCESSING_MICROSERVICE_INSTALLATION", "Clamp has requested DCAE to install the microservices "
+ + "defined in the DCAE blueprint and it's currently processing the request");
+ public static final ExternalComponentState MICROSERVICE_INSTALLATION_FAILED = new ExternalComponentState(
+ "MICROSERVICE_INSTALLATION_FAILED",
+ "Clamp has requested DCAE to install the microservices defined in the DCAE blueprint and it failed");
+ public static final ExternalComponentState MICROSERVICE_INSTALLED_SUCCESSFULLY = new ExternalComponentState(
+ "MICROSERVICE_INSTALLED_SUCCESSFULLY",
+ "Clamp has requested DCAE to install the DCAE blueprint and it has been installed successfully");
+ public static final ExternalComponentState PROCESSING_MICROSERVICE_UNINSTALLATION = new ExternalComponentState(
+ "PROCESSING_MICROSERVICE_UNINSTALLATION", "Clamp has requested DCAE to uninstall the microservices "
+ + "defined in the DCAE blueprint and it's currently processing the request");
+ public static final ExternalComponentState MICROSERVICE_UNINSTALLATION_FAILED = new ExternalComponentState(
+ "MICROSERVICE_UNINSTALLATION_FAILED",
+ "Clamp has requested DCAE to uninstall the microservices defined in the DCAE blueprint and it failed");
+ public static final ExternalComponentState MICROSERVICE_UNINSTALLED_SUCCESSFULLY = new ExternalComponentState(
+ "MICROSERVICE_UNINSTALLED_SUCCESSFULLY",
+ "Clamp has requested DCAE to uninstall the DCAE blueprint and it has been uninstalled successfully");
+ public static final ExternalComponentState IN_ERROR = new ExternalComponentState("IN_ERROR",
+ "There was an error during the request done to DCAE, look at the logs or try again");
+
+ public DcaeComponent() {
+ super(BLUEPRINT_DEPLOYED);
+ this.name = "DCAE";
+ }
+
+ public DcaeComponent(String name) {
+ super(BLUEPRINT_DEPLOYED);
+ this.name = "DCAE_" + name;
+ }
+
+ @Override
+ public String getComponentName() {
+ return name;
+ }
+
+
+ /**
+ * Convert the json response to a DcaeOperationStatusResponse.
+ *
+ * @param responseBody The DCAE response Json paylaod
+ * @return The dcae object provisioned
+ */
+ public static DcaeOperationStatusResponse convertDcaeResponse(String responseBody) {
+ if (responseBody != null && !responseBody.isEmpty()) {
+ return JsonUtils.GSON_JPA_MODEL.fromJson(responseBody, DcaeOperationStatusResponse.class);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * Generate the deployment id, it's random.
+ *
+ * @return The deployment id
+ */
+ public static String generateDeploymentId() {
+ return DCAE_DEPLOYMENT_PREFIX + UUID.randomUUID();
+ }
+
+ /**
+ * This method prepare the url returned by DCAE to check the status if fine. It
+ * extracts it from the dcaeResponse.
+ *
+ * @param dcaeResponse The dcae response object
+ * @return the Right Url modified if needed
+ */
+ public static String getStatusUrl(DcaeOperationStatusResponse dcaeResponse) {
+ return dcaeResponse.getLinks().getStatus();
+ }
+
+ /**
+ * Return the deploy payload for DCAE.
+ *
+ * @param loop The loop object
+ * @return The payload used to send deploy closed loop request
+ */
+ public static String getDeployPayload(Loop loop) {
+ JsonObject globalProp = loop.getGlobalPropertiesJson();
+ JsonObject deploymentProp = globalProp.getAsJsonObject(DEPLOYMENT_PARAMETER).getAsJsonObject(
+ UNIQUE_BLUEPRINT_PARAMETERS);
+
+ String serviceTypeId = loop.getLoopTemplate().getDcaeBlueprintId();
+
+ JsonObject rootObject = new JsonObject();
+ rootObject.addProperty(DCAE_SERVICETYPE_ID, serviceTypeId);
+ if (deploymentProp != null) {
+ rootObject.add(DCAE_INPUTS, deploymentProp);
+ }
+ logger.info("DCAE Deploy payload for unique blueprint: " + rootObject.toString());
+ return rootObject.toString();
+ }
+
+ /**
+ * Return the deploy payload for DCAE.
+ *
+ * @param loop The loop object
+ * @param microServicePolicy The micro service policy
+ * @return The payload used to send deploy closed loop request
+ */
+ public static String getDeployPayload(Loop loop, MicroServicePolicy microServicePolicy) {
+ JsonObject globalProp = loop.getGlobalPropertiesJson();
+ JsonObject deploymentProp =
+ globalProp.getAsJsonObject(DEPLOYMENT_PARAMETER).getAsJsonObject(microServicePolicy.getName());
+
+ String serviceTypeId = microServicePolicy.getDcaeBlueprintId();
+
+ JsonObject rootObject = new JsonObject();
+ rootObject.addProperty(DCAE_SERVICETYPE_ID, serviceTypeId);
+ if (deploymentProp != null) {
+ rootObject.add(DCAE_INPUTS, deploymentProp);
+ }
+ logger.info("DCAE Deploy payload for multiple blueprints: " + rootObject.toString());
+ return rootObject.toString();
+ }
+
+ /**
+ * Return the uninstallation payload for DCAE.
+ *
+ * @param loop The loop object
+ * @return The payload in string (json)
+ */
+ public static String getUndeployPayload(Loop loop) {
+ JsonObject rootObject = new JsonObject();
+ rootObject.addProperty(DCAE_SERVICETYPE_ID, loop.getLoopTemplate().getDcaeBlueprintId());
+ logger.info("DCAE Undeploy payload for unique blueprint: " + rootObject.toString());
+ return rootObject.toString();
+ }
+
+ /**
+ * Return the uninstallation payload for DCAE.
+ *
+ * @param policy The microServicePolicy object
+ * @return The payload in string (json)
+ */
+ public static String getUndeployPayload(MicroServicePolicy policy) {
+ JsonObject rootObject = new JsonObject();
+ rootObject.addProperty(DCAE_SERVICETYPE_ID, policy.getDcaeBlueprintId());
+ logger.info("DCAE Undeploy payload for multiple blueprints: " + rootObject.toString());
+ return rootObject.toString();
+ }
+
+ @Override
+ public ExternalComponentState computeState(Exchange camelExchange) {
+
+ DcaeOperationStatusResponse dcaeResponse = (DcaeOperationStatusResponse) camelExchange.getIn().getExchange()
+ .getProperty("dcaeResponse");
+
+ if (dcaeResponse == null) {
+ setState(BLUEPRINT_DEPLOYED);
+ } else {
+ if (dcaeResponse.getOperationType().equals("install") && dcaeResponse.getStatus().equals("succeeded")) {
+ setState(MICROSERVICE_INSTALLED_SUCCESSFULLY);
+ } else {
+ if (dcaeResponse.getOperationType().equals("install") && dcaeResponse.getStatus()
+ .equals("processing")) {
+ setState(PROCESSING_MICROSERVICE_INSTALLATION);
+ } else {
+ if (dcaeResponse.getOperationType().equals("install") && dcaeResponse.getStatus()
+ .equals("failed")) {
+ setState(MICROSERVICE_INSTALLATION_FAILED);
+ } else {
+ if (dcaeResponse.getOperationType().equals("uninstall")
+ && dcaeResponse.getStatus().equals("succeeded")) {
+ setState(MICROSERVICE_UNINSTALLED_SUCCESSFULLY);
+ } else {
+ if (dcaeResponse.getOperationType().equals("uninstall")
+ && dcaeResponse.getStatus().equals("processing")) {
+ setState(PROCESSING_MICROSERVICE_UNINSTALLATION);
+ } else {
+ if (dcaeResponse.getOperationType().equals("uninstall") && dcaeResponse.getStatus()
+ .equals("failed")) {
+ setState(MICROSERVICE_UNINSTALLATION_FAILED);
+ } else {
+ setState(IN_ERROR);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ return this.getState();
+ }
+
+ /**
+ * Convert the json response to a DcaeInventoryResponse.
+ *
+ * @param responseBody The DCAE response Json paylaod
+ * @return list of DcaeInventoryResponse
+ * @throws ParseException In case of issues with the Json parsing
+ */
+ public static List<DcaeInventoryResponse> convertToDcaeInventoryResponse(String responseBody)
+ throws ParseException {
+ JSONParser parser = new JSONParser();
+ JSONObject jsonObj = (JSONObject) parser.parse(responseBody);
+ JSONArray itemsArray = (JSONArray) jsonObj.get("items");
+ Iterator it = itemsArray.iterator();
+ List<DcaeInventoryResponse> inventoryResponseList = new LinkedList<>();
+ while (it.hasNext()) {
+ JSONObject item = (JSONObject) it.next();
+ DcaeInventoryResponse response = JsonUtils.GSON.fromJson(item.toString(), DcaeInventoryResponse.class);
+ inventoryResponseList.add(response);
+ }
+ return inventoryResponseList;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/components/external/ExternalComponent.java b/runtime/src/main/java/org/onap/policy/clamp/loop/components/external/ExternalComponent.java
new file mode 100644
index 000000000..ce7efe494
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/components/external/ExternalComponent.java
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.components.external;
+
+import com.google.gson.annotations.Expose;
+import org.apache.camel.Exchange;
+
+/**
+ * Should be abstract but Gson can't instantiate it if it's an abstract.
+ */
+public class ExternalComponent {
+ @Expose
+ private ExternalComponentState componentState;
+
+ public void setState(ExternalComponentState newState) {
+ this.componentState = newState;
+ }
+
+ public ExternalComponentState getState() {
+ return this.componentState;
+ }
+
+ public String getComponentName() {
+ return null;
+ }
+
+ public ExternalComponentState computeState(Exchange camelExchange) {
+ return new ExternalComponentState("INIT", "no desc", 0);
+ }
+
+ public ExternalComponent(ExternalComponentState initialState) {
+ setState(initialState);
+ }
+
+ public ExternalComponent() {
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/components/external/ExternalComponentState.java b/runtime/src/main/java/org/onap/policy/clamp/loop/components/external/ExternalComponentState.java
new file mode 100644
index 000000000..a57800025
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/components/external/ExternalComponentState.java
@@ -0,0 +1,128 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.components.external;
+
+import com.google.gson.annotations.Expose;
+
+/**
+ * This is a transient state reflecting the deployment status of a component. It
+ * can be Policy, DCAE, or whatever... This is object is generic. Clamp is now
+ * stateless, so it triggers the different components at runtime, the status per
+ * component is stored here. The state level is used to re-compute the global
+ * state when multiple sub states are required for that computation (generally
+ * provided sequentially to the method computeState from the camel routes.
+ *
+ */
+public class ExternalComponentState implements Comparable<ExternalComponentState> {
+ @Expose
+ private String stateName;
+ @Expose
+ private String description;
+ private int stateLevel;
+
+ /**
+ * Constructor taking stateName, description and its level.
+ *
+ * @param stateName The stateName in string
+ * @param description The description in string
+ * @param level The level, higher value has higher priority and can't be
+ * down-graded
+ */
+ public ExternalComponentState(String stateName, String description, int level) {
+ this.stateName = stateName;
+ this.description = description;
+ this.stateLevel = level;
+ }
+
+ public ExternalComponentState(String stateName, String description) {
+ this(stateName, description, 0);
+ }
+
+ public ExternalComponentState() {
+ }
+
+ public String getStateName() {
+ return stateName;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String toString() {
+ return stateName;
+ }
+
+ public int getLevel() {
+ return stateLevel;
+ }
+
+ public void setLevel(int priority) {
+ this.stateLevel = priority;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((stateName == null) ? 0 : stateName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ExternalComponentState other = (ExternalComponentState) obj;
+ if (stateName == null) {
+ if (other.stateName != null) {
+ return false;
+ }
+ } else if (!stateName.equals(other.stateName)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * This method compares this object by using the level of them.
+ *
+ * @param stateToCompare The state to compare to the current object
+ * @return If the one given in input has a higher level than the current object
+ * it returns -1, 1 otherwise and 0 if equals.
+ */
+ @Override
+ public int compareTo(ExternalComponentState stateToCompare) {
+ return Integer.compare(this.getLevel(), stateToCompare.getLevel());
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/components/external/PolicyComponent.java b/runtime/src/main/java/org/onap/policy/clamp/loop/components/external/PolicyComponent.java
new file mode 100644
index 000000000..27e8e1a13
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/components/external/PolicyComponent.java
@@ -0,0 +1,128 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.components.external;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import javax.persistence.Transient;
+import org.apache.camel.Exchange;
+import org.onap.policy.clamp.loop.Loop;
+import org.onap.policy.clamp.policy.pdpgroup.PdpGroupPayload;
+
+/**
+ * This class represents the policy state according to all policies involved in the control loop.
+ * It can compute it with all policy queries result.
+ * It contains also the method to generate the PDP payload used for the policies deployment.
+ */
+public class PolicyComponent extends ExternalComponent {
+
+ @Transient
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(PolicyComponent.class);
+
+ public static final ExternalComponentState IN_ERROR = new ExternalComponentState("IN_ERROR",
+ "There was an error during the sending to policy, the policy engine may be corrupted or inconsistent", 100);
+ public static final ExternalComponentState NOT_SENT = new ExternalComponentState("NOT_SENT",
+ "The policies defined have NOT yet been created on the policy engine", 90);
+ public static final ExternalComponentState SENT = new ExternalComponentState("SENT",
+ "The policies defined have been created but NOT deployed on the policy engine", 50);
+ public static final ExternalComponentState SENT_AND_DEPLOYED = new ExternalComponentState("SENT_AND_DEPLOYED",
+ "The policies defined have been created and deployed on the policy engine", 10);
+ public static final ExternalComponentState UNKNOWN = new ExternalComponentState("UNKNOWN",
+ "The current status is not clear. Need to refresh the status to get the current status.", 0);
+
+ /**
+ * Default constructor.
+ */
+ public PolicyComponent() {
+ /*
+ * We assume it's good by default as we will receive the state for each policy
+ * on by one, each time we increase the level we can't decrease it anymore.
+ * That's why it starts with the lowest one SENT_AND_DEPLOYED.
+ */
+ super(UNKNOWN);
+ }
+
+ @Override
+ public String getComponentName() {
+ return "POLICY";
+ }
+
+ /**
+ * Generates the Json that must be sent to policy to add all policies to Active
+ * PDP group.
+ *
+ * @param loop the loop object
+ * @param action POST (to add policy to group) or DELETE (to delete policy from group)
+ * @return The json, payload to send
+ */
+ public static String createPoliciesPayloadPdpGroup(Loop loop, String action) {
+ PdpGroupPayload pdpGroupPayload = new PdpGroupPayload();
+ loop.getOperationalPolicies().stream().forEach(opPolicy -> pdpGroupPayload
+ .updatePdpGroupMap(opPolicy.getPdpGroup(), opPolicy.getPdpSubgroup(), opPolicy.getName(), "1.0.0",
+ action));
+
+ loop.getMicroServicePolicies().stream().forEach(msPolicy -> pdpGroupPayload
+ .updatePdpGroupMap(msPolicy.getPdpGroup(), msPolicy.getPdpSubgroup(), msPolicy.getName(), "1.0.0",
+ action));
+ return pdpGroupPayload.generatePdpGroupPayload();
+ }
+
+ private static ExternalComponentState findNewState(boolean found, boolean deployed) {
+
+ ExternalComponentState newState = NOT_SENT;
+ if (found && deployed) {
+ newState = SENT_AND_DEPLOYED;
+ } else {
+ if (found) {
+ newState = SENT;
+ } else {
+ if (deployed) {
+ newState = IN_ERROR;
+ }
+ }
+ }
+ return newState;
+ }
+
+ private static ExternalComponentState mergeStates(ExternalComponentState oldState,
+ ExternalComponentState newState) {
+ return (oldState.compareTo(newState) < 0) ? newState : oldState;
+ }
+
+ /**
+ * This is a method that expect the results of the queries getPolicy and
+ * getPolicyDeployed for a unique policy (op, config, etc ...). It
+ * re-computes the global policy state for each policy results given. Therefore
+ * this method is called multiple times from the camel route and must be reset
+ * for a new global policy state retrieval. The state to compute the global
+ * policy state is stored in this class.
+ */
+ @Override
+ public ExternalComponentState computeState(Exchange camelExchange) {
+ this.setState(mergeStates(this.getState(),
+ findNewState((boolean) camelExchange.getIn().getExchange().getProperty("policyFound"),
+ (boolean) camelExchange.getIn().getExchange().getProperty("policyDeployed"))));
+ return this.getState();
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/deploy/DcaeDeployParameters.java b/runtime/src/main/java/org/onap/policy/clamp/loop/deploy/DcaeDeployParameters.java
new file mode 100644
index 000000000..1a1414611
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/deploy/DcaeDeployParameters.java
@@ -0,0 +1,112 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.deploy;
+
+import com.google.gson.JsonObject;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.loop.Loop;
+import org.onap.policy.clamp.loop.components.external.DcaeComponent;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * To decode the bluprint input parameters.
+ */
+public class DcaeDeployParameters {
+
+ private static LinkedHashMap<String, JsonObject> init(Loop loop) {
+ LinkedHashMap<String, JsonObject> deploymentParamMap = new LinkedHashMap<>();
+ Set<MicroServicePolicy> microServiceList = loop.getMicroServicePolicies();
+
+ for (MicroServicePolicy microService : microServiceList) {
+ deploymentParamMap.put(microService.getName(),
+ generateDcaeDeployParameter(microService));
+ }
+ return deploymentParamMap;
+ }
+
+ private static JsonObject generateDcaeDeployParameter(MicroServicePolicy microService) {
+ return generateDcaeDeployParameter(microService.getLoopElementModel().getBlueprint(),
+ microService.getName());
+ }
+
+ private static JsonObject generateDcaeDeployParameter(String blueprint, String policyId) {
+ JsonObject deployJsonBody = new JsonObject();
+ Yaml yaml = new Yaml();
+ Map<String, Object> inputsNodes = ((Map<String, Object>) ((Map<String, Object>) yaml
+ .load(blueprint)).get("inputs"));
+ inputsNodes.entrySet().stream().filter(e -> !e.getKey().contains("policy_id")).forEach(elem -> {
+ Object defaultValue = ((Map<String, Object>) elem.getValue()).get("default");
+ if (defaultValue != null) {
+ addPropertyToNode(deployJsonBody, elem.getKey(), defaultValue);
+ } else {
+ deployJsonBody.addProperty(elem.getKey(), "");
+ }
+ });
+ deployJsonBody.addProperty("policy_id", policyId);
+ return deployJsonBody;
+ }
+
+ private static void addPropertyToNode(JsonObject node, String key, Object value) {
+ if (value instanceof String) {
+ node.addProperty(key, (String) value);
+ } else if (value instanceof Number) {
+ node.addProperty(key, (Number) value);
+ } else if (value instanceof Boolean) {
+ node.addProperty(key, (Boolean) value);
+ } else if (value instanceof Character) {
+ node.addProperty(key, (Character) value);
+ } else {
+ node.addProperty(key, JsonUtils.GSON.toJson(value));
+ }
+ }
+
+ /**
+ * Convert the object in Json.
+ *
+ * @return The deploymentParameters in Json
+ */
+ public static JsonObject getDcaeDeploymentParametersInJson(Loop loop) {
+ JsonObject globalProperties = new JsonObject();
+ JsonObject deployParamJson = new JsonObject();
+ if (loop.getLoopTemplate().getUniqueBlueprint()) {
+ // Normally the unique blueprint could contain multiple microservices but then we can't guess
+ // the policy id params that will be used, so here we expect only one by default.
+ deployParamJson.add(DcaeComponent.UNIQUE_BLUEPRINT_PARAMETERS,
+ generateDcaeDeployParameter(loop.getLoopTemplate().getBlueprint(),
+ ((MicroServicePolicy) loop.getMicroServicePolicies().toArray()[0]).getName()));
+
+ } else {
+ LinkedHashMap<String, JsonObject> deploymentParamMap = init(loop);
+ for (Map.Entry<String, JsonObject> mapElement : deploymentParamMap.entrySet()) {
+ deployParamJson.add(mapElement.getKey(), mapElement.getValue());
+ }
+ }
+ globalProperties.add("dcaeDeployParameters", deployParamJson);
+ return globalProperties;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/log/LogType.java b/runtime/src/main/java/org/onap/policy/clamp/loop/log/LogType.java
new file mode 100644
index 000000000..50f6571d6
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/log/LogType.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.log;
+
+public enum LogType {
+ INFO, WARNING, ERROR;
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/log/LoopLog.java b/runtime/src/main/java/org/onap/policy/clamp/loop/log/LoopLog.java
new file mode 100644
index 000000000..00f7e1f41
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/log/LoopLog.java
@@ -0,0 +1,193 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.log;
+
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import org.onap.policy.clamp.loop.Loop;
+
+/**
+ * This class holds the logs created by the Clamp Backend. The Instant is always
+ * rounded to the nearest second as the nano seconds can't be stored in the
+ * database. The logs can be therefore exposed to the UI or the client doing
+ * some GET Loop on the backend.
+ *
+ */
+@Entity
+@Table(name = "loop_logs")
+public class LoopLog implements Serializable, Comparable<LoopLog> {
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 1988276670074437631L;
+
+ @Expose
+ @Id
+ @GeneratedValue(strategy = GenerationType.AUTO)
+ private Long id;
+
+ @Expose
+ @Column(name = "log_type", nullable = false)
+ @Enumerated(EnumType.STRING)
+ private LogType logType;
+
+ @Expose
+ @Column(name = "log_component", nullable = false)
+ private String logComponent;
+
+ @Expose
+ @Column(name = "message", columnDefinition = "MEDIUMTEXT", nullable = false)
+ private String message;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "loop_id", nullable = false)
+ private Loop loop;
+
+ @Expose
+ @Column(name = "log_instant", nullable = false)
+ private Instant logInstant = Instant.now().truncatedTo(ChronoUnit.SECONDS);
+
+ public LoopLog() {
+ }
+
+ /**
+ * Constructor For LoopLog taking message and logtype, logComponent and loop
+ * reference.
+ *
+ * @param message The message as string
+ * @param logType Type like INFO, WARN, DEBUG
+ * @param logComponent A String with DCAE, POLICY, CLAMP ,etc...
+ * @param loop The loop object that this log is about
+ */
+ public LoopLog(String message, LogType logType, String logComponent, Loop loop) {
+ this.message = message;
+ this.logType = logType;
+ this.loop = loop;
+ this.logComponent = logComponent;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public LogType getLogType() {
+ return logType;
+ }
+
+ public void setLogType(LogType logType) {
+ this.logType = logType;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ public Loop getLoop() {
+ return loop;
+ }
+
+ public void setLoop(Loop loop) {
+ this.loop = loop;
+ }
+
+ public Instant getLogInstant() {
+ return logInstant;
+ }
+
+ public void setLogInstant(Instant logInstant) {
+ this.logInstant = logInstant.truncatedTo(ChronoUnit.SECONDS);
+ }
+
+ public String getLogComponent() {
+ return logComponent;
+ }
+
+ public void setLogComponent(String logComponent) {
+ this.logComponent = logComponent;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((id == null) ? 0 : id.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LoopLog other = (LoopLog) obj;
+ if (id == null) {
+ if (other.id != null) {
+ return false;
+ }
+ } else if (!id.equals(other.id)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int compareTo(LoopLog arg0) {
+ // Reverse it, so that by default we have the latest
+ if (getId() == null) {
+ return 1;
+ }
+ if (arg0.getId() == null) {
+ return -1;
+ }
+ return arg0.getId().compareTo(this.getId());
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/log/LoopLogRepository.java b/runtime/src/main/java/org/onap/policy/clamp/loop/log/LoopLogRepository.java
new file mode 100644
index 000000000..df1f3919e
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/log/LoopLogRepository.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.log;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface LoopLogRepository extends JpaRepository<LoopLog, Long> {
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/log/LoopLogService.java b/runtime/src/main/java/org/onap/policy/clamp/loop/log/LoopLogService.java
new file mode 100644
index 000000000..a2f133f2f
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/log/LoopLogService.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.log;
+
+import org.onap.policy.clamp.loop.Loop;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class LoopLogService {
+
+ private final LoopLogRepository repository;
+
+ @Autowired
+ public LoopLogService(LoopLogRepository repository) {
+ this.repository = repository;
+ }
+
+ public void addLog(String message, String logType, Loop loop) {
+ this.addLogForComponent(message, logType, "CLAMP", loop);
+ }
+
+ public void addLogForComponent(String message, String logType, String component, Loop loop) {
+ loop.addLog(repository.save(new LoopLog(message, LogType.valueOf(logType), component, loop)));
+ }
+
+ public boolean isExisting(Long logId) {
+ return repository.existsById(logId);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/service/CsarServiceInstaller.java b/runtime/src/main/java/org/onap/policy/clamp/loop/service/CsarServiceInstaller.java
new file mode 100644
index 000000000..1429d73c2
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/service/CsarServiceInstaller.java
@@ -0,0 +1,129 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.service;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import java.util.Map.Entry;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.policy.clamp.clds.sdc.controller.installer.CsarHandler;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.sdc.tosca.parser.api.IEntityDetails;
+import org.onap.sdc.tosca.parser.elements.queries.EntityQuery;
+import org.onap.sdc.tosca.parser.elements.queries.TopologyTemplateQuery;
+import org.onap.sdc.tosca.parser.enums.EntityTemplateType;
+import org.onap.sdc.tosca.parser.enums.SdcTypes;
+import org.onap.sdc.toscaparser.api.NodeTemplate;
+import org.onap.sdc.toscaparser.api.Property;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+@Component
+@Qualifier("csarInstaller")
+public class CsarServiceInstaller {
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(CsarServiceInstaller.class);
+
+ @Autowired
+ ServicesRepository serviceRepository;
+
+ /**
+ * Install the Service from the csar.
+ *
+ * @param csar The Csar Handler
+ * @return The service object
+ */
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public Service installTheService(CsarHandler csar) {
+ logger.info("Start to install the Service from csar");
+ JsonObject serviceDetails = JsonUtils.GSON.fromJson(
+ JsonUtils.GSON.toJson(csar.getSdcCsarHelper().getServiceMetadataAllProperties()), JsonObject.class);
+
+ // Add properties details for each type, VfModule, VF, VFC, ....
+ JsonObject resourcesProp = createServicePropertiesByType(csar);
+ resourcesProp.add("VFModule", createVfModuleProperties(csar));
+
+ Service modelService = new Service(serviceDetails, resourcesProp,
+ csar.getSdcNotification().getServiceVersion());
+
+ serviceRepository.save(modelService);
+ logger.info("Successfully installed the Service");
+ return modelService;
+ }
+
+ private JsonObject createServicePropertiesByType(CsarHandler csar) {
+ JsonObject resourcesProp = new JsonObject();
+ // Iterate on all types defined in the tosca lib
+ for (SdcTypes type : SdcTypes.values()) {
+ JsonObject resourcesPropByType = new JsonObject();
+ // For each type, get the metadata of each nodetemplate
+ for (NodeTemplate nodeTemplate : csar.getSdcCsarHelper().getServiceNodeTemplateBySdcType(type)) {
+ resourcesPropByType.add(nodeTemplate.getName(),
+ JsonUtils.GSON.toJsonTree(nodeTemplate.getMetaData().getAllProperties()));
+ }
+ resourcesProp.add(type.getValue(), resourcesPropByType);
+ }
+ return resourcesProp;
+ }
+
+ private static JsonObject createVfModuleProperties(CsarHandler csar) {
+ JsonObject vfModuleProps = new JsonObject();
+ // Loop on all Groups defined in the service (VFModule entries type:
+ // org.openecomp.groups.VfModule)
+ for (IEntityDetails entity : csar.getSdcCsarHelper().getEntity(
+ EntityQuery.newBuilder(EntityTemplateType.GROUP).build(),
+ TopologyTemplateQuery.newBuilder(SdcTypes.SERVICE).build(), false)) {
+ // Get all metadata info
+ JsonObject allVfProps = (JsonObject) JsonUtils.GSON.toJsonTree(entity.getMetadata().getAllProperties());
+ vfModuleProps.add(entity.getMetadata().getAllProperties().get("vfModuleModelName"), allVfProps);
+ // now append the properties section so that we can also have isBase,
+ // volume_group, etc ... fields under the VFmodule name
+ for (Entry<String, Property> additionalProp : entity.getProperties().entrySet()) {
+ allVfProps.add(additionalProp.getValue().getName(),
+ JsonUtils.GSON.toJsonTree(additionalProp.getValue().getValue()));
+ }
+ }
+ return vfModuleProps;
+ }
+
+ /**
+ * Verify whether Service in Csar is deployed.
+ *
+ * @param csar The Csar Handler
+ * @return The flag indicating whether Service is deployed
+ * @throws SdcArtifactInstallerException The SdcArtifactInstallerException
+ */
+ public boolean isServiceAlreadyDeployed(CsarHandler csar) throws SdcArtifactInstallerException {
+ boolean alreadyInstalled = true;
+ JsonObject serviceDetails = JsonUtils.GSON.fromJson(
+ JsonUtils.GSON.toJson(csar.getSdcCsarHelper().getServiceMetadataAllProperties()), JsonObject.class);
+ alreadyInstalled = serviceRepository.existsById(serviceDetails.get("UUID").getAsString());
+
+ return alreadyInstalled;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/service/Service.java b/runtime/src/main/java/org/onap/policy/clamp/loop/service/Service.java
new file mode 100644
index 000000000..b7442abc5
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/service/Service.java
@@ -0,0 +1,169 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.service;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.dao.model.jsontype.StringJsonUserType;
+
+@Entity
+@Table(name = "services")
+@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)})
+public class Service implements Serializable {
+
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = 1331119060272760758L;
+
+ @Transient
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(Service.class);
+
+ @Id
+ @Column(name = "service_uuid", unique = true)
+ private String serviceUuid;
+
+ @Column(nullable = false, name = "name")
+ private String name;
+
+ @Column(name = "version")
+ private String version;
+
+ @Expose
+ @Type(type = "json")
+ @Column(columnDefinition = "json", name = "service_details")
+ private JsonObject serviceDetails;
+
+ @Expose
+ @Type(type = "json")
+ @Column(columnDefinition = "json", name = "resource_details")
+ private JsonObject resourceDetails;
+
+ /**
+ * Default constructor for serialization.
+ */
+ public Service() {
+ }
+
+ /**
+ * Constructor with string.
+ */
+ public Service(String serviceDetails, String resourceDetails) {
+ JsonObject serviceDetailsJson = JsonUtils.GSON.fromJson(serviceDetails, JsonObject.class);
+ this.name = serviceDetailsJson.get("name").getAsString();
+ this.serviceUuid = serviceDetailsJson.get("UUID").getAsString();
+ this.serviceDetails = serviceDetailsJson;
+ this.resourceDetails = JsonUtils.GSON.fromJson(resourceDetails, JsonObject.class);
+ }
+
+ /**
+ * Constructor with Json Object.
+ */
+ public Service(JsonObject serviceDetails, JsonObject resourceDetails, String version) {
+ this.name = serviceDetails.get("name").getAsString();
+ this.serviceUuid = serviceDetails.get("UUID").getAsString();
+ this.serviceDetails = serviceDetails;
+ this.resourceDetails = resourceDetails;
+ this.version = version;
+ }
+
+ public String getServiceUuid() {
+ return serviceUuid;
+ }
+
+ public JsonObject getServiceDetails() {
+ return serviceDetails;
+ }
+
+ public JsonObject getResourceDetails() {
+ return resourceDetails;
+ }
+
+ public JsonObject getResourceByType(String type) {
+ return (JsonObject) resourceDetails.get(type);
+ }
+
+ /**
+ * Name getter.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Version getter.
+ *
+ * @return the version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((serviceUuid == null) ? 0 : serviceUuid.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Service other = (Service) obj;
+ if (serviceUuid == null) {
+ if (other.serviceUuid != null) {
+ return false;
+ }
+ } else {
+ if (!serviceUuid.equals(other.serviceUuid)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/service/ServicesRepository.java b/runtime/src/main/java/org/onap/policy/clamp/loop/service/ServicesRepository.java
new file mode 100644
index 000000000..62596a08e
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/service/ServicesRepository.java
@@ -0,0 +1,31 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.service;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ServicesRepository extends JpaRepository<Service, String> {
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopElementModel.java b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopElementModel.java
new file mode 100644
index 000000000..6eb3c7195
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopElementModel.java
@@ -0,0 +1,295 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.template;
+
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import org.hibernate.annotations.SortNatural;
+import org.onap.policy.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.policy.clamp.loop.Loop;
+import org.onap.policy.clamp.loop.common.AuditEntity;
+import org.onap.policy.clamp.policy.Policy;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.policy.clamp.policy.operational.OperationalPolicy;
+
+/**
+ * This class represents a micro service/operational/... model for a loop template.
+ * So it's an element in the flow (a box shown in the loop).
+ */
+
+@Entity
+@Table(name = "loop_element_models")
+public class LoopElementModel extends AuditEntity implements Serializable {
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = -286522707701376645L;
+
+ @Id
+ @Expose
+ @Column(nullable = false, name = "name", unique = true)
+ private String name;
+
+ @Expose
+ @Column(name = "dcae_blueprint_id")
+ private String dcaeBlueprintId;
+
+ /**
+ * Here we store the blueprint coming from DCAE, it can be null if this is not a micro service model.
+ */
+ @Column(columnDefinition = "MEDIUMTEXT", name = "blueprint_yaml")
+ private String blueprint;
+
+ public static final String MICRO_SERVICE_TYPE = "MICRO_SERVICE_TYPE";
+ public static final String OPERATIONAL_POLICY_TYPE = "OPERATIONAL_POLICY_TYPE";
+ /**
+ * The type of element.
+ */
+ @Expose
+ @Column(nullable = false, name = "loop_element_type")
+ private String loopElementType;
+
+ /**
+ * This variable is used to display the micro-service name in the SVG.
+ */
+ @Expose
+ @Column(name = "short_name")
+ private String shortName;
+
+ /**
+ * This variable is used to store the type mentioned in the micro-service
+ * blueprint.
+ */
+ @Expose
+ @ManyToMany(
+ fetch = FetchType.EAGER,
+ cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
+ @JoinTable(
+ name = "loopelementmodels_to_policymodels",
+ joinColumns = @JoinColumn(name = "loop_element_name", referencedColumnName = "name"),
+ inverseJoinColumns = {
+ @JoinColumn(name = "policy_model_type", referencedColumnName = "policy_model_type"),
+ @JoinColumn(name = "policy_model_version", referencedColumnName = "version")})
+ @SortNatural
+ private SortedSet<PolicyModel> policyModels = new TreeSet<>();
+
+ @OneToMany(fetch = FetchType.LAZY, mappedBy = "loopElementModel", orphanRemoval = true)
+ private Set<LoopTemplateLoopElementModel> usedByLoopTemplates = new HashSet<>();
+
+ /**
+ * policyModels getter.
+ *
+ * @return the policyModel
+ */
+ public SortedSet<PolicyModel> getPolicyModels() {
+ return policyModels;
+ }
+
+ /**
+ * Method to add a new policyModel to the list.
+ *
+ * @param policyModel The policy model
+ */
+ public void addPolicyModel(PolicyModel policyModel) {
+ policyModels.add(policyModel);
+ policyModel.getUsedByElementModels().add(this);
+ }
+
+ /**
+ * name getter.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * name setter.
+ *
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * blueprint getter.
+ *
+ * @return the blueprint
+ */
+ public String getBlueprint() {
+ return blueprint;
+ }
+
+ /**
+ * blueprint setter.
+ *
+ * @param blueprint the blueprint to set
+ */
+ public void setBlueprint(String blueprint) {
+ this.blueprint = blueprint;
+ }
+
+ /**
+ * dcaeBlueprintId getter.
+ *
+ * @return the dcaeBlueprintId
+ */
+ public String getDcaeBlueprintId() {
+ return dcaeBlueprintId;
+ }
+
+ /**
+ * dcaeBlueprintId setter.
+ *
+ * @param dcaeBlueprintId the dcaeBlueprintId to set
+ */
+ public void setDcaeBlueprintId(String dcaeBlueprintId) {
+ this.dcaeBlueprintId = dcaeBlueprintId;
+ }
+
+ /**
+ * loopElementType getter.
+ *
+ * @return the loopElementType
+ */
+ public String getLoopElementType() {
+ return loopElementType;
+ }
+
+ /**
+ * loopElementType setter.
+ *
+ * @param loopElementType the loopElementType to set
+ */
+ public void setLoopElementType(String loopElementType) {
+ this.loopElementType = loopElementType;
+ }
+
+ /**
+ * shortName getter.
+ *
+ * @return the shortName
+ */
+ public String getShortName() {
+ return shortName;
+ }
+
+ /**
+ * * @param shortName the shortName to set.
+ */
+ public void setShortName(String shortName) {
+ this.shortName = shortName;
+ }
+
+ /**
+ * usedByLoopTemplates getter.
+ *
+ * @return the usedByLoopTemplates
+ */
+ public Set<LoopTemplateLoopElementModel> getUsedByLoopTemplates() {
+ return usedByLoopTemplates;
+ }
+
+ /**
+ * Default constructor for serialization.
+ */
+ public LoopElementModel() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The name id
+ * @param loopElementType The type of loop element
+ * @param blueprint The blueprint defined for dcae that contains the
+ * policy type to use
+ */
+ public LoopElementModel(String name, String loopElementType, String blueprint) {
+ this.name = name;
+ this.loopElementType = loopElementType;
+ this.blueprint = blueprint;
+ }
+
+ /**
+ * Create a policy instance from the current loop element model.
+ *
+ * @return A Policy object.
+ */
+ public Policy createPolicyInstance(Loop loop, ToscaConverterWithDictionarySupport toscaConverter) {
+ if (LoopElementModel.MICRO_SERVICE_TYPE.equals(this.getLoopElementType())) {
+ return new MicroServicePolicy(loop, loop.getModelService(), this, toscaConverter);
+ } else if (LoopElementModel.OPERATIONAL_POLICY_TYPE.equals(this.getLoopElementType())) {
+ return new OperationalPolicy(loop, loop.getModelService(), this, toscaConverter);
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LoopElementModel other = (LoopElementModel) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopElementModelsRepository.java b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopElementModelsRepository.java
new file mode 100644
index 000000000..d9b879d0f
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopElementModelsRepository.java
@@ -0,0 +1,31 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.template;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface LoopElementModelsRepository extends JpaRepository<LoopElementModel, String> {
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplate.java b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplate.java
new file mode 100644
index 000000000..ab7367aaf
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplate.java
@@ -0,0 +1,341 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.template;
+
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Convert;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import org.hibernate.annotations.SortNatural;
+import org.onap.policy.clamp.loop.common.AuditEntity;
+import org.onap.policy.clamp.loop.service.Service;
+
+@Entity
+@Table(name = "loop_templates")
+public class LoopTemplate extends AuditEntity implements Serializable {
+
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = -286522707701388642L;
+
+ @Id
+ @Expose
+ @Column(nullable = false, name = "name", unique = true)
+ private String name;
+
+ @Expose
+ @Column(name = "dcae_blueprint_id")
+ private String dcaeBlueprintId;
+
+ /**
+ * This field is used when we have a blueprint defining all microservices. The
+ * other option would be to have independent blueprint for each microservices.
+ * In that case they are stored in each MicroServiceModel
+ */
+ @Column(columnDefinition = "MEDIUMTEXT", name = "blueprint_yaml")
+ private String blueprint;
+
+ @Expose
+ @OneToMany(
+ cascade = CascadeType.ALL,
+ fetch = FetchType.EAGER,
+ mappedBy = "loopTemplate",
+ orphanRemoval = true)
+ @SortNatural
+ private SortedSet<LoopTemplateLoopElementModel> loopElementModelsUsed = new TreeSet<>();
+
+ @Expose
+ @ManyToOne(
+ fetch = FetchType.EAGER,
+ cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH})
+ @JoinColumn(name = "service_uuid")
+ private Service modelService;
+
+ @Expose
+ @Column(name = "maximum_instances_allowed")
+ private Integer maximumInstancesAllowed;
+
+ @Expose
+ @Column(name = "unique_blueprint", columnDefinition = "boolean default false")
+ private boolean uniqueBlueprint;
+
+ /**
+ * Type of Loop allowed to be created.
+ */
+ @Expose
+ @Column(name = "allowed_loop_type")
+ @Convert(converter = LoopTypeConvertor.class)
+ private LoopType allowedLoopType = LoopType.CLOSED;
+
+ /**
+ * name getter.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * name setter.
+ *
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * blueprint getter.
+ *
+ * @return the blueprint
+ */
+ public String getBlueprint() {
+ return blueprint;
+ }
+
+ /**
+ * dcaeBlueprintId getter.
+ *
+ * @return the dcaeBlueprintId
+ */
+ public String getDcaeBlueprintId() {
+ return dcaeBlueprintId;
+ }
+
+ /**
+ * dcaeBlueprintId setter.
+ *
+ * @param dcaeBlueprintId the dcaeBlueprintId to set
+ */
+ public void setDcaeBlueprintId(String dcaeBlueprintId) {
+ this.dcaeBlueprintId = dcaeBlueprintId;
+ }
+
+ /**
+ * blueprint setter.
+ *
+ * @param blueprint the blueprint to set
+ */
+ public void setBlueprint(String blueprint) {
+ this.blueprint = blueprint;
+ if (blueprint == null) {
+ this.uniqueBlueprint = false;
+ } else {
+ this.uniqueBlueprint = true;
+ }
+ }
+
+ /**
+ * loopElementModelsUsed getter.
+ *
+ * @return the loopElementModelsUsed
+ */
+ public SortedSet<LoopTemplateLoopElementModel> getLoopElementModelsUsed() {
+ return loopElementModelsUsed;
+ }
+
+ /**
+ * maximumInstancesAllowed getter.
+ *
+ * @return the maximumInstancesAllowed
+ */
+ public Integer getMaximumInstancesAllowed() {
+ return maximumInstancesAllowed;
+ }
+
+ /**
+ * maximumInstancesAllowed setter.
+ *
+ * @param maximumInstancesAllowed the maximumInstancesAllowed to set
+ */
+ public void setMaximumInstancesAllowed(Integer maximumInstancesAllowed) {
+ this.maximumInstancesAllowed = maximumInstancesAllowed;
+ }
+
+ /**
+ * allowedLoopType getter.
+ *
+ * @return the allowedLoopType Type of Loop allowed to be created
+ */
+ public LoopType getAllowedLoopType() {
+ return allowedLoopType;
+ }
+
+ /**
+ * allowedLoopType setter.
+ *
+ * @param allowedLoopType the allowedLoopType to set
+ */
+ public void setAllowedLoopType(LoopType allowedLoopType) {
+ this.allowedLoopType = allowedLoopType;
+ }
+
+ /**
+ * Add list of loopElements to the current template, each loopElementModel is
+ * added at the end of the list so the flowOrder is computed automatically.
+ *
+ * @param loopElementModels The loopElementModel set to add
+ */
+ public void addLoopElementModels(Set<LoopElementModel> loopElementModels) {
+ for (LoopElementModel loopElementModel : loopElementModels) {
+ addLoopElementModel(loopElementModel);
+ }
+ }
+
+ /**
+ * Add a loopElement to the current template, the loopElementModel is added at
+ * the end of the list so the flowOrder is computed automatically.
+ *
+ * @param loopElementModel The loopElementModel to add
+ */
+ public void addLoopElementModel(LoopElementModel loopElementModel) {
+ this.addLoopElementModel(loopElementModel, this.loopElementModelsUsed.size());
+ }
+
+ /**
+ * Add a loopElement model to the current template, the flow order must be
+ * specified manually.
+ *
+ * @param loopElementModel The loopElementModel to add
+ * @param listPosition The position in the flow
+ */
+ public void addLoopElementModel(LoopElementModel loopElementModel, Integer listPosition) {
+ LoopTemplateLoopElementModel jointEntry =
+ new LoopTemplateLoopElementModel(this, loopElementModel, listPosition);
+ this.loopElementModelsUsed.add(jointEntry);
+ loopElementModel.getUsedByLoopTemplates().add(jointEntry);
+ }
+
+ /**
+ * modelService getter.
+ *
+ * @return the modelService
+ */
+ public Service getModelService() {
+ return modelService;
+ }
+
+ /**
+ * modelService setter.
+ *
+ * @param modelService the modelService to set
+ */
+ public void setModelService(Service modelService) {
+ this.modelService = modelService;
+ }
+
+ /**
+ * uniqueBlueprint getter.
+ *
+ * @return the uniqueBlueprint
+ */
+ public boolean getUniqueBlueprint() {
+ return uniqueBlueprint;
+ }
+
+ /**
+ * Default constructor for serialization.
+ */
+ public LoopTemplate() {
+
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The loop template name id
+ * @param blueprint The blueprint containing all microservices (legacy
+ * case)
+ * @param maxInstancesAllowed The maximum number of instances that can be
+ * created from that template
+ * @param service The service associated to that loop template
+ */
+ public LoopTemplate(String name, String blueprint, Integer maxInstancesAllowed, Service service) {
+ this.name = name;
+ this.setBlueprint(blueprint);
+
+ this.maximumInstancesAllowed = maxInstancesAllowed;
+ this.modelService = service;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LoopTemplate other = (LoopTemplate) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Generate the loop template name.
+ *
+ * @param serviceName The service name
+ * @param serviceVersion The service version
+ * @param resourceName The resource name
+ * @param blueprintFileName The blueprint file name
+ * @return The generated loop template name
+ */
+ public static String generateLoopTemplateName(String serviceName, String serviceVersion,
+ String resourceName, String blueprintFileName) {
+ StringBuilder buffer = new StringBuilder("LOOP_TEMPLATE_").append(serviceName).append("_v")
+ .append(serviceVersion).append("_").append(resourceName).append("_")
+ .append(blueprintFileName.replaceAll(".yaml", ""));
+ return buffer.toString().replace('.', '_').replaceAll(" ", "");
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplateLoopElementModel.java b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplateLoopElementModel.java
new file mode 100644
index 000000000..c0b0c7d24
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplateLoopElementModel.java
@@ -0,0 +1,192 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.template;
+
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.MapsId;
+import javax.persistence.Table;
+
+@Entity
+@Table(name = "looptemplates_to_loopelementmodels")
+public class LoopTemplateLoopElementModel implements Serializable, Comparable<LoopTemplateLoopElementModel> {
+
+ /**
+ * Serial ID.
+ */
+ private static final long serialVersionUID = 5924989899078094245L;
+
+ @EmbeddedId
+ private LoopTemplateLoopElementModelId loopTemplateLoopElementModelId;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @MapsId("loopTemplateName")
+ @JoinColumn(name = "loop_template_name")
+ private LoopTemplate loopTemplate;
+
+ @Expose
+ @ManyToOne(fetch = FetchType.EAGER, cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REFRESH })
+ @MapsId("loopElementModelName")
+ @JoinColumn(name = "loop_element_model_name")
+ private LoopElementModel loopElementModel;
+
+ @Expose
+ @Column(nullable = false, name = "flow_order")
+ private Integer flowOrder;
+
+ /**
+ * Default constructor for serialization.
+ */
+ public LoopTemplateLoopElementModel() {
+
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param loopTemplate The loop template object
+ * @param loopElementModel The loopElementModel object
+ * @param flowOrder The position of the micro service in the flow
+ */
+ public LoopTemplateLoopElementModel(LoopTemplate loopTemplate, LoopElementModel loopElementModel,
+ Integer flowOrder) {
+ this.loopTemplate = loopTemplate;
+ this.loopElementModel = loopElementModel;
+ this.flowOrder = flowOrder;
+ this.loopTemplateLoopElementModelId = new LoopTemplateLoopElementModelId(loopTemplate.getName(),
+ loopElementModel.getName());
+ }
+
+ /**
+ * loopTemplate getter.
+ *
+ * @return the loopTemplate
+ */
+ public LoopTemplate getLoopTemplate() {
+ return loopTemplate;
+ }
+
+ /**
+ * loopTemplate setter.
+ *
+ * @param loopTemplate the loopTemplate to set
+ */
+ public void setLoopTemplate(LoopTemplate loopTemplate) {
+ this.loopTemplate = loopTemplate;
+ }
+
+ /**
+ * loopElementModel getter.
+ *
+ * @return the loopElementModel
+ */
+ public LoopElementModel getLoopElementModel() {
+ return loopElementModel;
+ }
+
+ /**
+ * loopElementModel setter.
+ *
+ * @param loopElementModel the loopElementModel to set
+ */
+ public void setLoopElementModel(LoopElementModel loopElementModel) {
+ this.loopElementModel = loopElementModel;
+ }
+
+ /**
+ * flowOrder getter.
+ *
+ * @return the flowOrder
+ */
+ public Integer getFlowOrder() {
+ return flowOrder;
+ }
+
+ /**
+ * flowOrder setter.
+ *
+ * @param flowOrder the flowOrder to set
+ */
+ public void setFlowOrder(Integer flowOrder) {
+ this.flowOrder = flowOrder;
+ }
+
+ @Override
+ public int compareTo(LoopTemplateLoopElementModel arg0) {
+ // Reverse it, so that by default we have the latest
+ if (getFlowOrder() == null) {
+ return 1;
+ }
+ if (arg0.getFlowOrder() == null) {
+ return -1;
+ }
+ return arg0.getFlowOrder().compareTo(this.getFlowOrder());
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((loopTemplate == null) ? 0 : loopTemplate.hashCode());
+ result = prime * result + ((loopElementModel == null) ? 0 : loopElementModel.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ LoopTemplateLoopElementModel other = (LoopTemplateLoopElementModel) obj;
+ if (loopTemplate == null) {
+ if (other.loopTemplate != null) {
+ return false;
+ }
+ } else if (!loopTemplate.equals(other.loopTemplate)) {
+ return false;
+ }
+ if (loopElementModel == null) {
+ if (other.loopElementModel != null) {
+ return false;
+ }
+ } else if (!loopElementModel.equals(other.loopElementModel)) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplateLoopElementModelId.java b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplateLoopElementModelId.java
new file mode 100644
index 000000000..9da8272bd
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplateLoopElementModelId.java
@@ -0,0 +1,100 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.template;
+
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+
+@Embeddable
+public class LoopTemplateLoopElementModelId implements Serializable {
+
+ /**
+ * Serial ID.
+ */
+ private static final long serialVersionUID = 4089888115504914773L;
+
+ @Expose
+ @Column(name = "loop_template_name")
+ private String loopTemplateName;
+
+ @Expose
+ @Column(name = "loop_element_model_name")
+ private String loopElementModelName;
+
+ /**
+ * Default constructor for serialization.
+ */
+ public LoopTemplateLoopElementModelId() {
+
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param loopTemplateName The loop template name id
+ * @param microServiceModelName THe micro Service name id
+ */
+ public LoopTemplateLoopElementModelId(String loopTemplateName, String microServiceModelName) {
+ this.loopTemplateName = loopTemplateName;
+ this.loopElementModelName = microServiceModelName;
+ }
+
+ /**
+ * loopTemplateName getter.
+ *
+ * @return the loopTemplateName
+ */
+ public String getLoopTemplateName() {
+ return loopTemplateName;
+ }
+
+ /**
+ * loopTemplateName setter.
+ *
+ * @param loopTemplateName the loopTemplateName to set
+ */
+ public void setLoopTemplateName(String loopTemplateName) {
+ this.loopTemplateName = loopTemplateName;
+ }
+
+ /**
+ * microServiceModelName getter.
+ *
+ * @return the microServiceModelName
+ */
+ public String getLoopElementModelName() {
+ return loopElementModelName;
+ }
+
+ /**
+ * loopElementModelName setter.
+ *
+ * @param loopElementModelName the loopElementModelName to set
+ */
+ public void setLoopElementModelName(String loopElementModelName) {
+ this.loopElementModelName = loopElementModelName;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplatesRepository.java b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplatesRepository.java
new file mode 100644
index 000000000..3993dee34
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplatesRepository.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.template;
+
+import java.util.List;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface LoopTemplatesRepository extends JpaRepository<LoopTemplate, String> {
+
+ @Query("SELECT looptemplate.name FROM LoopTemplate as looptemplate")
+ List<String> getAllLoopTemplateNames();
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplatesService.java b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplatesService.java
new file mode 100644
index 000000000..974cf3b5c
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTemplatesService.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.template;
+
+import java.util.List;
+import org.onap.policy.clamp.clds.sdc.controller.installer.ChainGenerator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class LoopTemplatesService {
+
+ private final LoopTemplatesRepository loopTemplatesRepository;
+
+ @Autowired
+ ChainGenerator chainGenerator;
+
+ /**
+ * Constructor.
+ */
+ @Autowired
+ public LoopTemplatesService(LoopTemplatesRepository loopTemplatesRepository) {
+ this.loopTemplatesRepository = loopTemplatesRepository;
+
+ }
+
+ public LoopTemplate saveOrUpdateLoopTemplate(LoopTemplate loopTemplate) {
+ return loopTemplatesRepository.save(loopTemplate);
+ }
+
+ public List<String> getLoopTemplateNames() {
+ return loopTemplatesRepository.getAllLoopTemplateNames();
+ }
+
+ public List<LoopTemplate> getAllLoopTemplates() {
+ return loopTemplatesRepository.findAll();
+ }
+
+ public LoopTemplate getLoopTemplate(String name) {
+ return loopTemplatesRepository.findById(name).orElse(null);
+ }
+
+ public void deleteLoopTemplate(String name) {
+ loopTemplatesRepository.deleteById(name);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopType.java b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopType.java
new file mode 100644
index 000000000..eacfecb5e
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopType.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.template;
+
+/**
+ * Enums for AllowedLoopType in LoopTemplate enity.
+ *
+ */
+public enum LoopType {
+ OPEN("OPEN"), CLOSED("CLOSED"), HYBRID("HYBRID");
+
+ private String value;
+
+ private LoopType(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTypeConvertor.java b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTypeConvertor.java
new file mode 100644
index 000000000..81ca18d57
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/template/LoopTypeConvertor.java
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.template;
+
+import java.util.stream.Stream;
+import javax.persistence.AttributeConverter;
+
+/**
+ * Attribute Converter to allow using LoopType Enum values in DB and Java classes.
+ *
+ */
+public class LoopTypeConvertor implements AttributeConverter<LoopType, String> {
+
+ @Override
+ public String convertToDatabaseColumn(LoopType loopType) {
+ if (loopType == null) {
+ return null;
+ }
+ return loopType.getValue();
+ }
+
+ @Override
+ public LoopType convertToEntityAttribute(String value) {
+ if (value == null) {
+ return null;
+ }
+
+ return Stream.of(LoopType.values()).filter(c -> c.getValue().equals(value)).findFirst()
+ .orElseThrow(IllegalArgumentException::new);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModel.java b/runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModel.java
new file mode 100644
index 000000000..2414377d7
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModel.java
@@ -0,0 +1,282 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.template;
+
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
+import org.onap.policy.clamp.dao.model.jsontype.StringJsonUserType;
+import org.onap.policy.clamp.loop.common.AuditEntity;
+import org.onap.policy.clamp.util.SemanticVersioning;
+
+/**
+ * This class represents the policy model tosca revision that we can have to a
+ * specific microservice.
+ */
+@Entity
+@Table(name = "policy_models")
+@IdClass(PolicyModelId.class)
+@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)})
+public class PolicyModel extends AuditEntity implements Serializable, Comparable<PolicyModel> {
+
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = -286522705701376645L;
+
+ /**
+ * This variable is used to store the type mentioned in the micro-service
+ * blueprint.
+ */
+ @Id
+ @Expose
+ @Column(nullable = false, name = "policy_model_type")
+ private String policyModelType;
+
+ /**
+ * Semantic versioning on policy side.
+ */
+ @Id
+ @Expose
+ @Column(name = "version", nullable = false)
+ private String version;
+
+ @Column(columnDefinition = "MEDIUMTEXT", name = "policy_tosca")
+ private String policyModelTosca;
+
+ @Expose
+ @Column(name = "policy_acronym")
+ private String policyAcronym;
+
+ @ManyToMany(mappedBy = "policyModels", fetch = FetchType.EAGER)
+ private Set<LoopElementModel> usedByElementModels = new HashSet<>();
+
+ @Expose
+ @Type(type = "json")
+ @Column(columnDefinition = "json", name = "policy_pdp_group")
+ private JsonObject policyPdpGroup;
+
+ /**
+ * usedByElementModels getter.
+ *
+ * @return the usedByElementModels
+ */
+ public Set<LoopElementModel> getUsedByElementModels() {
+ return usedByElementModels;
+ }
+
+ /**
+ * policyPdpGroup getter.
+ *
+ * @return the policyPdpGroup
+ */
+ public JsonObject getPolicyPdpGroup() {
+ return policyPdpGroup;
+ }
+
+ /**
+ * policyPdpGroup setter.
+ *
+ * @param policyPdpGroup the policyPdpGroup to set
+ */
+ public void setPolicyPdpGroup(JsonObject policyPdpGroup) {
+ this.policyPdpGroup = policyPdpGroup;
+ }
+
+ /**
+ * policyModelTosca getter.
+ *
+ * @return the policyModelTosca
+ */
+ public String getPolicyModelTosca() {
+ return policyModelTosca;
+ }
+
+ /**
+ * policyModelTosca setter.
+ *
+ * @param policyModelTosca the policyModelTosca to set
+ */
+ public void setPolicyModelTosca(String policyModelTosca) {
+ this.policyModelTosca = policyModelTosca;
+ }
+
+ /**
+ * policyModelType getter.
+ *
+ * @return the modelType
+ */
+ public String getPolicyModelType() {
+ return policyModelType;
+ }
+
+ /**
+ * policyModelType setter.
+ *
+ * @param modelType the modelType to set
+ */
+ public void setPolicyModelType(String modelType) {
+ this.policyModelType = modelType;
+ }
+
+ /**
+ * version getter.
+ *
+ * @return the version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * version setter.
+ *
+ * @param version the version to set
+ */
+ public void setVersion(String version) {
+ // Try to convert it before
+ this.version = version;
+ }
+
+ /**
+ * policyAcronym getter.
+ *
+ * @return the policyAcronym value
+ */
+ public String getPolicyAcronym() {
+ return policyAcronym;
+ }
+
+ /**
+ * policyAcronym setter.
+ *
+ * @param policyAcronym The policyAcronym to set
+ */
+ public void setPolicyAcronym(String policyAcronym) {
+ this.policyAcronym = policyAcronym;
+ }
+
+ /**
+ * Default constructor for serialization.
+ */
+ public PolicyModel() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param policyType The policyType (referenced in the blueprint
+ * @param policyModelTosca The policy tosca model in yaml
+ * @param version the version like 1.0.0
+ * @param policyAcronym Subtype for policy if it exists (could be used by UI)
+ */
+ public PolicyModel(String policyType, String policyModelTosca, String version,
+ String policyAcronym) {
+ this.policyModelType = policyType;
+ this.policyModelTosca = policyModelTosca;
+ this.version = version;
+ this.policyAcronym = policyAcronym;
+ if (this.policyAcronym == null) {
+ this.policyAcronym = createDefaultPolicyAcronym(policyType);
+ }
+ }
+
+ /**
+ * Constructor with acronym generated by default from policyType.
+ *
+ * @param policyType The policyType (referenced in the blueprint
+ * @param policyModelTosca The policy tosca model in yaml
+ * @param version the version like 1.0.0
+ */
+ public PolicyModel(String policyType, String policyModelTosca, String version) {
+ this(policyType, policyModelTosca, version, null);
+ }
+
+ public static String createDefaultPolicyAcronym(String policyType) {
+ String[] policyNameArray = policyType.split("\\.");
+ return policyNameArray[policyNameArray.length - 1];
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((policyModelType == null) ? 0 : policyModelType.hashCode());
+ result = prime * result + ((version == null) ? 0 : version.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ PolicyModel other = (PolicyModel) obj;
+ if (policyModelType == null) {
+ if (other.policyModelType != null) {
+ return false;
+ }
+ } else if (!policyModelType.equals(other.policyModelType)) {
+ return false;
+ }
+ if (version == null) {
+ if (other.version != null) {
+ return false;
+ }
+ } else if (!version.equals(other.version)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int compareTo(PolicyModel arg0) {
+
+ if (this.getPolicyModelType().equals(arg0.getPolicyModelType())) {
+ // Reverse it, so that by default we have the latest in they are same model type
+ return SemanticVersioning.compare(arg0.getVersion(), this.version);
+ } else {
+ return this.getPolicyModelType().compareTo(arg0.getPolicyModelType());
+ }
+
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModelId.java b/runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModelId.java
new file mode 100644
index 000000000..2591bd174
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModelId.java
@@ -0,0 +1,92 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.template;
+
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+
+public class PolicyModelId implements Serializable {
+
+ /**
+ * Serial Id.
+ */
+ private static final long serialVersionUID = -2846526482064334745L;
+
+ @Expose
+ private String policyModelType;
+
+ @Expose
+ private String version;
+
+ /**
+ * Default constructor for serialization.
+ */
+ public PolicyModelId() {
+
+ }
+
+ /**
+ * Constructor.
+ */
+ public PolicyModelId(String policyModelType, String version) {
+ this.policyModelType = policyModelType;
+ this.version = version;
+ }
+
+ /**
+ * policyModelType getter.
+ *
+ * @return the policyModelType
+ */
+ public String getPolicyModelType() {
+ return policyModelType;
+ }
+
+ /**
+ * policyModelType setter.
+ *
+ * @param policyModelType the policyModelType to set
+ */
+ public void setPolicyModelType(String policyModelType) {
+ this.policyModelType = policyModelType;
+ }
+
+ /**
+ * version getter.
+ *
+ * @return the version
+ */
+ public String getVersion() {
+ return version;
+ }
+
+ /**
+ * version setter.
+ *
+ * @param version the version to set
+ */
+ public void setVersion(String version) {
+ this.version = version;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModelsRepository.java b/runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModelsRepository.java
new file mode 100644
index 000000000..6ff7e3d0c
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModelsRepository.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.template;
+
+import java.util.List;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface PolicyModelsRepository extends JpaRepository<PolicyModel, PolicyModelId> {
+ @Query("SELECT policymodel.policyModelType FROM PolicyModel as policymodel")
+ List<String> getAllPolicyModelType();
+
+ List<PolicyModel> findByPolicyModelType(String policyModelType);
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModelsService.java b/runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModelsService.java
new file mode 100644
index 000000000..2d31b3b10
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/loop/template/PolicyModelsService.java
@@ -0,0 +1,138 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.template;
+
+import com.google.gson.JsonObject;
+import java.util.List;
+import org.onap.policy.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.policy.clamp.policy.pdpgroup.PdpGroupsAnalyzer;
+import org.onap.policy.models.pdp.concepts.PdpGroups;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * This class contains the methods to access the policyModel object in db.
+ */
+@Service
+public class PolicyModelsService {
+ private final PolicyModelsRepository policyModelsRepository;
+
+ /**
+ * This is the new tosca converter that must be used in clamp.
+ */
+ @Autowired
+ private ToscaConverterWithDictionarySupport toscaConverterWithDictionarySupport;
+
+ @Autowired
+ public PolicyModelsService(PolicyModelsRepository policyModelrepo) {
+ policyModelsRepository = policyModelrepo;
+ }
+
+ /**
+ * Save or Update Policy Model.
+ *
+ * @param policyModel The policyModel
+ * @return The Policy Model
+ */
+ public PolicyModel saveOrUpdatePolicyModel(PolicyModel policyModel) {
+ return policyModelsRepository.saveAndFlush(policyModel);
+ }
+
+ /**
+ * Verify whether Policy Model exist by ID.
+ *
+ * @param policyModelId The policyModel Id
+ * @return The flag indicates whether Policy Model exist
+ */
+ public boolean existsById(PolicyModelId policyModelId) {
+ return policyModelsRepository.existsById(policyModelId);
+ }
+
+ /**
+ * This method retrieves the tosca model and convert it to a Json schema.
+ * That json schema is normally used by the UI.
+ *
+ * @param policyType The policy model type id
+ * @param policyTypeVersion The policy model type version
+ * @return A JsonObject with the json schema describing the tosca
+ */
+ public JsonObject getPolicyModelJson(String policyType, String policyTypeVersion) {
+ PolicyModel thePolicyModel = getPolicyModel(policyType, policyTypeVersion);
+ // In the following use case we are not in the context of a closed loop, so the enrichment
+ // of the json cannot be done, that's why the serviceModel provided is NULL.
+ return toscaConverterWithDictionarySupport
+ .convertToscaToJsonSchemaObject(thePolicyModel.getPolicyModelTosca(), policyType, null);
+ }
+
+ public List<String> getAllPolicyModelTypes() {
+ return policyModelsRepository.getAllPolicyModelType();
+ }
+
+ public Iterable<PolicyModel> getAllPolicyModels() {
+ return policyModelsRepository.findAll();
+ }
+
+ public PolicyModel getPolicyModel(String type, String version) {
+ return policyModelsRepository.findById(new PolicyModelId(type, version)).orElse(null);
+ }
+
+ public Iterable<PolicyModel> getAllPolicyModelsByType(String type) {
+ return policyModelsRepository.findByPolicyModelType(type);
+ }
+
+ /**
+ * Retrieves the Tosca model Yaml string.
+ *
+ * @param type The Policy Model Type
+ * @param version The policy model version
+ * @return The Tosca model Yaml string
+ */
+ public String getPolicyModelTosca(String type, String version) {
+ return policyModelsRepository.findById(new PolicyModelId(type, version))
+ .orElse(new PolicyModel()).getPolicyModelTosca();
+ }
+
+ /**
+ * This method creates an PolicyModel in Db if it does not exist.
+ *
+ * @param policyModel The policyModel to save
+ */
+ @Transactional(propagation = Propagation.REQUIRES_NEW)
+ public PolicyModel savePolicyModelInNewTransaction(PolicyModel policyModel) {
+ return policyModelsRepository.saveAndFlush(policyModel);
+ }
+
+ /**
+ * Update the Pdp Group info in Policy Model DB.
+ *
+ * @param pdpGroups The list of Pdp Group info received from Policy Engine
+ */
+ public void updatePdpGroupInfo(PdpGroups pdpGroups) {
+ List<PolicyModel> policyModelsList = policyModelsRepository.findAll();
+ PdpGroupsAnalyzer.updatePdpGroupOfPolicyModels(policyModelsList, pdpGroups);
+ this.policyModelsRepository.saveAll(policyModelsList);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/Policy.java b/runtime/src/main/java/org/onap/policy/clamp/policy/Policy.java
new file mode 100644
index 000000000..f8bdab6c2
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/Policy.java
@@ -0,0 +1,255 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2021 AT&T
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import java.io.UnsupportedEncodingException;
+import java.util.Map;
+import javax.persistence.Column;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinColumns;
+import javax.persistence.ManyToOne;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.Transient;
+import org.hibernate.annotations.Type;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
+import org.json.JSONObject;
+import org.onap.policy.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.policy.clamp.dao.model.jsontype.StringJsonUserType;
+import org.onap.policy.clamp.loop.common.AuditEntity;
+import org.onap.policy.clamp.loop.service.Service;
+import org.onap.policy.clamp.loop.template.LoopElementModel;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.yaml.snakeyaml.Yaml;
+
+@MappedSuperclass
+@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)})
+public abstract class Policy extends AuditEntity {
+
+ @Transient
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(Policy.class);
+
+ @Expose
+ @Type(type = "json")
+ @Column(columnDefinition = "json", name = "json_representation", nullable = false)
+ private JsonObject jsonRepresentation;
+
+ @Expose
+ @Type(type = "json")
+ @Column(columnDefinition = "json", name = "configurations_json")
+ private JsonObject configurationsJson;
+
+ /**
+ * This attribute can be null when the user add a policy on the loop instance, not the template.
+ * When null, It therefore indicates that this policy is not by default in the loop template.
+ */
+ @Expose
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumn(name = "loop_element_model_id")
+ private LoopElementModel loopElementModel;
+
+ @Expose
+ @Column(name = "pdp_group")
+ private String pdpGroup;
+
+ @Expose
+ @Column(name = "pdp_sub_group")
+ private String pdpSubgroup;
+
+ @Expose
+ @ManyToOne(fetch = FetchType.EAGER)
+ @JoinColumns({@JoinColumn(name = "policy_model_type", referencedColumnName = "policy_model_type"),
+ @JoinColumn(name = "policy_model_version", referencedColumnName = "version")})
+ private PolicyModel policyModel;
+
+ /**
+ * This method create the policy payload that must be sent to PEF.
+ *
+ * @return A String containing the payload
+ * @throws UnsupportedEncodingException In case of failure
+ */
+ public String createPolicyPayload() throws UnsupportedEncodingException {
+ return PolicyPayload
+ .createPolicyPayload(this.getPolicyModel().getPolicyModelType(), this.getPolicyModel().getVersion(),
+ this.getName(), this.getPolicyModel().getVersion(), this.getConfigurationsJson(),
+ this.getPolicyModel() != null ? this.getPolicyModel().getPolicyModelTosca() : "");
+ }
+
+ /**
+ * Name getter.
+ *
+ * @return the name
+ */
+ public abstract String getName();
+
+ /**
+ * Name setter.
+ */
+ public abstract void setName(String name);
+
+ /**
+ * jsonRepresentation getter.
+ *
+ * @return the jsonRepresentation
+ */
+ public JsonObject getJsonRepresentation() {
+ return jsonRepresentation;
+ }
+
+ /**
+ * jsonRepresentation setter.
+ *
+ * @param jsonRepresentation The jsonRepresentation to set
+ */
+ public void setJsonRepresentation(JsonObject jsonRepresentation) {
+ this.jsonRepresentation = jsonRepresentation;
+ }
+
+ /**
+ * Regenerate the Policy Json Representation.
+ *
+ * @param toscaConverter The tosca converter required to regenerate the json schema
+ * @param serviceModel The service model associated
+ */
+ public abstract void updateJsonRepresentation(ToscaConverterWithDictionarySupport toscaConverter,
+ Service serviceModel);
+
+ /**
+ * policyModel getter.
+ *
+ * @return the policyModel
+ */
+ public PolicyModel getPolicyModel() {
+ return policyModel;
+ }
+
+ /**
+ * policyModel setter.
+ *
+ * @param policyModel The new policyModel
+ */
+ public void setPolicyModel(PolicyModel policyModel) {
+ this.policyModel = policyModel;
+ }
+
+ /**
+ * configurationsJson getter.
+ *
+ * @return The configurationsJson
+ */
+ public JsonObject getConfigurationsJson() {
+ return configurationsJson;
+ }
+
+ /**
+ * configurationsJson setter.
+ *
+ * @param configurationsJson the configurationsJson to set
+ */
+ public void setConfigurationsJson(JsonObject configurationsJson) {
+ this.configurationsJson = configurationsJson;
+ }
+
+ /**
+ * loopElementModel getter.
+ *
+ * @return the loopElementModel
+ */
+ public LoopElementModel getLoopElementModel() {
+ return loopElementModel;
+ }
+
+ /**
+ * loopElementModel setter.
+ *
+ * @param loopElementModel the loopElementModel to set
+ */
+ public void setLoopElementModel(LoopElementModel loopElementModel) {
+ this.loopElementModel = loopElementModel;
+ }
+
+ /**
+ * pdpGroup getter.
+ *
+ * @return the pdpGroup
+ */
+ public String getPdpGroup() {
+ return pdpGroup;
+ }
+
+ /**
+ * pdpGroup setter.
+ *
+ * @param pdpGroup the pdpGroup to set
+ */
+ public void setPdpGroup(String pdpGroup) {
+ this.pdpGroup = pdpGroup;
+ }
+
+ /**
+ * pdpSubgroup getter.
+ *
+ * @return the pdpSubgroup
+ */
+ public String getPdpSubgroup() {
+ return pdpSubgroup;
+ }
+
+ /**
+ * pdpSubgroup setter.
+ *
+ * @param pdpSubgroup the pdpSubgroup to set
+ */
+ public void setPdpSubgroup(String pdpSubgroup) {
+ this.pdpSubgroup = pdpSubgroup;
+ }
+
+ /**
+ * Generate the policy name.
+ *
+ * @param policyType The policy type
+ * @param serviceName The service name
+ * @param serviceVersion The service version
+ * @param resourceName The resource name
+ * @param blueprintFilename The blueprint file name
+ * @return The generated policy name
+ */
+ public static String generatePolicyName(String policyType, String serviceName, String serviceVersion,
+ String resourceName, String blueprintFilename) {
+ StringBuilder buffer = new StringBuilder(policyType).append("_").append(serviceName).append("_v")
+ .append(serviceVersion).append("_").append(resourceName).append("_")
+ .append(blueprintFilename.replaceAll(".yaml", ""));
+ return buffer.toString().replace('.', '_').replaceAll(" ", "");
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/PolicyEngineServices.java b/runtime/src/main/java/org/onap/policy/clamp/policy/PolicyEngineServices.java
new file mode 100644
index 000000000..4142841e2
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/PolicyEngineServices.java
@@ -0,0 +1,223 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.IOException;
+import java.util.LinkedHashMap;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.ExchangeBuilder;
+import org.onap.policy.clamp.clds.config.ClampProperties;
+import org.onap.policy.clamp.clds.sdc.controller.installer.BlueprintMicroService;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.loop.template.PolicyModelsService;
+import org.onap.policy.models.pdp.concepts.PdpGroups;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.stereotype.Component;
+import org.yaml.snakeyaml.DumperOptions;
+import org.yaml.snakeyaml.Yaml;
+
+
+/**
+ * The class implements the communication with the Policy Engine to retrieve
+ * policy models (tosca). It mainly delegates the physical calls to Camel
+ * engine.
+ * It supports a retry mechanism for these calls, configurations can be specified in the
+ * application.properties "policy.retry.interval"(default 0) and "policy.retry.limit"(default 1).
+ */
+@Component
+public class PolicyEngineServices {
+ private final CamelContext camelContext;
+
+ private final PolicyModelsService policyModelsService;
+
+ private static final String RAISE_EXCEPTION_FLAG = "raiseHttpExceptionFlag";
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(PolicyEngineServices.class);
+ private int retryInterval = 0;
+ private int retryLimit = 1;
+
+ public static final String POLICY_RETRY_INTERVAL = "policy.retry.interval";
+ public static final String POLICY_RETRY_LIMIT = "policy.retry.limit";
+
+ /**
+ * Default constructor.
+ *
+ * @param camelContext Camel context bean
+ * @param clampProperties ClampProperties bean
+ * @param policyModelsService policyModel service
+ */
+ @Autowired
+ public PolicyEngineServices(CamelContext camelContext, ClampProperties clampProperties,
+ PolicyModelsService policyModelsService) {
+ this.camelContext = camelContext;
+ this.policyModelsService = policyModelsService;
+ if (clampProperties.getStringValue(POLICY_RETRY_LIMIT) != null) {
+ retryLimit = Integer.parseInt(clampProperties.getStringValue(POLICY_RETRY_LIMIT));
+ }
+ if (clampProperties.getStringValue(POLICY_RETRY_INTERVAL) != null) {
+ retryInterval = Integer.parseInt(clampProperties.getStringValue(POLICY_RETRY_INTERVAL));
+ }
+ }
+
+ /**
+ * This method query Policy engine and create a PolicyModel object with type and version.
+ * If the policy already exist in the db it returns the existing one.
+ *
+ * @param policyType The policyType id
+ * @param policyVersion The policy version of that type
+ * @return A PolicyModel created from policyEngine data or null if nothing is found on policyEngine
+ */
+ public PolicyModel createPolicyModelFromPolicyEngine(String policyType, String policyVersion) {
+ PolicyModel policyModelFound = policyModelsService.getPolicyModel(policyType, policyVersion);
+ if (policyModelFound == null) {
+ String policyTosca = this.downloadOnePolicyToscaModel(policyType, policyVersion);
+ if (policyTosca != null && !policyTosca.isEmpty()) {
+ return policyModelsService.savePolicyModelInNewTransaction(
+ new PolicyModel(policyType, policyTosca, policyVersion));
+ } else {
+ logger.error("Policy not found in the Policy Engine, returning null: " + policyType
+ + "/" + policyVersion);
+ return null;
+ }
+ } else {
+ logger.info("Skipping policy model download as it exists already in the database " + policyType
+ + "/" + policyVersion);
+ return policyModelFound;
+ }
+ }
+
+ /**
+ * This method query Policy engine and create a PolicyModel object with type and version.
+ *
+ * @param microService microservice object instance
+ * @return A PolicyModel created from policyEngine data
+ */
+ public PolicyModel createPolicyModelFromPolicyEngine(BlueprintMicroService microService) {
+ return createPolicyModelFromPolicyEngine(microService.getModelType(), microService.getModelVersion());
+ }
+
+ /**
+ * This method synchronize the clamp database and the policy engine.
+ * So it creates the required PolicyModel.
+ */
+ public void synchronizeAllPolicies() {
+ LinkedHashMap<String, Object> loadedYaml;
+ loadedYaml = new Yaml().load(downloadAllPolicyModels());
+ if (loadedYaml == null || loadedYaml.isEmpty()) {
+ logger.warn("getAllPolicyType yaml returned by policy engine could not be decoded, as it's null or empty");
+ return;
+ }
+
+ LinkedHashMap<String, Object> policyTypesMap = (LinkedHashMap<String, Object>) loadedYaml.get("policy_types");
+ policyTypesMap.forEach((key, value) ->
+ this.createPolicyModelFromPolicyEngine(key,
+ ((String) ((LinkedHashMap<String, Object>) value).get("version"))));
+ }
+
+ /**
+ * This method can be used to download all policy types + data types defined in
+ * policy engine.
+ *
+ * @return A yaml containing all policy Types and all data types
+ */
+ public String downloadAllPolicyModels() {
+ return callCamelRoute(
+ ExchangeBuilder.anExchange(camelContext).withProperty(RAISE_EXCEPTION_FLAG, true).build(),
+ "direct:get-all-policy-models", "Get all policies models");
+ }
+
+ /**
+ * This method can be used to download a policy tosca model on the engine.
+ *
+ * @param policyType The policy type (id)
+ * @param policyVersion The policy version
+ * @return A string with the whole policy tosca model
+ */
+ public String downloadOnePolicyToscaModel(String policyType, String policyVersion) {
+ logger.info("Downloading the policy tosca model " + policyType + "/" + policyVersion);
+ DumperOptions options = new DumperOptions();
+ options.setDefaultScalarStyle(DumperOptions.ScalarStyle.PLAIN);
+ options.setIndent(4);
+ options.setPrettyFlow(true);
+ options.setDefaultFlowStyle(DumperOptions.FlowStyle.BLOCK);
+ Yaml yamlParser = new Yaml(options);
+ String responseBody = callCamelRoute(
+ ExchangeBuilder.anExchange(camelContext).withProperty("policyModelType", policyType)
+ .withProperty("policyModelVersion", policyVersion).withProperty(RAISE_EXCEPTION_FLAG, false)
+ .build(), "direct:get-policy-tosca-model",
+ "Get one policy");
+
+ if (responseBody == null || responseBody.isEmpty()) {
+ logger.warn("getPolicyToscaModel returned by policy engine could not be decoded, as it's null or empty");
+ return null;
+ }
+
+ return yamlParser.dump(yamlParser.load(responseBody));
+ }
+
+ /**
+ * This method can be used to download all Pdp Groups data from policy engine.
+ */
+ public void downloadPdpGroups() {
+ String responseBody =
+ callCamelRoute(
+ ExchangeBuilder.anExchange(camelContext).withProperty(RAISE_EXCEPTION_FLAG, false).build(),
+ "direct:get-all-pdp-groups", "Get Pdp Groups");
+
+ if (responseBody == null || responseBody.isEmpty()) {
+ logger.warn("getPdpGroups returned by policy engine could not be decoded, as it's null or empty");
+ return;
+ }
+
+ policyModelsService.updatePdpGroupInfo(JsonUtils.GSON.fromJson(responseBody, PdpGroups.class));
+ }
+
+ private String callCamelRoute(Exchange exchange, String camelFlow, String logMsg) {
+ for (int i = 0; i < retryLimit; i++) {
+ try (ProducerTemplate producerTemplate = camelContext.createProducerTemplate()) {
+ Exchange exchangeResponse = producerTemplate.send(camelFlow, exchange);
+ if (HttpStatus.valueOf((Integer) exchangeResponse.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE))
+ .is2xxSuccessful()) {
+ return (String) exchangeResponse.getIn().getBody();
+ } else {
+ logger.info(logMsg + " query " + retryInterval + "ms before retrying ...");
+ // wait for a while and try to connect to DCAE again
+ Thread.sleep(retryInterval);
+
+ }
+ } catch (IOException e) {
+ logger.error("IOException caught when trying to call Camel flow:" + camelFlow, e);
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ }
+ }
+ return "";
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/PolicyPayload.java b/runtime/src/main/java/org/onap/policy/clamp/policy/PolicyPayload.java
new file mode 100644
index 000000000..d2c860150
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/PolicyPayload.java
@@ -0,0 +1,91 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.io.UnsupportedEncodingException;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+import org.json.JSONObject;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * This class is a utility class to create the policy payload.
+ */
+public class PolicyPayload {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(PolicyPayload.class);
+
+ private static JsonObject createJsonFromPolicyTosca(String toscaContent) {
+ Map<String, Object> map =
+ new Yaml().load(!StringUtils.isEmpty(toscaContent) ? toscaContent : "");
+ return JsonUtils.GSON.fromJson(new JSONObject(map).toString(), JsonObject.class);
+ }
+
+ /**
+ * This method create the policy payload that must be sent to PEF.
+ *
+ * @return A String containing the payload
+ * @throws UnsupportedEncodingException In case of failure
+ */
+ public static String createPolicyPayload(String policyModelType, String policyModelVersion, String policyName,
+ String policyVersion, JsonObject policyProperties, String toscaContent)
+ throws UnsupportedEncodingException {
+ JsonObject policyPayloadResult = new JsonObject();
+
+ policyPayloadResult.add("tosca_definitions_version",
+ createJsonFromPolicyTosca(toscaContent).get("tosca_definitions_version"));
+
+ JsonObject topologyTemplateNode = new JsonObject();
+ policyPayloadResult.add("topology_template", topologyTemplateNode);
+
+ JsonArray policiesArray = new JsonArray();
+ topologyTemplateNode.add("policies", policiesArray);
+
+ JsonObject thisPolicy = new JsonObject();
+ policiesArray.add(thisPolicy);
+
+ JsonObject policyDetails = new JsonObject();
+ thisPolicy.add(policyName, policyDetails);
+ policyDetails.addProperty("type", policyModelType);
+ policyDetails.addProperty("type_version", policyModelVersion);
+ policyDetails.addProperty("version", policyVersion);
+ policyDetails.addProperty("name", policyName);
+
+ JsonObject policyMetadata = new JsonObject();
+ policyDetails.add("metadata", policyMetadata);
+ policyMetadata.addProperty("policy-id", policyName);
+ policyMetadata.addProperty("policy-version", policyVersion);
+
+ policyDetails.add("properties", policyProperties);
+
+ String policyPayload = JsonUtils.GSON.toJson(policyPayloadResult);
+ logger.info("Policy payload: " + policyPayload);
+ return policyPayload;
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/PolicyService.java b/runtime/src/main/java/org/onap/policy/clamp/policy/PolicyService.java
new file mode 100644
index 000000000..35ffa2443
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/PolicyService.java
@@ -0,0 +1,35 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy;
+
+import java.util.List;
+import java.util.Set;
+import org.onap.policy.clamp.loop.Loop;
+
+public interface PolicyService<T extends Policy> {
+
+ Set<T> updatePolicies(Loop loop, List<T> newPolicies);
+
+ boolean isExisting(String policyName);
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/downloader/PolicyEngineController.java b/runtime/src/main/java/org/onap/policy/clamp/policy/downloader/PolicyEngineController.java
new file mode 100644
index 000000000..81775e5da
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/downloader/PolicyEngineController.java
@@ -0,0 +1,76 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.downloader;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.time.Instant;
+import org.json.simple.parser.ParseException;
+import org.onap.policy.clamp.loop.template.PolicyModelsRepository;
+import org.onap.policy.clamp.policy.PolicyEngineServices;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.scheduling.annotation.Scheduled;
+
+/**
+ * This class implements a periodic job that is done in the background to
+ * synchronize policy models available on the policy engine and the clamp
+ * database table PolicyModel.
+ */
+@Configuration
+@Profile("clamp-policy-controller")
+public class PolicyEngineController {
+
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(PolicyEngineController.class);
+ protected static final EELFLogger auditLogger = EELFManager.getInstance().getAuditLogger();
+ protected static final EELFLogger metricsLogger = EELFManager.getInstance().getMetricsLogger();
+ public static final String POLICY_RETRY_INTERVAL = "policy.retry.interval";
+ public static final String POLICY_RETRY_LIMIT = "policy.retry.limit";
+
+ private final PolicyEngineServices policyEngineServices;
+
+ private Instant lastInstantExecuted;
+
+ @Autowired
+ public PolicyEngineController(PolicyEngineServices policyEngineService,
+ PolicyModelsRepository policyModelsRepository) {
+ this.policyEngineServices = policyEngineService;
+ }
+
+ @Scheduled(fixedRate = 300000)
+ public synchronized void synchronizeAllPolicies() {
+ policyEngineServices.synchronizeAllPolicies();
+ lastInstantExecuted = Instant.now();
+ }
+
+ public Instant getLastInstantExecuted() {
+ return lastInstantExecuted;
+ }
+
+ @Scheduled(fixedRate = 300000)
+ public synchronized void downloadPdpGroups() throws ParseException {
+ policyEngineServices.downloadPdpGroups();
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/microservice/MicroServicePolicy.java b/runtime/src/main/java/org/onap/policy/clamp/policy/microservice/MicroServicePolicy.java
new file mode 100644
index 000000000..be5e7917c
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/microservice/MicroServicePolicy.java
@@ -0,0 +1,276 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.microservice;
+
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.security.SecureRandom;
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
+import org.onap.policy.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.policy.clamp.dao.model.jsontype.StringJsonUserType;
+import org.onap.policy.clamp.loop.Loop;
+import org.onap.policy.clamp.loop.service.Service;
+import org.onap.policy.clamp.loop.template.LoopElementModel;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.policy.Policy;
+
+@Entity
+@Table(name = "micro_service_policies")
+@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)})
+public class MicroServicePolicy extends Policy implements Serializable {
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 6271238288583332616L;
+
+ @Expose
+ @Id
+ @Column(nullable = false, name = "name", unique = true)
+ private String name;
+
+ @Expose
+ @Column(name = "context")
+ private String context;
+
+ @Expose
+ @Column(name = "device_type_scope")
+ private String deviceTypeScope;
+
+ @Expose
+ @Column(name = "shared", nullable = false)
+ private Boolean shared;
+
+ @ManyToMany(mappedBy = "microServicePolicies", fetch = FetchType.EAGER)
+ private Set<Loop> usedByLoops = new HashSet<>();
+
+ @Expose
+ @Column(name = "dcae_deployment_id")
+ private String dcaeDeploymentId;
+
+ @Expose
+ @Column(name = "dcae_deployment_status_url")
+ private String dcaeDeploymentStatusUrl;
+
+ @Expose
+ @Column(name = "dcae_blueprint_id")
+ private String dcaeBlueprintId;
+
+ /**
+ * Constructor for serialization.
+ */
+ public MicroServicePolicy() {
+ }
+
+ /**
+ * The constructor that does not make use of ToscaYamlToJsonConvertor but take
+ * the jsonRepresentation instead.
+ *
+ * @param name The name of the MicroService
+ * @param policyModel The policy model type of the MicroService
+ * @param shared The flag indicate whether the MicroService is
+ * shared
+ * @param jsonRepresentation The UI representation in json format
+ * @param loopElementModel The loop element model from which this instance should be created
+ * @param pdpGroup The Pdp Group info
+ * @param pdpSubgroup The Pdp Subgroup info
+ */
+ public MicroServicePolicy(String name, PolicyModel policyModel, Boolean shared,
+ JsonObject jsonRepresentation, LoopElementModel loopElementModel, String pdpGroup,
+ String pdpSubgroup) {
+ this.name = name;
+ this.setPolicyModel(policyModel);
+ this.shared = shared;
+ this.setJsonRepresentation(jsonRepresentation);
+ this.setLoopElementModel(loopElementModel);
+ this.setPdpGroup(pdpGroup);
+ this.setPdpSubgroup(pdpSubgroup);
+ }
+
+ /**
+ * Constructor with tosca converter.
+ *
+ * @param loop The loop instance
+ * @param service The service model object
+ * @param loopElementModel The loop element model from which this microservice instance is created
+ * @param toscaConverter The tosca converter that will used to convert the tosca policy model
+ */
+ public MicroServicePolicy(Loop loop, Service service, LoopElementModel loopElementModel,
+ ToscaConverterWithDictionarySupport toscaConverter) {
+ this(Policy.generatePolicyName("MICROSERVICE", service.getName(), service.getVersion(),
+ loopElementModel.getPolicyModels().first().getPolicyAcronym() + '_'
+ + loopElementModel.getPolicyModels().first().getVersion(),
+ RandomStringUtils.random(3, 0, 0, true, true, null, new SecureRandom())),
+ loopElementModel.getPolicyModels().first(), false, new JsonObject(), loopElementModel, null, null);
+ this.updateJsonRepresentation(toscaConverter, service);
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * name setter.
+ *
+ * @param name the name to set
+ */
+ @Override
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void updateJsonRepresentation(ToscaConverterWithDictionarySupport toscaConverter, Service serviceModel) {
+ this.setJsonRepresentation(
+ toscaConverter.convertToscaToJsonSchemaObject(this.getPolicyModel().getPolicyModelTosca(),
+ this.getPolicyModel().getPolicyModelType(), serviceModel));
+ }
+
+ public Boolean getShared() {
+ return shared;
+ }
+
+ void setShared(Boolean shared) {
+ this.shared = shared;
+ }
+
+ public Set<Loop> getUsedByLoops() {
+ return usedByLoops;
+ }
+
+ void setUsedByLoops(Set<Loop> usedBy) {
+ this.usedByLoops = usedBy;
+ }
+
+ public String getContext() {
+ return context;
+ }
+
+ public void setContext(String context) {
+ this.context = context;
+ }
+
+ public String getDeviceTypeScope() {
+ return deviceTypeScope;
+ }
+
+ public void setDeviceTypeScope(String deviceTypeScope) {
+ this.deviceTypeScope = deviceTypeScope;
+ }
+
+ /**
+ * dcaeDeploymentId getter.
+ *
+ * @return the dcaeDeploymentId
+ */
+ public String getDcaeDeploymentId() {
+ return dcaeDeploymentId;
+ }
+
+ /**
+ * dcaeDeploymentId setter.
+ *
+ * @param dcaeDeploymentId the dcaeDeploymentId to set
+ */
+ public void setDcaeDeploymentId(String dcaeDeploymentId) {
+ this.dcaeDeploymentId = dcaeDeploymentId;
+ }
+
+ /**
+ * dcaeDeploymentStatusUrl getter.
+ *
+ * @return the dcaeDeploymentStatusUrl
+ */
+ public String getDcaeDeploymentStatusUrl() {
+ return dcaeDeploymentStatusUrl;
+ }
+
+ /**
+ * dcaeDeploymentStatusUrl setter.
+ *
+ * @param dcaeDeploymentStatusUrl the dcaeDeploymentStatusUrl to set
+ */
+ public void setDcaeDeploymentStatusUrl(String dcaeDeploymentStatusUrl) {
+ this.dcaeDeploymentStatusUrl = dcaeDeploymentStatusUrl;
+ }
+
+ /**
+ * dcaeBlueprintId getter.
+ *
+ * @return the dcaeBlueprintId
+ */
+ public String getDcaeBlueprintId() {
+ return dcaeBlueprintId;
+ }
+
+ /**
+ * dcaeBlueprintId setter.
+ *
+ * @param dcaeBlueprintId the dcaeBlueprintId to set
+ */
+ void setDcaeBlueprintId(String dcaeBlueprintId) {
+ this.dcaeBlueprintId = dcaeBlueprintId;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ MicroServicePolicy other = (MicroServicePolicy) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/microservice/MicroServicePolicyRepository.java b/runtime/src/main/java/org/onap/policy/clamp/policy/microservice/MicroServicePolicyRepository.java
new file mode 100644
index 000000000..2ce2c4f17
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/microservice/MicroServicePolicyRepository.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.microservice;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface MicroServicePolicyRepository extends JpaRepository<MicroServicePolicy, String> {
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/microservice/MicroServicePolicyService.java b/runtime/src/main/java/org/onap/policy/clamp/policy/microservice/MicroServicePolicyService.java
new file mode 100644
index 000000000..b9871049e
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/microservice/MicroServicePolicyService.java
@@ -0,0 +1,112 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.microservice;
+
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.onap.policy.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.policy.clamp.loop.Loop;
+import org.onap.policy.clamp.policy.PolicyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class MicroServicePolicyService implements PolicyService<MicroServicePolicy> {
+
+ private final MicroServicePolicyRepository microServiceRepository;
+
+ @Autowired
+ public MicroServicePolicyService(MicroServicePolicyRepository microServiceRepository) {
+ this.microServiceRepository = microServiceRepository;
+ }
+
+ @Override
+ public Set<MicroServicePolicy> updatePolicies(Loop loop, List<MicroServicePolicy> newMicroservicePolicies) {
+ return newMicroservicePolicies.stream().map(policy -> getAndUpdateMicroServicePolicy(loop, policy))
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public boolean isExisting(String policyName) {
+ return microServiceRepository.existsById(policyName);
+ }
+
+ /**
+ * Get and update the MicroService policy properties.
+ *
+ * @param loop The loop
+ * @param policy The new MicroService policy
+ * @return The updated MicroService policy
+ */
+ public MicroServicePolicy getAndUpdateMicroServicePolicy(Loop loop, MicroServicePolicy policy) {
+ return microServiceRepository.save(
+ microServiceRepository
+ .findById(policy.getName()).map(p -> updateMicroservicePolicyProperties(p, policy, loop))
+ .orElse(new MicroServicePolicy(policy.getName(), policy.getPolicyModel(),
+ policy.getShared(), policy.getJsonRepresentation(), null, policy.getPdpGroup(),
+ policy.getPdpSubgroup())));
+ }
+
+ private MicroServicePolicy updateMicroservicePolicyProperties(MicroServicePolicy oldPolicy,
+ MicroServicePolicy newPolicy, Loop loop) {
+ oldPolicy.setConfigurationsJson(newPolicy.getConfigurationsJson());
+ if (!oldPolicy.getUsedByLoops().contains(loop)) {
+ oldPolicy.getUsedByLoops().add(loop);
+ }
+ oldPolicy.setPdpGroup(newPolicy.getPdpGroup());
+ oldPolicy.setPdpSubgroup(newPolicy.getPdpSubgroup());
+ return oldPolicy;
+ }
+
+ /**
+ * Update the MicroService policy deployment related parameters.
+ *
+ * @param microServicePolicy The micro service policy
+ * @param deploymentId The deployment ID as returned by DCAE
+ * @param deploymentUrl The Deployment URL as returned by DCAE
+ */
+ public void updateDcaeDeploymentFields(MicroServicePolicy microServicePolicy, String deploymentId,
+ String deploymentUrl) {
+ microServicePolicy.setDcaeDeploymentId(deploymentId);
+ microServicePolicy.setDcaeDeploymentStatusUrl(deploymentUrl);
+ microServiceRepository.saveAndFlush(microServicePolicy);
+ }
+
+
+ /**
+ * Api to refresh the MicroService Policy UI window.
+ *
+ * @param microServicePolicy The micro Service policy object
+ * @param toscaConverter The tosca converter required to convert the tosca model to json schema
+ * @param loop As a microservice object can belong to multiple loops, we need it here
+ */
+ public void refreshMicroServicePolicyJsonRepresentation(MicroServicePolicy microServicePolicy,
+ ToscaConverterWithDictionarySupport toscaConverter,
+ Loop loop) {
+ microServicePolicy.updateJsonRepresentation(toscaConverter, loop.getModelService());
+ this.microServiceRepository.saveAndFlush(microServicePolicy);
+
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicy.java b/runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicy.java
new file mode 100644
index 000000000..1646a7cc7
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicy.java
@@ -0,0 +1,219 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.operational;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonObject;
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.io.UnsupportedEncodingException;
+import java.security.SecureRandom;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.hibernate.annotations.TypeDef;
+import org.hibernate.annotations.TypeDefs;
+import org.onap.policy.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.policy.clamp.dao.model.jsontype.StringJsonUserType;
+import org.onap.policy.clamp.loop.Loop;
+import org.onap.policy.clamp.loop.service.Service;
+import org.onap.policy.clamp.loop.template.LoopElementModel;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.policy.Policy;
+
+@Entity
+@Table(name = "operational_policies")
+@TypeDefs({@TypeDef(name = "json", typeClass = StringJsonUserType.class)})
+public class OperationalPolicy extends Policy implements Serializable {
+ /**
+ * The serial version ID.
+ */
+ private static final long serialVersionUID = 6117076450841538255L;
+
+ @Transient
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(OperationalPolicy.class);
+
+ @Id
+ @Expose
+ @Column(nullable = false, name = "name", unique = true)
+ private String name;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "loop_id", nullable = false)
+ private Loop loop;
+
+ /**
+ * Constructor for serialization.
+ */
+ public OperationalPolicy() {
+ }
+
+ /**
+ * The constructor.
+ *
+ * @param name The name of the operational policy
+ * @param configurationsJson The operational policy property in the format of
+ * json
+ * @param jsonRepresentation The jsonObject defining the json schema
+ * @param policyModel The policy model associated if any, can be null
+ * @param loopElementModel The loop element from which this instance is supposed to be created
+ * @param pdpGroup The Pdp Group info
+ * @param pdpSubgroup The Pdp Subgroup info
+ */
+ public OperationalPolicy(String name, JsonObject configurationsJson,
+ JsonObject jsonRepresentation, PolicyModel policyModel,
+ LoopElementModel loopElementModel, String pdpGroup, String pdpSubgroup) {
+ this.name = name;
+ this.setPolicyModel(policyModel);
+ this.setConfigurationsJson(configurationsJson);
+ this.setPdpGroup(pdpGroup);
+ this.setPdpSubgroup(pdpSubgroup);
+ this.setLoopElementModel(loopElementModel);
+ this.setJsonRepresentation(jsonRepresentation);
+
+ }
+
+ /**
+ * Create an operational policy from a loop element model.
+ *
+ * @param loop The parent loop
+ * @param service The loop service
+ * @param loopElementModel The loop element model
+ * @param toscaConverter The tosca converter that must be used to create the Json representation
+ */
+ public OperationalPolicy(Loop loop, Service service, LoopElementModel loopElementModel,
+ ToscaConverterWithDictionarySupport toscaConverter) {
+ this(Policy.generatePolicyName("OPERATIONAL", service.getName(), service.getVersion(),
+ loopElementModel.getPolicyModels().first().getPolicyAcronym() + '_'
+ + loopElementModel.getPolicyModels().first().getVersion(),
+ RandomStringUtils.random(3, 0, 0, true, true, null, new SecureRandom())), new JsonObject(),
+ new JsonObject(), loopElementModel.getPolicyModels().first(), loopElementModel, null, null);
+ this.setLoop(loop);
+ this.updateJsonRepresentation(toscaConverter, service);
+ }
+
+ /**
+ * Create an operational policy from a policy model.
+ *
+ * @param loop The parent loop
+ * @param service The loop service
+ * @param policyModel The policy model
+ * @param toscaConverter The tosca converter that must be used to create the Json representation
+ */
+ public OperationalPolicy(Loop loop, Service service, PolicyModel policyModel,
+ ToscaConverterWithDictionarySupport toscaConverter) {
+ this(Policy.generatePolicyName("OPERATIONAL", service.getName(), service.getVersion(),
+ policyModel.getPolicyAcronym() + '_' + policyModel.getVersion(),
+ RandomStringUtils.random(3, 0, 0, true, true, null, new SecureRandom())),
+ new JsonObject(),
+ new JsonObject(), policyModel, null, null, null);
+ this.setLoop(loop);
+ this.updateJsonRepresentation(toscaConverter, service);
+ }
+
+ public void setLoop(Loop loopName) {
+ this.loop = loopName;
+ }
+
+ public Loop getLoop() {
+ return loop;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * name setter.
+ *
+ * @param name the name to set
+ */
+ @Override
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void updateJsonRepresentation(ToscaConverterWithDictionarySupport toscaConverter, Service serviceModel) {
+ {
+ this.setJsonRepresentation(new JsonObject());
+ if (this.getPolicyModel() == null) {
+ return;
+ }
+
+ // Generic Case
+ this.setJsonRepresentation(toscaConverter.convertToscaToJsonSchemaObject(
+ this.getPolicyModel().getPolicyModelTosca(),
+ this.getPolicyModel().getPolicyModelType(), serviceModel));
+
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ OperationalPolicy other = (OperationalPolicy) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else {
+ if (!name.equals(other.name)) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public String createPolicyPayload() throws UnsupportedEncodingException {
+ return super.createPolicyPayload();
+
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicyRepository.java b/runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicyRepository.java
new file mode 100644
index 000000000..b0a33669a
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicyRepository.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.operational;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface OperationalPolicyRepository extends JpaRepository<OperationalPolicy, String> {
+ void deleteByName(String policyName);
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java b/runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java
new file mode 100644
index 000000000..6718475ca
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicyRepresentationBuilder.java
@@ -0,0 +1,348 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.operational;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.loop.service.Service;
+
+public class OperationalPolicyRepresentationBuilder {
+
+ private static final EELFLogger logger =
+ EELFManager.getInstance().getLogger(OperationalPolicyRepresentationBuilder.class);
+
+ public static final String PROPERTIES = "properties";
+ public static final String ITEMS = "items";
+ public static final String ANY_OF = "anyOf";
+ public static final String TITLE = "title";
+ public static final String RECIPE = "recipe";
+ public static final String DEFAULT = "default";
+ public static final String STRING = "string";
+ public static final String TYPE = "type";
+ public static final String TYPE_LIST = "list";
+ public static final String TYPE_OBJECT = "object";
+ public static final String TYPE_ARRAY = "array";
+
+ private OperationalPolicyRepresentationBuilder() {
+ throw new IllegalStateException("This is Utility class, not supposed to be initiated.");
+ }
+
+ /**
+ * This method generates the operational policy json representation that will be
+ * used by ui for rendering. It uses the model (VF and VFModule) defined in the
+ * loop object to do so, so it's dynamic. It also uses the operational policy
+ * schema template defined in the resource folder.
+ *
+ * @param modelJson The loop model json
+ * @return The json representation
+ */
+ public static JsonObject generateOperationalPolicySchema(Service modelJson) {
+
+ JsonObject jsonSchema = null;
+ try {
+ jsonSchema = JsonUtils.GSON.fromJson(
+ ResourceFileUtils
+ .getResourceAsString("clds/json-schema/operational_policies/operational_policy.json"),
+ JsonObject.class);
+ jsonSchema.get(PROPERTIES).getAsJsonObject()
+ .get("operational_policy").getAsJsonObject().get(PROPERTIES).getAsJsonObject().get("policies")
+ .getAsJsonObject().get(ITEMS).getAsJsonObject().get(PROPERTIES).getAsJsonObject().get("target")
+ .getAsJsonObject().get(ANY_OF).getAsJsonArray().addAll(createAnyOfArray(modelJson, true));
+
+ // update CDS recipe and payload information to schema
+ for (JsonElement actor : jsonSchema.get(PROPERTIES).getAsJsonObject()
+ .get("operational_policy").getAsJsonObject().get(PROPERTIES).getAsJsonObject().get("policies")
+ .getAsJsonObject().get(ITEMS).getAsJsonObject().get(PROPERTIES).getAsJsonObject().get("actor")
+ .getAsJsonObject().get(ANY_OF).getAsJsonArray()) {
+ if ("CDS".equalsIgnoreCase(actor.getAsJsonObject().get(TITLE).getAsString())) {
+ actor.getAsJsonObject().get(PROPERTIES).getAsJsonObject().get(RECIPE).getAsJsonObject()
+ .get(ANY_OF).getAsJsonArray()
+ .addAll(createAnyOfArrayForCdsRecipe(modelJson));
+ }
+ }
+ return jsonSchema;
+ } catch (IOException e) {
+ logger.error("Unable to generate the json schema because of an exception", e);
+ return new JsonObject();
+ }
+ }
+
+ private static JsonObject createSchemaProperty(String title, String type, String defaultValue, String readOnlyFlag,
+ String[] enumArray) {
+ JsonObject property = new JsonObject();
+ property.addProperty(TITLE, title);
+ property.addProperty(TYPE, type);
+ property.addProperty(DEFAULT, defaultValue);
+ property.addProperty("readOnly", readOnlyFlag);
+
+ if (enumArray != null) {
+ JsonArray jsonArray = new JsonArray();
+ property.add("enum", jsonArray);
+ for (String val : enumArray) {
+ jsonArray.add(val);
+ }
+ }
+ return property;
+ }
+
+ private static JsonArray createVnfSchema(Service modelService, boolean generateType) {
+ JsonArray vnfSchemaArray = new JsonArray();
+ JsonObject modelVnfs = modelService.getResourceByType("VF");
+
+ for (Entry<String, JsonElement> entry : modelVnfs.entrySet()) {
+ JsonObject vnfOneOfSchema = new JsonObject();
+ vnfOneOfSchema.addProperty(TITLE, "VNF" + "-" + entry.getKey());
+ JsonObject properties = new JsonObject();
+ if (generateType) {
+ properties.add(TYPE, createSchemaProperty("Type", STRING, "VNF", "True", null));
+ }
+ properties.add("resourceID", createSchemaProperty("Resource ID", STRING,
+ modelVnfs.get(entry.getKey()).getAsJsonObject().get("invariantUUID").getAsString(), "True", null));
+
+ vnfOneOfSchema.add(PROPERTIES, properties);
+ vnfSchemaArray.add(vnfOneOfSchema);
+ }
+ return vnfSchemaArray;
+ }
+
+ private static JsonArray createBlankEntry() {
+ JsonArray result = new JsonArray();
+ JsonObject blankObject = new JsonObject();
+ blankObject.addProperty(TITLE, "User defined");
+ blankObject.add(PROPERTIES, new JsonObject());
+ result.add(blankObject);
+ return result;
+ }
+
+ private static JsonArray createVfModuleSchema(Service modelService, boolean generateType) {
+ JsonArray vfModuleOneOfSchemaArray = new JsonArray();
+ JsonObject modelVfModules = modelService.getResourceByType("VFModule");
+
+ for (Entry<String, JsonElement> entry : modelVfModules.entrySet()) {
+ JsonObject vfModuleOneOfSchema = new JsonObject();
+ vfModuleOneOfSchema.addProperty(TITLE, "VFMODULE" + "-" + entry.getKey());
+ JsonObject properties = new JsonObject();
+ if (generateType) {
+ properties.add(TYPE, createSchemaProperty("Type", STRING, "VFMODULE", "True", null));
+ }
+ properties.add("resourceID",
+ createSchemaProperty("Resource ID", STRING,
+ modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelName").getAsString(),
+ "True", null));
+ properties.add("modelInvariantId",
+ createSchemaProperty("Model Invariant Id (ModelInvariantUUID)", STRING,
+ modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelInvariantUUID")
+ .getAsString(),
+ "True", null));
+ properties.add("modelVersionId",
+ createSchemaProperty("Model Version Id (ModelUUID)", STRING,
+ modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelUUID").getAsString(),
+ "True", null));
+ properties.add("modelName",
+ createSchemaProperty("Model Name", STRING,
+ modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelName").getAsString(),
+ "True", null));
+ properties.add("modelVersion", createSchemaProperty("Model Version", STRING,
+ modelVfModules.get(entry.getKey()).getAsJsonObject().get("vfModuleModelVersion").getAsString(),
+ "True", null));
+ properties
+ .add("modelCustomizationId",
+ createSchemaProperty("Customization ID", STRING,
+ modelVfModules.get(entry.getKey()).getAsJsonObject()
+ .get("vfModuleModelCustomizationUUID").getAsString(), "True",
+ null));
+
+ vfModuleOneOfSchema.add(PROPERTIES, properties);
+ vfModuleOneOfSchemaArray.add(vfModuleOneOfSchema);
+ }
+ return vfModuleOneOfSchemaArray;
+ }
+
+ /**
+ * Create an anyOf array of possible structure we may have for Target.
+ *
+ * @param modelJson The service object
+ * @return A JsonArray with everything inside
+ */
+ public static JsonArray createAnyOfArray(Service modelJson, boolean generateType) {
+ JsonArray targetOneOfStructure = new JsonArray();
+ // First entry must be user defined
+ targetOneOfStructure.addAll(createBlankEntry());
+ targetOneOfStructure.addAll(createVnfSchema(modelJson, generateType));
+ targetOneOfStructure.addAll(createVfModuleSchema(modelJson, generateType));
+ return targetOneOfStructure;
+ }
+
+ private static JsonArray createAnyOfArrayForCdsRecipe(Service modelJson) {
+ JsonArray anyOfStructure = new JsonArray();
+ anyOfStructure.addAll(createAnyOfCdsRecipe(modelJson.getResourceDetails().getAsJsonObject("VF")));
+ anyOfStructure.addAll(createAnyOfCdsRecipe(modelJson.getResourceDetails().getAsJsonObject("PNF")));
+ return anyOfStructure;
+ }
+
+ private static JsonArray createAnyOfCdsRecipe(JsonObject jsonObject) {
+ JsonArray schemaArray = new JsonArray();
+ for (Entry<String, JsonElement> entry : jsonObject.entrySet()) {
+ JsonObject controllerProperties = entry.getValue().getAsJsonObject()
+ .getAsJsonObject("controllerProperties");
+
+ if (controllerProperties != null && controllerProperties.getAsJsonObject("workflows") != null) {
+ JsonObject workflows = controllerProperties.getAsJsonObject("workflows");
+ for (Entry<String, JsonElement> workflowsEntry : workflows.entrySet()) {
+ JsonObject obj = new JsonObject();
+ obj.addProperty(TITLE, workflowsEntry.getKey());
+ obj.addProperty(TYPE, TYPE_OBJECT);
+ obj.add(PROPERTIES, createPayloadProperty(workflowsEntry.getValue().getAsJsonObject(),
+ controllerProperties, workflowsEntry.getKey()));
+ schemaArray.add(obj);
+ }
+
+ }
+ }
+ return schemaArray;
+ }
+
+ private static JsonObject createPayloadProperty(JsonObject workFlow,
+ JsonObject controllerProperties, String workFlowName) {
+ JsonObject payload = new JsonObject();
+ payload.addProperty(TITLE, "Payload");
+ payload.addProperty(TYPE, TYPE_OBJECT);
+ payload.add(PROPERTIES, createInputPropertiesForPayload(workFlow, controllerProperties,
+ workFlowName));
+ JsonObject properties = new JsonObject();
+ properties.add(RECIPE, createRecipeForCdsWorkflow(workFlowName));
+ properties.add("payload", payload);
+ return properties;
+ }
+
+ private static JsonObject createRecipeForCdsWorkflow(String workflow) {
+ JsonObject recipe = new JsonObject();
+ recipe.addProperty(TITLE, RECIPE);
+ recipe.addProperty(TYPE, STRING);
+ recipe.addProperty(DEFAULT, workflow);
+ JsonObject options = new JsonObject();
+ options.addProperty("hidden", true);
+ recipe.add("options", options);
+ return recipe;
+ }
+
+ /**
+ * Returns the properties of payload based on the cds work flows.
+ *
+ * @param workFlow cds work flows to update payload
+ * @param controllerProperties cds properties to get blueprint name and
+ * version
+ * @param workFlowName work flow name
+ * @return returns the properties of payload
+ */
+ public static JsonObject createInputPropertiesForPayload(JsonObject workFlow,
+ JsonObject controllerProperties,
+ String workFlowName) {
+ String artifactName = controllerProperties.get("sdnc_model_name").getAsString();
+ String artifactVersion = controllerProperties.get("sdnc_model_version").getAsString();
+ JsonObject inputs = workFlow.getAsJsonObject("inputs");
+ JsonObject jsonObject = new JsonObject();
+ jsonObject.add("artifact_name", createSchemaProperty(
+ "artifact name", STRING, artifactName, "True", null));
+ jsonObject.add("artifact_version", createSchemaProperty(
+ "artifact version", STRING, artifactVersion, "True", null));
+ jsonObject.add("mode", createCdsInputProperty(
+ "mode", STRING, "async", null));
+ jsonObject.add("data", createDataProperty(inputs, workFlowName));
+ return jsonObject;
+ }
+
+ private static JsonObject createDataProperty(JsonObject inputs, String workflowName) {
+ JsonObject data = new JsonObject();
+ data.addProperty(TITLE, "data");
+ JsonObject dataObj = new JsonObject();
+ addDataFields(inputs, dataObj, workflowName);
+ data.add(PROPERTIES, dataObj);
+ return data;
+ }
+
+ private static void addDataFields(JsonObject inputs,
+ JsonObject dataObj,
+ String workFlowName) {
+ Set<Map.Entry<String, JsonElement>> entrySet = inputs.entrySet();
+ for (Map.Entry<String, JsonElement> entry : entrySet) {
+ String key = entry.getKey();
+ JsonObject inputProperty = inputs.getAsJsonObject(key);
+ if (key.equalsIgnoreCase(workFlowName + "-properties")) {
+ addDataFields(entry.getValue().getAsJsonObject().get(PROPERTIES).getAsJsonObject(),
+ dataObj, workFlowName);
+ } else {
+ dataObj.add(entry.getKey(),
+ createCdsInputProperty(key, inputProperty.get(TYPE).getAsString(), null,
+ entry.getValue().getAsJsonObject()));
+ }
+ }
+ }
+
+ private static JsonObject createCdsInputProperty(String title,
+ String type,
+ String defaultValue,
+ JsonObject cdsProperty) {
+ JsonObject property = new JsonObject();
+ property.addProperty(TITLE, title);
+
+ if (TYPE_LIST.equalsIgnoreCase(type)) {
+ property.addProperty(TYPE, TYPE_ARRAY);
+ if (cdsProperty != null && cdsProperty.get(PROPERTIES) != null) {
+ JsonObject listProperties = new JsonObject();
+ listProperties.add(PROPERTIES, getProperties(cdsProperty.get(PROPERTIES).getAsJsonObject()));
+ property.add(ITEMS, listProperties);
+ }
+ } else if (cdsProperty != null && TYPE_OBJECT.equalsIgnoreCase(type)) {
+ property.addProperty(TYPE, TYPE_OBJECT);
+ property.add(PROPERTIES, getProperties(cdsProperty.get(PROPERTIES).getAsJsonObject()));
+ } else {
+ property.addProperty(TYPE, type);
+ }
+
+ if (defaultValue != null) {
+ property.addProperty(DEFAULT, defaultValue);
+ }
+ return property;
+ }
+
+ private static JsonObject getProperties(JsonObject inputProperties) {
+ if (inputProperties == null) {
+ return null;
+ }
+ JsonObject dataObject = new JsonObject();
+ addDataFields(inputProperties, dataObject, null);
+ return dataObject;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicyService.java b/runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicyService.java
new file mode 100644
index 000000000..3f3f39b45
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/operational/OperationalPolicyService.java
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.operational;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.onap.policy.clamp.clds.tosca.update.ToscaConverterWithDictionarySupport;
+import org.onap.policy.clamp.loop.Loop;
+import org.onap.policy.clamp.loop.template.PolicyModelsRepository;
+import org.onap.policy.clamp.policy.PolicyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class OperationalPolicyService implements PolicyService<OperationalPolicy> {
+
+ private final OperationalPolicyRepository operationalPolicyRepository;
+
+ private final PolicyModelsRepository policyModelsRepository;
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(OperationalPolicyService.class);
+
+ @Autowired
+ public OperationalPolicyService(OperationalPolicyRepository repository,
+ PolicyModelsRepository policyModelsRepository) {
+ this.operationalPolicyRepository = repository;
+ this.policyModelsRepository = policyModelsRepository;
+ }
+
+ @Override
+ public Set<OperationalPolicy> updatePolicies(Loop loop, List<OperationalPolicy> operationalPolicies) {
+ return operationalPolicies
+ .parallelStream()
+ .map(policy ->
+ operationalPolicyRepository
+ .findById(policy.getName())
+ .map(p -> setConfiguration(p, policy))
+ .orElse(initializeMissingFields(loop, policy)))
+ .collect(Collectors.toSet());
+ }
+
+ @Override
+ public boolean isExisting(String policyName) {
+ return operationalPolicyRepository.existsById(policyName);
+ }
+
+ private OperationalPolicy initializeMissingFields(Loop loop, OperationalPolicy policy) {
+ policy.setLoop(loop);
+ return policy;
+ }
+
+ private OperationalPolicy setConfiguration(OperationalPolicy policy, OperationalPolicy newPolicy) {
+ policy.setConfigurationsJson(newPolicy.getConfigurationsJson());
+ policy.setPdpGroup(newPolicy.getPdpGroup());
+ policy.setPdpSubgroup(newPolicy.getPdpSubgroup());
+ return policy;
+ }
+
+ /**
+ * Api to refresh the Operational Policy UI window.
+ *
+ * @param operationalPolicy The operational policy object
+ * @param toscaConverter the tosca converter required to convert the tosca model to json schema
+ */
+ public void refreshOperationalPolicyJsonRepresentation(OperationalPolicy operationalPolicy,
+ ToscaConverterWithDictionarySupport toscaConverter) {
+ operationalPolicy.updateJsonRepresentation(toscaConverter, operationalPolicy.getLoop().getModelService());
+ this.operationalPolicyRepository.saveAndFlush(operationalPolicy);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayload.java b/runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayload.java
new file mode 100644
index 000000000..c6b44076f
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayload.java
@@ -0,0 +1,141 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.pdpgroup;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.google.gson.JsonElement;
+import java.util.ArrayList;
+import java.util.Arrays;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.models.pdp.concepts.DeploymentGroup;
+import org.onap.policy.models.pdp.concepts.DeploymentGroups;
+import org.onap.policy.models.pdp.concepts.DeploymentSubGroup;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+/**
+ * This is an utility class that build the PDP group policy payload.
+ * This is used when policies have to be deployed to PDP group/subgroups on the Policy Engine.
+ * Currently it does not group the queries per pdpgroup/subgroups/action.
+ * This is currently NOT thread safe, do not use parallel streams to update the structure.
+ */
+public class PdpGroupPayload {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(PdpGroupPayload.class);
+
+ /**
+ * The default node that will contain the actions array.
+ */
+ public static final String PDP_ACTIONS = "PdpActions";
+
+ private final DeploymentGroups deploymentGroups = new DeploymentGroups();
+
+ /**
+ * Default constructor.
+ */
+ public PdpGroupPayload() {
+ deploymentGroups.setGroups(new ArrayList<>());
+ }
+
+ /**
+ * Constructor that takes a list of actions in input.
+ *
+ * @param listOfPdpActions The list of actions that needs to be done.
+ * e.g: {"Pdpactions":["DELETE/PdpGroup1/PdpSubGroup1/PolicyName1/1.0.0",....]}
+ * @throws PdpGroupPayloadException in case of issues to read the listOfActions
+ */
+ public PdpGroupPayload(final JsonElement listOfPdpActions) throws PdpGroupPayloadException {
+ this();
+ this.readListOfActions(listOfPdpActions);
+ }
+
+ /**
+ * This method converts the list of actions directly to the pdp payload query as String.
+ *
+ * @param listOfPdpActions The list of actions that needs to be done.
+ * e.g: {"Pdpactions":["DELETE/PdpGroup1/PdpSubGroup1/PolicyName1/1.0.0",....]}
+ * @return The string containing the PDP payload that can be sent directly
+ * @throws PdpGroupPayloadException in case of issues to read the listOfActions
+ */
+ public static String generatePdpGroupPayloadFromList(final JsonElement listOfPdpActions)
+ throws PdpGroupPayloadException {
+ return new PdpGroupPayload(listOfPdpActions).generatePdpGroupPayload();
+ }
+
+
+ private void readListOfActions(final JsonElement listOfPdpActions) throws PdpGroupPayloadException {
+ for (JsonElement action : listOfPdpActions.getAsJsonObject().getAsJsonArray(PDP_ACTIONS)) {
+ String[] opParams = action.getAsString().split("/");
+ if (opParams.length == 5) {
+ this.updatePdpGroupMap(opParams[1], opParams[2], opParams[3], opParams[4], opParams[0]);
+ } else {
+ logger.error("One PDP push command does not contain the right number of arguments: " + action);
+ throw new PdpGroupPayloadException(
+ "One PDP push command does not contain the right number of arguments: " + action);
+ }
+ }
+ }
+
+ /**
+ * This method updates the pdpGroupMap structure for a specific policy/version/pdpdGroup/PdpSubGroup.
+ *
+ * @param pdpGroup The pdp Group in String
+ * @param pdpSubGroup The pdp Sub Group in String
+ * @param policyName The policy name
+ * @param policyVersion The policy Version
+ * @param action DELETE or POST
+ */
+ public void updatePdpGroupMap(String pdpGroup,
+ String pdpSubGroup,
+ String policyName,
+ String policyVersion, String action) {
+ // create subgroup
+ DeploymentSubGroup newSubGroup = new DeploymentSubGroup();
+ newSubGroup.setPdpType(pdpSubGroup);
+ newSubGroup.setAction(DeploymentSubGroup.Action.valueOf(action));
+ newSubGroup.setPolicies(Arrays.asList(new ToscaConceptIdentifier(policyName, policyVersion)));
+ // Add to deployment Groups structure
+ this.deploymentGroups.getGroups().stream().filter(group ->
+ group.getName().equals(pdpGroup)).findFirst()
+ .ifPresentOrElse(group -> group.getDeploymentSubgroups().add(newSubGroup),
+ () -> {
+ DeploymentGroup newGroup = new DeploymentGroup();
+ newGroup.setName(pdpGroup);
+ newGroup.setDeploymentSubgroups(new ArrayList<>(Arrays.asList(newSubGroup)));
+ this.deploymentGroups.getGroups().add(newGroup);
+ });
+ }
+
+ /**
+ * This method generates the Payload in Json from the pdp Group structure containing the policies/versions
+ * that must be sent to the policy framework.
+ *
+ * @return The Json that can be sent to policy framework as String
+ */
+ public String generatePdpGroupPayload() {
+ String payload = JsonUtils.GSON.toJson(this.deploymentGroups);
+ logger.info("PdpGroup policy payload: " + payload);
+ return payload;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayloadException.java b/runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayloadException.java
new file mode 100644
index 000000000..4ce0721b2
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayloadException.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.pdpgroup;
+
+/**
+ * Exception during Pdp Group payload construction.
+ */
+public class PdpGroupPayloadException extends Exception {
+
+ /**
+ * serialization id.
+ */
+ private static final long serialVersionUID = -5676848693241134101L;
+
+ /**
+ * This constructor can be used to create a new PdpGroupPayloadException.
+ *
+ * @param message The message to dump
+ */
+ public PdpGroupPayloadException(final String message) {
+ super(message);
+ }
+
+ /**
+ * This constructor can be used to create a new PdpGroupPayloadException.
+ *
+ * @param message The message to dump
+ * @param cause The Throwable cause object
+ */
+ public PdpGroupPayloadException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupsAnalyzer.java b/runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupsAnalyzer.java
new file mode 100644
index 000000000..6098d0f63
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupsAnalyzer.java
@@ -0,0 +1,180 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.pdpgroup;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.ConcurrentHashMap;
+import org.apache.commons.collections4.CollectionUtils;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.models.pdp.concepts.PdpGroup;
+import org.onap.policy.models.pdp.concepts.PdpGroups;
+import org.onap.policy.models.pdp.concepts.PdpSubGroup;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+/**
+ * This is an utility class to do searching in pdp groups and create json object describing the result.
+ */
+public class PdpGroupsAnalyzer {
+
+ public static final String ASSIGNED_PDP_GROUPS_INFO = "pdpGroupInfo";
+ public static final String SUPPORTED_PDP_GROUPS_INFO = "supportedPdpGroups";
+
+ /**
+ * This structure holds the map of PdpGroups per policies, policies are identifed by ToscaConceptIdentifier.
+ */
+ private final Map<ToscaConceptIdentifier, Map<String, PdpGroup>> pdpGroupsDeploymentPerPolicy =
+ new ConcurrentHashMap<>();
+
+ /**
+ * Constructor taking he PDPGroups info from the PEF.
+ * It then caches the groups per policies and per types.
+ *
+ * @param pdpGroups The pdpgroup info from the PEF
+ */
+ public PdpGroupsAnalyzer(PdpGroups pdpGroups) {
+ this.analyzePdpGroups(pdpGroups);
+ }
+
+ /**
+ * Getter of the GroupDeploymentPerPolicy structure.
+ *
+ * @return The map of policies.
+ */
+ public Map<ToscaConceptIdentifier, Map<String, PdpGroup>> getPdpGroupsDeploymentPerPolicy() {
+ return pdpGroupsDeploymentPerPolicy;
+ }
+
+ private static void addInfoToPdpGroupsStructure(ToscaConceptIdentifier toscaId,
+ Map<ToscaConceptIdentifier,
+ Map<String,
+ PdpGroup>> pdpGroupsDeploymentPerToscaIdentifier,
+ PdpGroup pdpGroupSource,
+ PdpSubGroup pdpSubGroupSource) {
+ // Copy the subgroup but empty the policies & types
+ pdpGroupsDeploymentPerToscaIdentifier.computeIfAbsent(toscaId, toscaKey -> new ConcurrentHashMap<>())
+ .computeIfAbsent(pdpGroupSource.getName(), pdpGroupName -> {
+ PdpGroup pdpGroupCopy = new PdpGroup(pdpGroupSource);
+ pdpGroupCopy.setPdpSubgroups(new ArrayList<>());
+ return pdpGroupCopy;
+ }).getPdpSubgroups().add(new PdpSubGroup(pdpSubGroupSource));
+ }
+
+ private void analyzePdpGroups(PdpGroups pdpGroups) {
+ CollectionUtils.emptyIfNull(pdpGroups.getGroups()).stream()
+ .forEach(group -> CollectionUtils.emptyIfNull(group.getPdpSubgroups()).stream().forEach(subGroup ->
+ CollectionUtils.emptyIfNull(subGroup.getPolicies()).parallelStream().forEach(policy ->
+ PdpGroupsAnalyzer.addInfoToPdpGroupsStructure(policy, this.pdpGroupsDeploymentPerPolicy,
+ group, subGroup))));
+ }
+
+ /**
+ * This method retrieves all pdpGroups and subgroups where a specific policy name/version is deployed.
+ *
+ * @param policyName The policy name that must be used for searching
+ * @param version THe policy version that must be used for searching
+ * @return It returns a JsonObject containing each pdpGroup and subgroups associated
+ */
+ public JsonObject getPdpGroupsForPolicy(String policyName, String version) {
+ Map<String, PdpGroup> mapOfGroups =
+ this.pdpGroupsDeploymentPerPolicy.get(new ToscaConceptIdentifier(policyName, version));
+ if (mapOfGroups != null) {
+ JsonObject policyPdpGroups = new JsonObject();
+ JsonArray pdpGroupsArray = new JsonArray();
+ policyPdpGroups.add(ASSIGNED_PDP_GROUPS_INFO, pdpGroupsArray);
+ pdpGroupsArray.add(JsonUtils.GSON
+ .toJsonTree(mapOfGroups));
+ return policyPdpGroups;
+ }
+ return null;
+ }
+
+ /**
+ * Get supported subGroups based on the defined policy type and version for specific PDPGroup.
+ * It returns null if the Group is TERMINATED or if the policytype/version has not been found in the PDPSubgroups.
+ *
+ * @param pdpGroup The pdpGroup that must be analyzed
+ * @param policyType The policy type
+ * @param version The version
+ * @return The supported subGroups list in Json format
+ * @see org.onap.policy.models.pdp.concepts.PdpGroup
+ * @see org.onap.policy.models.pdp.enums.PdpState
+ */
+ private static JsonObject getSupportedPdpSubgroupsForModelType(PdpGroup pdpGroup, String policyType,
+ String version) {
+ if (PdpState.TERMINATED.equals(pdpGroup.getPdpGroupState())) {
+ return null;
+ }
+ JsonObject supportedPdpGroup = new JsonObject();
+ JsonArray supportedSubgroups = new JsonArray();
+ supportedPdpGroup.add(pdpGroup.getName(), supportedSubgroups);
+ pdpGroup.getPdpSubgroups().stream().forEach(pdpSubGroup -> {
+ if (pdpSubGroup.getSupportedPolicyTypes().stream().anyMatch(policyTypeIdentifier ->
+ policyType.matches(policyTypeIdentifier.getName().replace(".", "\\.").replace("*", ".*"))
+ && version.equals(policyTypeIdentifier.getVersion()))) {
+ supportedSubgroups.add(pdpSubGroup.getPdpType());
+ }
+ });
+ return supportedSubgroups.size() == 0 ? null : supportedPdpGroup;
+ }
+
+ /**
+ * This method retrieves all supported pdpGroups and subgroups for a specific policy type/version.
+ *
+ * @param pdpGroups The PdpGroups object containing all PEF pdp groups info
+ * @param policyType The policy type that must be used for searching
+ * @param version THe policy type version that must be used for searching
+ * @return It returns a JsonObject containing each pdpGroup and subgroups associated
+ */
+ public static JsonObject getSupportedPdpGroupsForModelType(PdpGroups pdpGroups, String policyType, String version) {
+ JsonObject supportedPdpGroups = new JsonObject();
+ JsonArray pdpGroupsArray = new JsonArray();
+ supportedPdpGroups.add(SUPPORTED_PDP_GROUPS_INFO, pdpGroupsArray);
+
+ pdpGroups.getGroups().stream().map(pdpGroup -> PdpGroupsAnalyzer.getSupportedPdpSubgroupsForModelType(pdpGroup,
+ policyType, version)).filter(Objects::nonNull)
+ .forEach(pdpGroupsArray::add);
+
+ return pdpGroupsArray.size() != 0 ? supportedPdpGroups : null;
+ }
+
+ /**
+ * This method updates each element in the policyModelsList given in argument based on the pdpGroups given.
+ *
+ * @param policyModelsList The list of Policy Models where each PolicyModel will be updated
+ * @param pdpGroups The PdpGroups containing all PDP group definition
+ */
+ public static void updatePdpGroupOfPolicyModels(List<PolicyModel> policyModelsList, PdpGroups pdpGroups) {
+ policyModelsList.parallelStream().forEach(policyModel -> policyModel
+ .setPolicyPdpGroup(getSupportedPdpGroupsForModelType(pdpGroups, policyModel.getPolicyModelType(),
+ policyModel.getVersion())));
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMerger.java b/runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMerger.java
new file mode 100644
index 000000000..6775eb0c6
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMerger.java
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.pdpgroup;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.util.stream.StreamSupport;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.models.pdp.concepts.PdpGroups;
+
+/**
+ * This is an utility class that contains methods to work on the different results provided by the PEF.
+ * Mainly used to aggregate the results.
+ */
+public class PoliciesPdpMerger {
+
+ private PoliciesPdpMerger() {}
+
+ /**
+ * This method extract the content of a policy without knowing the key (policy Id).
+ * This JsonElement normally contains only the policy ID then the content,
+ * there is only one member in the Json element.
+ * As this is not really practical to use this method remove that
+ * nested Json.
+ *
+ * @param policyJsonElement The policy as JsonElement
+ * @return It return the content as JsonObject
+ */
+ public static JsonObject getPolicyContentOutOfJsonElement(JsonElement policyJsonElement) {
+ mergeJsonElement(policyJsonElement.getAsJsonObject(), policyJsonElement.getAsJsonObject()
+ .remove(((String) policyJsonElement.getAsJsonObject().keySet().toArray()[0])).getAsJsonObject());
+ return policyJsonElement.getAsJsonObject();
+ }
+
+ /**
+ * This method merges 2 JsonElement together. If the jsonToMerge is null nothing is changed.
+ *
+ * @param json The initial json that will received the data
+ * @param jsonToMerge The json that will be added to the first json object
+ */
+ public static void mergeJsonElement(JsonObject json, JsonObject jsonToMerge) {
+ if (jsonToMerge != null) {
+ jsonToMerge.entrySet().stream().forEach(entry -> json.add(entry.getKey(), entry.getValue()));
+ }
+ }
+
+ /**
+ * This method merges the result of the policy listing and the associated Pdp Group info.
+ * It can be seen as an enrichment of the policy listing.
+ *
+ * @param jsonPoliciesList The Json containing the policies from the PEF
+ * @param pdpGroupsJson The json containing the PDP groups info from the PEF
+ * @return It returns a JsonObject containing the policies list enriched with PdpGroup info
+ */
+ public static JsonObject mergePoliciesAndPdpGroupStates(String jsonPoliciesList, String pdpGroupsJson) {
+ PdpGroups pdpGroups = JsonUtils.GSON.fromJson(pdpGroupsJson, PdpGroups.class);
+ JsonObject policiesListJson =
+ JsonUtils.GSON.fromJson(jsonPoliciesList, JsonObject.class).get("topology_template")
+ .getAsJsonObject();
+ StreamSupport.stream(policiesListJson.get("policies").getAsJsonArray().spliterator(), true)
+ .forEach(policyJson -> enrichOnePolicy(pdpGroups, getPolicyContentOutOfJsonElement(policyJson)));
+ return policiesListJson;
+ }
+
+ /**
+ * Enrich one policy json node object with pdpGroup info.
+ *
+ * @param pdpGroups The pdpGroups from PEF to search the policy
+ * @param policyJsonNode The policy json node that must be enriched
+ */
+ private static void enrichOnePolicy(PdpGroups pdpGroups, JsonObject policyJsonNode) {
+ PdpGroupsAnalyzer pdpGroupAnalyzer = new PdpGroupsAnalyzer(pdpGroups);
+ JsonObject deploymentPdpJson = pdpGroupAnalyzer
+ .getPdpGroupsForPolicy(policyJsonNode.get("name").getAsString(),
+ policyJsonNode.get("version").getAsString());
+ mergeJsonElement(policyJsonNode, deploymentPdpJson);
+
+ JsonObject supportedPdpGroupsJson = PdpGroupsAnalyzer
+ .getSupportedPdpGroupsForModelType(pdpGroups, policyJsonNode.get("type").getAsString(),
+ policyJsonNode.get("type_version").getAsString());
+ mergeJsonElement(policyJsonNode, supportedPdpGroupsJson);
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/java/org/onap/policy/clamp/tosca/Dictionary.java b/runtime/src/main/java/org/onap/policy/clamp/tosca/Dictionary.java
new file mode 100644
index 000000000..4b01d6902
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/tosca/Dictionary.java
@@ -0,0 +1,219 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.tosca;
+
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import org.onap.policy.clamp.loop.common.AuditEntity;
+
+/**
+ * Represents Dictionary.
+ */
+
+@Entity
+@Table(name = "dictionary")
+public class Dictionary extends AuditEntity implements Serializable {
+
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = -286522707701388645L;
+
+ @Id
+ @Expose
+ @Column(nullable = false, name = "name", unique = true)
+ private String name;
+
+ @Expose
+ @Column(name = "dictionary_second_level")
+ private int secondLevelDictionary = 0;
+
+ @Expose
+ @Column(name = "dictionary_type")
+ private String subDictionaryType;
+
+ @Expose
+ @ManyToMany(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
+ @JoinTable(
+ name = "dictionary_to_dictionaryelements",
+ joinColumns = @JoinColumn(name = "dictionary_name", referencedColumnName = "name"),
+ inverseJoinColumns = {@JoinColumn(
+ name = "dictionary_element_short_name",
+ referencedColumnName = "short_name")})
+ private Set<DictionaryElement> dictionaryElements = new HashSet<>();
+
+ /**
+ * name getter.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * name setter.
+ *
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * secondLevelDictionary getter.
+ *
+ * @return the secondLevelDictionary
+ */
+ public int getSecondLevelDictionary() {
+ return secondLevelDictionary;
+ }
+
+ /**
+ * secondLevelDictionary setter.
+ *
+ * @param secondLevelDictionary the secondLevelDictionary to set
+ */
+ public void setSecondLevelDictionary(int secondLevelDictionary) {
+ this.secondLevelDictionary = secondLevelDictionary;
+ }
+
+ /**
+ * subDictionaryType getter.
+ *
+ * @return the subDictionaryType
+ */
+ public String getSubDictionaryType() {
+ return subDictionaryType;
+ }
+
+ /**
+ * subDictionaryType setter.
+ *
+ * @param subDictionaryType the subDictionaryType to set
+ */
+ public void setSubDictionaryType(String subDictionaryType) {
+ this.subDictionaryType = subDictionaryType;
+ }
+
+ /**
+ * dictionaryElements getter.
+ *
+ * @return the dictionaryElements List of dictionary element
+ */
+ public Set<DictionaryElement> getDictionaryElements() {
+ return dictionaryElements;
+ }
+
+ /**
+ * Method to add a new dictionaryElement to the list.
+ *
+ * @param dictionaryElement The dictionary element
+ */
+ public void addDictionaryElements(DictionaryElement dictionaryElement) {
+ dictionaryElements.add(dictionaryElement);
+ dictionaryElement.getUsedByDictionaries().add(this);
+ }
+
+ /**
+ * Method to set dictionaryElements.
+ *
+ * @param dictionaryElements The dictionary elements set
+ */
+ public void setDictionaryElements(Set<DictionaryElement> dictionaryElements) {
+ this.dictionaryElements = dictionaryElements;
+ }
+
+ /**
+ * Method to delete a dictionaryElement from the list.
+ *
+ * @param dictionaryElement The dictionary element
+ */
+ public void removeDictionaryElement(DictionaryElement dictionaryElement) {
+ dictionaryElements.remove(dictionaryElement);
+ dictionaryElement.getUsedByDictionaries().remove(this);
+ }
+
+ /**
+ * Default Constructor.
+ */
+ public Dictionary() {
+
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The Dictionary name
+ * @param secondLevelDictionary defines if dictionary is a secondary level
+ * @param subDictionaryType defines the type of secondary level dictionary
+ */
+ public Dictionary(String name, int secondLevelDictionary, String subDictionaryType) {
+ this.name = name;
+ this.secondLevelDictionary = secondLevelDictionary;
+ this.subDictionaryType = subDictionaryType;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ Dictionary other = (Dictionary) obj;
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryElement.java b/runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryElement.java
new file mode 100644
index 000000000..ecf4b876c
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryElement.java
@@ -0,0 +1,254 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.tosca;
+
+import com.google.gson.annotations.Expose;
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import org.onap.policy.clamp.loop.common.AuditEntity;
+
+/**
+ * Represents a Dictionary Item.
+ */
+@Entity
+@Table(name = "dictionary_elements")
+public class DictionaryElement extends AuditEntity implements Serializable {
+
+ /**
+ * The serial version id.
+ */
+ private static final long serialVersionUID = -286522707701388644L;
+
+ @Id
+ @Expose
+ @Column(nullable = false, name = "short_name")
+ private String shortName;
+
+ @Expose
+ @Column(nullable = false, name = "name")
+ private String name;
+
+ @Expose
+ @Column(nullable = false, name = "description")
+ private String description;
+
+ @Expose
+ @Column(nullable = false, name = "type")
+ private String type;
+
+ @Expose
+ @Column(nullable = true, name = "subdictionary_name")
+ private String subDictionary;
+
+ @ManyToMany(mappedBy = "dictionaryElements", fetch = FetchType.EAGER)
+ private Set<Dictionary> usedByDictionaries = new HashSet<>();
+
+ /**
+ * name getter.
+ *
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * name setter.
+ *
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * shortName getter.
+ *
+ * @return the shortName
+ */
+ public String getShortName() {
+ return shortName;
+ }
+
+ /**
+ * shortName setter.
+ *
+ * @param shortName the shortName to set
+ */
+ public void setShortName(String shortName) {
+ this.shortName = shortName;
+ }
+
+ /**
+ * description getter.
+ *
+ * @return the description
+ */
+ public String getDescription() {
+ return description;
+ }
+
+ /**
+ * description setter.
+ *
+ * @param description the description to set
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ /**
+ * type getter.
+ *
+ * @return the type
+ */
+ public String getType() {
+ return type;
+ }
+
+ /**
+ * type setter.
+ *
+ * @param type the type to set
+ */
+ public void setType(String type) {
+ this.type = type;
+ }
+
+ /**
+ * subDictionary getter.
+ *
+ * @return the subDictionary
+ */
+ public String getSubDictionary() {
+ return subDictionary;
+ }
+
+ /**
+ * subDictionary setter.
+ *
+ * @param subDictionary the subDictionary to set
+ */
+ public void setSubDictionary(String subDictionary) {
+ this.subDictionary = subDictionary;
+ }
+
+ /**
+ * usedByDictionaries getter.
+ *
+ * @return the usedByDictionaries
+ */
+ public Set<Dictionary> getUsedByDictionaries() {
+ return usedByDictionaries;
+ }
+
+ /**
+ * usedByDictionaries setter.
+ *
+ * @param usedByDictionaries the usedByDictionaries to set
+ */
+ public void setUsedByDictionaries(Set<Dictionary> usedByDictionaries) {
+ this.usedByDictionaries = usedByDictionaries;
+ }
+
+ /**
+ * Default Constructor.
+ */
+ public DictionaryElement() {
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The Dictionary element name
+ * @param shortName The short name
+ * @param description The description
+ * @param type The type of element
+ * @param subDictionary The sub type
+ */
+ public DictionaryElement(String name, String shortName, String description, String type,
+ String subDictionary) {
+ this.name = name;
+ this.shortName = shortName;
+ this.description = description;
+ this.type = type;
+ this.subDictionary = subDictionary;
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param name The Dictionary element name
+ * @param shortName The short name
+ * @param description The description
+ * @param type The type of element
+ * @param subDictionary The sub type
+ */
+ public DictionaryElement(String name, String shortName, String description, String type,
+ String subDictionary, Set<Dictionary> usedByDictionaries) {
+ this.name = name;
+ this.shortName = shortName;
+ this.description = description;
+ this.type = type;
+ this.subDictionary = subDictionary;
+ this.usedByDictionaries = usedByDictionaries;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((shortName == null) ? 0 : shortName.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ DictionaryElement other = (DictionaryElement) obj;
+ if (shortName == null) {
+ if (other.shortName != null) {
+ return false;
+ }
+ } else if (!shortName.equals(other.shortName)) {
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryElementsRepository.java b/runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryElementsRepository.java
new file mode 100644
index 000000000..0bc50fe1a
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryElementsRepository.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.tosca;
+
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface DictionaryElementsRepository extends JpaRepository<DictionaryElement, String> {
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryRepository.java b/runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryRepository.java
new file mode 100644
index 000000000..a2f417d17
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryRepository.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.tosca;
+
+import java.util.List;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface DictionaryRepository extends JpaRepository<Dictionary, String> {
+
+ @Query("SELECT dict.name FROM Dictionary as dict")
+ List<String> getAllDictionaryNames();
+
+ @Query("SELECT dict.name FROM Dictionary as dict where dict.secondLevelDictionary = 1")
+ List<String> getAllSecondaryLevelDictionaryNames();
+
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryService.java b/runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryService.java
new file mode 100644
index 000000000..849d4baae
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/tosca/DictionaryService.java
@@ -0,0 +1,141 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.tosca;
+
+import com.google.common.collect.Sets;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.persistence.EntityNotFoundException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class DictionaryService {
+
+ private final DictionaryRepository dictionaryRepository;
+ private final DictionaryElementsRepository dictionaryElementsRepository;
+
+ /**
+ * Constructor.
+ */
+ @Autowired
+ public DictionaryService(DictionaryRepository dictionaryRepository,
+ DictionaryElementsRepository dictionaryElementsRepository) {
+ this.dictionaryRepository = dictionaryRepository;
+ this.dictionaryElementsRepository = dictionaryElementsRepository;
+
+ }
+
+ public Dictionary saveOrUpdateDictionary(Dictionary dictionary) {
+ return dictionaryRepository.saveAndFlush(dictionary);
+ }
+
+ /**
+ * Creates or Updates Dictionary Element.
+ *
+ * @param dictionaryName The Dictionary name
+ * @param dictionary The Dictionary object with dictionary elements
+ * @return updated Dictionary object with all dictionary elements
+ */
+ public Dictionary saveOrUpdateDictionaryElement(String dictionaryName, Dictionary dictionary) {
+ Dictionary dict = getDictionary(dictionaryName);
+
+ Set<DictionaryElement> newDictionaryElements = dictionary.getDictionaryElements();
+
+ if (newDictionaryElements != null && !newDictionaryElements.isEmpty()) {
+ Set<DictionaryElement> updatedDictionaryElements = newDictionaryElements.stream()
+ .map(dictionaryElement -> getAndUpdateDictionaryElement(dict, dictionaryElement))
+ .collect(Collectors.toSet());
+
+ dict.getDictionaryElements().forEach(dictElement -> {
+ if (!updatedDictionaryElements.contains(dictElement)) {
+ updatedDictionaryElements.add(dictElement);
+ }
+ });
+ dict.setDictionaryElements(updatedDictionaryElements);
+ }
+ return dictionaryRepository.saveAndFlush(dict);
+
+ }
+
+ private DictionaryElement getAndUpdateDictionaryElement(Dictionary dictionary,
+ DictionaryElement element) {
+ return dictionaryElementsRepository
+ .save(dictionaryElementsRepository.findById(element.getShortName())
+ .map(p -> updateDictionaryElement(p, element, dictionary))
+ .orElse(new DictionaryElement(element.getName(), element.getShortName(),
+ element.getDescription(), element.getType(), element.getSubDictionary(),
+ Sets.newHashSet(dictionary))));
+ }
+
+ public void deleteDictionary(Dictionary dictionary) {
+ dictionaryRepository.delete(dictionary);
+ }
+
+ public void deleteDictionary(String dictionaryName) {
+ dictionaryRepository.deleteById(dictionaryName);
+ }
+
+ public List<Dictionary> getAllDictionaries() {
+ return dictionaryRepository.findAll();
+ }
+
+ public List<String> getAllSecondaryLevelDictionaryNames() {
+ return dictionaryRepository.getAllSecondaryLevelDictionaryNames();
+ }
+
+ public Dictionary getDictionary(String dictionaryName) {
+ return dictionaryRepository.findById(dictionaryName).orElseThrow(
+ () -> new EntityNotFoundException("Couldn't find Dictionary named: " + dictionaryName));
+ }
+
+ /**
+ * Deletes a dictionary element from Dictionary by shortName.
+ *
+ * @param dictionaryName The dictionary name
+ * @param dictionaryElementShortName the dictionary Element Short name
+ */
+ public void deleteDictionaryElement(String dictionaryName, String dictionaryElementShortName) {
+ if (dictionaryRepository.existsById(dictionaryName)) {
+ DictionaryElement element =
+ dictionaryElementsRepository.findById(dictionaryElementShortName).orElse(null);
+ if (element != null) {
+ Dictionary dict = getDictionary(dictionaryName);
+ dict.removeDictionaryElement(element);
+ dictionaryRepository.saveAndFlush(dict);
+ }
+ }
+ }
+
+ private DictionaryElement updateDictionaryElement(DictionaryElement oldDictionaryElement,
+ DictionaryElement newDictionaryElement, Dictionary dictionary) {
+ oldDictionaryElement.setName(newDictionaryElement.getName());
+ oldDictionaryElement.setDescription(newDictionaryElement.getDescription());
+ oldDictionaryElement.setType(newDictionaryElement.getType());
+ oldDictionaryElement.setSubDictionary(newDictionaryElement.getSubDictionary());
+ oldDictionaryElement.getUsedByDictionaries().add(dictionary);
+ return oldDictionaryElement;
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/util/PassDecoder.java b/runtime/src/main/java/org/onap/policy/clamp/util/PassDecoder.java
new file mode 100644
index 000000000..b8e90e3d0
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/util/PassDecoder.java
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ */
+
+package org.onap.policy.clamp.util;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import java.io.IOException;
+import org.onap.aaf.cadi.Symm;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+
+/**
+ * PassDecoder for decrypting the truststore and keystore password.
+ */
+public class PassDecoder {
+
+ private PassDecoder() {
+ }
+
+ /**
+ * Used to log PassDecoder class.
+ */
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(PassDecoder.class);
+
+ /**
+ * Decode the password.
+ *
+ * @param encryptedPass The encrypted password
+ * @param keyFileName The key file name in String
+ */
+ public static String decode(String encryptedPass, String keyFileName) {
+ if (null == keyFileName) {
+ logger.debug("Key file is not defined, thus password will not be decrypted");
+ return encryptedPass;
+ }
+ if (null == encryptedPass) {
+ logger.error("Encrypted password is not defined");
+ return null;
+ }
+ try {
+ return Symm.obtain(ResourceFileUtils.getResourceAsStream(keyFileName)).depass(encryptedPass);
+ } catch (IOException e) {
+ logger.error("Exception occurred during the key decryption", e);
+ return null;
+ }
+ }
+}
diff --git a/runtime/src/main/java/org/onap/policy/clamp/util/SemanticVersioning.java b/runtime/src/main/java/org/onap/policy/clamp/util/SemanticVersioning.java
new file mode 100644
index 000000000..58367193f
--- /dev/null
+++ b/runtime/src/main/java/org/onap/policy/clamp/util/SemanticVersioning.java
@@ -0,0 +1,91 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.util;
+
+/**
+ * This class is the base class for object that requires semantic versioning.
+ * ... This class supports also a.b.c.d... etc ... as a version.
+ */
+public class SemanticVersioning {
+ public static final int BEFORE = -1;
+ public static final int EQUAL = 0;
+ public static final int AFTER = 1;
+ public static final String DEFAULT_VERSION = "1.0.0";
+
+ /**
+ * The compare method that compare arg0 to arg1.
+ *
+ * @param arg0 A version in string for semantic versioning (a.b.c.d...)
+ * @param arg1 A version in string for semantic versioning (a.b.c.d...)
+ * @return objects (arg0, arg1) given as parameters. It returns the value: 0: if
+ * (arg0==arg1) -1: if (arg0 < arg1) 1: if (arg0 > arg1)
+ */
+ public static int compare(String arg0, String arg1) {
+
+ if (arg0 == null && arg1 == null) {
+ return EQUAL;
+ }
+ if (arg0 == null) {
+ return BEFORE;
+ }
+ if (arg1 == null) {
+ return AFTER;
+ }
+ String[] arg0Array = arg0.split("\\.");
+ String[] arg1Array = arg1.split("\\.");
+
+ int smalestStringLength = Math.min(arg0Array.length, arg1Array.length);
+
+ for (int currentVersionIndex =
+ 0; currentVersionIndex < smalestStringLength; ++currentVersionIndex) {
+ if (Integer.parseInt(arg0Array[currentVersionIndex]) < Integer
+ .parseInt(arg1Array[currentVersionIndex])) {
+ return BEFORE;
+ } else if (Integer.parseInt(arg0Array[currentVersionIndex]) > Integer
+ .parseInt(arg1Array[currentVersionIndex])) {
+ return AFTER;
+ }
+ // equals, so do not return anything, continue
+ }
+ if (arg0Array.length == arg1Array.length) {
+ return EQUAL;
+ } else {
+ return Integer.compare(arg0Array.length, arg1Array.length);
+ }
+ }
+
+ /**
+ * Method to increment a version from its current version.
+ *
+ * @param currentVersion The current Version
+ * @return the increment version string
+ */
+ public static String incrementMajorVersion(String currentVersion) {
+ if (currentVersion == null || currentVersion.isEmpty()) {
+ return DEFAULT_VERSION;
+ }
+ String[] versionArray = currentVersion.split("\\.");
+ return String.valueOf(Integer.parseInt(versionArray[0]) + 1) + ".0.0";
+ }
+}
diff --git a/runtime/src/main/resources/META-INF/resources/swagger.html b/runtime/src/main/resources/META-INF/resources/swagger.html
new file mode 100644
index 000000000..f7fbeb039
--- /dev/null
+++ b/runtime/src/main/resources/META-INF/resources/swagger.html
@@ -0,0 +1,4508 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+<meta charset="UTF-8">
+<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+<meta name="generator" content="Asciidoctor 1.5.7.1">
+<title>Clamp Rest API</title>
+<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
+<style>
+/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
+/* Uncomment @import statement below to use as custom stylesheet */
+/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
+article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
+audio,canvas,video{display:inline-block}
+audio:not([controls]){display:none;height:0}
+script{display:none!important}
+html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
+a{background:transparent}
+a:focus{outline:thin dotted}
+a:active,a:hover{outline:0}
+h1{font-size:2em;margin:.67em 0}
+abbr[title]{border-bottom:1px dotted}
+b,strong{font-weight:bold}
+dfn{font-style:italic}
+hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
+mark{background:#ff0;color:#000}
+code,kbd,pre,samp{font-family:monospace;font-size:1em}
+pre{white-space:pre-wrap}
+q{quotes:"\201C" "\201D" "\2018" "\2019"}
+small{font-size:80%}
+sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
+sup{top:-.5em}
+sub{bottom:-.25em}
+img{border:0}
+svg:not(:root){overflow:hidden}
+figure{margin:0}
+fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
+legend{border:0;padding:0}
+button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
+button,input{line-height:normal}
+button,select{text-transform:none}
+button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
+button[disabled],html input[disabled]{cursor:default}
+input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
+button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
+textarea{overflow:auto;vertical-align:top}
+table{border-collapse:collapse;border-spacing:0}
+*,*::before,*::after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
+html,body{font-size:100%}
+body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto;tab-size:4;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}
+a:hover{cursor:pointer}
+img,object,embed{max-width:100%;height:auto}
+object,embed{height:100%}
+img{-ms-interpolation-mode:bicubic}
+.left{float:left!important}
+.right{float:right!important}
+.text-left{text-align:left!important}
+.text-right{text-align:right!important}
+.text-center{text-align:center!important}
+.text-justify{text-align:justify!important}
+.hide{display:none}
+img,object,svg{display:inline-block;vertical-align:middle}
+textarea{height:auto;min-height:50px}
+select{width:100%}
+.center{margin-left:auto;margin-right:auto}
+.stretch{width:100%}
+.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
+div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
+a{color:#2156a5;text-decoration:underline;line-height:inherit}
+a:hover,a:focus{color:#1d4b8f}
+a img{border:none}
+p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
+p aside{font-size:.875em;line-height:1.35;font-style:italic}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
+h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
+h1{font-size:2.125em}
+h2{font-size:1.6875em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
+h4,h5{font-size:1.125em}
+h6{font-size:1em}
+hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
+em,i{font-style:italic;line-height:inherit}
+strong,b{font-weight:bold;line-height:inherit}
+small{font-size:60%;line-height:inherit}
+code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
+ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
+ul,ol{margin-left:1.5em}
+ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
+ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
+ul.square{list-style-type:square}
+ul.circle{list-style-type:circle}
+ul.disc{list-style-type:disc}
+ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
+dl dt{margin-bottom:.3125em;font-weight:bold}
+dl dd{margin-bottom:1.25em}
+abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
+abbr{text-transform:none}
+blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
+blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
+blockquote cite::before{content:"\2014 \0020"}
+blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
+blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
+@media screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
+h1{font-size:2.75em}
+h2{font-size:2.3125em}
+h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
+h4{font-size:1.4375em}}
+table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
+table thead,table tfoot{background:#f7f8f7}
+table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
+table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
+table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
+table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
+h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
+h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
+.clearfix::before,.clearfix::after,.float-group::before,.float-group::after{content:" ";display:table}
+.clearfix::after,.float-group::after{clear:both}
+*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed;word-wrap:break-word}
+*:not(pre)>code.nobreak{word-wrap:normal}
+*:not(pre)>code.nowrap{white-space:nowrap}
+pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
+em em{font-style:normal}
+strong strong{font-weight:400}
+.keyseq{color:rgba(51,51,51,.8)}
+kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
+.keyseq kbd:first-child{margin-left:0}
+.keyseq kbd:last-child{margin-right:0}
+.menuseq,.menuref{color:#000}
+.menuseq b:not(.caret),.menuref{font-weight:inherit}
+.menuseq{word-spacing:-.02em}
+.menuseq b.caret{font-size:1.25em;line-height:.8}
+.menuseq i.caret{font-weight:bold;text-align:center;width:.45em}
+b.button::before,b.button::after{position:relative;top:-1px;font-weight:400}
+b.button::before{content:"[";padding:0 3px 0 2px}
+b.button::after{content:"]";padding:0 2px 0 3px}
+p a>code:hover{color:rgba(0,0,0,.9)}
+#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
+#header::before,#header::after,#content::before,#content::after,#footnotes::before,#footnotes::after,#footer::before,#footer::after{content:" ";display:table}
+#header::after,#content::after,#footnotes::after,#footer::after{clear:both}
+#content{margin-top:1.25em}
+#content::before{content:none}
+#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
+#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
+#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
+#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
+#header .details span:first-child{margin-left:-.125em}
+#header .details span.email a{color:rgba(0,0,0,.85)}
+#header .details br{display:none}
+#header .details br+span::before{content:"\00a0\2013\00a0"}
+#header .details br+span.author::before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
+#header .details br+span#revremark::before{content:"\00a0|\00a0"}
+#header #revnumber{text-transform:capitalize}
+#header #revnumber::after{content:"\00a0"}
+#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
+#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
+#toc>ul{margin-left:.125em}
+#toc ul.sectlevel0>li>a{font-style:italic}
+#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
+#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
+#toc li{line-height:1.3334;margin-top:.3334em}
+#toc a{text-decoration:none}
+#toc a:active{text-decoration:underline}
+#toctitle{color:#7a2518;font-size:1.2em}
+@media screen and (min-width:768px){#toctitle{font-size:1.375em}
+body.toc2{padding-left:15em;padding-right:0}
+#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
+#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
+#toc.toc2>ul{font-size:.9em;margin-bottom:0}
+#toc.toc2 ul ul{margin-left:0;padding-left:1em}
+#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
+body.toc2.toc-right{padding-left:0;padding-right:15em}
+body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
+@media screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
+#toc.toc2{width:20em}
+#toc.toc2 #toctitle{font-size:1.375em}
+#toc.toc2>ul{font-size:.95em}
+#toc.toc2 ul ul{padding-left:1.25em}
+body.toc2.toc-right{padding-left:0;padding-right:20em}}
+#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
+#content #toc>:first-child{margin-top:0}
+#content #toc>:last-child{margin-bottom:0}
+#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
+#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
+#content{margin-bottom:.625em}
+.sect1{padding-bottom:.625em}
+@media screen and (min-width:768px){#content{margin-bottom:1.25em}
+.sect1{padding-bottom:1.25em}}
+.sect1:last-child{padding-bottom:0}
+.sect1+.sect1{border-top:1px solid #efefed}
+#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
+#content h1>a.anchor::before,h2>a.anchor::before,h3>a.anchor::before,#toctitle>a.anchor::before,.sidebarblock>.content>.title>a.anchor::before,h4>a.anchor::before,h5>a.anchor::before,h6>a.anchor::before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
+#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
+#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
+#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
+.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
+.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
+table.tableblock.fit-content>caption.title{white-space:nowrap;width:0}
+.paragraph.lead>p,#preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:1.21875em;line-height:1.6;color:rgba(0,0,0,.85)}
+table.tableblock #preamble>.sectionbody>[class="paragraph"]:first-of-type p{font-size:inherit}
+.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
+.admonitionblock>table td.icon{text-align:center;width:80px}
+.admonitionblock>table td.icon img{max-width:none}
+.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
+.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
+.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
+.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
+.exampleblock>.content>:first-child{margin-top:0}
+.exampleblock>.content>:last-child{margin-bottom:0}
+.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
+.sidebarblock>:first-child{margin-top:0}
+.sidebarblock>:last-child{margin-bottom:0}
+.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
+.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
+.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
+.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
+.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
+.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
+@media screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
+@media screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
+.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
+.listingblock pre.highlightjs{padding:0}
+.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
+.listingblock pre.prettyprint{border-width:0}
+.listingblock>.content{position:relative}
+.listingblock code[data-lang]::before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
+.listingblock:hover code[data-lang]::before{display:block}
+.listingblock.terminal pre .command::before{content:attr(data-prompt);padding-right:.5em;color:#999}
+.listingblock.terminal pre .command:not([data-prompt])::before{content:"$"}
+table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
+table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
+table.pyhltable td.code{padding-left:.75em;padding-right:0}
+pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
+pre.pygments .lineno{display:inline-block;margin-right:.25em}
+table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
+.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
+.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
+.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
+.quoteblock blockquote{margin:0;padding:0;border:0}
+.quoteblock blockquote::before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
+.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
+.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
+.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
+.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
+.quoteblock .quoteblock blockquote::before{display:none}
+.verseblock{margin:0 1em 1.25em}
+.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
+.verseblock pre strong{font-weight:400}
+.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
+.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
+.quoteblock .attribution br,.verseblock .attribution br{display:none}
+.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
+.quoteblock.abstract{margin:0 1em 1.25em;display:block}
+.quoteblock.abstract>.title{margin:0 0 .375em;font-size:1.15em;text-align:center}
+.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{word-spacing:0;line-height:1.6}
+.quoteblock.abstract blockquote::before,.quoteblock.abstract p::before{display:none}
+table.tableblock{max-width:100%;border-collapse:separate}
+p.tableblock:last-child{margin-bottom:0}
+td.tableblock>.content{margin-bottom:-1.25em}
+table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
+table.grid-all>thead>tr>.tableblock,table.grid-all>tbody>tr>.tableblock{border-width:0 1px 1px 0}
+table.grid-all>tfoot>tr>.tableblock{border-width:1px 1px 0 0}
+table.grid-cols>*>tr>.tableblock{border-width:0 1px 0 0}
+table.grid-rows>thead>tr>.tableblock,table.grid-rows>tbody>tr>.tableblock{border-width:0 0 1px}
+table.grid-rows>tfoot>tr>.tableblock{border-width:1px 0 0}
+table.grid-all>*>tr>.tableblock:last-child,table.grid-cols>*>tr>.tableblock:last-child{border-right-width:0}
+table.grid-all>tbody>tr:last-child>.tableblock,table.grid-all>thead:last-child>tr>.tableblock,table.grid-rows>tbody>tr:last-child>.tableblock,table.grid-rows>thead:last-child>tr>.tableblock{border-bottom-width:0}
+table.frame-all{border-width:1px}
+table.frame-sides{border-width:0 1px}
+table.frame-topbot,table.frame-ends{border-width:1px 0}
+table.stripes-all tr,table.stripes-odd tr:nth-of-type(odd){background:#f8f8f7}
+table.stripes-none tr,table.stripes-odd tr:nth-of-type(even){background:none}
+th.halign-left,td.halign-left{text-align:left}
+th.halign-right,td.halign-right{text-align:right}
+th.halign-center,td.halign-center{text-align:center}
+th.valign-top,td.valign-top{vertical-align:top}
+th.valign-bottom,td.valign-bottom{vertical-align:bottom}
+th.valign-middle,td.valign-middle{vertical-align:middle}
+table thead th,table tfoot th{font-weight:bold}
+tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
+tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
+p.tableblock>code:only-child{background:none;padding:0}
+p.tableblock{font-size:1em}
+td>div.verse{white-space:pre}
+ol{margin-left:1.75em}
+ul li ol{margin-left:1.5em}
+dl dd{margin-left:1.125em}
+dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
+ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
+ul.checklist,ul.none,ol.none,ul.no-bullet,ol.no-bullet,ol.unnumbered,ul.unstyled,ol.unstyled{list-style-type:none}
+ul.no-bullet,ol.no-bullet,ol.unnumbered{margin-left:.625em}
+ul.unstyled,ol.unstyled{margin-left:0}
+ul.checklist{margin-left:.625em}
+ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1.25em;font-size:.8em;position:relative;bottom:.125em}
+ul.checklist li>p:first-child>input[type="checkbox"]:first-child{margin-right:.25em}
+ul.inline{display:-ms-flexbox;display:-webkit-box;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap;list-style:none;margin:0 0 .625em -1.25em}
+ul.inline>li{margin-left:1.25em}
+.unstyled dl dt{font-weight:400;font-style:normal}
+ol.arabic{list-style-type:decimal}
+ol.decimal{list-style-type:decimal-leading-zero}
+ol.loweralpha{list-style-type:lower-alpha}
+ol.upperalpha{list-style-type:upper-alpha}
+ol.lowerroman{list-style-type:lower-roman}
+ol.upperroman{list-style-type:upper-roman}
+ol.lowergreek{list-style-type:lower-greek}
+.hdlist>table,.colist>table{border:0;background:none}
+.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
+td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
+td.hdlist1{font-weight:bold;padding-bottom:1.25em}
+.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
+.colist td:not([class]):first-child{padding:.4em .75em 0;line-height:1;vertical-align:top}
+.colist td:not([class]):first-child img{max-width:none}
+.colist td:not([class]):last-child{padding:.25em 0}
+.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
+.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
+.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
+.imageblock>.title{margin-bottom:0}
+.imageblock.thumb,.imageblock.th{border-width:6px}
+.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
+.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
+.image.left{margin-right:.625em}
+.image.right{margin-left:.625em}
+a.image{text-decoration:none;display:inline-block}
+a.image object{pointer-events:none}
+sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
+sup.footnote a,sup.footnoteref a{text-decoration:none}
+sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
+#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
+#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em;border-width:1px 0 0}
+#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;margin-bottom:.2em}
+#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none;margin-left:-1.05em}
+#footnotes .footnote:last-of-type{margin-bottom:0}
+#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
+.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
+.gist .file-data>table td.line-data{width:99%}
+div.unbreakable{page-break-inside:avoid}
+.big{font-size:larger}
+.small{font-size:smaller}
+.underline{text-decoration:underline}
+.overline{text-decoration:overline}
+.line-through{text-decoration:line-through}
+.aqua{color:#00bfbf}
+.aqua-background{background-color:#00fafa}
+.black{color:#000}
+.black-background{background-color:#000}
+.blue{color:#0000bf}
+.blue-background{background-color:#0000fa}
+.fuchsia{color:#bf00bf}
+.fuchsia-background{background-color:#fa00fa}
+.gray{color:#606060}
+.gray-background{background-color:#7d7d7d}
+.green{color:#006000}
+.green-background{background-color:#007d00}
+.lime{color:#00bf00}
+.lime-background{background-color:#00fa00}
+.maroon{color:#600000}
+.maroon-background{background-color:#7d0000}
+.navy{color:#000060}
+.navy-background{background-color:#00007d}
+.olive{color:#606000}
+.olive-background{background-color:#7d7d00}
+.purple{color:#600060}
+.purple-background{background-color:#7d007d}
+.red{color:#bf0000}
+.red-background{background-color:#fa0000}
+.silver{color:#909090}
+.silver-background{background-color:#bcbcbc}
+.teal{color:#006060}
+.teal-background{background-color:#007d7d}
+.white{color:#bfbfbf}
+.white-background{background-color:#fafafa}
+.yellow{color:#bfbf00}
+.yellow-background{background-color:#fafa00}
+span.icon>.fa{cursor:default}
+a span.icon>.fa{cursor:inherit}
+.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
+.admonitionblock td.icon .icon-note::before{content:"\f05a";color:#19407c}
+.admonitionblock td.icon .icon-tip::before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
+.admonitionblock td.icon .icon-warning::before{content:"\f071";color:#bf6900}
+.admonitionblock td.icon .icon-caution::before{content:"\f06d";color:#bf3400}
+.admonitionblock td.icon .icon-important::before{content:"\f06a";color:#bf0000}
+.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
+.conum[data-value] *{color:#fff!important}
+.conum[data-value]+b{display:none}
+.conum[data-value]::after{content:attr(data-value)}
+pre .conum[data-value]{position:relative;top:-.125em}
+b.conum *{color:inherit!important}
+.conum:not([data-value]):empty{display:none}
+dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
+h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
+p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
+p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
+p{margin-bottom:1.25rem}
+.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
+.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
+.print-only{display:none!important}
+@page{margin:1.25cm .75cm}
+@media print{*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
+html{font-size:80%}
+a{color:inherit!important;text-decoration:underline!important}
+a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
+a[href^="http:"]:not(.bare)::after,a[href^="https:"]:not(.bare)::after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
+abbr[title]::after{content:" (" attr(title) ")"}
+pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
+thead{display:table-header-group}
+svg{max-width:100%}
+p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
+h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
+#toc,.sidebarblock,.exampleblock>.content{background:none!important}
+#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
+body.book #header{text-align:center}
+body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em}
+body.book #header .details{border:0!important;display:block;padding:0!important}
+body.book #header .details span:first-child{margin-left:0!important}
+body.book #header .details br{display:block}
+body.book #header .details br+span::before{content:none!important}
+body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
+body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
+.listingblock code[data-lang]::before{display:block}
+#footer{padding:0 .9375em}
+.hide-on-print{display:none!important}
+.print-only{display:block!important}
+.hide-for-print{display:none!important}
+.show-for-print{display:inherit!important}}
+@media print,amzn-kf8{#header>h1:first-child{margin-top:1.25rem}
+.sect1{padding:0!important}
+.sect1+.sect1{border:0}
+#footer{background:none}
+#footer-text{color:rgba(0,0,0,.6);font-size:.9em}}
+@media amzn-kf8{#header,#content,#footnotes,#footer{padding:0}}
+</style>
+</head>
+<body class="book toc2 toc-left">
+<div id="header">
+<h1>Clamp Rest API</h1>
+<div id="toc" class="toc2">
+<div id="toctitle">Table of Contents</div>
+<ul class="sectlevel1">
+<li><a href="#_overview">1. Overview</a>
+<ul class="sectlevel2">
+<li><a href="#_version_information">1.1. Version information</a></li>
+<li><a href="#_uri_scheme">1.2. URI scheme</a></li>
+</ul>
+</li>
+<li><a href="#_paths">2. Paths</a>
+<ul class="sectlevel2">
+<li><a href="#_verb189">2.1. GET /v1/healthcheck</a>
+<ul class="sectlevel3">
+<li><a href="#_responses">2.1.1. Responses</a></li>
+<li><a href="#_produces">2.1.2. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb190">2.2. GET /v1/user/getUser</a>
+<ul class="sectlevel3">
+<li><a href="#_responses_2">2.2.1. Responses</a></li>
+<li><a href="#_produces_2">2.2.2. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb188">2.3. GET /v2/clampInformation</a>
+<ul class="sectlevel3">
+<li><a href="#_responses_3">2.3.1. Responses</a></li>
+<li><a href="#_produces_3">2.3.2. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb173">2.4. GET /v2/dictionary</a>
+<ul class="sectlevel3">
+<li><a href="#_responses_4">2.4.1. Responses</a></li>
+<li><a href="#_produces_4">2.4.2. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb176">2.5. PUT /v2/dictionary</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters">2.5.1. Parameters</a></li>
+<li><a href="#_responses_5">2.5.2. Responses</a></li>
+<li><a href="#_consumes">2.5.3. Consumes</a></li>
+<li><a href="#_produces_5">2.5.4. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb174">2.6. GET /v2/dictionary/secondary/names</a>
+<ul class="sectlevel3">
+<li><a href="#_responses_6">2.6.1. Responses</a></li>
+<li><a href="#_produces_6">2.6.2. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb175">2.7. GET /v2/dictionary/{dictionaryName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_2">2.7.1. Parameters</a></li>
+<li><a href="#_responses_7">2.7.2. Responses</a></li>
+<li><a href="#_produces_7">2.7.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb177">2.8. PUT /v2/dictionary/{name}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_3">2.8.1. Parameters</a></li>
+<li><a href="#_responses_8">2.8.2. Responses</a></li>
+<li><a href="#_consumes_2">2.8.3. Consumes</a></li>
+<li><a href="#_produces_8">2.8.4. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb178">2.9. DELETE /v2/dictionary/{name}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_4">2.9.1. Parameters</a></li>
+<li><a href="#_responses_9">2.9.2. Responses</a></li>
+<li><a href="#_produces_9">2.9.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb179">2.10. DELETE /v2/dictionary/{name}/elements/{shortName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_5">2.10.1. Parameters</a></li>
+<li><a href="#_responses_10">2.10.2. Responses</a></li>
+<li><a href="#_produces_10">2.10.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb167">2.11. PUT /v2/loop/addOperationaPolicy/{loopName}/policyModel/{policyType}/{policyVersion}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_6">2.11.1. Parameters</a></li>
+<li><a href="#_responses_11">2.11.2. Responses</a></li>
+<li><a href="#_produces_11">2.11.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb169">2.12. POST /v2/loop/create/{loopName}?templateName={templateName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_7">2.12.1. Parameters</a></li>
+<li><a href="#_responses_12">2.12.2. Responses</a></li>
+<li><a href="#_consumes_3">2.12.3. Consumes</a></li>
+<li><a href="#_produces_12">2.12.4. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb165">2.13. PUT /v2/loop/delete/{loopName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_8">2.13.1. Parameters</a></li>
+<li><a href="#_responses_13">2.13.2. Responses</a></li>
+</ul>
+</li>
+<li><a href="#_verb158">2.14. PUT /v2/loop/deploy/{loopName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_9">2.14.1. Parameters</a></li>
+<li><a href="#_responses_14">2.14.2. Responses</a></li>
+<li><a href="#_produces_13">2.14.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb153">2.15. GET /v2/loop/getAllNames</a>
+<ul class="sectlevel3">
+<li><a href="#_responses_15">2.15.1. Responses</a></li>
+<li><a href="#_produces_14">2.15.2. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb166">2.16. GET /v2/loop/getstatus/{loopName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_10">2.16.1. Parameters</a></li>
+<li><a href="#_responses_16">2.16.2. Responses</a></li>
+<li><a href="#_produces_15">2.16.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb159">2.17. PUT /v2/loop/refreshMicroServicePolicyJsonSchema/{loopName}/{microServicePolicyName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_11">2.17.1. Parameters</a></li>
+<li><a href="#_responses_17">2.17.2. Responses</a></li>
+<li><a href="#_produces_16">2.17.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb160">2.18. PUT /v2/loop/refreshOperationalPolicyJsonSchema/{loopName}/{operationalPolicyName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_12">2.18.1. Parameters</a></li>
+<li><a href="#_responses_18">2.18.2. Responses</a></li>
+<li><a href="#_produces_17">2.18.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb168">2.19. PUT /v2/loop/removeOperationaPolicy/{loopName}/policyModel/{policyType}/{policyVersion}/{policyName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_13">2.19.1. Parameters</a></li>
+<li><a href="#_responses_19">2.19.2. Responses</a></li>
+<li><a href="#_produces_18">2.19.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb163">2.20. PUT /v2/loop/restart/{loopName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_14">2.20.1. Parameters</a></li>
+<li><a href="#_responses_20">2.20.2. Responses</a></li>
+<li><a href="#_produces_19">2.20.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb162">2.21. PUT /v2/loop/stop/{loopName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_15">2.21.1. Parameters</a></li>
+<li><a href="#_responses_21">2.21.2. Responses</a></li>
+<li><a href="#_produces_20">2.21.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb164">2.22. PUT /v2/loop/submit/{loopName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_16">2.22.1. Parameters</a></li>
+<li><a href="#_responses_22">2.22.2. Responses</a></li>
+<li><a href="#_produces_21">2.22.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb161">2.23. PUT /v2/loop/undeploy/{loopName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_17">2.23.1. Parameters</a></li>
+<li><a href="#_responses_23">2.23.2. Responses</a></li>
+<li><a href="#_produces_22">2.23.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb155">2.24. POST /v2/loop/updateGlobalProperties/{loopName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_18">2.24.1. Parameters</a></li>
+<li><a href="#_responses_24">2.24.2. Responses</a></li>
+<li><a href="#_consumes_4">2.24.3. Consumes</a></li>
+<li><a href="#_produces_23">2.24.4. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb157">2.25. POST /v2/loop/updateMicroservicePolicy/{loopName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_19">2.25.1. Parameters</a></li>
+<li><a href="#_responses_25">2.25.2. Responses</a></li>
+<li><a href="#_consumes_5">2.25.3. Consumes</a></li>
+<li><a href="#_produces_24">2.25.4. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb156">2.26. POST /v2/loop/updateOperationalPolicies/{loopName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_20">2.26.1. Parameters</a></li>
+<li><a href="#_responses_26">2.26.2. Responses</a></li>
+<li><a href="#_consumes_6">2.26.3. Consumes</a></li>
+<li><a href="#_produces_25">2.26.4. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb154">2.27. GET /v2/loop/{loopName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_21">2.27.1. Parameters</a></li>
+<li><a href="#_responses_27">2.27.2. Responses</a></li>
+<li><a href="#_produces_26">2.27.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb183">2.28. GET /v2/policies</a>
+<ul class="sectlevel3">
+<li><a href="#_responses_28">2.28.1. Responses</a></li>
+<li><a href="#_produces_27">2.28.2. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb186">2.29. PUT /v2/policies/pdpDeployment</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_22">2.29.1. Parameters</a></li>
+<li><a href="#_responses_29">2.29.2. Responses</a></li>
+<li><a href="#_consumes_7">2.29.3. Consumes</a></li>
+</ul>
+</li>
+<li><a href="#_verb187">2.30. POST /v2/policies/policytype</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_23">2.30.1. Parameters</a></li>
+<li><a href="#_responses_30">2.30.2. Responses</a></li>
+<li><a href="#_consumes_8">2.30.3. Consumes</a></li>
+</ul>
+</li>
+<li><a href="#_verb184">2.31. POST /v2/policies/{policyModelType}/{policyModelVersion}/{policyName}/{policyVersion}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_24">2.31.1. Parameters</a></li>
+<li><a href="#_responses_31">2.31.2. Responses</a></li>
+<li><a href="#_consumes_9">2.31.3. Consumes</a></li>
+<li><a href="#_produces_28">2.31.4. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb185">2.32. DELETE /v2/policies/{policyModelType}/{policyModelVersion}/{policyName}/{policyVersion}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_25">2.32.1. Parameters</a></li>
+<li><a href="#_responses_32">2.32.2. Responses</a></li>
+</ul>
+</li>
+<li><a href="#_verb180">2.33. GET /v2/policyToscaModels</a>
+<ul class="sectlevel3">
+<li><a href="#_responses_33">2.33.1. Responses</a></li>
+<li><a href="#_produces_29">2.33.2. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb182">2.34. GET /v2/policyToscaModels/yaml/{policyModelType}/{policyModelVersion}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_26">2.34.1. Parameters</a></li>
+<li><a href="#_responses_34">2.34.2. Responses</a></li>
+<li><a href="#_produces_30">2.34.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb181">2.35. GET /v2/policyToscaModels/{policyModelType}/{policyModelVersion}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_27">2.35.1. Parameters</a></li>
+<li><a href="#_responses_35">2.35.2. Responses</a></li>
+<li><a href="#_produces_31">2.35.3. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb170">2.36. GET /v2/templates</a>
+<ul class="sectlevel3">
+<li><a href="#_responses_36">2.36.1. Responses</a></li>
+<li><a href="#_produces_32">2.36.2. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb172">2.37. GET /v2/templates/names</a>
+<ul class="sectlevel3">
+<li><a href="#_responses_37">2.37.1. Responses</a></li>
+<li><a href="#_produces_33">2.37.2. Produces</a></li>
+</ul>
+</li>
+<li><a href="#_verb171">2.38. GET /v2/templates/{templateName}</a>
+<ul class="sectlevel3">
+<li><a href="#_parameters_28">2.38.1. Parameters</a></li>
+<li><a href="#_responses_38">2.38.2. Responses</a></li>
+<li><a href="#_produces_34">2.38.3. Produces</a></li>
+</ul>
+</li>
+</ul>
+</li>
+<li><a href="#_definitions">3. Definitions</a>
+<ul class="sectlevel2">
+<li><a href="#_clampinformation">3.1. ClampInformation</a></li>
+<li><a href="#_cldshealthcheck">3.2. CldsHealthCheck</a></li>
+<li><a href="#_dictionary">3.3. Dictionary</a></li>
+<li><a href="#_dictionaryelement">3.4. DictionaryElement</a></li>
+<li><a href="#_externalcomponent">3.5. ExternalComponent</a></li>
+<li><a href="#_externalcomponentstate">3.6. ExternalComponentState</a></li>
+<li><a href="#_jsonarray">3.7. JsonArray</a></li>
+<li><a href="#_jsonelement">3.8. JsonElement</a></li>
+<li><a href="#_jsonnull">3.9. JsonNull</a></li>
+<li><a href="#_jsonobject">3.10. JsonObject</a></li>
+<li><a href="#_jsonprimitive">3.11. JsonPrimitive</a></li>
+<li><a href="#_loop">3.12. Loop</a></li>
+<li><a href="#_loopelementmodel">3.13. LoopElementModel</a></li>
+<li><a href="#_looplog">3.14. LoopLog</a></li>
+<li><a href="#_looptemplate">3.15. LoopTemplate</a></li>
+<li><a href="#_looptemplateloopelementmodel">3.16. LoopTemplateLoopElementModel</a></li>
+<li><a href="#_microservicepolicy">3.17. MicroServicePolicy</a></li>
+<li><a href="#_number">3.18. Number</a></li>
+<li><a href="#_operationalpolicy">3.19. OperationalPolicy</a></li>
+<li><a href="#_policymodel">3.20. PolicyModel</a></li>
+<li><a href="#_service">3.21. Service</a></li>
+</ul>
+</li>
+</ul>
+</div>
+</div>
+<div id="content">
+<div class="sect1">
+<h2 id="_overview"><a class="anchor" href="#_overview"></a><a class="link" href="#_overview">1. Overview</a></h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_version_information"><a class="anchor" href="#_version_information"></a><a class="link" href="#_version_information">1.1. Version information</a></h3>
+<div class="paragraph">
+<p><em>Version</em> : 6.1.2-SNAPSHOT</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_uri_scheme"><a class="anchor" href="#_uri_scheme"></a><a class="link" href="#_uri_scheme">1.2. URI scheme</a></h3>
+<div class="paragraph">
+<p><em>Host</em> : localhost:37747<br>
+<em>BasePath</em> : /restservices/clds/<br>
+<em>Schemes</em> : HTTP</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_paths"><a class="anchor" href="#_paths"></a><a class="link" href="#_paths">2. Paths</a></h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_verb189"><a class="anchor" href="#_verb189"></a><a class="link" href="#_verb189">2.1. GET /v1/healthcheck</a></h3>
+<div class="sect3">
+<h4 id="_responses"><a class="anchor" href="#_responses"></a><a class="link" href="#_responses">2.1.1. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_cldshealthcheck">CldsHealthCheck</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces"><a class="anchor" href="#_produces"></a><a class="link" href="#_produces">2.1.2. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb190"><a class="anchor" href="#_verb190"></a><a class="link" href="#_verb190">2.2. GET /v1/user/getUser</a></h3>
+<div class="sect3">
+<h4 id="_responses_2"><a class="anchor" href="#_responses_2"></a><a class="link" href="#_responses_2">2.2.1. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 66.6667%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">No Content</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_2"><a class="anchor" href="#_produces_2"></a><a class="link" href="#_produces_2">2.2.2. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>text/plain</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb188"><a class="anchor" href="#_verb188"></a><a class="link" href="#_verb188">2.3. GET /v2/clampInformation</a></h3>
+<div class="sect3">
+<h4 id="_responses_3"><a class="anchor" href="#_responses_3"></a><a class="link" href="#_responses_3">2.3.1. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_clampinformation">ClampInformation</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_3"><a class="anchor" href="#_produces_3"></a><a class="link" href="#_produces_3">2.3.2. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb173"><a class="anchor" href="#_verb173"></a><a class="link" href="#_verb173">2.4. GET /v2/dictionary</a></h3>
+<div class="sect3">
+<h4 id="_responses_4"><a class="anchor" href="#_responses_4"></a><a class="link" href="#_responses_4">2.4.1. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_dictionary">Dictionary</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_4"><a class="anchor" href="#_produces_4"></a><a class="link" href="#_produces_4">2.4.2. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb176"><a class="anchor" href="#_verb176"></a><a class="link" href="#_verb176">2.5. PUT /v2/dictionary</a></h3>
+<div class="sect3">
+<h4 id="_parameters"><a class="anchor" href="#_parameters"></a><a class="link" href="#_parameters">2.5.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_dictionary">Dictionary</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_5"><a class="anchor" href="#_responses_5"></a><a class="link" href="#_responses_5">2.5.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_dictionary">Dictionary</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_consumes"><a class="anchor" href="#_consumes"></a><a class="link" href="#_consumes">2.5.3. Consumes</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_produces_5"><a class="anchor" href="#_produces_5"></a><a class="link" href="#_produces_5">2.5.4. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb174"><a class="anchor" href="#_verb174"></a><a class="link" href="#_verb174">2.6. GET /v2/dictionary/secondary/names</a></h3>
+<div class="sect3">
+<h4 id="_responses_6"><a class="anchor" href="#_responses_6"></a><a class="link" href="#_responses_6">2.6.1. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; string &gt; array</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_6"><a class="anchor" href="#_produces_6"></a><a class="link" href="#_produces_6">2.6.2. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb175"><a class="anchor" href="#_verb175"></a><a class="link" href="#_verb175">2.7. GET /v2/dictionary/{dictionaryName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_2"><a class="anchor" href="#_parameters_2"></a><a class="link" href="#_parameters_2">2.7.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dictionaryName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_7"><a class="anchor" href="#_responses_7"></a><a class="link" href="#_responses_7">2.7.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_dictionary">Dictionary</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_7"><a class="anchor" href="#_produces_7"></a><a class="link" href="#_produces_7">2.7.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb177"><a class="anchor" href="#_verb177"></a><a class="link" href="#_verb177">2.8. PUT /v2/dictionary/{name}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_3"><a class="anchor" href="#_parameters_3"></a><a class="link" href="#_parameters_3">2.8.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_dictionary">Dictionary</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_8"><a class="anchor" href="#_responses_8"></a><a class="link" href="#_responses_8">2.8.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_dictionary">Dictionary</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_consumes_2"><a class="anchor" href="#_consumes_2"></a><a class="link" href="#_consumes_2">2.8.3. Consumes</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_produces_8"><a class="anchor" href="#_produces_8"></a><a class="link" href="#_produces_8">2.8.4. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb178"><a class="anchor" href="#_verb178"></a><a class="link" href="#_verb178">2.9. DELETE /v2/dictionary/{name}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_4"><a class="anchor" href="#_parameters_4"></a><a class="link" href="#_parameters_4">2.9.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_9"><a class="anchor" href="#_responses_9"></a><a class="link" href="#_responses_9">2.9.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 66.6667%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">No Content</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_9"><a class="anchor" href="#_produces_9"></a><a class="link" href="#_produces_9">2.9.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb179"><a class="anchor" href="#_verb179"></a><a class="link" href="#_verb179">2.10. DELETE /v2/dictionary/{name}/elements/{shortName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_5"><a class="anchor" href="#_parameters_5"></a><a class="link" href="#_parameters_5">2.10.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>shortName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_10"><a class="anchor" href="#_responses_10"></a><a class="link" href="#_responses_10">2.10.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 66.6667%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">No Content</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_10"><a class="anchor" href="#_produces_10"></a><a class="link" href="#_produces_10">2.10.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb167"><a class="anchor" href="#_verb167"></a><a class="link" href="#_verb167">2.11. PUT /v2/loop/addOperationaPolicy/{loopName}/policyModel/{policyType}/{policyVersion}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_6"><a class="anchor" href="#_parameters_6"></a><a class="link" href="#_parameters_6">2.11.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyType</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyVersion</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_11"><a class="anchor" href="#_responses_11"></a><a class="link" href="#_responses_11">2.11.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_11"><a class="anchor" href="#_produces_11"></a><a class="link" href="#_produces_11">2.11.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb169"><a class="anchor" href="#_verb169"></a><a class="link" href="#_verb169">2.12. POST /v2/loop/create/{loopName}?templateName={templateName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_7"><a class="anchor" href="#_parameters_7"></a><a class="link" href="#_parameters_7">2.12.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>templateName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_12"><a class="anchor" href="#_responses_12"></a><a class="link" href="#_responses_12">2.12.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_consumes_3"><a class="anchor" href="#_consumes_3"></a><a class="link" href="#_consumes_3">2.12.3. Consumes</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_produces_12"><a class="anchor" href="#_produces_12"></a><a class="link" href="#_produces_12">2.12.4. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb165"><a class="anchor" href="#_verb165"></a><a class="link" href="#_verb165">2.13. PUT /v2/loop/delete/{loopName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_8"><a class="anchor" href="#_parameters_8"></a><a class="link" href="#_parameters_8">2.13.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_13"><a class="anchor" href="#_responses_13"></a><a class="link" href="#_responses_13">2.13.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 66.6667%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">No Content</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb158"><a class="anchor" href="#_verb158"></a><a class="link" href="#_verb158">2.14. PUT /v2/loop/deploy/{loopName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_9"><a class="anchor" href="#_parameters_9"></a><a class="link" href="#_parameters_9">2.14.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_14"><a class="anchor" href="#_responses_14"></a><a class="link" href="#_responses_14">2.14.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_13"><a class="anchor" href="#_produces_13"></a><a class="link" href="#_produces_13">2.14.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb153"><a class="anchor" href="#_verb153"></a><a class="link" href="#_verb153">2.15. GET /v2/loop/getAllNames</a></h3>
+<div class="sect3">
+<h4 id="_responses_15"><a class="anchor" href="#_responses_15"></a><a class="link" href="#_responses_15">2.15.1. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; string &gt; array</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_14"><a class="anchor" href="#_produces_14"></a><a class="link" href="#_produces_14">2.15.2. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb166"><a class="anchor" href="#_verb166"></a><a class="link" href="#_verb166">2.16. GET /v2/loop/getstatus/{loopName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_10"><a class="anchor" href="#_parameters_10"></a><a class="link" href="#_parameters_10">2.16.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_16"><a class="anchor" href="#_responses_16"></a><a class="link" href="#_responses_16">2.16.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_15"><a class="anchor" href="#_produces_15"></a><a class="link" href="#_produces_15">2.16.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb159"><a class="anchor" href="#_verb159"></a><a class="link" href="#_verb159">2.17. PUT /v2/loop/refreshMicroServicePolicyJsonSchema/{loopName}/{microServicePolicyName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_11"><a class="anchor" href="#_parameters_11"></a><a class="link" href="#_parameters_11">2.17.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>microServicePolicyName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_17"><a class="anchor" href="#_responses_17"></a><a class="link" href="#_responses_17">2.17.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_16"><a class="anchor" href="#_produces_16"></a><a class="link" href="#_produces_16">2.17.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb160"><a class="anchor" href="#_verb160"></a><a class="link" href="#_verb160">2.18. PUT /v2/loop/refreshOperationalPolicyJsonSchema/{loopName}/{operationalPolicyName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_12"><a class="anchor" href="#_parameters_12"></a><a class="link" href="#_parameters_12">2.18.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>operationalPolicyName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_18"><a class="anchor" href="#_responses_18"></a><a class="link" href="#_responses_18">2.18.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_17"><a class="anchor" href="#_produces_17"></a><a class="link" href="#_produces_17">2.18.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb168"><a class="anchor" href="#_verb168"></a><a class="link" href="#_verb168">2.19. PUT /v2/loop/removeOperationaPolicy/{loopName}/policyModel/{policyType}/{policyVersion}/{policyName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_13"><a class="anchor" href="#_parameters_13"></a><a class="link" href="#_parameters_13">2.19.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyType</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyVersion</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_19"><a class="anchor" href="#_responses_19"></a><a class="link" href="#_responses_19">2.19.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_18"><a class="anchor" href="#_produces_18"></a><a class="link" href="#_produces_18">2.19.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb163"><a class="anchor" href="#_verb163"></a><a class="link" href="#_verb163">2.20. PUT /v2/loop/restart/{loopName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_14"><a class="anchor" href="#_parameters_14"></a><a class="link" href="#_parameters_14">2.20.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_20"><a class="anchor" href="#_responses_20"></a><a class="link" href="#_responses_20">2.20.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_19"><a class="anchor" href="#_produces_19"></a><a class="link" href="#_produces_19">2.20.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb162"><a class="anchor" href="#_verb162"></a><a class="link" href="#_verb162">2.21. PUT /v2/loop/stop/{loopName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_15"><a class="anchor" href="#_parameters_15"></a><a class="link" href="#_parameters_15">2.21.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_21"><a class="anchor" href="#_responses_21"></a><a class="link" href="#_responses_21">2.21.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_20"><a class="anchor" href="#_produces_20"></a><a class="link" href="#_produces_20">2.21.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb164"><a class="anchor" href="#_verb164"></a><a class="link" href="#_verb164">2.22. PUT /v2/loop/submit/{loopName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_16"><a class="anchor" href="#_parameters_16"></a><a class="link" href="#_parameters_16">2.22.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_22"><a class="anchor" href="#_responses_22"></a><a class="link" href="#_responses_22">2.22.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_21"><a class="anchor" href="#_produces_21"></a><a class="link" href="#_produces_21">2.22.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb161"><a class="anchor" href="#_verb161"></a><a class="link" href="#_verb161">2.23. PUT /v2/loop/undeploy/{loopName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_17"><a class="anchor" href="#_parameters_17"></a><a class="link" href="#_parameters_17">2.23.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_23"><a class="anchor" href="#_responses_23"></a><a class="link" href="#_responses_23">2.23.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_22"><a class="anchor" href="#_produces_22"></a><a class="link" href="#_produces_22">2.23.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb155"><a class="anchor" href="#_verb155"></a><a class="link" href="#_verb155">2.24. POST /v2/loop/updateGlobalProperties/{loopName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_18"><a class="anchor" href="#_parameters_18"></a><a class="link" href="#_parameters_18">2.24.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_24"><a class="anchor" href="#_responses_24"></a><a class="link" href="#_responses_24">2.24.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_consumes_4"><a class="anchor" href="#_consumes_4"></a><a class="link" href="#_consumes_4">2.24.3. Consumes</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_produces_23"><a class="anchor" href="#_produces_23"></a><a class="link" href="#_produces_23">2.24.4. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb157"><a class="anchor" href="#_verb157"></a><a class="link" href="#_verb157">2.25. POST /v2/loop/updateMicroservicePolicy/{loopName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_19"><a class="anchor" href="#_parameters_19"></a><a class="link" href="#_parameters_19">2.25.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_microservicepolicy">MicroServicePolicy</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_25"><a class="anchor" href="#_responses_25"></a><a class="link" href="#_responses_25">2.25.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_microservicepolicy">MicroServicePolicy</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_consumes_5"><a class="anchor" href="#_consumes_5"></a><a class="link" href="#_consumes_5">2.25.3. Consumes</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_produces_24"><a class="anchor" href="#_produces_24"></a><a class="link" href="#_produces_24">2.25.4. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb156"><a class="anchor" href="#_verb156"></a><a class="link" href="#_verb156">2.26. POST /v2/loop/updateOperationalPolicies/{loopName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_20"><a class="anchor" href="#_parameters_20"></a><a class="link" href="#_parameters_20">2.26.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonarray">JsonArray</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_26"><a class="anchor" href="#_responses_26"></a><a class="link" href="#_responses_26">2.26.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_consumes_6"><a class="anchor" href="#_consumes_6"></a><a class="link" href="#_consumes_6">2.26.3. Consumes</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_produces_25"><a class="anchor" href="#_produces_25"></a><a class="link" href="#_produces_25">2.26.4. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb154"><a class="anchor" href="#_verb154"></a><a class="link" href="#_verb154">2.27. GET /v2/loop/{loopName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_21"><a class="anchor" href="#_parameters_21"></a><a class="link" href="#_parameters_21">2.27.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_27"><a class="anchor" href="#_responses_27"></a><a class="link" href="#_responses_27">2.27.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_26"><a class="anchor" href="#_produces_26"></a><a class="link" href="#_produces_26">2.27.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb183"><a class="anchor" href="#_verb183"></a><a class="link" href="#_verb183">2.28. GET /v2/policies</a></h3>
+<div class="sect3">
+<h4 id="_responses_28"><a class="anchor" href="#_responses_28"></a><a class="link" href="#_responses_28">2.28.1. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_27"><a class="anchor" href="#_produces_27"></a><a class="link" href="#_produces_27">2.28.2. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb186"><a class="anchor" href="#_verb186"></a><a class="link" href="#_verb186">2.29. PUT /v2/policies/pdpDeployment</a></h3>
+<div class="sect3">
+<h4 id="_parameters_22"><a class="anchor" href="#_parameters_22"></a><a class="link" href="#_parameters_22">2.29.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonelement">JsonElement</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_29"><a class="anchor" href="#_responses_29"></a><a class="link" href="#_responses_29">2.29.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 66.6667%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">No Content</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_consumes_7"><a class="anchor" href="#_consumes_7"></a><a class="link" href="#_consumes_7">2.29.3. Consumes</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb187"><a class="anchor" href="#_verb187"></a><a class="link" href="#_verb187">2.30. POST /v2/policies/policytype</a></h3>
+<div class="sect3">
+<h4 id="_parameters_23"><a class="anchor" href="#_parameters_23"></a><a class="link" href="#_parameters_23">2.30.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_30"><a class="anchor" href="#_responses_30"></a><a class="link" href="#_responses_30">2.30.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 66.6667%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">No Content</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_consumes_8"><a class="anchor" href="#_consumes_8"></a><a class="link" href="#_consumes_8">2.30.3. Consumes</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>plain/text</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb184"><a class="anchor" href="#_verb184"></a><a class="link" href="#_verb184">2.31. POST /v2/policies/{policyModelType}/{policyModelVersion}/{policyName}/{policyVersion}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_24"><a class="anchor" href="#_parameters_24"></a><a class="link" href="#_parameters_24">2.31.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelType</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelVersion</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyVersion</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Body</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>body</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonelement">JsonElement</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_31"><a class="anchor" href="#_responses_31"></a><a class="link" href="#_responses_31">2.31.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_consumes_9"><a class="anchor" href="#_consumes_9"></a><a class="link" href="#_consumes_9">2.31.3. Consumes</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_produces_28"><a class="anchor" href="#_produces_28"></a><a class="link" href="#_produces_28">2.31.4. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb185"><a class="anchor" href="#_verb185"></a><a class="link" href="#_verb185">2.32. DELETE /v2/policies/{policyModelType}/{policyModelVersion}/{policyName}/{policyVersion}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_25"><a class="anchor" href="#_parameters_25"></a><a class="link" href="#_parameters_25">2.32.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelType</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelVersion</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyVersion</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_32"><a class="anchor" href="#_responses_32"></a><a class="link" href="#_responses_32">2.32.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 33.3333%;">
+<col style="width: 66.6667%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">No Content</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb180"><a class="anchor" href="#_verb180"></a><a class="link" href="#_verb180">2.33. GET /v2/policyToscaModels</a></h3>
+<div class="sect3">
+<h4 id="_responses_33"><a class="anchor" href="#_responses_33"></a><a class="link" href="#_responses_33">2.33.1. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_policymodel">PolicyModel</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_29"><a class="anchor" href="#_produces_29"></a><a class="link" href="#_produces_29">2.33.2. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb182"><a class="anchor" href="#_verb182"></a><a class="link" href="#_verb182">2.34. GET /v2/policyToscaModels/yaml/{policyModelType}/{policyModelVersion}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_26"><a class="anchor" href="#_parameters_26"></a><a class="link" href="#_parameters_26">2.34.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelType</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelVersion</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_34"><a class="anchor" href="#_responses_34"></a><a class="link" href="#_responses_34">2.34.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_30"><a class="anchor" href="#_produces_30"></a><a class="link" href="#_produces_30">2.34.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb181"><a class="anchor" href="#_verb181"></a><a class="link" href="#_verb181">2.35. GET /v2/policyToscaModels/{policyModelType}/{policyModelVersion}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_27"><a class="anchor" href="#_parameters_27"></a><a class="link" href="#_parameters_27">2.35.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelType</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelVersion</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_35"><a class="anchor" href="#_responses_35"></a><a class="link" href="#_responses_35">2.35.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_31"><a class="anchor" href="#_produces_31"></a><a class="link" href="#_produces_31">2.35.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb170"><a class="anchor" href="#_verb170"></a><a class="link" href="#_verb170">2.36. GET /v2/templates</a></h3>
+<div class="sect3">
+<h4 id="_responses_36"><a class="anchor" href="#_responses_36"></a><a class="link" href="#_responses_36">2.36.1. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_looptemplate">LoopTemplate</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_32"><a class="anchor" href="#_produces_32"></a><a class="link" href="#_produces_32">2.36.2. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb172"><a class="anchor" href="#_verb172"></a><a class="link" href="#_verb172">2.37. GET /v2/templates/names</a></h3>
+<div class="sect3">
+<h4 id="_responses_37"><a class="anchor" href="#_responses_37"></a><a class="link" href="#_responses_37">2.37.1. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; string &gt; array</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_33"><a class="anchor" href="#_produces_33"></a><a class="link" href="#_produces_33">2.37.2. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_verb171"><a class="anchor" href="#_verb171"></a><a class="link" href="#_verb171">2.38. GET /v2/templates/{templateName}</a></h3>
+<div class="sect3">
+<h4 id="_parameters_28"><a class="anchor" href="#_parameters_28"></a><a class="link" href="#_parameters_28">2.38.1. Parameters</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 22.2222%;">
+<col style="width: 33.3333%;">
+<col style="width: 44.4445%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Type</th>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>Path</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>templateName</strong><br>
+<em>required</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_responses_38"><a class="anchor" href="#_responses_38"></a><a class="link" href="#_responses_38">2.38.2. Responses</a></h4>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 10%;">
+<col style="width: 70%;">
+<col style="width: 20%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">HTTP Code</th>
+<th class="tableblock halign-left valign-middle">Description</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>200</strong></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">Output type</p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_looptemplate">LoopTemplate</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect3">
+<h4 id="_produces_34"><a class="anchor" href="#_produces_34"></a><a class="link" href="#_produces_34">2.38.3. Produces</a></h4>
+<div class="ulist">
+<ul>
+<li>
+<p><code>application/json</code></p>
+</li>
+</ul>
+</div>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_definitions"><a class="anchor" href="#_definitions"></a><a class="link" href="#_definitions">3. Definitions</a></h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_clampinformation"><a class="anchor" href="#_clampinformation"></a><a class="link" href="#_clampinformation">3.1. ClampInformation</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>allPermissions</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; string &gt; array</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>cldsVersion</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>userName</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_cldshealthcheck"><a class="anchor" href="#_cldshealthcheck"></a><a class="link" href="#_cldshealthcheck">3.2. CldsHealthCheck</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>description</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>healthCheckComponent</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>healthCheckStatus</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_dictionary"><a class="anchor" href="#_dictionary"></a><a class="link" href="#_dictionary">3.3. Dictionary</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dictionaryElements</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; <a href="#_dictionaryelement">DictionaryElement</a> &gt; array</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>secondLevelDictionary</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>subDictionaryType</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_dictionaryelement"><a class="anchor" href="#_dictionaryelement"></a><a class="link" href="#_dictionaryelement">3.4. DictionaryElement</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>description</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>shortName</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>subDictionary</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>type</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>usedByDictionaries</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; <a href="#_dictionary">Dictionary</a> &gt; array</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_externalcomponent"><a class="anchor" href="#_externalcomponent"></a><a class="link" href="#_externalcomponent">3.5. ExternalComponent</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>componentName</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>state</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_externalcomponentstate">ExternalComponentState</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_externalcomponentstate"><a class="anchor" href="#_externalcomponentstate"></a><a class="link" href="#_externalcomponentstate">3.6. ExternalComponentState</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>description</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>level</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>stateName</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_jsonarray"><a class="anchor" href="#_jsonarray"></a><a class="link" href="#_jsonarray">3.7. JsonArray</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigDecimal</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigInteger</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBoolean</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asByte</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string (byte)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asCharacter</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asDouble</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number (double)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asFloat</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number (float)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asInt</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonArray</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonarray">JsonArray</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonNull</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonnull">JsonNull</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonObject</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonPrimitive</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonprimitive">JsonPrimitive</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asLong</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asNumber</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_number">Number</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asShort</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asString</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonArray</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonNull</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonObject</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonPrimitive</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_jsonelement"><a class="anchor" href="#_jsonelement"></a><a class="link" href="#_jsonelement">3.8. JsonElement</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigDecimal</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigInteger</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBoolean</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asByte</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string (byte)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asCharacter</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asDouble</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number (double)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asFloat</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number (float)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asInt</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonArray</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonarray">JsonArray</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonNull</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonnull">JsonNull</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonObject</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonPrimitive</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonprimitive">JsonPrimitive</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asLong</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asNumber</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_number">Number</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asShort</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asString</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonArray</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonNull</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonObject</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonPrimitive</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_jsonnull"><a class="anchor" href="#_jsonnull"></a><a class="link" href="#_jsonnull">3.9. JsonNull</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigDecimal</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigInteger</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBoolean</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asByte</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string (byte)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asCharacter</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asDouble</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number (double)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asFloat</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number (float)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asInt</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonArray</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonarray">JsonArray</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonNull</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonnull">JsonNull</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonObject</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonPrimitive</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonprimitive">JsonPrimitive</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asLong</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asNumber</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_number">Number</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asShort</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asString</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonArray</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonNull</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonObject</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonPrimitive</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_jsonobject"><a class="anchor" href="#_jsonobject"></a><a class="link" href="#_jsonobject">3.10. JsonObject</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigDecimal</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigInteger</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBoolean</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asByte</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string (byte)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asCharacter</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asDouble</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number (double)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asFloat</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number (float)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asInt</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonArray</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonarray">JsonArray</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonNull</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonnull">JsonNull</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonObject</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonPrimitive</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonprimitive">JsonPrimitive</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asLong</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asNumber</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_number">Number</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asShort</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asString</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonArray</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonNull</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonObject</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonPrimitive</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_jsonprimitive"><a class="anchor" href="#_jsonprimitive"></a><a class="link" href="#_jsonprimitive">3.11. JsonPrimitive</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigDecimal</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBigInteger</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asBoolean</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asByte</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string (byte)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asCharacter</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asDouble</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number (double)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asFloat</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">number (float)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asInt</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonArray</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonarray">JsonArray</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonNull</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonnull">JsonNull</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonObject</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asJsonPrimitive</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonprimitive">JsonPrimitive</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asLong</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asNumber</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_number">Number</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asShort</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>asString</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>boolean</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonArray</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonNull</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonObject</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonPrimitive</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>number</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>string</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_loop"><a class="anchor" href="#_loop"></a><a class="link" href="#_loop">3.12. Loop</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>components</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; string, <a href="#_externalcomponent">ExternalComponent</a> &gt; map</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeDeploymentId</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeDeploymentStatusUrl</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>globalPropertiesJson</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>lastComputedState</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">enum (DESIGN, SUBMITTED, DEPLOYED, RUNNING, STOPPED, IN_ERROR, WAITING)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopLogs</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; <a href="#_looplog">LoopLog</a> &gt; array</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopTemplate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_looptemplate">LoopTemplate</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>microServicePolicies</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; <a href="#_microservicepolicy">MicroServicePolicy</a> &gt; array</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>modelService</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_service">Service</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>operationalPolicies</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; <a href="#_operationalpolicy">OperationalPolicy</a> &gt; array</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_loopelementmodel"><a class="anchor" href="#_loopelementmodel"></a><a class="link" href="#_loopelementmodel">3.13. LoopElementModel</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>blueprint</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeBlueprintId</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopElementType</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModels</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; <a href="#_policymodel">PolicyModel</a> &gt; array</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>shortName</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>usedByLoopTemplates</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; <a href="#_looptemplateloopelementmodel">LoopTemplateLoopElementModel</a> &gt; array</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_looplog"><a class="anchor" href="#_looplog"></a><a class="link" href="#_looplog">3.14. LoopLog</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>id</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>logComponent</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>logInstant</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>logType</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">enum (INFO, WARNING, ERROR)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loop</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>message</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_looptemplate"><a class="anchor" href="#_looptemplate"></a><a class="link" href="#_looptemplate">3.15. LoopTemplate</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>allowedLoopType</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">enum (OPEN, CLOSED, HYBRID)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>blueprint</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeBlueprintId</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopElementModelsUsed</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; <a href="#_looptemplateloopelementmodel">LoopTemplateLoopElementModel</a> &gt; array</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>maximumInstancesAllowed</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>modelService</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_service">Service</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>uniqueBlueprint</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_looptemplateloopelementmodel"><a class="anchor" href="#_looptemplateloopelementmodel"></a><a class="link" href="#_looptemplateloopelementmodel">3.16. LoopTemplateLoopElementModel</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>flowOrder</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int32)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopElementModel</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loopelementmodel">LoopElementModel</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopTemplate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_looptemplate">LoopTemplate</a></p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_microservicepolicy"><a class="anchor" href="#_microservicepolicy"></a><a class="link" href="#_microservicepolicy">3.17. MicroServicePolicy</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>configurationsJson</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>context</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeBlueprintId</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeDeploymentId</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>dcaeDeploymentStatusUrl</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>deviceTypeScope</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonRepresentation</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopElementModel</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loopelementmodel">LoopElementModel</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>pdpGroup</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>pdpSubgroup</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModel</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_policymodel">PolicyModel</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>shared</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">boolean</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>usedByLoops</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; <a href="#_loop">Loop</a> &gt; array</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_number"><a class="anchor" href="#_number"></a><a class="link" href="#_number">3.18. Number</a></h3>
+<div class="paragraph">
+<p><em>Type</em> : object</p>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_operationalpolicy"><a class="anchor" href="#_operationalpolicy"></a><a class="link" href="#_operationalpolicy">3.19. OperationalPolicy</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>configurationsJson</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>jsonRepresentation</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loop</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loop">Loop</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>loopElementModel</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_loopelementmodel">LoopElementModel</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>pdpGroup</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>pdpSubgroup</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModel</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_policymodel">PolicyModel</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_policymodel"><a class="anchor" href="#_policymodel"></a><a class="link" href="#_policymodel">3.20. PolicyModel</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>createdDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyAcronym</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelTosca</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyModelType</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>policyPdpGroup</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedBy</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>updatedDate</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">integer (int64)</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>usedByElementModels</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">&lt; <a href="#_loopelementmodel">LoopElementModel</a> &gt; array</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>version</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+<div class="sect2">
+<h3 id="_service"><a class="anchor" href="#_service"></a><a class="link" href="#_service">3.21. Service</a></h3>
+<table class="tableblock frame-all grid-all stretch">
+<colgroup>
+<col style="width: 42.8571%;">
+<col style="width: 57.1429%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-middle">Name</th>
+<th class="tableblock halign-left valign-middle">Schema</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>name</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>resourceDetails</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>serviceDetails</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><a href="#_jsonobject">JsonObject</a></p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>serviceUuid</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-middle"><p class="tableblock"><strong>version</strong><br>
+<em>optional</em></p></td>
+<td class="tableblock halign-left valign-middle"><p class="tableblock">string</p></td>
+</tr>
+</tbody>
+</table>
+</div>
+</div>
+</div>
+</div>
+<div id="footer">
+<div id="footer-text">
+Last updated 2021-05-10 12:05:55 IST
+</div>
+</div>
+</body>
+</html>
diff --git a/runtime/src/main/resources/META-INF/services/org/apache/camel/dataformat/clamp-gson b/runtime/src/main/resources/META-INF/services/org/apache/camel/dataformat/clamp-gson
new file mode 100644
index 000000000..04caffa99
--- /dev/null
+++ b/runtime/src/main/resources/META-INF/services/org/apache/camel/dataformat/clamp-gson
@@ -0,0 +1,23 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ */
+
+class=org.onap.policy.clamp.configuration.ClampGsonDataFormat \ No newline at end of file
diff --git a/runtime/src/main/resources/application-noaaf.properties b/runtime/src/main/resources/application-noaaf.properties
new file mode 100644
index 000000000..1145b393d
--- /dev/null
+++ b/runtime/src/main/resources/application-noaaf.properties
@@ -0,0 +1,190 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP POLICY-CLAMP
+# ================================================================================
+# Copyright (C) 2017-2019, 2021 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+### Set the port for HTTP or HTTPS protocol (Controlled by Spring framework, only one at a time).
+### (See below for the parameter 'server.http.port' if you want to have both enabled)
+### To have only HTTP, keep the lines server.ssl.* commented
+### To have only HTTPS enabled, uncomment the server.ssl.* lines and specify a right keystore location
+### server.port=8080
+### Settings for HTTPS (this automatically enables the HTTPS on the port 'server.port')
+#server.ssl.key-store=file:/tmp/mykey.jks
+#server.ssl.key-store-password=pass
+#server.ssl.key-password=pass
+
+### In order to be user friendly when HTTPS is enabled,
+### you can add another HTTP port that will be automatically redirected to HTTPS
+### by enabling this parameter (server.http.port) and set it to another port (80 or 8080, 8090, etc ...)
+#server.http-to-https-redirection.port=8090
+
+### HTTP Example:
+###--------------
+### server.port=8080
+
+### HTTPS Example:
+### --------------
+### server.port=8443
+### server.ssl.key-store=file:/tmp/mykey.jks
+### server.ssl.key-store-password=mypass
+### server.ssl.key-password=mypass
+server.port=8443
+## Config part for Server certificates
+# Can be a classpath parameter instead of file:/
+server.ssl.key-store=classpath:/clds/aaf/org.onap.clamp.p12
+server.ssl.key-store-password=enc:WWCxchk4WGBNSvuzLq3MLjMs5ObRybJtts5AI0XD1Vc
+server.ssl.key-password=enc:WWCxchk4WGBNSvuzLq3MLjMs5ObRybJtts5AI0XD1Vc
+server.ssl.key-store-type=PKCS12
+server.ssl.key-alias=clamptest
+
+## Config part for Client certificates
+server.ssl.client-auth=want
+server.ssl.trust-store=classpath:/clds/aaf/truststoreONAPall.jks
+server.ssl.trust-store-password=enc:iDnPBBLq_EMidXlMa1FEuBR8TZzYxrCg66vq_XfLHdJ
+
+# The key file used to decode the key store and trust store password
+# If not defined, the key store and trust store password will not be decrypted
+clamp.config.keyFile=classpath:/clds/aaf/org.onap.clamp.keyfile
+
+#server.http-to-https-redirection.port=8080
+
+server.servlet.context-path=/
+#Modified engine-rest applicationpath
+spring.profiles.active=clamp-default,clamp-default-user,clamp-sdc-controller,clamp-ssl-config,clamp-policy-controller,default-dictionary-elements
+spring.http.converters.preferred-json-mapper=gson
+
+#The max number of active threads in this pool
+server.tomcat.max-threads=200
+#The minimum number of threads always kept alive
+server.tomcat.min-Spare-Threads=25
+#The number of milliseconds before an idle thread shutsdown, unless the number of active threads are less or equal to minSpareThreads
+server.tomcat.max-idle-time=60000
+
+#Servlet context parameters
+server.context_parameters.p-name=value #context parameter with p-name as key and value as value.
+
+camel.springboot.tracing=true
+camel.springboot.consumer-template-cache-size=1000
+camel.springboot.producer-template-cache-size=1000
+camel.springboot.jmx-enabled=true
+camel.defaultthreadpool.poolsize=10
+camel.defaultthreadpool.maxpoolsize=20
+camel.defaultthreadpool.maxqueuesize=1000
+camel.defaultthreadpool.keepaliveTime=60
+camel.defaultthreadpool.rejectpolicy=CallerRuns
+camel.springboot.xml-routes=classpath:/clds/camel/routes/*.xml
+camel.springboot.xml-rests=classpath:/clds/camel/rest/*.xml
+camel.springboot.backlog-tracing=true
+camel.springboot.tracing=true
+
+#clds datasource connection details
+spring.datasource.driverClassName=org.mariadb.jdbc.Driver
+spring.datasource.url=jdbc:mariadb:sequential://localhost:3306/cldsdb4?autoReconnect=true&connectTimeout=10000&socketTimeout=10000&retriesAllDown=3
+spring.datasource.username=clds
+spring.datasource.password=sidnnd83K
+spring.datasource.validationQuery=SELECT 1
+spring.datasource.validationQueryTimeout=20000
+spring.datasource.validationInterval=30000
+spring.datasource.testWhileIdle = true
+spring.datasource.minIdle = 0
+spring.datasource.initialSize=0
+# Automatically test whether a connection provided is good or not
+spring.datasource.testOnBorrow=true
+spring.datasource.ignoreExceptionOnPreLoad=true
+# control the sql db initialization (from schema.sql and data.sql)
+spring.datasource..initialize=false
+
+spring.jpa.properties.javax.persistence.schema-generation.database.action=none
+s#pring.jpa.properties.javax.persistence.schema-generation.create-source=metadata
+#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create
+#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql
+# disable Hibernate DDL generation because the schema will be generated from a sql script
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
+spring.jpa.properties.hibernate.ddl-auto=validate
+spring.jpa.properties.hibernate.hbm2ddl.delimiter=;
+spring.jpa.properties.hibernate.format_sql=true
+spring.jpa.properties.hibernate.use-new-id-generator-mappings=true
+
+# Whether to enable logging of SQL statements.
+#spring.jpa.show-sql=true
+
+#Async Executor default Parameters
+async.core.pool.size=10
+async.max.pool.size=20
+async.queue.capacity=500
+
+#For EELF logback file
+#clamp.config.logback.path=
+clamp.config.logback.filename=logback-default.xml
+#The log folder that will be used in logback.xml file
+clamp.config.log.path=/var/log/onap/clamp
+clamp.config.files.systemProperties=classpath:/system.properties
+clamp.config.files.cldsUsers=classpath:/clds/clds-users.json
+clamp.config.files.globalProperties=classpath:/clds/templates/globalProperties.json
+clamp.config.files.sdcController=classpath:/clds/sdc-controllers-config.json
+
+clamp.config.httpclient.socketTimeout=60000
+clamp.config.httpclient.connectTimeout=10000
+
+#
+# Configuration Settings for Policy Engine Components
+clamp.config.policy.api.url=http://localhost:8085
+clamp.config.policy.api.userName=healthcheck
+clamp.config.policy.api.password=zb!XztG34
+clamp.config.policy.pap.url=http://localhost:8085
+clamp.config.policy.pap.userName=healthcheck
+clamp.config.policy.pap.password=zb!XztG34
+
+#
+# Sdc service properties
+clamp.config.sdc.csarFolder = /tmp/sdc-controllers
+
+#DCAE Inventory Url Properties
+clamp.config.dcae.inventory.url=http://localhost:8085
+clamp.config.dcae.intentory.retry.interval=10000
+clamp.config.dcae.intentory.retry.limit=5
+
+#DCAE Deployment Url Properties
+clamp.config.dcae.deployment.url=http://localhost:8085
+clamp.config.dcae.deployment.userName=test
+clamp.config.dcae.deployment.password=test
+
+#Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case !
+clamp.config.security.permission.type.cl=org.onap.clamp.clds.cl
+clamp.config.security.permission.type.cl.manage=org.onap.clamp.clds.cl.manage
+clamp.config.security.permission.type.cl.event=org.onap.clamp.clds.cl.event
+clamp.config.security.permission.type.filter.vf=org.onap.clamp.clds.filter.vf
+clamp.config.security.permission.type.template=org.onap.clamp.clds.template
+clamp.config.security.permission.type.tosca=org.onap.clamp.clds.tosca
+clamp.config.security.permission.type.policies=org.onap.clamp.clds.policies
+#This one indicates the type of instances (dev|prod|perf...), this must be set accordingly in clds-users.properties
+clamp.config.security.permission.instance=dev
+clamp.config.security.authentication.class=org.onap.aaf.cadi.principal.X509Principal, org.onap.aaf.cadi.principal.CachedBasicPrincipal
+
+## Tosca converter
+clamp.config.tosca.converter.json.schema.templates=classpath:/clds/tosca-converter/templates.json
+clamp.config.tosca.converter.default.datatypes=classpath:/clds/tosca-converter/default-tosca-types.yaml
+clamp.config.tosca.converter.dictionary.support.enabled=true
+
+# Configuration settings for CDS
+clamp.config.cds.url=http://cds-blueprints-processor-http:8080
+clamp.config.cds.userName=ccsdkapps
+clamp.config.cds.password=ccsdkapps \ No newline at end of file
diff --git a/runtime/src/main/resources/application.properties b/runtime/src/main/resources/application.properties
new file mode 100644
index 000000000..3cbb7e8af
--- /dev/null
+++ b/runtime/src/main/resources/application.properties
@@ -0,0 +1,203 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP POLICY-CLAMP
+# ================================================================================
+# Copyright (C) 2017-2019, 2021 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Modifications copyright (c) 2019 Nokia
+# ================================================================================\
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+### Set the port for HTTP or HTTPS protocol (Controlled by Spring framework, only one at a time).
+### (See below for the parameter 'server.http.port' if you want to have both enabled)
+### To have only HTTP, keep the lines server.ssl.* commented
+### To have only HTTPS enabled, uncomment the server.ssl.* lines and specify a right keystore location
+### server.port=8080
+### Settings for HTTPS (this automatically enables the HTTPS on the port 'server.port')
+#server.ssl.key-store=file:/tmp/mykey.jks
+#server.ssl.key-store-password=pass
+#server.ssl.key-password=pass
+
+### In order to be user friendly when HTTPS is enabled,
+### you can add another HTTP port that will be automatically redirected to HTTPS
+### by enabling this parameter (server.http.port) and set it to another port (80 or 8080, 8090, etc ...)
+#server.http-to-https-redirection.port=8090
+
+### HTTP Example:
+###--------------
+### server.port=8080
+
+### HTTPS Example:
+### --------------
+### server.port=8443
+### server.ssl.key-store=file:/tmp/mykey.jks
+### server.ssl.key-store-password=mypass
+### server.ssl.key-password=mypass
+
+### HTTP (Redirected to HTTPS) and HTTPS Example:
+### --------------------------------------------
+server.port=8443
+## Config part for Server certificates
+# Can be a classpath parameter instead of file:/
+server.ssl.key-store=classpath:/clds/aaf/org.onap.clamp.p12
+server.ssl.key-store-password=enc:WWCxchk4WGBNSvuzLq3MLjMs5ObRybJtts5AI0XD1Vc
+server.ssl.key-password=enc:WWCxchk4WGBNSvuzLq3MLjMs5ObRybJtts5AI0XD1Vc
+server.ssl.key-store-type=PKCS12
+server.ssl.key-alias=clamptest
+
+# The key file used to decode the key store and trust store password
+# If not defined, the key store and trust store password will not be decrypted
+clamp.config.keyFile=classpath:/clds/aaf/org.onap.clamp.keyfile
+clamp.config.caCerts=classpath:/clds/aaf/ssl/ca-certs.pem
+
+## Config part for Client certificates
+server.ssl.client-auth=want
+server.ssl.trust-store=classpath:/clds/aaf/truststoreONAPall.jks
+server.ssl.trust-store-password=enc:iDnPBBLq_EMidXlMa1FEuBR8TZzYxrCg66vq_XfLHdJ
+
+#server.http-to-https-redirection.port=8080
+
+server.servlet.context-path=/
+#Modified engine-rest applicationpath
+spring.profiles.active=clamp-default,clamp-aaf-authentication,clamp-sdc-controller,clamp-ssl-config,clamp-policy-controller,default-dictionary-elements
+spring.http.converters.preferred-json-mapper=gson
+
+#The max number of active threads in this pool
+server.tomcat.max-threads=200
+#The minimum number of threads always kept alive
+server.tomcat.min-Spare-Threads=25
+#The number of milliseconds before an idle thread shutsdown, unless the number of active threads are less or equal to minSpareThreads
+server.tomcat.max-idle-time=60000
+
+#Servlet context parameters
+server.context_parameters.p-name=value #context parameter with p-name as key and value as value.
+camel.springboot.tracing=true
+camel.springboot.consumer-template-cache-size=1000
+camel.springboot.producer-template-cache-size=1000
+camel.springboot.jmx-enabled=true
+camel.defaultthreadpool.poolsize=10
+camel.defaultthreadpool.maxpoolsize=20
+camel.defaultthreadpool.maxqueuesize=1000
+camel.defaultthreadpool.keepaliveTime=60
+camel.defaultthreadpool.rejectpolicy=CallerRuns
+camel.springboot.xml-routes=classpath:/clds/camel/routes/*.xml
+camel.springboot.xml-rests=classpath:/clds/camel/rest/*.xml
+camel.springboot.backlog-tracing=true
+camel.springboot.tracing=true
+
+#clds datasource connection details
+spring.datasource.driverClassName=org.mariadb.jdbc.Driver
+spring.datasource.url=jdbc:mariadb:sequential://localhost:3306/cldsdb4?autoReconnect=true&connectTimeout=10000&socketTimeout=10000&retriesAllDown=3
+spring.datasource.username=clds
+spring.datasource.password=sidnnd83K
+spring.datasource.validationQuery=SELECT 1
+spring.datasource.validationQueryTimeout=20000
+spring.datasource.validationInterval=30000
+spring.datasource.testWhileIdle = true
+spring.datasource.minIdle = 0
+spring.datasource.initialSize=0
+# Automatically test whether a connection provided is good or not
+spring.datasource.testOnBorrow=true
+spring.datasource.ignoreExceptionOnPreLoad=true
+
+spring.jpa.properties.javax.persistence.schema-generation.database.action=none
+#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata
+#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create
+#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql
+# disable Hibernate DDL generation because the schema will be generated from a sql script
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
+spring.jpa.properties.hibernate.ddl-auto=validate
+spring.jpa.properties.hibernate.hbm2ddl.delimiter=;
+spring.jpa.properties.hibernate.format_sql=true
+spring.jpa.properties.hibernate.use-new-id-generator-mappings=true
+
+# Whether to enable logging of SQL statements.
+#spring.jpa.show-sql=true
+
+#Async Executor default Parameters
+async.core.pool.size=10
+async.max.pool.size=20
+async.queue.capacity=500
+
+#For EELF logback file
+#clamp.config.logback.path=
+clamp.config.logback.filename=logback-default.xml
+#The log folder that will be used in logback.xml file
+clamp.config.log.path=/var/log/onap/clamp
+clamp.config.files.systemProperties=classpath:/system.properties
+clamp.config.files.cldsUsers=classpath:/clds/clds-users.json
+clamp.config.files.globalProperties=classpath:/clds/templates/globalProperties.json
+clamp.config.files.sdcController=classpath:/clds/sdc-controllers-config.json
+
+clamp.config.httpclient.socketTimeout=60000
+clamp.config.httpclient.connectTimeout=10000
+#
+# Configuration Settings for Policy Engine Components
+clamp.config.policy.api.url=http://policy.api.simpledemo.onap.org:6969
+clamp.config.policy.api.userName=healthcheck
+clamp.config.policy.api.password=zb!XztG34
+clamp.config.policy.pap.url=http://policy.api.simpledemo.onap.org:6969
+clamp.config.policy.pap.userName=healthcheck
+clamp.config.policy.pap.password=zb!XztG34
+
+#
+# Sdc service properties
+clamp.config.sdc.csarFolder=/tmp/sdc-controllers
+
+#DCAE Inventory Url Properties
+clamp.config.dcae.inventory.url=http://dcae.api.simpledemo.onap.org:8080
+clamp.config.dcae.intentory.retry.interval=10000
+clamp.config.dcae.intentory.retry.limit=5
+
+#DCAE Deployment Url Properties
+clamp.config.dcae.deployment.url=http://dcae.api.simpledemo.onap.org:8188
+clamp.config.dcae.deployment.userName=test
+clamp.config.dcae.deployment.password=test
+
+#Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case !
+clamp.config.security.permission.type.cl=org.onap.clamp.clds.cl
+clamp.config.security.permission.type.cl.manage=org.onap.clamp.clds.cl.manage
+clamp.config.security.permission.type.cl.event=org.onap.clamp.clds.cl.event
+clamp.config.security.permission.type.filter.vf=org.onap.clamp.clds.filter.vf
+clamp.config.security.permission.type.template=org.onap.clamp.clds.template
+clamp.config.security.permission.type.tosca=org.onap.clamp.clds.tosca
+clamp.config.security.permission.type.policies=org.onap.clamp.clds.policies
+#This one indicates the type of instances (dev|prod|perf...), this must be set accordingly in clds-users.properties
+clamp.config.security.permission.instance=dev
+clamp.config.security.authentication.class=org.onap.aaf.cadi.principal.X509Principal, org.onap.aaf.cadi.principal.CachedBasicPrincipal
+
+#AAF related parameters
+clamp.config.cadi.cadiLoglevel=DEBUG
+clamp.config.cadi.cadiLatitude=10
+clamp.config.cadi.cadiLongitude=10
+clamp.config.cadi.aafLocateUrl=https://aaf-locate:30251
+clamp.config.cadi.oauthTokenUrl= https://AAF_LOCATE_URL/locate/onap.org.osaaf.aaf.token:2.1/token
+clamp.config.cadi.oauthIntrospectUrll=https://AAF_LOCATE_URL/locate/onap.org.osaaf.aaf.introspect:2.1/introspect
+clamp.config.cadi.aafEnv=DEV
+clamp.config.cadi.aafUrl=https://AAF_LOCATE_URL/onap.org.osaaf.aaf.service:2.1
+clamp.config.cadi.cadiX509Issuers=CN=intermediateCA_1, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_7, OU=OSAAF, O=ONAP, C=US:CN=intermediateCA_9, OU=OSAAF, O=ONAP, C=US
+
+## Tosca converter
+clamp.config.tosca.converter.json.schema.templates=classpath:/clds/tosca-converter/templates.json
+clamp.config.tosca.converter.default.datatypes=classpath:/clds/tosca-converter/default-tosca-types.yaml
+clamp.config.tosca.converter.dictionary.support.enabled=true
+
+# Configuration settings for CDS
+clamp.config.cds.url=http://cds-blueprints-processor-http:8080
+clamp.config.cds.userName=ccsdkapps
+clamp.config.cds.password=ccsdkapps \ No newline at end of file
diff --git a/runtime/src/main/resources/asciidoc/swagger.adoc b/runtime/src/main/resources/asciidoc/swagger.adoc
new file mode 100644
index 000000000..6896747fd
--- /dev/null
+++ b/runtime/src/main/resources/asciidoc/swagger.adoc
@@ -0,0 +1,4 @@
+include::{generated}/overview.adoc[]
+include::{generated}/paths.adoc[]
+include::{generated}/security.adoc[]
+include::{generated}/definitions.adoc[] \ No newline at end of file
diff --git a/runtime/src/main/resources/boot-message.txt b/runtime/src/main/resources/boot-message.txt
new file mode 100644
index 000000000..5a6cf1824
--- /dev/null
+++ b/runtime/src/main/resources/boot-message.txt
@@ -0,0 +1,16 @@
+
+ ___ _ _ _ ____ ___ _ _ _
+ / _ \| \ | | / \ | _ \ |_ _|___| |_ __ _ _ __ | |__ _ _| |
+ | | | | \| | / _ \ | |_) | | |/ __| __/ _` | '_ \| '_ \| | | | |
+ | |_| | |\ |/ ___ \| __/ | |\__ \ || (_| | | | | |_) | |_| | |
+ \___/|_| \_/_/ \_\_| |___|___/\__\__,_|_| |_|_.__/ \__,_|_|
+ ____ ___ _ ___ ______ __ ____ _ _ __ __ ____
+ | _ \ / _ \| | |_ _/ ___\ \ / / / ___| | / \ | \/ | _ \
+ | |_) | | | | | | | | \ V /____| | | | / _ \ | |\/| | |_) |
+ | __/| |_| | |___ | | |___ | |_____| |___| |___ / ___ \| | | | __/
+ |_| \___/|_____|___\____| |_| \____|_____/_/ \_\_| |_|_|
+
+
+
+
+ :: Starting :: \ No newline at end of file
diff --git a/runtime/src/main/resources/clds-version.properties b/runtime/src/main/resources/clds-version.properties
new file mode 100644
index 000000000..a0dbcdead
--- /dev/null
+++ b/runtime/src/main/resources/clds-version.properties
@@ -0,0 +1,24 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+clds.version=${project.version} \ No newline at end of file
diff --git a/runtime/src/main/resources/clds/aaf/org.onap.clamp.keyfile b/runtime/src/main/resources/clds/aaf/org.onap.clamp.keyfile
new file mode 100644
index 000000000..c2521fc81
--- /dev/null
+++ b/runtime/src/main/resources/clds/aaf/org.onap.clamp.keyfile
@@ -0,0 +1,27 @@
+kzJMxgphAoBxJz1_vYjxx-V87fahDQdYUqBIyWhZp8ojXdNpmB-96T9CvgJScJynbLcqw2Cj2CYx
+wd97vFOYhlyz5zK3tSyIuydOkVGJsJ1S4PviTtjhiJvNourJNDHgtas1Y1y2fQ5_8aVxj-s4W72N
+MNYhkeTinaQx_d_5hkBPABJlgCxKLnmxHo2jAJktnZYa5t5h48m7KiUx_RVEkQVtEvux-7vgXaC4
+ymTXj6zI9XoMTVxM0OAl4y7kBiUoOUaxS4tVKV34RJYNNqBjiUTQa_ag-KeUacRABk1ozfwzpvE5
+Sjz8WCy0L-LtCQnapkhKLt04ndCZtw8LDJ-Zz0ZgR2PVIPpTgs9VnVuOi5jf4LzTrtUatvOWkKB9
+drXKzp6cNXnZ0jkD3vV1BzqzhynKnZR2o_ilZv5CTTdpGUt906N_DwZuX6LfcV_7yvjX42bTfeIR
+ycPtodFPXlqqn9VUyh5nOauJlnOHAQmSDzjMEgjy17nQX3Ad7s4BfvujzUl-d0MqB_HCKbaW32UT
+xcY-0JfI1Y-2IdYfIkUdhVmxop6sSg0jAobWzgCRoRQkP3a2iIlKdfMyskshoWKIDVtlr-3fkDEb
+x_b_o1rRoUfzUzxEdphaUAq80Sc0i77ZLT3KF9vJOhyU_pBnApYFxVk7Hkk3VRxJKS7jyL4H7k1x
+2m5-2G8fB9XbYZT82xmAquNx4oBdpwj3_ncGF9YRF94K6NZgqemT5iWhpXMoelSU1blASgT3qlTm
+B6YgbD5owExNHwRVd8KeRsYrOnBWUiktsIhXFhNZmDUNWMFGQ2KxEcOt1tJwsQDehJFgY_l1JQ0d
+643wJ7rTJkGkYX309cydRQUX4Z0ckSQS9LhMd9stxF5XOHlvHdbW0pXNS7SaLbzKCVldUgncvI6z
+KWkwrWbftrZK2RT1UZKNngQDMGOk9OhbHAs7YzhFNFARZoRNobIv5tZVDomy-YgJb9-mD1UTkRBL
+WXOyoryDlgKrgFsgHclGDI1UFO5N-JfebPKxbP505f4924hxF2r8bspvVW8ZtHQo_SJmhauOX8n_
+eN_LK43LB9k53WAHZ_utvs0s6wGf7I73oj_N7DIFaHTDSm_MhDsFDLVG_wUzCpZ5FP2uL3nnqMkF
+Ob-l1fywfmfOmrz1BY6g4sRPPeWXuclYTnRnDRu5VQyc7_aBEVkyt3zw0JEex0vJNFUJl3pYjS55
+GplAB6p7VbS9ceZEtc5Z3qFIVHEzKWZxT190E23t_LlMuEoQ1zaqdHynNaMs61-q_A2aHRiTqlRm
+7FahVB3RX4AVLl23mu4u3A9ZDXc40nzjs9mwOVsuKlPvQ2rteDUG1njr2R1_V_MyQuoJjdfbIkPG
+4eF0QzlSMdbkeprdQxSfV5YT-yPpkBxSsCMMM43sKm4Hy7_CUdvp4Iayrp3vtK3oYMuCGi6qTadz
+KzxfTf8meKan3eMZW4RLByyniH5nQnX_KGfBly05AmFyVH_j0fyOg-48kDhtEKeqmDnP4C01jOID
+Ip_AKaB6e0GwsHzVTLZOklHwu_qzsaTzchBOG_dJJju7bxY7qv78Pa92wZIP311gSCVbc-gxxbsR
+qI555twmYEoasFm4xz10OYDOkvM1E1Rtxu3ymRLZpe6AoyFBVzEW7Dncdw7O98dKcgrp8ZlQ_8Wg
+5zZH0Cic7xnIZ0bNZyQXw56CSUiXVWuwVY3e0djXP3F-FO5gP8VTxbpW4C0t6McXAOlvSEfFKxN7
+u6OBeOKwjrtHaJk2ghF8MUcpDXanhbAgHez9larGlscCkgvoRLNaRH9GIdSVgY3HtNhJRaJIq01S
+OGeBjC5J4o-nTrqRFkwyDAYcPL373eYX1dBFFVHR-4q50H9m_zMxZHXETafxzV4DT3Qi8Sxh3uaS
+ZX7mRaNaOE0uC1n87_IZ9WhrwIQaZng2lnd9yZ-4rx8fB8WA8KQzifzvHAcMb_HV10JWGaz5A2Rm
+EXDsfexQC6CqYg5rdzzlNWDPNlHy5ubyz7fRXZ99uIwBY9aJcvCXCiEXJkC6utj3NcXQrJmk \ No newline at end of file
diff --git a/runtime/src/main/resources/clds/aaf/ssl/ca-certs.pem b/runtime/src/main/resources/clds/aaf/ssl/ca-certs.pem
new file mode 100644
index 000000000..70bb844b7
--- /dev/null
+++ b/runtime/src/main/resources/clds/aaf/ssl/ca-certs.pem
@@ -0,0 +1,32 @@
+Bag Attributes
+ friendlyName: CN=intermediateCA_9,OU=OSAAF,O=ONAP,C=US
+subject=C = US, O = ONAP, OU = OSAAF, CN = intermediateCA_9
+
+issuer=OU = OSAAF, O = ONAP, C = US
+
+-----BEGIN CERTIFICATE-----
+MIIEdTCCAl2gAwIBAgIBBzANBgkqhkiG9w0BAQsFADAsMQ4wDAYDVQQLDAVPU0FB
+RjENMAsGA1UECgwET05BUDELMAkGA1UEBhMCVVMwHhcNMTgwODE3MTg1MTM3WhcN
+MjMwODE3MTg1MTM3WjBHMQswCQYDVQQGEwJVUzENMAsGA1UECgwET05BUDEOMAwG
+A1UECwwFT1NBQUYxGTAXBgNVBAMMEGludGVybWVkaWF0ZUNBXzkwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCv0HHUkba3uNtNI3jPKimUcd6RNwmhSCJL
+neMWpnjqp5/A+HCKyNsEaT4y177hNLmCm/aMm1u2JIfikc+8wEqLCSBBPz+P0h+d
+o+sZ7U+4oeQizdYYpEdzHJ2SieHHa8vtu80rU3nO2NEIkuYC20HcKSEtl8fFKsk3
+nqlhY+tGfYJPTXcDOQAO40BTcgat3C3uIJHkWJJ4RivunE4LEuRv9QyKgAw7rkJV
+v+f7guqpZlXy6dzAkuU7XULWcgo55MkZlssoiErMvEZJad5aWKvRY3g7qUjaQ6wO
+15wOAUoRBW96eeZZbytgn8kybcBy++Ue49gPtgm1MF/KlAsp0MD5AgMBAAGjgYYw
+gYMwHQYDVR0OBBYEFIH3mVsQuciM3vNSXupOaaBDPqzdMB8GA1UdIwQYMBaAFFNV
+M/JL69BRscF4msEoMXvv6u1JMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/
+BAQDAgGGMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjANBgkqhkiG9w0B
+AQsFAAOCAgEADxNymiCNr2e37iLReoaxKmZvwox0cTiNAaj7iafRzmwIoY3VXO8Q
+ix5IYcp4FaQ7fV1jyp/AmaSnyHf6Osl0sx8PxsQkO7ALttxKUrjfbvNSVUA2C/vl
+u5m7UVJLIUtFDZBWanzUSmkTsYLHpiANFQKd2c/cU1qXcyzgJVFEFVyyHNkF7Is+
++pjG9M1hwQHOoTnEuU013P7X1mHek+RXEfhJWwe7UsZnBKZaZKbQZu7hEtqKWYp/
+QsHgnjoLYXsh0WD5rz/mBxdTdDLGpFqWDzDqb8rsYnqBzoowvsasV8X8OSkov0Ht
+8Yka0ckFH9yf8j1Cwmbl6ttuonOhky3N/gwLEozuhy7TPcZGVyzevF70kXy7g1CX
+kpFGJyEHXoprlNi8FR4I+NFzbDe6a2cFow1JN19AJ9Z5Rk5m7M0mQPaQ4RcikjB3
+aoLsASCJTm1OpOFHfxEKiBW4Lsp3Uc5/Rb9ZNbfLrwqWZRM7buW1e3ekLqntgbky
+uKKISHqVJuw/vXHl1jNibEo9+JuQ88VNuAcm7WpGUogeCa2iAlPTckPZei+MwZ8w
+tpvxTyYlZEC8DWzY1VC29+W2N5cvh01e2E3Ql08W1zL63dqrgdEZ3VWjzooYi4ep
+BmMXTvouW+Flyvcw/0oTcfN0biDIt0mCkZ5CQVjfGL9DTOYteR5hw+k=
+-----END CERTIFICATE-----
diff --git a/runtime/src/main/resources/clds/aaf/ssl/clamp.key b/runtime/src/main/resources/clds/aaf/ssl/clamp.key
new file mode 100644
index 000000000..bcbb9f17e
--- /dev/null
+++ b/runtime/src/main/resources/clds/aaf/ssl/clamp.key
@@ -0,0 +1,32 @@
+Bag Attributes
+ friendlyName: clamp@clamp.onap.org
+ localKeyID: 54 69 6D 65 20 31 35 38 30 38 32 39 30 36 35 34 37 39
+Key Attributes: <No Attributes>
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCTB30nMh0hczIk
+vWJo7Omg7cAHhz50NBhLB7u+60oXRGCya4SqssqqxNnNqNQQP9MmflW2q/bZepWn
+8Rk23X6CLmoIUlrj8BMPkUCRqzgvlaWPSNAK5QcOp6GUvXTuX4EsaWxJhbs9Ujz2
++qi137iNOqfAx1sUygah1kjALrqHkXDqJGvIfxU5ES0akBi/lB7A3WpE52KTioSF
+JS5Kbnpj1ogffGNKyAiNqU61LcF1FjWmINat2z3ZMk/3Xm+HCDg/GLPnbh4E1KoE
+10O22AMys6YGEyPvgRfrTF13DsDX52PmmUHbkSB6kwS/CeV5Uu++8b6T2IWpPyZ2
++5ptmL+tAgMBAAECggEBAIUplzRUswWEq7mSvPqC9+YE7pLi7rGYLRhnXKdBuszv
+5RQzROjFHcEkoI8fhVFiPP70FPVpMh0uZTTBrDCA0v9cwjPfQuqGmPzUdUJ5bF3M
+jzICpEn5vDaNpE5ueOUcIoXyxVyhfj+/p++YfgybHy7qHN0AsYFWqEMTLLjCmbYF
+pZozbAcGQoAR8PSfwuvgusuEezrhYertHsdFwlfZhDtJvnm/4YKRUVEBzuaaA7B9
+sUhnQFS8ScqiUbkAGdjfY9wOYRHnQgjtqiP8poIzLkqCNSoVctgh5Pdv4jp4HO90
+J5QC+f7m7rOoWUw8EYbRo/4C4Mckh0GQQ+oP4xzrtZECgYEA3DYALFgOEY+0RR1K
+61HAKqdNy1YbeuidpCBEJEwmIbzdgO1DcJdNznbfdRlmS7VB9orwRfNbf7Hxm2w/
+/xn9USENXWx7fvDoISqSDegvEsBSq5hSEMVl3f7CfQZrYl1f6gxfe7L/jtmbn0eQ
+avsr9RaUCWP794DEXKuA9pC8hVsCgYEAquy5I4hO4jNBQ6v5+omjsEgk4513/RNs
+f47Md8bsDHKJMbCMKCdqM1D3J1xbgV3DgSv0yNlKdU2wenWdgQAyBtz18NBgno85
+YNanFhp1CymgLFHdLJHSOqAkzutSuCNnGTT6AKspOQvy+cuj7XsnbsxtYK3Cgw5h
+Mom3RnUy9ZcCgYAnForHVEYDBgAYuI9g39z9dT8Q1dMA6SN6S6Ps0Xt/R5gF15e9
+941/FYiqr3yB+cWgrp7hu8XFD9/0F63waTuW2AgYSjZNnROHN5g/UbRxXqQOA3al
+tXRUiHEbYjVTe4GX+ORF/8rvH19JUZmn87ekxII4fH/wOfIhBOxaV+yuuwKBgHtz
+5Tizz/3y9TWSdkgtt6uwP+yipLKGn/v1wNrWM1G+PDdGg8TQyxTrasfkHjdu6LFY
+dUHIJ85X4ZphbvRolrl8SKq5Zr+/RLsb7qy5SUZZt1Wrfysc25H6bvuA3ksfTuzW
+5acr+Oc6KTGgkvMI229cebe1aONNtIhTDav3JGpbAoGAX5DQvNreqnP8qSAvUN2I
+TAHXIzawR3f6vgGgVIdkHkiS2eKzs/fgP3VAK80TbrGSR8HvBcPEcR/icOn1u/e6
+tDp0j6mGt5aPKK9VQkBn94bW35T12FUbdB+L8FWWTUrfiVWJtEW8tEsKil5ac8U4
+Bn3vC5WUeKhW6v6kD4AigqE=
+-----END PRIVATE KEY-----
diff --git a/runtime/src/main/resources/clds/aaf/ssl/clamp.pem b/runtime/src/main/resources/clds/aaf/ssl/clamp.pem
new file mode 100644
index 000000000..a01b587a5
--- /dev/null
+++ b/runtime/src/main/resources/clds/aaf/ssl/clamp.pem
@@ -0,0 +1,33 @@
+Bag Attributes
+ friendlyName: clamp@clamp.onap.org
+ localKeyID: 54 69 6D 65 20 31 35 38 30 38 32 39 30 36 35 34 37 39
+subject=CN = clamp, emailAddress = mark.d.manager@people.osaaf.com, OU = clamp@clamp.onap.org:DEV, OU = OSAAF, O = ONAP, C = US
+
+issuer=C = US, O = ONAP, OU = OSAAF, CN = intermediateCA_9
+
+-----BEGIN CERTIFICATE-----
+MIIEWDCCA0CgAwIBAgIILw1zyDGqB5IwDQYJKoZIhvcNAQELBQAwRzELMAkGA1UE
+BhMCVVMxDTALBgNVBAoMBE9OQVAxDjAMBgNVBAsMBU9TQUFGMRkwFwYDVQQDDBBp
+bnRlcm1lZGlhdGVDQV85MB4XDTIwMDIwNDEyMjM1MloXDTIxMDIwNDEyMjM1Mlow
+gY8xDjAMBgNVBAMMBWNsYW1wMS4wLAYJKoZIhvcNAQkBFh9tYXJrLmQubWFuYWdl
+ckBwZW9wbGUub3NhYWYuY29tMSEwHwYDVQQLDBhjbGFtcEBjbGFtcC5vbmFwLm9y
+ZzpERVYxDjAMBgNVBAsMBU9TQUFGMQ0wCwYDVQQKDARPTkFQMQswCQYDVQQGEwJV
+UzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJMHfScyHSFzMiS9Ymjs
+6aDtwAeHPnQ0GEsHu77rShdEYLJrhKqyyqrE2c2o1BA/0yZ+Vbar9tl6lafxGTbd
+foIuaghSWuPwEw+RQJGrOC+VpY9I0ArlBw6noZS9dO5fgSxpbEmFuz1SPPb6qLXf
+uI06p8DHWxTKBqHWSMAuuoeRcOoka8h/FTkRLRqQGL+UHsDdakTnYpOKhIUlLkpu
+emPWiB98Y0rICI2pTrUtwXUWNaYg1q3bPdkyT/deb4cIOD8Ys+duHgTUqgTXQ7bY
+AzKzpgYTI++BF+tMXXcOwNfnY+aZQduRIHqTBL8J5XlS777xvpPYhak/Jnb7mm2Y
+v60CAwEAAaOB/jCB+zAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIF4DAgBgNVHSUB
+Af8EFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwVAYDVR0jBE0wS4AUgfeZWxC5yIze
+81Je6k5poEM+rN2hMKQuMCwxDjAMBgNVBAsMBU9TQUFGMQ0wCwYDVQQKDARPTkFQ
+MQswCQYDVQQGEwJVU4IBBzAdBgNVHQ4EFgQUzfIed+18wgFs7E6q0b6BbMICtfsw
+RwYDVR0RBEAwPoIFY2xhbXCCCmNsYW1wLW9uYXCCHWNsYW1wLmFwaS5zaW1wbGVk
+ZW1vLm9uYXAub3JnggpjbGFtcC5vbmFwMA0GCSqGSIb3DQEBCwUAA4IBAQBizhsW
+XrJ9wQy3PrBxgh90sOF15tayXPRZSFYPoQb5LhRh3IY/PvXLaSHlkgPHlCLLx36S
+0/DiVf86/83ABvyaq9gJIyg/m4ntNae23OKH1AkA1aN+JCKA8yhsAzDBcRF6Aj7E
+VJ+vQlSzz5oh+efP1e/8DUMd1/WwbTXvRd0Iqv/fyZunbjb82qNMrsK1mQ2q+87A
+0jx9u1EdeMihP6vWiuKzlwy4mKoNT573SPpvaOkjX3yDlmf2CTQZ9vdAvjmFmVsH
+1wyrNZOIgW4VjluiZfAk3mOEskrZiP/7aUXnxmNnYTpgZMbhiouLbRrTc4lLEyhx
+G7A61/KGTsLZlvxb
+-----END CERTIFICATE-----
diff --git a/runtime/src/main/resources/clds/aaf/truststoreONAPall.jks b/runtime/src/main/resources/clds/aaf/truststoreONAPall.jks
new file mode 100644
index 000000000..ff844b109
--- /dev/null
+++ b/runtime/src/main/resources/clds/aaf/truststoreONAPall.jks
Binary files differ
diff --git a/runtime/src/main/resources/clds/camel/rest/clamp-api-v2.xml b/runtime/src/main/resources/clds/camel/rest/clamp-api-v2.xml
new file mode 100644
index 000000000..4659a90bf
--- /dev/null
+++ b/runtime/src/main/resources/clds/camel/rest/clamp-api-v2.xml
@@ -0,0 +1,1472 @@
+<rests xmlns="http://camel.apache.org/schema/spring">
+ <rest>
+ <get uri="/v2/loop/getAllNames" outType="java.lang.String[]"
+ produces="application/json">
+ <route>
+ <removeHeaders pattern="*"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Loop')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','read')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopController?method=getLoopNames()"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="GET All Loop names FAILED: ${exception.stacktrace}"/>
+
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>GET All Loop names FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </get>
+ <get uri="/v2/loop/{loopName}" outType="org.onap.policy.clamp.loop.Loop"
+ produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET Loop')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','read')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopController?method=getLoop(${header.loopName})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="GET Loop request failed for loop: ${header.loopName}, ${exception.stacktrace}"/>
+
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>GET Loop FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </get>
+
+ <post uri="/v2/loop/updateGlobalProperties/{loopName}"
+ type="com.google.gson.JsonObject" consumes="application/json"
+ outType="org.onap.policy.clamp.loop.Loop" produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Update the global properties')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <setHeader name="GlobalPropertiesJson">
+ <simple>${body}</simple>
+ </setHeader>
+ <to uri="direct:load-loop"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopController?method=updateGlobalPropertiesJson(${header.loopName},${header.GlobalPropertiesJson})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('Global Properties UPDATED','INFO',${exchangeProperty[loopObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="UPDATE Global properties FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>UPDATE Global properties FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </post>
+ <post uri="/v2/loop/updateOperationalPolicies/{loopName}"
+ type="com.google.gson.JsonArray" consumes="application/json"
+ outType="org.onap.policy.clamp.loop.Loop" produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Update operational policies')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <setHeader name="OperationalPoliciesArray">
+ <simple>${body}</simple>
+ </setHeader>
+ <to uri="direct:load-loop"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopController?method=updateOperationalPolicies(${header.loopName},${header.OperationalPoliciesArray})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('Operational policies UPDATED','INFO',${exchangeProperty[loopObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="UPDATE Operational policies FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('UPDATE Operational policies request FAILED, Error reported: ${exception.message}','ERROR',${exchangeProperty[loopObject]})"/>
+
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>UPDATE Operational policies FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </post>
+ <post uri="/v2/loop/updateMicroservicePolicy/{loopName}"
+ type="org.onap.policy.clamp.policy.microservice.MicroServicePolicy"
+ consumes="application/json"
+ outType="org.onap.policy.clamp.policy.microservice.MicroServicePolicy"
+ produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Update Microservice policies')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <setProperty name="MicroServicePolicyObject">
+ <simple>${body}</simple>
+ </setProperty>
+
+ <to uri="direct:load-loop"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopController?method=updateMicroservicePolicy(${header.loopName},${exchangeProperty[MicroServicePolicyObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('Micro Service policies UPDATED','INFO',${exchangeProperty[loopObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="UPDATE MicroService policy FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('UPDATE MicroService policy request FAILED, Error reported: ${exception.message}','ERROR',${exchangeProperty[loopObject]})"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>UPDATE MicroService policy FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </post>
+ <put uri="/v2/loop/deploy/{loopName}"
+ outType="org.onap.policy.clamp.loop.Loop" produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="DCAE DEPLOY request for loop: ${header.loopName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'DCAE DEPLOY request')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <to uri="direct:load-loop"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('DCAE DEPLOY request','INFO',${exchangeProperty[loopObject]})"/>
+ <to uri="direct:deploy-loop"/>
+
+ <log loggingLevel="INFO"
+ message="DEPLOY request successfully executed for loop: ${header.loopName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('DEPLOY request successfully executed','INFO',${exchangeProperty[loopObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="DEPLOY request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('DEPLOY request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>DEPLOY request FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </put>
+ <put uri="/v2/loop/refreshMicroServicePolicyJsonSchema/{loopName}/{microServicePolicyName}"
+ outType="org.onap.policy.clamp.loop.Loop" produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName|microServicePolicyName"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Refresh Micro Service Policy UI for loop: ${header.loopName} and ${header.microServicePolicyName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'REFRESH Micro Service Policy UI request')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <to uri="direct:load-loop"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.cds.CdsDataInstaller?method=updateCdsServiceProperties(${exchangeProperty[loopObject].getModelService()})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopController?method=refreshMicroServicePolicyJsonRepresentation(${exchangeProperty[loopObject]},${header.microServicePolicyName})"/>
+ <log loggingLevel="INFO"
+ message="REFRESH Micro Service policy request successfully executed for loop: ${header.loopName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('REFRESH Micro Service policy request successfully executed','INFO',${exchangeProperty[loopObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="REFRESH json schema request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('REFRESH Json schema request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>REFRESH json schema request FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </put>
+ <put uri="/v2/loop/refreshOperationalPolicyJsonSchema/{loopName}/{operationalPolicyName}"
+ outType="org.onap.policy.clamp.loop.Loop" produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName|operationalPolicyName"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Refresh Operational Policy UI for loop: ${header.loopName} and ${header.operationalPolicyName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'REFRESH Operational Policy UI request')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <to uri="direct:load-loop"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.cds.CdsDataInstaller?method=updateCdsServiceProperties(${exchangeProperty[loopObject].getModelService()})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopController?method=refreshOperationalPolicyJsonRepresentation(${exchangeProperty[loopObject]},${header.operationalPolicyName})"/>
+ <log loggingLevel="INFO"
+ message="REFRESH operational policy request successfully executed for loop: ${header.loopName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('REFRESH operational policy request successfully executed','INFO',${exchangeProperty[loopObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="REFRESH json schema request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('REFRESH Json schema request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>REFRESH json schema request FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </put>
+ <put uri="/v2/loop/undeploy/{loopName}"
+ outType="org.onap.policy.clamp.loop.Loop" produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="DCAE UNDEPLOY request for loop: ${header.loopName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'DCAE UNDEPLOY request')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <to uri="direct:load-loop"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('DCAE UNDEPLOY request','INFO',${exchangeProperty[loopObject]})"/>
+ <to uri="direct:undeploy-loop"/>
+
+ <log loggingLevel="INFO"
+ message="UNDEPLOY request successfully executed for loop: ${header.loopName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('UNDEPLOY request successfully executed','INFO',${exchangeProperty[loopObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="UNDEPLOY request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('UNDEPLOY request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>UNDEPLOY request FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </put>
+ <put uri="/v2/loop/stop/{loopName}"
+ outType="org.onap.policy.clamp.loop.Loop" produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="STOP request for loop: ${header.loopName}"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*,'STOP request')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <to uri="direct:load-loop"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('STOP request','INFO',${exchangeProperty[loopObject]})"/>
+
+ <to uri="direct:remove-all-policy-from-active-pdp-group"/>
+ <log loggingLevel="INFO"
+ message="STOP request successfully executed for loop: ${header.loopName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('STOP request successfully executed','INFO',${exchangeProperty[loopObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="STOP request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('STOP request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>STOP request FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </put>
+ <put uri="/v2/loop/restart/{loopName}"
+ outType="org.onap.policy.clamp.loop.Loop" produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="RESTART request for loop: ${header.loopName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*,'RESTART request')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <to uri="direct:load-loop"/>
+
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('RESTART request','INFO',${exchangeProperty[loopObject]})"/>
+
+ <to uri="direct:add-policies-from-loop-to-pdp-group"/>
+ <log loggingLevel="INFO"
+ message="RESTART request successfully executed for loop: ${header.loopName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('RESTART request successfully executed','INFO',${exchangeProperty[loopObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="RESTART request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('RESTART request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>RESTART request FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </put>
+ <put uri="/v2/loop/submit/{loopName}"
+ outType="org.onap.policy.clamp.loop.Loop" produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="POLICY SUBMIT request for loop: ${header.loopName}"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'POLICY SUBMIT request')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <to uri="direct:load-loop"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('POLICY SUBMIT request','INFO',${exchangeProperty[loopObject]})"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <to uri="direct:remove-all-policy-from-active-pdp-group"/>
+ <log loggingLevel="INFO"
+ message="Processing all MICRO-SERVICES policies defined in loop ${exchangeProperty[loopObject].getName()}"/>
+ <split>
+ <simple>${exchangeProperty[loopObject].getMicroServicePolicies()}
+ </simple>
+ <setProperty name="policy">
+ <simple>${body}</simple>
+ </setProperty>
+ <log loggingLevel="INFO"
+ message="Processing Micro Service Policy: ${exchangeProperty[policy].getName()}"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <to uri="direct:delete-policy-from-loop-object"/>
+ <to uri="direct:create-policy-from-loop-object"/>
+ </split>
+ <log loggingLevel="INFO"
+ message="Processing all OPERATIONAL policies defined in loop ${exchangeProperty[loopObject].getName()}"/>
+ <split>
+ <simple>${exchangeProperty[loopObject].getOperationalPolicies()}
+ </simple>
+ <setProperty name="policy">
+ <simple>${body}</simple>
+ </setProperty>
+ <log loggingLevel="INFO"
+ message="Processing Operational Policy: ${exchangeProperty[policy].getName()}"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+
+ <to uri="direct:delete-policy-from-loop-object"/>
+ <to uri="direct:create-policy-from-loop-object"/>
+ </split>
+
+ <delay>
+ <constant>3000</constant>
+ </delay>
+
+ <to uri="direct:add-policies-from-loop-to-pdp-group"/>
+
+ <log loggingLevel="INFO"
+ message="SUBMIT request successfully executed for loop: ${header.loopName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('SUBMIT request successfully executed','INFO',${exchangeProperty[loopObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="SUBMIT request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('SUBMIT request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>SUBMIT request FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </put>
+ <put uri="/v2/loop/delete/{loopName}">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="DELETE request for loop: ${header.loopName}"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*,'DELETE request')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <to uri="direct:load-loop"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('DELETE request','INFO',${exchangeProperty[loopObject]})"/>
+ <to uri="direct:undeploy-loop"/>
+ <to uri="direct:remove-all-policy-from-active-pdp-group"/>
+ <log loggingLevel="INFO"
+ message="Deleting all MICRO-SERVICES policies defined in loop ${exchangeProperty[loopObject].getName()}"/>
+ <split>
+ <simple>${exchangeProperty[loopObject].getMicroServicePolicies()}
+ </simple>
+ <setProperty name="policy">
+ <simple>${body}</simple>
+ </setProperty>
+ <log loggingLevel="INFO"
+ message="Deleting Micro Service Policy: ${exchangeProperty[policy].getName()}"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <to uri="direct:delete-policy-from-loop-object"/>
+ </split>
+ <log loggingLevel="INFO"
+ message="Deleting all OPERATIONAL policies defined in loop ${exchangeProperty[loopObject].getName()}"/>
+ <split>
+ <simple>${exchangeProperty[loopObject].getOperationalPolicies()}
+ </simple>
+ <setProperty name="policy">
+ <simple>${body}</simple>
+ </setProperty>
+ <log loggingLevel="INFO"
+ message="Deleting Operational Policy: ${exchangeProperty[policy].getName()}"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <to uri="direct:delete-policy-from-loop-object"/>
+ </split>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopController?method=deleteLoop(${header.loopName})"/>
+ <log loggingLevel="INFO"
+ message="DELETE request successfully executed for loop: ${header.loopName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="DELETE request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('DELETE request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>DELETE request FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </put>
+ <get uri="/v2/loop/getstatus/{loopName}"
+ outType="org.onap.policy.clamp.loop.Loop" produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="GET STATUS request for loop: ${header.loopName}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET STATUS request')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','read')"/>
+ <to uri="direct:load-loop"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('GET STATUS request','INFO',${exchangeProperty[loopObject]})"/>
+ <to uri="direct:update-policy-status-for-loop"/>
+ <to uri="direct:update-dcae-status-for-loop"/>
+ <to uri="direct:update-loop-state"/>
+
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('GET STATUS request successfully executed','INFO',${exchangeProperty[loopObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="GET STATUS request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('GET STATUS request failed, Error reported: ${exception} - Body: ${exception.responseBody}','ERROR',${exchangeProperty[loopObject]})"/>
+ </doCatch>
+ <doFinally>
+ <setBody>
+ <simple>${exchangeProperty[loopObject]}</simple>
+ </setBody>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>200</constant>
+ </setHeader>
+ </doFinally>
+ </doTry>
+ </route>
+ </get>
+
+ <put uri="/v2/loop/addOperationaPolicy/{loopName}/policyModel/{policyType}/{policyVersion}"
+ outType="org.onap.policy.clamp.loop.Loop" produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName|policyType|policyVersion"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Add operational Policy')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <to uri="direct:load-loop"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopController?method=addOperationalPolicy(${header.loopName},${header.policyType},${header.policyVersion})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('ADD OperationalPolicy request successfully executed','INFO',${exchangeProperty[loopObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="ADD operational policy request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('ADD OperationalPolicy request failed','ERROR',${exchangeProperty[loopObject]})"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>ADD Operational policy request FAILED for loop: ${header.loopName},
+ ${exception.message}"
+ </simple>
+ </setBody>
+
+ </doCatch>
+ </doTry>
+ </route>
+ </put>
+ <put uri="/v2/loop/removeOperationaPolicy/{loopName}/policyModel/{policyType}/{policyVersion}/{policyName}"
+ outType="org.onap.policy.clamp.loop.Loop" produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="loopName|policyType|policyVersion|policyName"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'REMOVE operational Policy')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <to uri="direct:load-loop"/>
+ <setProperty name="policyName">
+ <simple>${header.policyName}</simple>
+ </setProperty>
+ <setProperty name="policy">
+ <simple>${exchangeProperty[loopObject].getOperationalPolicy(header.policyName)}</simple>
+ </setProperty>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <to uri="direct:remove-one-policy-from-active-pdp-group"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <to uri="direct:delete-policy-from-loop-object"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopController?method=removeOperationalPolicy(${header.loopName},${header.policyType},${header.policyVersion})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('REMOVE OperationalPolicy request successfully executed','INFO',${exchangeProperty[loopObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="REMOVE operational policy request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('REMOVE OperationalPolicy request failed','ERROR',${exchangeProperty[loopObject]})"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>REMOVE Operational policy request FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </put>
+ <post
+ uri="/v2/loop/create/{loopName}?templateName={templateName}"
+ outType="org.onap.policy.clamp.loop.Loop" consumes="application/json"
+ produces="application/json">
+ <route>
+ <removeHeaders
+ pattern="*"
+ excludePattern="loopName|templateName"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Create Loop')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'cl','','update')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopController?method=createLoop(${header.loopName}, ${header.templateName})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="CREATE Loop from Template request failed for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('CREATE Loop from template request failed','ERROR',${exchangeProperty[loopObject]})"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>CREATE Loop from template FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </post>
+ <get uri="/v2/templates"
+ outType="org.onap.policy.clamp.loop.template.LoopTemplate"
+ produces="application/json">
+ <route>
+ <removeHeaders pattern="*"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Templates')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'template','','read')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.template.LoopTemplatesService?method=getAllLoopTemplates()"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="GET ALL templates request failed: ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>GET ALL templates FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </get>
+ <get uri="/v2/templates/{templateName}"
+ outType="org.onap.policy.clamp.loop.template.LoopTemplate"
+ produces="application/json">
+ <route>
+ <removeHeaders pattern="*"
+ excludePattern="templateName"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET a Template by NAME')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'template','','read')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.template.LoopTemplatesService?method=getLoopTemplate(${header.templateName})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="GET Template request failed for template: ${header.templateName}, ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>GET Template FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </get>
+ <get uri="/v2/templates/names" outType="java.lang.String[]"
+ produces="application/json">
+ <route>
+ <removeHeaders pattern="*"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Loop Template Names')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'template','','read')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.template.LoopTemplatesService?method=getLoopTemplateNames()"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="GET All Template names request failed for template: ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>GET All Template names FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </get>
+
+ <!-- NON LOOP related endpoints -->
+ <get uri="/v2/dictionary"
+ outType="org.onap.policy.clamp.tosca.Dictionary" produces="application/json">
+ <route>
+ <removeHeaders pattern="*"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Dictionaries')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','read')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.tosca.DictionaryService?method=getAllDictionaries()"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="GET Dictionary request failed: ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>GET Dictionary FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </get>
+
+ <get uri="/v2/dictionary/secondary/names"
+ outType="java.lang.String[]" produces="application/json">
+ <route>
+ <removeHeaders pattern="*"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Secondary Dictionary Level Names')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','read')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.tosca.DictionaryService?method=getAllSecondaryLevelDictionaryNames()"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="GET Dictionary request failed: ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>GET Dictionary FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </get>
+ <get uri="/v2/dictionary/{dictionaryName}"
+ outType="org.onap.policy.clamp.tosca.Dictionary" produces="application/json">
+ <route>
+ <removeHeaders pattern="*"
+ excludePattern="dictionaryName"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Dictionary Elements for a Dictionary Name')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','read')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.tosca.DictionaryService?method=getDictionary(${header.dictionaryName})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="GET Dictionary request failed for: ${header.dictionaryName}, ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>GET Dictionary FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </get>
+ <put uri="/v2/dictionary" type="org.onap.policy.clamp.tosca.Dictionary"
+ outType="org.onap.policy.clamp.tosca.Dictionary" consumes="application/json"
+ produces="application/json">
+ <route>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Add New or Update Dictionary')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','update')"/>
+ <setProperty name="DictionaryObject">
+ <simple>${body}</simple>
+ </setProperty>
+ <to
+ uri="bean:org.onap.policy.clamp.tosca.DictionaryService?method=saveOrUpdateDictionary(${exchangeProperty[DictionaryObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="PUT Dictionary request failed for: ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>PUT Dictionary FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </put>
+
+ <put uri="/v2/dictionary/{name}"
+ type="org.onap.policy.clamp.tosca.Dictionary"
+ outType="org.onap.policy.clamp.tosca.Dictionary" consumes="application/json"
+ produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="name"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Add New or Update Dictionary Element')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','update')"/>
+ <setProperty name="DictionaryObject">
+ <simple>${body}</simple>
+ </setProperty>
+ <to
+ uri="bean:org.onap.policy.clamp.tosca.DictionaryService?method=saveOrUpdateDictionaryElement(${header.name}, ${exchangeProperty[DictionaryObject]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="PUT Dictionary request failed for: ${header.name}, ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>PUT Dictionary FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </put>
+
+ <delete uri="/v2/dictionary/{name}" produces="application/json">
+ <route>
+ <removeHeaders pattern="*" excludePattern="name"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Delete Dictionary')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','update')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.tosca.DictionaryService?method=deleteDictionary(${header.name})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="DELETE Dictionary request failed for: ${header.name}, ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>DELETE Dictionary FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </delete>
+
+ <delete uri="/v2/dictionary/{name}/elements/{shortName}"
+ produces="application/json">
+ <route>
+ <removeHeaders pattern="*"
+ excludePattern="name|shortName"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Delete Dictionary Element')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','update')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.tosca.DictionaryService?method=deleteDictionaryElement(${header.name}, ${header.shortName})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="DELETE Dictionary element request failed for: ${header.name}, ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>DELETE Dictionary element FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </delete>
+
+ <get uri="/v2/policyToscaModels"
+ outType="org.onap.policy.clamp.loop.template.PolicyModel"
+ produces="application/json">
+ <route>
+ <removeHeaders pattern="*"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET ALL Tosca Policy Models')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','read')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.template.PolicyModelsService?method=getAllPolicyModels()"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="GET Policy Models request failed for: ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>GET Policy models FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </get>
+ <get uri="/v2/policyToscaModels/{policyModelType}/{policyModelVersion}"
+ outType="com.google.gson.JsonObject" produces="application/json">
+ <route>
+ <removeHeaders pattern="*"
+ excludePattern="policyModelType|policyModelVersion"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET Tosca Policy Model by Name/Version')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','read')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.template.PolicyModelsService?method=getPolicyModelJson(${header.policyModelType},${header.policyModelVersion})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="GET Policy Model request failed for type: ${header.policyModelType}, ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>GET Policy model FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </get>
+ <get uri="/v2/policyToscaModels/yaml/{policyModelType}/{policyModelVersion}"
+ outType="java.lang.String" produces="application/json">
+ <route>
+ <removeHeaders pattern="*"
+ excludePattern="policyModelType|policyModelVersion"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET Tosca Policy Model Yaml String by Name/Version')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'tosca','','read')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.template.PolicyModelsService?method=getPolicyModelTosca(${header.policyModelType},${header.policyModelVersion})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="GET Policy Model YAML request failed for type: ${header.policyModelType}, ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>GET Policy model YAML FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </get>
+
+ <!-- Policy Related endpoints, not related to LOOP -->
+ <get uri="/v2/policies" outType="com.google.gson.JsonObject" produces="application/json">
+ <route>
+ <removeHeaders pattern="*"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'GET Policies List ')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'policies','','read')"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <to uri="direct:get-all-policies"/>
+ <setProperty name="policiesListResponse">
+ <simple>${body}</simple>
+ </setProperty>
+ <to uri="direct:get-all-pdp-groups"/>
+ <setProperty name="pdpGroupInfoResponse">
+ <simple>${body}</simple>
+ </setProperty>
+ <setBody>
+ <method ref="org.onap.policy.clamp.policy.pdpgroup.PoliciesPdpMerger"
+ method="mergePoliciesAndPdpGroupStates(${exchangeProperty[policiesListResponse]},${exchangeProperty[pdpGroupInfoResponse]})"/>
+ </setBody>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="GET Policies list JSON request failed: ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>GET Policies list JSON FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </get>
+
+ <!-- Create a new policy -->
+ <post uri="/v2/policies/{policyModelType}/{policyModelVersion}/{policyName}/{policyVersion}"
+ type="com.google.gson.JsonElement"
+ consumes="application/json"
+ outType="com.google.gson.JsonObject"
+ produces="application/json">
+ <route>
+ <removeHeaders pattern="*"
+ excludePattern="policyModelType|policyModelVersion|policyName|policyVersion"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'CREATE a new Policy ')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'policies','','update')"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <setProperty name="policyModelType">
+ <simple>${header.policyModelType}</simple>
+ </setProperty>
+ <setProperty name="policyModelVersion">
+ <simple>${header.policyModelVersion}</simple>
+ </setProperty>
+ <setProperty name="policyProperties">
+ <simple>${body}</simple>
+ </setProperty>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.template.PolicyModelsService?method=getPolicyModelTosca(${header.policyModelType},${header.policyModelVersion})"/>
+ <setBody>
+ <method ref="org.onap.policy.clamp.policy.PolicyPayload"
+ method="createPolicyPayload(${header.policyModelType}, ${header.policyModelVersion},
+ ${header.policyName}, ${header.policyVersion}, ${exchangeProperty[policyProperties]}, ${body})"/>
+ </setBody>
+ <to uri="direct:create-policy"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="CREATE Policy request failed for type: ${header.policyModelType}/${header.policyModelVersion}, ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>CREATE Policy FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </post>
+
+ <delete uri="/v2/policies/{policyModelType}/{policyModelVersion}/{policyName}/{policyVersion}">
+ <route>
+ <removeHeaders pattern="*"
+ excludePattern="policyModelType|policyModelVersion|policyName|policyVersion"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'DELETE a Policy ')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'policies','','update')"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <setProperty name="policyModelType">
+ <simple>${header.policyModelType}</simple>
+ </setProperty>
+ <setProperty name="policyModelVersion">
+ <simple>${header.policyModelVersion}</simple>
+ </setProperty>
+ <setProperty name="policyName">
+ <simple>${header.policyName}</simple>
+ </setProperty>
+ <setProperty name="policyVersion">
+ <simple>${header.policyVersion}</simple>
+ </setProperty>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <to uri="direct:undeploy-one-policy-from-pap"/>
+ <to uri="direct:delete-policy"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="DELETE Policy request failed for policy: ${header.policyName}/${header.policyVersion}, ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>DELETE Policy FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </delete>
+
+ <put uri="/v2/policies/pdpDeployment" type="com.google.gson.JsonElement" consumes="application/json">
+ <route>
+ <removeHeaders pattern="*"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Pdp group deployment update')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'policies','','update')"/>
+ <setBody>
+ <method ref="org.onap.policy.clamp.policy.pdpgroup.PdpGroupPayload"
+ method="generatePdpGroupPayloadFromList(${body})"/>
+ </setBody>
+ <log loggingLevel="INFO"
+ message="PDP Group DEPLOY request payload: ${body}"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <to uri="direct:add-multiple-policies-to-pdp-group"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="PDP Group deployment request failed: ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>PDP Group deployment request FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </put>
+
+ <post uri="/v2/policies/policytype" type="java.lang.String" consumes="plain/text">
+ <route>
+ <removeHeaders pattern="*"/>
+ <doTry>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=startLog(*, 'Create policy type')"/>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=authorize(*,'policies','','update')"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <to uri="direct:create-policy-type"/>
+ <to
+ uri="bean:org.onap.policy.clamp.policy.downloader.PolicyEngineController?method=synchronizeAllPolicies()"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=endLog()"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=errorLog()"/>
+ <log loggingLevel="ERROR"
+ message="Create policy type request failed: ${exception.stacktrace}"/>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>500</constant>
+ </setHeader>
+ <setBody>
+ <simple>Create policy type request FAILED</simple>
+ </setBody>
+ </doCatch>
+ </doTry>
+ </route>
+ </post>
+
+ <get uri="/v2/clampInformation" outType="org.onap.policy.clamp.clds.model.ClampInformation"
+ produces="application/json">
+ <route>
+ <to
+ uri="bean:org.onap.policy.clamp.authorization.AuthorizationController?method=getClampInformation()"/>
+ </route>
+ </get>
+ </rest>
+</rests>
diff --git a/runtime/src/main/resources/clds/camel/rest/clds-services.xml b/runtime/src/main/resources/clds/camel/rest/clds-services.xml
new file mode 100644
index 000000000..aa4c3cbee
--- /dev/null
+++ b/runtime/src/main/resources/clds/camel/rest/clds-services.xml
@@ -0,0 +1,24 @@
+<rests xmlns="http://camel.apache.org/schema/spring">
+ <rest>
+ <get uri="/v1/healthcheck" produces="application/json"
+ outType="org.onap.policy.clamp.clds.model.CldsHealthCheck">
+ <route>
+ <setBody>
+ <method ref="org.onap.policy.clamp.clds.service.CldsHealthcheckService"
+ method="gethealthcheck()" />
+ </setBody>
+ <when>
+ <simple> ${body} == 'NOT-OK'</simple>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>404</constant>
+ </setHeader>
+ <log loggingLevel="ERROR" message="HealthCheck failed" />
+ </when>
+ </route>
+ </get>
+
+ <get uri="/v1/user/getUser" produces="text/plain">
+ <to uri="bean:org.onap.policy.clamp.authorization.UserService?method=getUser()" />
+ </get>
+ </rest>
+</rests>
diff --git a/runtime/src/main/resources/clds/camel/routes/cds-flows.xml b/runtime/src/main/resources/clds/camel/routes/cds-flows.xml
new file mode 100644
index 000000000..10fcb091e
--- /dev/null
+++ b/runtime/src/main/resources/clds/camel/routes/cds-flows.xml
@@ -0,0 +1,64 @@
+<routes xmlns="http://camel.apache.org/schema/spring">
+ <route id="get-blueprint-workflow-list">
+ <from uri="direct:get-blueprint-workflow-list"/>
+ <log loggingLevel="INFO"
+ message="Getting blueprint workflow list from CDS"/>
+ <to uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('CDS', 'Getting workflow list from CDS')"/>
+ <doTry>
+ <setHeader name="CamelHttpMethod">
+ <constant>GET</constant>
+ </setHeader>
+ <setHeader name="Content-Type">
+ <constant>application/json</constant>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to query workflows from CDS : {{clamp.config.cds.url}}/api/v1/blueprint-model/workflows/blueprint-name/${exchangeProperty[blueprintName]}/version/${exchangeProperty[blueprintVersion]}"></log>
+ <toD uri="{{clamp.config.cds.url}}/api/v1/blueprint-model/workflows/blueprint-name/${exchangeProperty[blueprintName]}/version/${exchangeProperty[blueprintVersion]}?bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.cds.userName}}&amp;authPassword={{clamp.config.cds.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <convertBodyTo type="java.lang.String"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+
+ <log loggingLevel="ERROR"
+ message="GET CDS request FAILED: ${exception.stacktrace}" />
+ </doCatch>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+ <route id="get-blueprint-workflow-input-properties">
+ <from uri="direct:get-blueprint-workflow-input-properties"/>
+ <log loggingLevel="INFO"
+ message="Getting blueprint input properties for workflow"/>
+ <to uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('CDS', 'Getting input properties for workflow')"/>
+ <doTry>
+ <setHeader name="CamelHttpMethod">
+ <constant>POST</constant>
+ </setHeader>
+ <setHeader name="Content-Type">
+ <constant>application/json</constant>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to query input properties for workflow from CDS : {{clamp.config.cds.url}}/api/v1/blueprint-model/workflow-spec"></log>
+ <toD uri="{{clamp.config.cds.url}}/api/v1/blueprint-model/workflow-spec?bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.cds.userName}}&amp;authPassword={{clamp.config.cds.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <convertBodyTo type="java.lang.String"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+
+ <log loggingLevel="ERROR"
+ message="GET CDS workflow input request FAILED: ${exception.stacktrace}" />
+ </doCatch>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+</routes> \ No newline at end of file
diff --git a/runtime/src/main/resources/clds/camel/routes/dcae-flows.xml b/runtime/src/main/resources/clds/camel/routes/dcae-flows.xml
new file mode 100644
index 000000000..d74bd91bf
--- /dev/null
+++ b/runtime/src/main/resources/clds/camel/routes/dcae-flows.xml
@@ -0,0 +1,501 @@
+<routes xmlns="http://camel.apache.org/schema/spring">
+ <route id="deploy-loop">
+ <from uri="direct:deploy-loop"/>
+ <choice>
+ <when>
+ <simple>${exchangeProperty['loopObject'].getLoopTemplate().getUniqueBlueprint()} == true
+ </simple>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <to uri="direct:deploy-loop-single-blueprint"/>
+ </when>
+ <when>
+ <simple>${exchangeProperty['loopObject'].getLoopTemplate().getUniqueBlueprint()} == false
+ </simple>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <to uri="direct:deploy-loop-multi-blueprint"/>
+ </when>
+ </choice>
+ </route>
+ <route id="deploy-loop-multi-blueprint">
+ <from uri="direct:deploy-loop-multi-blueprint"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Deploying the blueprints for loop: ${exchangeProperty[loopObject].getName()}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Deploying the loop with multiple blueprints')"/>
+ <split>
+ <simple>${exchangeProperty[loopObject].getMicroServicePolicies()}
+ </simple>
+ <setProperty name="microServicePolicy">
+ <simple>${body}</simple>
+ </setProperty>
+ <log
+ loggingLevel="INFO"
+ message="Processing Micro Service Policy: ${exchangeProperty[microServicePolicy].getName()}"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <setBody>
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="getDeployPayload(${exchangeProperty[loopObject]},${exchangeProperty[microServicePolicy]})"/>
+ </setBody>
+ <setProperty name="dcaeDeploymentId">
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="generateDeploymentId()"/>
+ </setProperty>
+ <setHeader name="CamelHttpMethod">
+ <constant>PUT</constant>
+ </setHeader>
+ <setHeader name="Content-Type">
+ <constant>application/json</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to deploy loop: {{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[dcaeDeploymentId]}"></log>
+ <toD
+ uri="{{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[dcaeDeploymentId]}?bridgeEndpoint=true&amp;useSystemProperties=true&amp;mapHttpMessageHeaders=false&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authUsername={{clamp.config.dcae.deployment.userName}}&amp;authPassword={{clamp.config.dcae.deployment.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <convertBodyTo type="java.lang.String"/>
+ <setProperty name="dcaeResponse">
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="convertDcaeResponse(${body})"/>
+ </setProperty>
+ <setProperty name="dcaeStatusUrl">
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="getStatusUrl(${exchangeProperty[dcaeResponse]})"/>
+ </setProperty>
+ <to
+ uri="bean:org.onap.policy.clamp.policy.microservice.MicroServicePolicyService?method=updateDcaeDeploymentFields(${exchangeProperty[microServicePolicy]},${exchangeProperty[dcaeDeploymentId]},${exchangeProperty[dcaeStatusUrl]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLogForComponent('Deploy for the micro service: ${exchangeProperty[microServicePolicy].getName()} - ${header.CamelHttpResponseCode} : ${header.CamelHttpResponseText}','INFO','DCAE',${exchangeProperty[loopObject]})"/>
+ </split>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>false</constant>
+ </handled>
+ <setProperty name="logMessage">
+ <simple>DEPLOY micro service failed
+ (MicroService name:${exchangeProperty[microServicePolicy].getName()}),
+ Dep-id:${exchangeProperty[dcaeDeploymentId]},
+ StatusUrl:${exchangeProperty[dcaeStatusUrl]})
+ </simple>
+ </setProperty>
+ <setProperty name="logComponent">
+ <simple>DCAE</simple>
+ </setProperty>
+ <to uri="direct:dump-loop-log-http-response"/>
+ </doCatch>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+ <route id="deploy-loop-single-blueprint">
+ <from uri="direct:deploy-loop-single-blueprint"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Deploying the loop: ${exchangeProperty[loopObject].getName()}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Deploying the loop')"/>
+ <setBody>
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="getDeployPayload(${exchangeProperty[loopObject]})"/>
+ </setBody>
+ <setProperty name="dcaeDeploymentId">
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="generateDeploymentId()"/>
+ </setProperty>
+ <setHeader name="CamelHttpMethod">
+ <constant>PUT</constant>
+ </setHeader>
+ <setHeader name="Content-Type">
+ <constant>application/json</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to deploy loop: {{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[dcaeDeploymentId]}"></log>
+ <toD
+ uri="{{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[dcaeDeploymentId]}?bridgeEndpoint=true&amp;useSystemProperties=true&amp;mapHttpMessageHeaders=false&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authUsername={{clamp.config.dcae.deployment.userName}}&amp;authPassword={{clamp.config.dcae.deployment.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <convertBodyTo type="java.lang.String"/>
+ <setProperty name="dcaeResponse">
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="convertDcaeResponse(${body})"/>
+ </setProperty>
+
+
+ <setProperty name="dcaeStatusUrl">
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="getStatusUrl(${exchangeProperty[dcaeResponse]})"/>
+ </setProperty>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopService?method=updateDcaeDeploymentFields(${exchangeProperty[loopObject]},${exchangeProperty[dcaeDeploymentId]},${exchangeProperty[dcaeStatusUrl]})"/>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ <setProperty name="logMessage">
+ <simple>DEPLOY loop status
+ (Dep-id:${exchangeProperty[dcaeDeploymentId]},
+ StatusUrl:${exchangeProperty[dcaeStatusUrl]})
+ </simple>
+ </setProperty>
+ <setProperty name="logComponent">
+ <simple>DCAE</simple>
+ </setProperty>
+ <to uri="direct:dump-loop-log-http-response"/>
+ </doFinally>
+ </doTry>
+ </route>
+ <route id="undeploy-loop">
+ <from uri="direct:undeploy-loop"/>
+ <choice>
+ <when>
+ <simple>${exchangeProperty['loopObject'].getLoopTemplate().getUniqueBlueprint()} == true
+ </simple>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <to uri="direct:undeploy-loop-single-blueprint"/>
+ </when>
+ <when>
+ <simple>${exchangeProperty['loopObject'].getLoopTemplate().getUniqueBlueprint()} == false
+ </simple>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <to uri="direct:undeploy-loop-multi-blueprint"/>
+ </when>
+ </choice>
+ </route>
+ <route id="undeploy-loop-multi-blueprint">
+ <from uri="direct:undeploy-loop-multi-blueprint"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Undeploying the blueprints for loop: ${exchangeProperty[loopObject].getName()}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Undeploying the loop with multiple blueprints')"/>
+ <split>
+ <simple>${exchangeProperty[loopObject].getMicroServicePolicies()}
+ </simple>
+ <setProperty name="microServicePolicy">
+ <simple>${body}</simple>
+ </setProperty>
+ <log
+ loggingLevel="INFO"
+ message="Processing Micro Service Policy: ${exchangeProperty[microServicePolicy].getName()}"/>
+ <choice>
+ <when>
+ <simple>${exchangeProperty[microServicePolicy].getDcaeDeploymentId()} != null
+ </simple>
+ <setBody>
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="getUndeployPayload(${exchangeProperty[microServicePolicy]})"/>
+ </setBody>
+ <setHeader name="CamelHttpMethod">
+ <constant>DELETE</constant>
+ </setHeader>
+ <setHeader name="Content-Type">
+ <constant>application/json</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to undeploy loop: {{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[microServicePolicy].getDcaeDeploymentId()}"></log>
+ <toD
+ uri="{{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[microServicePolicy].getDcaeDeploymentId()}?bridgeEndpoint=true&amp;useSystemProperties=true&amp;mapHttpMessageHeaders=false&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authUsername={{clamp.config.dcae.deployment.userName}}&amp;authPassword={{clamp.config.dcae.deployment.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <convertBodyTo type="java.lang.String"/>
+ <setProperty name="dcaeResponse">
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="convertDcaeResponse(${body})"/>
+ </setProperty>
+ <setProperty name="dcaeStatusUrl">
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="getStatusUrl(${exchangeProperty[dcaeResponse]})"/>
+ </setProperty>
+ <to
+ uri="bean:org.onap.policy.clamp.policy.microservice.MicroServicePolicyService?method=updateDcaeDeploymentFields(${exchangeProperty[microServicePolicy]},null,${exchangeProperty[dcaeStatusUrl]})"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLogForComponent('Undeploy for the micro service: ${exchangeProperty[microServicePolicy].getName()} - ${header.CamelHttpResponseCode} : ${header.CamelHttpResponseText}','INFO','DCAE',${exchangeProperty[loopObject]})"/>
+ </when>
+ <otherwise>
+ <log loggingLevel="WARN"
+ message="Cannot Undeploy for the micro service: ${exchangeProperty[microServicePolicy].getName()}, the Deployment ID does not exist !"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLogForComponent('Cannot Undeploy for the micro service: ${exchangeProperty[microServicePolicy].getName()}, the Deployment ID does not exist !','WARNING','DCAE',${exchangeProperty[loopObject]})"/>
+ </otherwise>
+ </choice>
+ </split>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>false</constant>
+ </handled>
+ <setProperty name="logMessage">
+ <simple>UNDEPLOY micro service failed
+ (MicroService name:${exchangeProperty[microServicePolicy].getName()})
+ </simple>
+ </setProperty>
+ <setProperty name="logComponent">
+ <simple>DCAE</simple>
+ </setProperty>
+ <to uri="direct:dump-loop-log-http-response"/>
+ </doCatch>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+ <route id="undeploy-loop-single-blueprint">
+ <from uri="direct:undeploy-loop-single-blueprint"/>
+ <log loggingLevel="INFO"
+ message="Undeploying the loop: ${exchangeProperty[loopObject].getName()} : ${exchangeProperty[loopObject].getDcaeDeploymentId()}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Undeploying the loop')"/>
+ <choice>
+ <when>
+ <simple>${exchangeProperty[loopObject].getDcaeDeploymentId()} != null</simple>
+ <doTry>
+ <setBody>
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="getUndeployPayload(${exchangeProperty[loopObject]})"/>
+ </setBody>
+ <setHeader name="CamelHttpMethod">
+ <constant>DELETE</constant>
+ </setHeader>
+ <setHeader name="Content-Type">
+ <constant>application/json</constant>
+ </setHeader>
+
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to undeploy loop: {{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[loopObject].getDcaeDeploymentId()}"></log>
+ <toD
+ uri="{{clamp.config.dcae.deployment.url}}/dcae-deployments/${exchangeProperty[loopObject].getDcaeDeploymentId()}?bridgeEndpoint=true&amp;useSystemProperties=true&amp;mapHttpMessageHeaders=false&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authUsername={{clamp.config.dcae.deployment.userName}}&amp;authPassword={{clamp.config.dcae.deployment.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <convertBodyTo type="java.lang.String"/>
+ <setProperty name="dcaeResponse">
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="convertDcaeResponse(${body})"/>
+ </setProperty>
+ <setProperty name="dcaeStatusUrl">
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="getStatusUrl(${exchangeProperty[dcaeResponse]})"/>
+ </setProperty>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopService?method=updateDcaeDeploymentFields(${exchangeProperty[loopObject]},null,${exchangeProperty[dcaeStatusUrl]})"/>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ <setProperty name="logMessage">
+ <simple>UNDEPLOY loop status</simple>
+ </setProperty>
+ <setProperty name="logComponent">
+ <simple>DCAE</simple>
+ </setProperty>
+ <to uri="direct:dump-loop-log-http-response"/>
+ </doFinally>
+ </doTry>
+ </when>
+ <otherwise>
+ <log loggingLevel="WARN"
+ message="Cannot Undeploy for the loop: ${exchangeProperty[loopObject].getName()}, the Deployment ID does not exist !"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('Cannot Undeploy for the loop: ${exchangeProperty[loopObject].getName()}, the Deployment ID does not exist !','WARNING',${exchangeProperty[loopObject]})"/>
+ </otherwise>
+ </choice>
+ </route>
+ <route id="get-dcae-deployment-status">
+ <from uri="direct:get-dcae-deployment-status"/>
+ <log loggingLevel="INFO"
+ message="Getting DCAE deployment status for loop: ${exchangeProperty[loopObject].getName()} - ${exchangeProperty[dcaeComponent].getComponentName()}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Getting Deployment status')"/>
+ <doTry>
+ <setHeader name="CamelHttpMethod">
+ <constant>GET</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to query microservice deployment status: ${exchangeProperty[getStatusUrlModified]}"></log>
+ <choice>
+ <when>
+ <simple>${exchangeProperty[getStatusUrl].contains("?")} == true
+ </simple>
+ <setProperty name="uriSeparator">
+ <simple>&amp;</simple>
+ </setProperty>
+ </when>
+ <otherwise>
+ <setProperty name="uriSeparator">
+ <simple>?</simple>
+ </setProperty>
+ </otherwise>
+ </choice>
+ <toD
+ uri="${exchangeProperty[getStatusUrl]}${exchangeProperty[uriSeparator]}bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.dcae.deployment.userName}}&amp;authPassword={{clamp.config.dcae.deployment.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+
+ <log loggingLevel="ERROR"
+ message="GET DCAE deployment request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('GET DCAE deployment request failed, Error reported: ${exception.message}','ERROR',${exchangeProperty[loopObject]})"/>
+ </doCatch>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ <setProperty name="logMessage">
+ <simple>DCAE deployment status</simple>
+ </setProperty>
+ <setProperty name="logComponent">
+ <simple>DCAE</simple>
+ </setProperty>
+ <to uri="direct:dump-loop-log-http-response"/>
+ </doFinally>
+ </doTry>
+ </route>
+ <route id="get-dcae-blueprint-inventory">
+ <from uri="direct:get-dcae-blueprint-inventory"/>
+ <log loggingLevel="INFO"
+ message="Getting DCAE blueprint id in inventory"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Getting blueprint id in inventory')"/>
+ <doTry>
+ <setHeader name="CamelHttpMethod">
+ <constant>GET</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to query Dcae inventory Loop status: {{clamp.config.dcae.inventory.url}}/dcae-service-types?${header[CamelHttpQuery]}"></log>
+ <toD
+ uri="{{clamp.config.dcae.inventory.url}}/dcae-service-types?asdcResourceId=${exchangeProperty[blueprintResourceId]}&amp;asdcServiceId=${exchangeProperty[blueprintServiceId]}&amp;typeName=${exchangeProperty[blueprintName]}&amp;bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.dcae.deployment.userName}}&amp;authPassword={{clamp.config.dcae.deployment.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <convertBodyTo type="java.lang.String"/>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+
+ </route>
+ <route id="get-all-dcae-blueprint-inventory">
+ <from uri="direct:get-all-dcae-blueprint-inventory"/>
+ <log loggingLevel="INFO"
+ message="Getting all DCAE blueprint from inventory"/>
+ <to uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('DCAE', 'Getting all blueprint from inventory')"/>
+ <doTry>
+ <setHeader name="CamelHttpMethod">
+ <constant>GET</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to query Blueprints from DCAE inventory: {{clamp.config.dcae.inventory.url}}/dcae-service-types?${header[CamelHttpQuery]}"></log>
+ <toD uri="{{clamp.config.dcae.inventory.url}}/dcae-service-types;bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.dcae.deployment.userName}}&amp;authPassword={{clamp.config.dcae.deployment.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <convertBodyTo type="java.lang.String"/>
+ <setProperty name="dcaeResponseList">
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="convertToDcaeInventoryResponse(${body})"/>
+ </setProperty>
+ <split>
+ <simple>${exchangeProperty[dcaeResponseList]}</simple>
+ <convertBodyTo type="org.onap.policy.clamp.clds.model.dcae.DcaeInventoryResponse"/>
+ <setProperty name="dcaeResponse">
+ <simple>${body}</simple>
+ </setProperty>
+ <to uri="bean:org.onap.policy.clamp.clds.model.dcae.DcaeInventoryCache?method=addDcaeInventoryResponse(${exchangeProperty[dcaeResponse]})"/>
+ </split>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+</routes> \ No newline at end of file
diff --git a/runtime/src/main/resources/clds/camel/routes/loop-flows.xml b/runtime/src/main/resources/clds/camel/routes/loop-flows.xml
new file mode 100644
index 000000000..4a3cc84b2
--- /dev/null
+++ b/runtime/src/main/resources/clds/camel/routes/loop-flows.xml
@@ -0,0 +1,256 @@
+<routes xmlns="http://camel.apache.org/schema/spring">
+ <route id="load-loop">
+ <from uri="direct:load-loop" />
+ <setBody>
+ <simple>${header.loopName}</simple>
+ </setBody>
+ <setProperty name="loopObject">
+ <method ref="org.onap.policy.clamp.loop.LoopService" method="getLoop" />
+ </setProperty>
+
+ <when>
+ <simple>${exchangeProperty[loopObject]} == null</simple>
+ <setHeader name="CamelHttpResponseCode">
+ <constant>404</constant>
+ </setHeader>
+ <log loggingLevel="WARN" message="Loop not found in database: ${body}" />
+ <stop />
+ </when>
+ </route>
+ <route id="update-policy-status-for-loop">
+ <from uri="direct:update-policy-status-for-loop" />
+ <setProperty name="policyComponent">
+ <simple>${exchangeProperty[loopObject].getComponent('POLICY')}
+ </simple>
+ </setProperty>
+ <setProperty name="policyFound">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <setProperty name="policyDeployed">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <log loggingLevel="INFO"
+ message="Processing all MICRO-SERVICES policies defined in loop ${exchangeProperty[loopObject].getName()}" />
+ <split>
+ <simple>${exchangeProperty[loopObject].getMicroServicePolicies()}
+ </simple>
+ <setProperty name="policyName">
+ <simple>${body.getName()}</simple>
+ </setProperty>
+ <setProperty name="policyType">
+ <simple>${body.getPolicyModel().getPolicyModelType()}</simple>
+ </setProperty>
+ <setProperty name="policyTypeVersion">
+ <simple>${body.getPolicyModel().getVersion()}</simple>
+ </setProperty>
+ <setProperty name="policyPdpGroup">
+ <simple>${body.getPdpGroup()}</simple>
+ </setProperty>
+ <setProperty name="policyVersion">
+ <simple>1.0.0</simple>
+ </setProperty>
+ <setBody>
+ <constant>null</constant>
+ </setBody>
+ <log loggingLevel="INFO"
+ message="Processing Micro Service Policy: ${exchangeProperty[policyName]} of type ${exchangeProperty[policyType]}" />
+ <to uri="direct:verify-one-policy" />
+ </split>
+ <log loggingLevel="INFO"
+ message="Processing all OPERATIONAL policies defined in loop ${exchangeProperty[loopObject].getName()}" />
+ <split>
+ <simple>${exchangeProperty[loopObject].getOperationalPolicies()}
+ </simple>
+ <setProperty name="policyName">
+ <simple>${body.getName()}</simple>
+ </setProperty>
+ <setProperty name="policyType">
+ <simple>${body.getPolicyModel().getPolicyModelType()}</simple>
+ </setProperty>
+ <setProperty name="policyTypeVersion">
+ <simple>${body.getPolicyModel().getVersion()}</simple>
+ </setProperty>
+ <setProperty name="policyVersion">
+ <simple>1.0.0</simple>
+ </setProperty>
+ <setProperty name="policyPdpGroup">
+ <simple>${body.getPdpGroup()}</simple>
+ </setProperty>
+ <setBody>
+ <constant>null</constant>
+ </setBody>
+ <log loggingLevel="INFO"
+ message="Processing Operational Policy: ${exchangeProperty[policyName]} of type ${exchangeProperty[policyType]}" />
+ <to uri="direct:verify-one-policy" />
+ </split>
+ <setProperty name="policyState">
+ <simple> ${exchangeProperty[policyComponent].getState()}
+ </simple>
+ </setProperty>
+ <log loggingLevel="INFO"
+ message="Policy state set to: ${exchangeProperty[policyState].getStateName()}" />
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLogForComponent('Policy state set to: ${exchangeProperty[policyState].getStateName()}','INFO','POLICY',${exchangeProperty[loopObject]})" />
+ </route>
+ <route id="update-dcae-status-for-loop">
+ <from uri="direct:update-dcae-status-for-loop" />
+ <log loggingLevel="INFO"
+ message="Updating DCAE status for loop: ${exchangeProperty[loopObject].getName()}" />
+ <choice>
+ <when>
+ <simple>${exchangeProperty['loopObject'].getLoopTemplate().getUniqueBlueprint()} == true
+ </simple>
+ <setProperty name="dcaeComponent">
+ <simple>${exchangeProperty[loopObject].getComponent('DCAE')}</simple>
+ </setProperty>
+ <when>
+ <simple>${exchangeProperty[loopObject].getDcaeDeploymentStatusUrl()} != null
+ </simple>
+ <setProperty name="getStatusUrl">
+ <simple>${exchangeProperty[loopObject].getDcaeDeploymentStatusUrl()}</simple>
+ </setProperty>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <to uri="direct:get-dcae-deployment-status" />
+ <when>
+ <simple> ${header.CamelHttpResponseCode} == 200 </simple>
+ <convertBodyTo type="java.lang.String" />
+ <setProperty name="dcaeResponse">
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="convertDcaeResponse(${body})" />
+ </setProperty>
+ </when>
+ </when>
+ <setProperty name="dcaeState">
+ <simple> ${exchangeProperty[dcaeComponent].computeState(*)}
+ </simple>
+ </setProperty>
+ <log loggingLevel="INFO"
+ message="DCAE state set to: ${exchangeProperty[dcaeState].getStateName()} - DCAE message: ${exchangeProperty[dcaeResponse].getError()}" />
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLogForComponent('DCAE state set to: ${exchangeProperty[dcaeState].getStateName()} - message: ${exchangeProperty[dcaeResponse].getError()}','INFO','DCAE',${exchangeProperty[loopObject]})" />
+ </when>
+ <when>
+ <simple>${exchangeProperty['loopObject'].getLoopTemplate().getUniqueBlueprint()} == false
+ </simple>
+ <split>
+ <simple>${exchangeProperty[loopObject].getMicroServicePolicies()}
+ </simple>
+ <setProperty name="microServicePolicy">
+ <simple>${body}</simple>
+ </setProperty>
+ <setProperty name="dcaeComponent">
+ <simple>${exchangeProperty[loopObject].getComponent('DCAE_' + ${exchangeProperty[microServicePolicy].getName()})}</simple>
+ </setProperty>
+ <when>
+ <simple>${exchangeProperty[microServicePolicy].getDcaeDeploymentStatusUrl()} != null
+ </simple>
+ <setProperty name="getStatusUrl">
+ <simple>${exchangeProperty[microServicePolicy].getDcaeDeploymentStatusUrl()}</simple>
+ </setProperty>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <to uri="direct:get-dcae-deployment-status" />
+ <when>
+ <simple> ${header.CamelHttpResponseCode} == 200 </simple>
+ <convertBodyTo type="java.lang.String" />
+ <setProperty name="dcaeResponse">
+ <method ref="org.onap.policy.clamp.loop.components.external.DcaeComponent"
+ method="convertDcaeResponse(${body})" />
+ </setProperty>
+ </when>
+ </when>
+ <setProperty name="dcaeState">
+ <simple> ${exchangeProperty[dcaeComponent].computeState(*)}
+ </simple>
+ </setProperty>
+ <log loggingLevel="INFO"
+ message="DCAE state set to: ${exchangeProperty[dcaeState].getStateName()} - DCAE message: ${exchangeProperty[dcaeResponse].getError()}" />
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLogForComponent('DCAE state set to: ${exchangeProperty[dcaeState].getStateName()} - message: ${exchangeProperty[dcaeResponse].getError()}','INFO','DCAE',${exchangeProperty[microServicePolicy]})" />
+ </split>>
+ </when>
+ </choice>
+ </route>
+ <route id="direct:update-loop-state">
+ <from uri="direct:update-loop-state" />
+ <log loggingLevel="INFO"
+ message="Updating status for loop: ${exchangeProperty[loopObject].getName()}" />
+ <choice>
+ <when>
+ <simple>${exchangeProperty['dcaeState'].getStateName()} ==
+ 'BLUEPRINT_DEPLOYED' &amp;&amp; ${exchangeProperty['policyState'].getStateName()}
+ == 'NOT_SENT'
+ </simple>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'DESIGN')" />
+ </when>
+ <when>
+ <simple>${exchangeProperty['dcaeState'].getStateName()} == 'IN_ERROR' ||
+ ${exchangeProperty['dcaeState'].getStateName()} ==
+ 'MICROSERVICE_INSTALLATION_FAILED'
+ </simple>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'IN_ERROR')" />
+ </when>
+ <when>
+ <simple>${exchangeProperty['dcaeState'].getStateName()} ==
+ 'MICROSERVICE_UNINSTALLATION_FAILED' ||
+ ${exchangeProperty['policyState'].getStateName()} == 'IN_ERROR'
+ </simple>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'IN_ERROR')" />
+ </when>
+ <when>
+ <simple>${exchangeProperty['dcaeState'].getStateName()} ==
+ 'MICROSERVICE_INSTALLED_SUCCESSFULLY' &amp;&amp;
+ ${exchangeProperty['policyState'].getStateName()} == 'SENT_AND_DEPLOYED'
+ </simple>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'RUNNING')" />
+ </when>
+ <when>
+ <simple>${exchangeProperty['dcaeState'].getStateName()} ==
+ 'MICROSERVICE_INSTALLED_SUCCESSFULLY' &amp;&amp;
+ ${exchangeProperty['policyState'].getStateName()} == 'SENT'
+ </simple>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'STOPPED')" />
+ </when>
+ <when>
+ <simple>${exchangeProperty['dcaeState'].getStateName()} ==
+ 'BLUEPRINT_DEPLOYED' || ${exchangeProperty['dcaeState'].getStateName()} ==
+ 'MICROSERVICE_UNINSTALLED_SUCCESSFULLY' &amp;&amp;
+ ${exchangeProperty['policyState'].getStateName()} == 'SENT_AND_DEPLOYED'
+ </simple>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'SUBMITTED')" />
+ </when>
+ <when>
+ <simple>${exchangeProperty['dcaeState'].getStateName()} ==
+ 'PROCESSING_MICROSERVICE_INSTALLATION' ||
+ ${exchangeProperty['dcaeState'].getStateName()} ==
+ 'PROCESSING_MICROSERVICE_UNINSTALLATION' &amp;&amp;
+ ${exchangeProperty['policyState'].getStateName()} == 'SENT_AND_DEPLOYED'
+ </simple>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'WAITING')" />
+ </when>
+ <when>
+ <simple>${exchangeProperty['dcaeState'].getStateName()} ==
+ 'MICROSERVICE_INSTALLED_SUCCESSFULLY' &amp;&amp;
+ ${exchangeProperty['policyState'].getStateName()} != 'NOT_SENT'
+ </simple>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.LoopService?method=updateLoopState(${exchangeProperty[loopObject]},'DEPLOYED')" />
+ </when>
+ </choice>
+ <log loggingLevel="INFO"
+ message="New loop state is: ${exchangeProperty[loopObject].getLastComputedState().toString()}" />
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('New loop state is: ${exchangeProperty[loopObject].getLastComputedState().toString()}','INFO',${exchangeProperty[loopObject]})" />
+
+ </route>
+</routes> \ No newline at end of file
diff --git a/runtime/src/main/resources/clds/camel/routes/policy-flows.xml b/runtime/src/main/resources/clds/camel/routes/policy-flows.xml
new file mode 100644
index 000000000..01862692c
--- /dev/null
+++ b/runtime/src/main/resources/clds/camel/routes/policy-flows.xml
@@ -0,0 +1,654 @@
+<routes xmlns="http://camel.apache.org/schema/spring">
+ <route id="verify-one-policy">
+ <from uri="direct:verify-one-policy"/>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <to uri="direct:get-policy"/>
+ <when>
+ <simple>${header.CamelHttpResponseCode} != 200</simple>
+ <setProperty name="policyFound">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <log loggingLevel="WARN"
+ message="At least one policy has not been found on policy engine: ${exchangeProperty[policyName]}"/>
+ </when>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <to uri="direct:get-deployment-policy"/>
+ <when>
+ <simple>${header.CamelHttpResponseCode} != 200</simple>
+ <setProperty name="policyDeployed">
+ <simple resultType="java.lang.Boolean">false</simple>
+ </setProperty>
+ <log loggingLevel="WARN"
+ message="At least one policy has not been deployed on policy engine: ${exchangeProperty[policyName]}"/>
+ </when>
+ <setProperty name="newPolicyState">
+ <simple>${exchangeProperty[policyComponent].computeState(*)}</simple>
+ </setProperty>
+ </route>
+
+ <route id="get-policy">
+ <from uri="direct:get-policy"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Getting Policy: ${exchangeProperty[policyName]}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Get Policy')"/>
+ <setHeader name="CamelHttpMethod">
+ <constant>GET</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to get policy: {{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policyType]}/versions/${exchangeProperty[policyTypeVersion]}/policies/${exchangeProperty[policyName]}/versions/${exchangeProperty[policyVersion]}"></log>
+ <toD
+ uri="{{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policyType]}/versions/${exchangeProperty[policyTypeVersion]}/policies/${exchangeProperty[policyName]}/versions/${exchangeProperty[policyVersion]}?bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.policy.api.userName}}&amp;authPassword={{clamp.config.policy.api.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+
+ <log loggingLevel="ERROR"
+ message="GET policy request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('GET policy request failed, Error reported: ${exception.message}','ERROR',${exchangeProperty[loopObject]})"/>
+ </doCatch>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ <setProperty name="logMessage">
+ <simple>${exchangeProperty[policyName]} GET
+ Policy status
+ </simple>
+ </setProperty>
+ <setProperty name="logComponent">
+ <simple>POLICY</simple>
+ </setProperty>
+ <to uri="direct:dump-loop-log-http-response"/>
+ </doFinally>
+ </doTry>
+ </route>
+
+ <route id="get-deployment-policy">
+ <from uri="direct:get-deployment-policy"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Getting the policy deployment in PDP: ${exchangeProperty[policyName]}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Getting the policy deployment in PDP')"/>
+ <setHeader name="CamelHttpMethod">
+ <constant>GET</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to get policy deployment status: {{clamp.config.policy.pap.url}}/policy/pap/v1/policies/status/${exchangeProperty[policyPdpGroup]}/${exchangeProperty[policyName]}/1.0.0"></log>
+ <toD
+ uri="{{clamp.config.policy.pap.url}}/policy/pap/v1/policies/status/${exchangeProperty[policyPdpGroup]}/${exchangeProperty[policyName]}/1.0.0?bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.policy.pap.userName}}&amp;authPassword={{clamp.config.policy.pap.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>true</constant>
+ </handled>
+
+ <log loggingLevel="ERROR"
+ message="GET policy request FAILED for loop: ${header.loopName}, ${exception.stacktrace}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('GET policy request failed, Error reported: ${exception.message}','ERROR',${exchangeProperty[loopObject]})"/>
+ </doCatch>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ <setProperty name="logMessage">
+ <simple>${exchangeProperty[policyName]} GET Policy deployment
+ status
+ </simple>
+ </setProperty>
+ <setProperty name="logComponent">
+ <simple>POLICY</simple>
+ </setProperty>
+ <to uri="direct:dump-loop-log-http-response"/>
+ </doFinally>
+ </doTry>
+ </route>
+
+ <route id="create-policy-from-loop-object">
+ <from uri="direct:create-policy-from-loop-object"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Creating Policy from loop object: ${exchangeProperty[policy].getName()}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Creating Policy from loop object')"/>
+ <setBody>
+ <simple>${exchangeProperty[policy].createPolicyPayload()}
+ </simple>
+ </setBody>
+ <setProperty name="policyModelType">
+ <simple>${exchangeProperty[policy].getPolicyModel().getPolicyModelType()}</simple>
+ </setProperty>
+ <setProperty name="policyModelVersion">
+ <simple>${exchangeProperty[policy].getPolicyModel().getVersion()}</simple>
+ </setProperty>
+ <to uri="direct:create-policy"/>
+ <doFinally>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ <setProperty name="logMessage">
+ <simple>${exchangeProperty[policy].getName()} creation
+ status
+ </simple>
+ </setProperty>
+ <setProperty name="logComponent">
+ <simple>POLICY</simple>
+ </setProperty>
+ <to uri="direct:dump-loop-log-http-response"/>
+ </doFinally>
+ </doTry>
+ </route>
+
+ <route id="delete-policy-from-loop-object">
+ <from uri="direct:delete-policy-from-loop-object"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Deleting Policy in a loop: ${exchangeProperty[policy].getName()}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Delete Policy in a loop')"/>
+ <setProperty name="policyModelType">
+ <simple>${exchangeProperty[policy].getPolicyModel().getPolicyModelType()}</simple>
+ </setProperty>
+ <setProperty name="policyModelVersion">
+ <simple>${exchangeProperty[policy].getPolicyModel().getVersion()}</simple>
+ </setProperty>
+ <setProperty name="policyName">
+ <simple>${exchangeProperty[policy].getName()}</simple>
+ </setProperty>
+ <setProperty name="policyVersion">
+ <simple>1.0.0</simple>
+ </setProperty>
+ <to uri="direct:delete-policy"/>
+ <doFinally>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ <setProperty name="logMessage">
+ <simple>${exchangeProperty[policy].getName()} removal
+ status
+ </simple>
+ </setProperty>
+ <setProperty name="logComponent">
+ <simple>POLICY</simple>
+ </setProperty>
+ <to uri="direct:dump-loop-log-http-response"/>
+ </doFinally>
+ </doTry>
+ </route>
+
+ <route id="add-policies-from-loop-to-pdp-group">
+ <from uri="direct:add-policies-from-loop-to-pdp-group"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Adding loop policies to PDP Group: ${exchangeProperty[loopObject].getName()}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Add policies to PDP group')"/>
+ <setBody>
+ <simple>
+ ${exchangeProperty[loopObject].getComponent("POLICY").createPoliciesPayloadPdpGroup(exchangeProperty[loopObject],"POST")}
+ </simple>
+ </setBody>
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ <to uri="direct:add-multiple-policies-to-pdp-group"/>
+ <doFinally>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ <setProperty name="logMessage">
+ <simple>PDP Group push ALL status</simple>
+ </setProperty>
+ <setProperty name="logComponent">
+ <simple>POLICY</simple>
+ </setProperty>
+ <to uri="direct:dump-loop-log-http-response"/>
+ </doFinally>
+ </doTry>
+ </route>
+
+ <route id="remove-all-policy-from-active-pdp-group">
+ <from uri="direct:remove-all-policy-from-active-pdp-group"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Removing loop policies from PDP Group: ${exchangeProperty[loopObject].getName()}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Remove policies from PDP group')"/>
+ <setBody>
+ <simple>
+ ${exchangeProperty[loopObject].getComponent("POLICY").createPoliciesPayloadPdpGroup(exchangeProperty[loopObject],"DELETE")}
+ </simple>
+ </setBody>
+ <setHeader name="CamelHttpMethod">
+ <constant>POST</constant>
+ </setHeader>
+ <setHeader name="Content-Type">
+ <constant>application/json</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to remove policies from PDP Group: {{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/deployments/batch"></log>
+ <toD
+ uri="{{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/deployments/batch?bridgeEndpoint=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;useSystemProperties=true&amp;authUsername={{clamp.config.policy.pap.userName}}&amp;authPassword={{clamp.config.policy.pap.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ <setProperty name="logMessage">
+ <simple>PDP Group remove ALL status</simple>
+ </setProperty>
+ <setProperty name="logComponent">
+ <simple>POLICY</simple>
+ </setProperty>
+ <to uri="direct:dump-loop-log-http-response"/>
+ </doFinally>
+ </doTry>
+ </route>
+
+ <route id="remove-one-policy-from-active-pdp-group">
+ <from uri="direct:remove-one-policy-from-active-pdp-group"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Removing policy from active PDP group for loop: ${exchangeProperty[loopObject].getName()}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Removing one policy PDP group')"/>
+ <setProperty name="policyVersion">
+ <simple>1.0.0</simple>
+ </setProperty>
+ <to uri="direct:undeploy-one-policy-from-pap"/>
+ <setProperty name="logMessage">
+ <simple>${exchangeProperty[policyName]} PDP Group removal status
+ </simple>
+ </setProperty>
+ <setProperty name="logComponent">
+ <simple>POLICY</simple>
+ </setProperty>
+ <to uri="direct:dump-loop-log-http-response"/>
+ <doCatch>
+ <exception>java.lang.Exception</exception>
+ <handled>
+ <constant>false</constant>
+ </handled>
+ <setProperty name="logMessage">
+ <simple>PDP Group removal, Error reported: ${exception}</simple>
+ </setProperty>
+ <setProperty name="logComponent">
+ <simple>POLICY</simple>
+ </setProperty>
+ <to uri="direct:dump-loop-log-http-response"/>
+ </doCatch>
+ <doFinally>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+
+ <!-- Camel routes not related to Loop context -->
+ <route id="get-all-policy-models">
+ <from uri="direct:get-all-policy-models"/>
+ <doTry>
+ <log loggingLevel="INFO" message="Getting all the policy models"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Getting all the policy models')"/>
+ <setHeader name="CamelHttpMethod">
+ <constant>GET</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to get all policy models: {{clamp.config.policy.api.url}}/policy/api/v1/policytypes"></log>
+ <toD
+ uri="{{clamp.config.policy.api.url}}/policy/api/v1/policytypes?bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.policy.api.userName}}&amp;authPassword={{clamp.config.policy.api.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <convertBodyTo type="java.lang.String"/>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+
+ <route id="get-policy-tosca-model">
+ <from uri="direct:get-policy-tosca-model"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Getting the policy tosca model: ${exchangeProperty[policyModelType]}/${exchangeProperty[policyModelVersion]}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Getting the policy model')"/>
+ <setHeader name="CamelHttpMethod">
+ <constant>GET</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to get policy model: {{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policyModelType]}/versions/${exchangeProperty[policyModelVersion]}"></log>
+ <toD
+ uri="{{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policyModelType]}/versions/${exchangeProperty[policyModelVersion]}?bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.policy.api.userName}}&amp;authPassword={{clamp.config.policy.api.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <convertBodyTo type="java.lang.String"/>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+
+ <route id="get-all-pdp-groups">
+ <from uri="direct:get-all-pdp-groups"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Getting the list of PDP Groups"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Getting the PDP Group list')"/>
+ <setHeader name="CamelHttpMethod">
+ <constant>GET</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to get policy model: {{clamp.config.policy.pap.url}}/policy/pap/v1/pdps"></log>
+ <toD
+ uri="{{clamp.config.policy.pap.url}}/policy/pap/v1/pdps?bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.policy.pap.userName}}&amp;authPassword={{clamp.config.policy.pap.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <convertBodyTo type="java.lang.String"/>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+
+ <route id="get-all-policies">
+ <from uri="direct:get-all-policies"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Getting the policies list"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Getting the policies list')"/>
+ <setHeader name="CamelHttpMethod">
+ <constant>GET</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to get policies list: {{clamp.config.policy.api.url}}/policy/api/v1/policies"></log>
+ <toD
+ uri="{{clamp.config.policy.api.url}}/policy/api/v1/policies?bridgeEndpoint=true&amp;useSystemProperties=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authMethod=Basic&amp;authUsername={{clamp.config.policy.api.userName}}&amp;authPassword={{clamp.config.policy.api.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <convertBodyTo type="java.lang.String"/>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+ <route id="add-multiple-policies-to-pdp-group">
+ <from uri="direct:add-multiple-policies-to-pdp-group"/>
+ <!-- Body should come from outside, expect a json describing the policy -->
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Add policies to PDP group"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Add policies to PDP group')"/>
+ <setHeader name="CamelHttpMethod">
+ <constant>POST</constant>
+ </setHeader>
+ <setHeader name="Content-Type">
+ <constant>application/json</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to add/remove policies in batch to PDP Group: {{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/deployments/batch"></log>
+ <toD
+ uri="{{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/deployments/batch?bridgeEndpoint=true&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;useSystemProperties=true&amp;authUsername={{clamp.config.policy.pap.userName}}&amp;authPassword={{clamp.config.policy.pap.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+ <route id="undeploy-one-policy-from-pap">
+ <from uri="direct:undeploy-one-policy-from-pap"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Undeploy POLICY from PAP: ${exchangeProperty[policyName]}/${exchangeProperty[policyVersion]}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Undeploy POLICY from PAP')"/>
+ <setBody>
+ <constant>null</constant>
+ </setBody>
+ <setHeader name="CamelHttpMethod">
+ <constant>DELETE</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to delete policy from PDP Group: {{clamp.config.policy.pap.url}}/pdps/policies/${exchangeProperty[policyName]}/versions/${exchangeProperty[policyVersion]}"></log>
+ <toD
+ uri="{{clamp.config.policy.pap.url}}/policy/pap/v1/pdps/policies/${exchangeProperty[policyName]}/versions/${exchangeProperty[policyVersion]}?bridgeEndpoint=true&amp;useSystemProperties=true&amp;mapHttpMessageHeaders=false&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authUsername={{clamp.config.policy.pap.userName}}&amp;authPassword={{clamp.config.policy.pap.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+
+ <route id="create-policy">
+ <!-- Body should come from outside, expect a json describing the policy -->
+ <from uri="direct:create-policy"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Create Policy from model ${exchangeProperty[policyModelType]}/${exchangeProperty[policyModelVersion]}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Create Policy')"/>
+ <setHeader name="CamelHttpMethod">
+ <constant>POST</constant>
+ </setHeader>
+ <setHeader name="Content-Type">
+ <constant>application/json</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to create policy: {{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policyModelType]}/versions/${exchangeProperty[policyModelVersion]}/policies"></log>
+ <toD
+ uri="{{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policyModelType]}/versions/${exchangeProperty[policyModelVersion]}/policies?bridgeEndpoint=true&amp;useSystemProperties=true&amp;mapHttpMessageHeaders=false&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authUsername={{clamp.config.policy.api.userName}}&amp;authPassword={{clamp.config.policy.api.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+ <route id="delete-policy">
+ <from uri="direct:delete-policy"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Deleting Policy: ${exchangeProperty[policyName]}"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Delete Policy')"/>
+ <setBody>
+ <constant>null</constant>
+ </setBody>
+ <setHeader name="CamelHttpMethod">
+ <constant>DELETE</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to delete policy: {{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policyModelType]}/versions/${exchangeProperty[policyModelVersion]}/policies/${exchangeProperty[policyName]}/versions/${exchangeProperty[policyVersion]}"></log>
+ <toD
+ uri="{{clamp.config.policy.api.url}}/policy/api/v1/policytypes/${exchangeProperty[policyModelType]}/versions/${exchangeProperty[policyModelVersion]}/policies/${exchangeProperty[policyName]}/versions/${exchangeProperty[policyVersion]}?bridgeEndpoint=true&amp;useSystemProperties=true&amp;mapHttpMessageHeaders=false&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;deleteWithBody=false&amp;mapHttpMessageBody=false&amp;mapHttpMessageFormUrlEncodedBody=false&amp;authUsername={{clamp.config.policy.api.userName}}&amp;authPassword={{clamp.config.policy.api.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+ <route id="create-policy-type">
+ <from uri="direct:create-policy-type"/>
+ <doTry>
+ <log loggingLevel="INFO"
+ message="Creating Policy type"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeLog('Policy', 'Create policy typ')"/>
+ <setHeader name="CamelHttpMethod">
+ <constant>POST</constant>
+ </setHeader>
+ <setHeader name="Content-Type">
+ <constant>application/yaml</constant>
+ </setHeader>
+ <setHeader name="X-ONAP-RequestID">
+ <simple>${exchangeProperty[X-ONAP-RequestID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-InvocationID">
+ <simple>${exchangeProperty[X-ONAP-InvocationID]}
+ </simple>
+ </setHeader>
+ <setHeader name="X-ONAP-PartnerName">
+ <simple>${exchangeProperty[X-ONAP-PartnerName]}
+ </simple>
+ </setHeader>
+ <log loggingLevel="INFO"
+ message="Endpoint to create policy type: {{clamp.config.policy.api.url}}/policy/api/v1/policytypes"></log>
+ <toD
+ uri="{{clamp.config.policy.api.url}}/policy/api/v1/policytypes?bridgeEndpoint=true&amp;useSystemProperties=true&amp;mapHttpMessageHeaders=false&amp;throwExceptionOnFailure=${exchangeProperty[raiseHttpExceptionFlag]}&amp;authUsername={{clamp.config.policy.api.userName}}&amp;authPassword={{clamp.config.policy.api.password}}&amp;authenticationPreemptive=true&amp;connectionClose=true"/>
+
+ <doFinally>
+ <to uri="direct:reset-raise-http-exception-flag"/>
+ <to
+ uri="bean:org.onap.policy.clamp.flow.log.FlowLogOperation?method=invokeReturnLog()"/>
+ </doFinally>
+ </doTry>
+ </route>
+</routes> \ No newline at end of file
diff --git a/runtime/src/main/resources/clds/camel/routes/utils-flows.xml b/runtime/src/main/resources/clds/camel/routes/utils-flows.xml
new file mode 100644
index 000000000..90900f842
--- /dev/null
+++ b/runtime/src/main/resources/clds/camel/routes/utils-flows.xml
@@ -0,0 +1,28 @@
+<routes xmlns="http://camel.apache.org/schema/spring">
+ <route id="reset-raise-http-exception-flag">
+ <from uri="direct:reset-raise-http-exception-flag" />
+ <setProperty name="raiseHttpExceptionFlag">
+ <simple resultType="java.lang.Boolean">true</simple>
+ </setProperty>
+ </route>
+
+ <route id="dump-loop-log-http-response">
+ <from uri="direct:dump-loop-log-http-response" />
+ <log loggingLevel="INFO"
+ message="${exchangeProperty[logMessage]} - ${header.CamelHttpResponseCode} : ${header.CamelHttpResponseText}" />
+ <choice>
+ <when>
+ <simple>${exchangeProperty[logComponent]} == null</simple>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLog('${exchangeProperty[logMessage]} - ${header.CamelHttpResponseCode} : ${header.CamelHttpResponseText}','INFO',${exchangeProperty[loopObject]})" />
+ </when>
+ <otherwise>
+ <to
+ uri="bean:org.onap.policy.clamp.loop.log.LoopLogService?method=addLogForComponent('${exchangeProperty[logMessage]} - ${header.CamelHttpResponseCode} : ${header.CamelHttpResponseText}','INFO','${exchangeProperty[logComponent]}',${exchangeProperty[loopObject]})" />
+ <setProperty name="logComponent">
+ <constant>null</constant>
+ </setProperty>
+ </otherwise>
+ </choice>
+ </route>
+</routes> \ No newline at end of file
diff --git a/runtime/src/main/resources/clds/clds-users.json b/runtime/src/main/resources/clds/clds-users.json
new file mode 100644
index 000000000..5a7f43841
--- /dev/null
+++ b/runtime/src/main/resources/clds/clds-users.json
@@ -0,0 +1,33 @@
+[
+ {
+ "user": "admin",
+ "password": "$2a$10$H/e21kl04Dw9C978CHuM7OewyMGUN5WGzAAx7SgIaR4ix8.wTcssi",
+ "permissions": [
+ "org.onap.clamp.clds.cl|dev|read",
+ "org.onap.clamp.clds.cl|dev|update",
+ "org.onap.clamp.clds.cl.manage|dev|*",
+ "org.onap.clamp.clds.cl.event|dev|*",
+ "org.onap.clamp.clds.filter.vf|dev|*",
+ "org.onap.clamp.clds.template|dev|read",
+ "org.onap.clamp.clds.template|dev|update",
+ "org.onap.clamp.clds.tosca|dev|read",
+ "org.onap.clamp.clds.tosca|dev|update",
+ "org.onap.clamp.clds.policies|dev|read",
+ "org.onap.clamp.clds.policies|dev|update"
+ ]
+ },
+ {
+ "user": "cs0008",
+ "password": "$2a$10$H/e21kl04Dw9C978CHuM7OewyMGUN5WGzAAx7SgIaR4ix8.wTcssi",
+ "permissions": [
+ "org.onap.clamp.clds.cl|dev|read",
+ "org.onap.clamp.clds.cl|dev|update",
+ "org.onap.clamp.clds.cl.manage|dev|*",
+ "org.onap.clamp.clds.filter.vf|dev|*",
+ "org.onap.clamp.clds.template|dev|read",
+ "org.onap.clamp.clds.template|dev|update",
+ "org.onap.clamp.clds.tosca|dev|read",
+ "org.onap.clamp.clds.tosca|dev|update"
+ ]
+ }
+]
diff --git a/runtime/src/main/resources/clds/json-schema/operational_policies/operational_policy.json b/runtime/src/main/resources/clds/json-schema/operational_policies/operational_policy.json
new file mode 100644
index 000000000..973028316
--- /dev/null
+++ b/runtime/src/main/resources/clds/json-schema/operational_policies/operational_policy.json
@@ -0,0 +1,320 @@
+{
+ "type": "object",
+ "title": "Configuration",
+ "required": [
+ "operational_policy"
+ ],
+ "properties": {
+ "operational_policy": {
+ "type": "object",
+ "title": "Related Parameters",
+ "required": [
+ "controlLoop",
+ "policies"
+ ],
+ "properties": {
+ "controlLoop": {
+ "type": "object",
+ "title": "Control Loop details",
+ "required": [
+ "timeout",
+ "abatement",
+ "trigger_policy",
+ "controlLoopName"
+ ],
+ "properties": {
+ "timeout": {
+ "type": "string",
+ "title": "Overall Time Limit",
+ "default": "0",
+ "format": "number"
+ },
+ "abatement": {
+ "type": "string",
+ "title": "Abatement",
+ "enum": [
+ "True",
+ "False"
+ ]
+ },
+ "trigger_policy": {
+ "type": "string",
+ "title": "Policy Decision Entry"
+ },
+ "controlLoopName": {
+ "type": "string",
+ "title": "Control loop name",
+ "readOnly": "True"
+ }
+ }
+ },
+ "policies": {
+ "uniqueItems": "true",
+ "id": "policies_array",
+ "type": "array",
+ "title": "Policy Decision Tree",
+ "format": "tabs-top",
+ "items": {
+ "title": "Policy Decision",
+ "type": "object",
+ "id": "policy_item",
+ "headerTemplate": "{{self.id}} - {{self.recipe}}",
+ "format": "categories",
+ "basicCategoryTitle": "recipe",
+ "required": [
+ "id",
+ "retry",
+ "timeout",
+ "actor",
+ "success",
+ "failure",
+ "failure_timeout",
+ "failure_retries",
+ "failure_exception",
+ "failure_guard",
+ "target"
+ ],
+ "properties": {
+ "id": {
+ "default": "Policy 1",
+ "title": "Policy ID",
+ "type": "string"
+ },
+ "retry": {
+ "default": "0",
+ "title": "Number of Retry",
+ "type": "string",
+ "format": "number"
+ },
+ "timeout": {
+ "default": "0",
+ "title": "Timeout",
+ "type": "string",
+ "format": "number"
+ },
+ "actor": {
+ "type": "object",
+ "title": "Actor",
+ "anyOf": [
+ {
+ "title": "APPC",
+ "type": "object",
+ "properties": {
+ "actor": {
+ "title": "actor",
+ "type": "string",
+ "default": "APPC",
+ "options": {
+ "hidden": true
+ }
+ },
+ "recipe": {
+ "title": "recipe",
+ "type": "string",
+ "default": "",
+ "enum": [
+ "Restart",
+ "Rebuild",
+ "Migrate",
+ "Health-Check",
+ "ModifyConfig"
+ ]
+ },
+ "payload": {
+ "title": "Payload (YAML)",
+ "type": "string",
+ "format": "textarea"
+ }
+ }
+ },
+ {
+ "title": "SO",
+ "type": "object",
+ "properties": {
+ "actor": {
+ "title": "actor",
+ "type": "string",
+ "default": "SO",
+ "options": {
+ "hidden": true
+ }
+ },
+ "recipe": {
+ "title": "recipe",
+ "type": "string",
+ "default": "",
+ "enum": [
+ "VF Module Create",
+ "VF Module Delete"
+ ]
+ },
+ "payload": {
+ "title": "Payload (YAML)",
+ "type": "string",
+ "format": "textarea"
+ }
+ }
+ },
+ {
+ "title": "SDNC",
+ "type": "object",
+ "properties": {
+ "actor": {
+ "title": "actor",
+ "type": "string",
+ "default": "SDNC",
+ "options": {
+ "hidden": true
+ }
+ },
+ "recipe": {
+ "title": "recipe",
+ "type": "string",
+ "default": "",
+ "enum": [
+ "Reroute",
+ "BandwidthOnDemand"
+ ]
+ },
+ "payload": {
+ "title": "Payload (YAML)",
+ "type": "string",
+ "format": "textarea"
+ }
+ }
+ },
+ {
+ "title": "VFC",
+ "type": "object",
+ "properties": {
+ "actor": {
+ "title": "actor",
+ "type": "string",
+ "default": "VFC",
+ "options": {
+ "hidden": true
+ }
+ },
+ "recipe": {
+ "title": "recipe",
+ "type": "string",
+ "default": "",
+ "enum": [
+ "ModifyConfig"
+ ]
+ },
+ "payload": {
+ "title": "Payload (YAML)",
+ "type": "string",
+ "format": "textarea"
+ }
+ }
+ },
+ {
+ "title": "CDS",
+ "type": "object",
+ "properties": {
+ "actor": {
+ "title": "actor",
+ "type": "string",
+ "default": "CDS",
+ "options": {
+ "hidden": true
+ }
+ },
+ "recipe": {
+ "title": "recipe",
+ "type": "object",
+ "anyOf": [
+ {
+ "title": "user-defined",
+ "type": "object",
+ "properties": {
+ "recipe": {
+ "title": "recipe",
+ "type": "string",
+ "default": "user-defined",
+ "format": "textarea"
+ },
+ "payload": {
+ "title": "Payload (YAML)",
+ "type": "string",
+ "default": "",
+ "format": "textarea"
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ "success": {
+ "default": "final_success",
+ "title": "When Success",
+ "type": "string"
+ },
+ "failure": {
+ "default": "final_failure",
+ "title": "When Failure",
+ "type": "string"
+ },
+ "failure_timeout": {
+ "default": "final_failure_timeout",
+ "title": "When Failure Timeout",
+ "type": "string"
+ },
+ "failure_retries": {
+ "default": "final_failure_retries",
+ "title": "When Failure Retries",
+ "type": "string"
+ },
+ "failure_exception": {
+ "default": "final_failure_exception",
+ "title": "When Failure Exception",
+ "type": "string"
+ },
+ "failure_guard": {
+ "default": "final_failure_guard",
+ "title": "When Failure Guard",
+ "type": "string"
+ },
+ "target": {
+ "type": "object",
+ "required": [
+ "type",
+ "resourceID"
+ ],
+ "anyOf": [
+ {
+ "title": "User Defined",
+ "additionalProperties": "True",
+ "properties": {
+ "type": {
+ "title": "Target type",
+ "type": "string",
+ "default": "",
+ "enum": [
+ "VNF",
+ "VFMODULE",
+ "VM"
+ ]
+ },
+ "resourceID": {
+ "title": "Target type",
+ "type": "string",
+ "default": ""
+ }
+ }
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
diff --git a/runtime/src/main/resources/clds/sdc-controllers-config.json b/runtime/src/main/resources/clds/sdc-controllers-config.json
new file mode 100644
index 000000000..be9d02c8d
--- /dev/null
+++ b/runtime/src/main/resources/clds/sdc-controllers-config.json
@@ -0,0 +1,18 @@
+{
+ "sdc-connections":{
+ "sdc-controller":{
+ "user": "clamp",
+ "consumerGroup": "clamp",
+ "consumerId": "clamp",
+ "environmentName": "AUTO",
+ "sdcAddress": "sdc.api.simpledemo.onap.org:8443",
+ "password": "enc:JPV4p067JlSXt2Fet9bfuI8JpkS4ZGYVcgypcPs98gXjgjCjTze_d3JxqmlKaaakdiOjIcEC_MJh6-5pJTLgdc",
+ "pollingInterval":30,
+ "pollingTimeout":30,
+ "activateServerTLSAuth":"false",
+ "keyStorePassword":"",
+ "keyStorePath":"",
+ "messageBusAddresses":["ueb.api.simpledemo.onap.org"]
+ }
+ }
+}
diff --git a/runtime/src/main/resources/clds/tosca-converter/default-tosca-types.yaml b/runtime/src/main/resources/clds/tosca-converter/default-tosca-types.yaml
new file mode 100644
index 000000000..a11a73698
--- /dev/null
+++ b/runtime/src/main/resources/clds/tosca-converter/default-tosca-types.yaml
@@ -0,0 +1,87 @@
+tosca_definitions_version: tosca_simple_yaml_1_1_0
+data_types:
+ tosca.datatypes.Root:
+ description: The TOSCA root Data Type all other TOSCA base Data Types derive from
+ tosca.datatypes.Credential:
+ derived_from: tosca.datatypes.Root
+ properties:
+ protocol:
+ type: string
+ required: false
+ token_type:
+ type: string
+ default: password
+ token:
+ type: string
+ keys:
+ type: map
+ required: false
+ entry_schema:
+ type: string
+ user:
+ type: string
+ required: false
+ tosca.datatypes.TimeInterval:
+ derived_from: tosca.datatypes.Root
+ properties:
+ start_time:
+ type: timestamp
+ required: true
+ end_time:
+ type: timestamp
+ required: true
+ tosca.datatypes.network.NetworkInfo:
+ derived_from: tosca.datatypes.Root
+ properties:
+ network_name:
+ type: string
+ network_id:
+ type: string
+ addresses:
+ type: list
+ entry_schema:
+ type: string
+ tosca.datatypes.network.PortInfo:
+ derived_from: tosca.datatypes.Root
+ properties:
+ port_name:
+ type: string
+ port_id:
+ type: string
+ network_id:
+ type: string
+ mac_address:
+ type: string
+ addresses:
+ type: list
+ entry_schema:
+ type: string
+ # tosca.datatypes.network.PortDef:
+ # derived_from: integer
+ # constraints:
+ # - in_range: [ 1, 65535 ]
+ # tosca.datatypes.network.PortSpec:
+ # derived_from: tosca.datatypes.Root
+ # properties:
+ # protocol:
+ # type: string
+ # required: true
+ # default: tcp
+ # constraints:
+ # - valid_values: [ udp, tcp, igmp ]
+ # target:
+ # type: PortDef
+ # required: false
+ # target_range:
+ # type: range
+ # required: false
+ # constraints:
+ # - in_range: [ 1, 65535 ]
+ # source:
+ # type: PortDef
+ # required: false
+ # source_range:
+ # type: range
+ # required: false
+ # constraints:
+ # - in_range: [ 1, 65535 ] \ No newline at end of file
diff --git a/runtime/src/main/resources/clds/tosca-converter/templates.json b/runtime/src/main/resources/clds/tosca-converter/templates.json
new file mode 100644
index 000000000..f709e2f6d
--- /dev/null
+++ b/runtime/src/main/resources/clds/tosca-converter/templates.json
@@ -0,0 +1,398 @@
+{
+ "integer":{
+ "type":{
+ "defaultValue":"integer",
+ "visible":true,
+ "static":false
+ },
+ "description":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "title":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+
+ },
+ "deprecated":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "default":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "enum":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "const":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "multipleOf":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "maximum":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "exclusiveMaximum":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "minimum":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "exclusiveMinimum":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ }
+ },
+ "number":{
+ "type":{
+ "defaultValue":"number",
+ "visible":true,
+ "static":false
+ },
+ "description":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "title":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+
+ },
+ "deprecated":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "default":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "enum":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "const":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "multipleOf":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "maximum":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "exclusiveMaximum":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "minimum":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "exclusiveMinimum":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ }
+ },
+ "boolean":{
+ "type":{
+ "defaultValue":"boolean",
+ "visible":true,
+ "static":false
+ },
+ "description":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "title":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "deprecated":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "default":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "const":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ }
+ },
+ "string":{
+ "type":{
+ "defaultValue":"string",
+ "visible":true,
+ "static":false
+ },
+ "description":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "title":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "deprecated":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "default":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "enum":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "const":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "length":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "minLength":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "maxLength":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "pattern":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "format":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ }
+ },
+ "timestamp":{
+ "type":{
+ "defaultValue":"string",
+ "visible":true,
+ "static":false
+ },
+ "description":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "title":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "deprecated":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "default":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "enum":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "const":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "length":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "minLength":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "maxLength":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "pattern":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "format":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ }
+ },
+ "array":{
+ "type":{
+ "defaultValue":"array",
+ "visible":true,
+ "static":false
+ },
+ "description":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "title":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "deprecated":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "default":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "const":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "uniqueItems":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "properties":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "minContains":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "maxContains":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "minItems":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "maxItems":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ }
+ },
+ "object":{
+ "type":{
+ "defaultValue":"object",
+ "visible":true,
+ "static":false
+ },
+ "description":{
+ "defaultValue":"",
+ "visible":true,
+ "static":true
+ },
+ "title":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "format":{
+ "defaultValue":"tabs",
+ "visible":true,
+ "static":true
+ },
+ "required":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "minProperties":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "maxProperties":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "properties":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "dependentRequired":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ },
+ "dependencies":{
+ "defaultValue":"",
+ "visible":true,
+ "static":false
+ }
+ }
+} \ No newline at end of file
diff --git a/runtime/src/main/resources/logback-default.xml b/runtime/src/main/resources/logback-default.xml
new file mode 100644
index 000000000..5397eab04
--- /dev/null
+++ b/runtime/src/main/resources/logback-default.xml
@@ -0,0 +1,329 @@
+<included>
+ <jmxConfigurator />
+ <!-- Example evaluator filter applied against console appender -->
+ <property
+ name="p_tim"
+ value="%d{&quot;yyyy-MM-dd'T'HH:mm:ss.SSSXXX&quot;, UTC}" />
+ <property
+ name="p_lvl"
+ value="%level" />
+ <property
+ name="p_log"
+ value="%logger" />
+ <property
+ name="p_mdc"
+ value="%replace(%replace(%mdc){'\t','\\\\t'}){'\n', '\\\\n'}" />
+ <property
+ name="p_msg"
+ value="%replace(%replace(%msg){'\t', '\\\\t'}){'\n','\\\\n'}" />
+ <property
+ name="p_exc"
+ value="%replace(%replace(%rootException){'\t', '\\\\t'}){'\n','\\\\n'}" />
+ <property
+ name="p_mak"
+ value="%replace(%replace(%marker){'\t', '\\\\t'}){'\n','\\\\n'}" />
+ <property
+ name="p_thr"
+ value="%thread" />
+ <property
+ name="defaultPattern"
+ value="%nopexception${p_tim}\t${p_thr}\t${p_lvl}\t${p_log}\t${p_mdc}\t${p_msg}\t${p_exc}\t${p_mak}\t%n" />
+ <property
+ name="debugPattern"
+ value="%nopexception${p_tim}|${p_lvl}|${p_mdc}|${p_exc}|%msg%n" />
+
+ <property
+ name="errorPattern"
+ value="%X{EntryTimestamp}|%X{RequestID}|%thread|%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}||||%msg%n" />
+
+ <property
+ name="auditPattern"
+ value="%X{EntryTimestamp}|%date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX,UTC}|%X{RequestID}|%X{ServiceInstanceId}|%thread|%X{VirtualServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDesc}|%X{InstanceUUID}|%.-5level|%X{Severity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}||||%marker|%mdc|||%msg%n" />
+
+ <property
+ name="metricPattern"
+ value="%X{InvokeTimestamp}|%date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX,UTC}|%X{RequestID}|%X{ServiceInstanceId}|%thread||%X{ServiceName}|%X{PartnerName}|%X{TargetEntity}|%X{TargetServiceName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDesc}|%X{InstanceUUID}|%.-5level|%X{Severity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}||||%X{TargetVirtualEntity}|%marker|%mdc|||%msg%n" />
+
+
+ <!-- Example evaluator filter applied against console appender -->
+ <appender
+ name="STDOUT"
+ class="ch.qos.logback.core.ConsoleAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ <level>INFO</level>
+ </filter>
+ <encoder>
+ <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n
+ </pattern>
+ </encoder>
+ </appender>
+
+ <appender
+ name="ERROR"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <level>ERROR</level>
+ <onMatch>ACCEPT</onMatch>
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ <file>${logDirectory}/error.log</file>
+ <append>true</append>
+ <encoder>
+ <pattern>${errorPattern}</pattern>
+ </encoder>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/error.%d{yyyy-MM-dd}.%i.log.zip
+ </fileNamePattern>
+ <maxFileSize>50MB</maxFileSize>
+ <maxHistory>20</maxHistory>
+ <totalSizeCap>1GB</totalSizeCap>
+ </rollingPolicy>
+ </appender>
+
+ <appender
+ name="DEBUG"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/debug.log</file>
+ <append>true</append>
+ <encoder>
+ <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{1024} - %msg%n
+ </pattern>
+ </encoder>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/debug.%d{yyyy-MM-dd}.%i.log.zip
+ </fileNamePattern>
+ <maxFileSize>50MB</maxFileSize>
+ <maxHistory>20</maxHistory>
+ <totalSizeCap>1GB</totalSizeCap>
+ </rollingPolicy>
+ </appender>
+
+
+ <appender
+ name="AUDIT"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+ <evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
+ <marker>ENTRY</marker>
+ <marker>EXIT</marker>
+ </evaluator>
+ <onMismatch>DENY</onMismatch>
+ <onMatch>ACCEPT</onMatch>
+ </filter>
+ <file>${logDirectory}/audit.log</file>
+ <append>true</append>
+ <encoder>
+ <pattern>${auditPattern}</pattern>
+ </encoder>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+ <FileNamePattern>${logDirectory}/audit.%d{yyyy-MM-dd}.%i.log.zip
+ </FileNamePattern>
+ <maxFileSize>50MB</maxFileSize>
+ <maxHistory>20</maxHistory>
+ <totalSizeCap>1GB</totalSizeCap>
+ </rollingPolicy>
+ </appender>
+ <appender
+ name="asyncEELFAudit"
+ class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>256</queueSize>
+ <appender-ref ref="AUDIT" />
+ </appender>
+
+ <appender
+ name="METRIC"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
+ <evaluator class="ch.qos.logback.classic.boolex.OnMarkerEvaluator">
+ <marker>INVOKE</marker>
+ <marker>INVOKE-RETURN</marker>
+ </evaluator>
+ <onMismatch>DENY</onMismatch>
+ <onMatch>ACCEPT</onMatch>
+ </filter>
+ <file>${logDirectory}/metric.log</file>
+ <append>true</append>
+ <encoder>
+ <pattern>${metricPattern}</pattern>
+ </encoder>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+ <FileNamePattern>${logDirectory}/metric.%d{yyyy-MM-dd}.%i.log.zip
+ </FileNamePattern>
+ <maxFileSize>50MB</maxFileSize>
+ <maxHistory>20</maxHistory>
+ <totalSizeCap>1GB</totalSizeCap>
+ </rollingPolicy>
+ </appender>
+
+ <appender
+ name="asyncEELFMetrics"
+ class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>256</queueSize>
+ <appender-ref ref="METRIC" />
+ </appender>
+
+ <!-- SECURITY related loggers -->
+ <appender
+ name="SECURITY"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${logDirectory}/security.log</file>
+ <append>true</append>
+ <encoder>
+ <pattern>%X{EntryTimestamp}|%date{yyyy-MM-dd'T'HH:mm:ss.SSSXXX,UTC}|%X{RequestID}|%X{ServiceInstanceId}|%.20thread|%X{VirtualServerName}|%X{ServiceName}|%X{PartnerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%.-5level|%X{AlertSeverity}|%X{ServerIPAddress}|%X{ElapsedTime}|%X{ServerFQDN}|%X{RemoteHost}|%X{ClassName}|%X{Unused}|%X{ProcessKey}|%X{CustomField1}|%X{CustomField2}|%X{CustomField3}|%X{CustomField4}|%msg%n
+ </pattern>
+ </encoder>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+ <FileNamePattern>${logDirectory}/security.%d{yyyy-MM-dd}.%i.log.zip
+ </FileNamePattern>
+ <maxFileSize>50MB</maxFileSize>
+ <maxHistory>20</maxHistory>
+ <totalSizeCap>1GB</totalSizeCap>
+ </rollingPolicy>
+ </appender>
+
+ <appender
+ name="asyncEELFSecurity"
+ class="ch.qos.logback.classic.AsyncAppender">
+ <queueSize>256</queueSize>
+ <appender-ref ref="SECURITY" />
+ </appender>
+ <!-- logback jms appenders & loggers definition starts here -->
+ <appender
+ name="auditLogs"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ </filter>
+ <file>${logDirectory}/Audits.log</file>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/Audits-%d{yyyy-MM-dd}.%i.log.zip
+ </fileNamePattern>
+ <maxFileSize>50MB</maxFileSize>
+ <maxHistory>20</maxHistory>
+ <totalSizeCap>1GB</totalSizeCap>
+ </rollingPolicy>
+ <encoder>
+ <pattern>"%d [%thread] %-5level %logger{1024} - %msg%n"</pattern>
+ </encoder>
+ </appender>
+
+ <appender
+ name="perfLogs"
+ class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
+ </filter>
+ <file>${logDirectory}/Perform.log</file>
+ <rollingPolicy
+ class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
+ <fileNamePattern>${logDirectory}/Perform--%d{yyyy-MM-dd}.%i.log.zip
+ </fileNamePattern>
+ <maxFileSize>50MB</maxFileSize>
+ <maxHistory>20</maxHistory>
+ <totalSizeCap>1GB</totalSizeCap>
+ </rollingPolicy>
+ <encoder>
+ <pattern>"%d [%thread] %-5level %logger{1024} - %msg%n"</pattern>
+ </encoder>
+ </appender>
+
+ <logger
+ name="org.onap.aaf"
+ level="DEBUG">
+ <appender-ref ref="DEBUG" />
+ </logger>
+ <logger
+ name="org.hibernate"
+ level="INFO">
+ <appender-ref ref="DEBUG" />
+ </logger>
+ <logger
+ name="org.apache.camel.Tracing"
+ level="INFO">
+ <appender-ref ref="DEBUG" />
+ </logger>
+
+ <logger
+ name="org.apache"
+ level="INFO">
+ <appender-ref ref="DEBUG" />
+ </logger>
+ <!-- Spring related loggers -->
+ <logger
+ name="org.springframework"
+ level="INFO">
+ <appender-ref ref="DEBUG" />
+ </logger>
+
+ <!-- CLAMP related loggers -->
+ <logger
+ name="org.onap.policy.clamp"
+ level="DEBUG">
+ <appender-ref ref="ERROR" />
+ <appender-ref ref="DEBUG" />
+ </logger>
+
+ <logger
+ name="com.att.eelf.error"
+ level="OFF">
+ <appender-ref ref="ERROR" />
+ </logger>
+ <!-- EELF related loggers -->
+ <logger
+ name="com.att.eelf.audit"
+ level="INFO"
+ additivity="false">
+ <appender-ref ref="asyncEELFAudit" />
+ </logger>
+ <logger
+ name="com.att.eelf.metrics"
+ level="DEBUG"
+ additivity="false">
+ <appender-ref ref="asyncEELFMetrics" />
+ </logger>
+ <logger
+ name="com.att.eelf.security"
+ level="DEBUG"
+ additivity="false">
+ <appender-ref ref="asyncEELFSecurity" />
+ </logger>
+
+ <!-- logback internals logging -->
+ <logger
+ name="ch.qos.logback.classic"
+ level="INFO" />
+ <logger
+ name="ch.qos.logback.core"
+ level="INFO" />
+ <logger
+ name="AuditRecord"
+ level="INFO"
+ additivity="false">
+ <appender-ref ref="auditLogs" />
+ </logger>
+ <logger
+ name="AuditRecord_DirectCall"
+ level="INFO"
+ additivity="false">
+ <appender-ref ref="auditLogs" />
+ </logger>
+ <logger
+ name="PerfTrackerRecord"
+ level="INFO"
+ additivity="false">
+ <appender-ref ref="perfLogs" />
+ </logger>
+ <!-- logback jms appenders & loggers definition ends here -->
+
+ <root level="DEBUG">
+ <appender-ref ref="DEBUG" />
+ <appender-ref ref="STDOUT" />
+ <appender-ref ref="AUDIT" />
+ <appender-ref ref="METRIC" />
+ <appender-ref ref="ERROR" />
+ </root>
+</included>
diff --git a/runtime/src/main/resources/logback-spring.xml b/runtime/src/main/resources/logback-spring.xml
new file mode 100644
index 000000000..ffa497f1d
--- /dev/null
+++ b/runtime/src/main/resources/logback-spring.xml
@@ -0,0 +1,19 @@
+<configuration debug="true">
+ <springProperty name="logbackFilePath"
+ source="clamp.config.logback.path" />
+ <springProperty name="logbackFileName"
+ source="clamp.config.logback.filename" />
+ <springProperty name="logDirectory"
+ source="clamp.config.log.path" />
+
+ <if condition='isNull("logbackFilePath")'>
+ <then>
+ <!-- Classpath case -->
+ <include resource="${logbackFileName}" />
+ </then>
+ <else>
+ <!-- File system case -->
+ <include file="${logbackFilePath}/${logbackFileName}" />
+ </else>
+ </if>
+</configuration> \ No newline at end of file
diff --git a/runtime/src/main/resources/logmessages.properties b/runtime/src/main/resources/logmessages.properties
new file mode 100644
index 000000000..fc9f74a36
--- /dev/null
+++ b/runtime/src/main/resources/logmessages.properties
@@ -0,0 +1,27 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+LOGSERVICE_EMAIL_ERROR=SERVICE0007I|Exception while sending e-mail:{0}|Resolution needed|action is required
+LOGSERVICE_EMAIL_CLASS=SERVICE0008I|classUrl.getFile:{0}|Resolution needed|action is required
+LOGSERVICE_EMAIL_CLASS_NULL=SERVICE0009I|classUrl is NULL|Resolution needed|action is required
+PROCESS_INSTANCE_ID=SERVICE0010I|Process Instance Id:{0}|No resolution needed|No action is required
diff --git a/runtime/src/main/resources/system.properties b/runtime/src/main/resources/system.properties
new file mode 100644
index 000000000..f95fc7009
--- /dev/null
+++ b/runtime/src/main/resources/system.properties
@@ -0,0 +1,27 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+### Static JVM parameters can be set here by the dev team
+### These will be loaded at Clamp startup
+#
+# JVM SSL/TLS properties
+jdk.tls.client.protocols=TLSv1.1,TLSv1.2
+https.protocols=TLSv1.1,TLSv1.2
diff --git a/runtime/src/main/script/SelectNpmRepo.groovy b/runtime/src/main/script/SelectNpmRepo.groovy
new file mode 100644
index 000000000..797d2d003
--- /dev/null
+++ b/runtime/src/main/script/SelectNpmRepo.groovy
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.maven.scripts
+
+println project.properties['clamp.project.version'];
+
+if ( project.properties['clamp.project.version'].endsWith("-SNAPSHOT") ) {
+ project.properties['npm.publish.url']="https://nexus3.onap.org/repository/npm.snapshot/"
+} else {
+ project.properties['npm.publish.url']="https://nexus3.onap.org/repository/npm.snapshot/"
+}
+
+println 'NPM repository: ' + project.properties['npm.publish.url'];
diff --git a/runtime/src/main/script/TagVersion.groovy b/runtime/src/main/script/TagVersion.groovy
new file mode 100644
index 000000000..271e2967f
--- /dev/null
+++ b/runtime/src/main/script/TagVersion.groovy
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.maven.scripts
+
+println project.properties['clamp.project.version'];
+def versionArray;
+if ( project.properties['clamp.project.version'] != null ) {
+ versionArray = project.properties['clamp.project.version'].split('\\.');
+}
+
+if ( project.properties['clamp.project.version'].endsWith("-SNAPSHOT") ) {
+ project.properties['project.docker.latesttag.version']=versionArray[0] + '.' + versionArray[1] + "-SNAPSHOT-latest";
+ project.properties['project.docker.latesttagtimestamp.version']=versionArray[0] + '.' + versionArray[1] + "-SNAPSHOT-"+project.properties['clamp.build.timestamp'];
+} else {
+ project.properties['project.docker.latesttag.version']=versionArray[0] + '.' + versionArray[1] + "-STAGING-latest";
+ project.properties['project.docker.latesttagtimestamp.version']=versionArray[0] + '.' + versionArray[1] + "-STAGING-"+project.properties['clamp.build.timestamp'];
+}
+
+println 'New Tag for docker:' + project.properties['project.docker.latesttag.version']; \ No newline at end of file
diff --git a/runtime/src/main/script/checkLibIndex.sh b/runtime/src/main/script/checkLibIndex.sh
new file mode 100644
index 000000000..fef9c1b7a
--- /dev/null
+++ b/runtime/src/main/script/checkLibIndex.sh
@@ -0,0 +1,122 @@
+#!/bin/bash
+###
+# ============LICENSE_START=======================================================
+# ONAP CLAMP
+# ================================================================================
+# Copyright (C) 2020 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+baseDir=$(git rev-parse --show-toplevel)
+
+if [[ ! -d $baseDir ]]
+then
+ echo "[ERROR] failed to determine git base directory"
+ exit 1
+fi
+
+tmpSrcFileList=/tmp/upldateLibIndex.$$.list
+reactUiBaseDir="${baseDir}/runtime/ui-react"
+reactLibIndexFile="runtime/ui-react-lib/libIndex.js"
+exclusionList="runtime/ui-react-lib/libExportExclusions.dat"
+
+
+if [[ ! -d "$reactUiBaseDir" ]]
+then
+ echo "[ERROR] reacUiBaseDir=$reacUiBaseDir is not accessible"
+ exit 1
+fi
+
+if [[ ! -d "$baseDir/$reactLibBaseDir" ]]
+then
+ echo "[ERROR] reactLibBaseDir=$baseDir/$reactLibBaseDir is not accessible"
+ exit 1
+fi
+
+if [[ ! -r "$baseDir/$reactLibIndexFile" ]]
+then
+ echo "[ERROR] file reactLibIndexFile=$baseDir/$reactLibIndexFile is not accessible"
+ exit 1
+fi
+
+
+if ! cd $reactUiBaseDir
+then
+ echo "[ERROR] could not cd to reactUiBaseDir=$reactUiBaseDir"
+ exit 1
+fi
+
+find ./src -name \*.js | egrep -v "__snapshot|\.test\." 2>/dev/null | sed 's/.js$//' > $tmpSrcFileList
+
+if [[ ! -s $tmpSrcFileList ]]
+then
+ echo "[ERROR] no source files found in reactUiBaseDir=$reactUiBaseDir"
+ rm -f $tmpSrcFileList
+ exit 1
+fi
+
+export nErrors=0
+
+# Verify that any .js file found within ui-react/src other than test related files
+# is also referenced in ui-react-lib/libIndex.js
+
+for srcFileName in `<$tmpSrcFileList`
+do
+ if [[ -r "$baseDir/$exclusionList" ]]
+ then
+ if grep $srcFileName $baseDir/$exclusionList >/dev/null 2>&1
+ then
+ continue
+ fi
+ fi
+
+ if ! grep $srcFileName "$baseDir/$reactLibIndexFile" > /dev/null 2>&1
+ then
+ echo "[ERROR] file=${srcFileName}.js is not declared in $reactLibIndexFile"
+ echo "[ERROR] and not found in exclsionList=${exclusionList}."
+ echo "[ERROR] Please either add it to $reactLibIndexFile"
+ echo "[ERROR] or to the exclusion list in ${exclusionList}."
+ echo ""
+ (( nErrors++ ))
+ fi
+done
+
+# Verify for each entry in ui-react-lib/libIndex.js, that the referenced source file exists
+# in ui-react/src; if not, developer probably forgot to remove it from libIndex.js.
+
+egrep '^export ' $baseDir/$reactLibIndexFile |\
+sed -e "s+.*\./src+./src+" -e "s+'.*+.js+" > $tmpSrcFileList
+
+for srcFileName in `<$tmpSrcFileList`
+do
+ if [[ ! -r "$srcFileName" ]]
+ then
+ echo "[ERROR] source file=$srcFileName in libIndex.js is not accessible"
+ (( nErrors++ ))
+ fi
+done
+
+rm -f $tmpSrcFileList
+
+if (( nErrors == 0 ))
+then
+ echo "[INFO] $reactLibIndexFile passes sanity check"
+ exit 0
+fi
+
+exit $nErrors
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/client/CdsServicesTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/client/CdsServicesTest.java
new file mode 100644
index 000000000..6e5300e23
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/client/CdsServicesTest.java
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ * ================================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.client;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import org.junit.Test;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+public class CdsServicesTest {
+
+ @Test
+ public void testParseCdsListTypeProperties() throws IOException {
+ String cdsResponse = ResourceFileUtils
+ .getResourceAsString("example/cds-response/vFW-CDS-resource-assignment-workflow.json");
+ CdsServices services = new CdsServices();
+ JsonObject output = services.parseCdsResponse(cdsResponse);
+ JSONAssert.assertEquals(ResourceFileUtils
+ .getResourceAsString("example/cds-response/vFW-CDS-resource-assignment-wf-expected-result.json"),
+ JsonUtils.GSON.toJson(output), true);
+ }
+
+ @Test
+ public void testParseCdsResponse() throws IOException {
+ String cdsResponse = ResourceFileUtils
+ .getResourceAsString("example/cds-response/vFW-CDS-modify-config-workflow.json");
+ CdsServices services = new CdsServices();
+ JsonObject output = services.parseCdsResponse(cdsResponse);
+ JSONAssert.assertEquals(ResourceFileUtils
+ .getResourceAsString("example/cds-response/vFW-CDS-modify-config-wf-expected-result.json"),
+ JsonUtils.GSON.toJson(output), true);
+ }
+
+} \ No newline at end of file
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/config/CldsUserJsonDecoderTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/config/CldsUserJsonDecoderTest.java
new file mode 100644
index 000000000..605ab99ae
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/config/CldsUserJsonDecoderTest.java
@@ -0,0 +1,99 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * Modifications copyright (c) 2018 Nokia
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.config;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+import org.onap.policy.clamp.authorization.CldsUser;
+import org.onap.policy.clamp.clds.exception.CldsUsersException;
+
+public class CldsUserJsonDecoderTest {
+
+ private String user1 = "admin1";
+ private String user2 = "admin2";
+ private String password = "5f4dcc3b5aa765d61d8327deb882cf99";
+ private String[] normalPermissionsArray = { "permission-type-cl|dev|read", "permission-type-cl|dev|update",
+ "permission-type-cl-manage|dev|*", "permission-type-filter-vf|dev|*", "permission-type-template|dev|read",
+ "permission-type-template|dev|update" };
+ private String[] incompletePermissionsArray = { "permission-type-cl|dev|*", "permission-type-cl|dev|*",
+ "permission-type-cl-manage|dev|*", "permission-type-filter-vf|dev|*", "permission-type-template|dev|read",
+ "permission-type-template|dev|update" };
+
+ @Test
+ public void testDecodingDoubleUsers() {
+
+ // when
+ CldsUser[] usersArray = CldsUserJsonDecoder
+ .decodeJson(CldsUserJsonDecoderTest.class.getResourceAsStream("/clds/clds-users-two-users.json"));
+
+ // then
+ assertThat(usersArray).hasSize(2);
+ assertThat(usersArray[0]).extracting(CldsUser::getUser, CldsUser::getPassword, CldsUser::getPermissionsString)
+ .containsExactly(user1, password, normalPermissionsArray);
+
+ assertThat(usersArray[1]).extracting(CldsUser::getUser, CldsUser::getPassword, CldsUser::getPermissionsString)
+ .containsExactly(user2, password, normalPermissionsArray);
+
+ }
+
+ @Test
+ public void testDecodingNoPermission() {
+ // when
+ CldsUser[] usersArray = CldsUserJsonDecoder
+ .decodeJson(this.getClass().getResourceAsStream("/clds/clds-users-no-permission.json"));
+
+ // then
+ assertThat(usersArray).hasSize(1);
+ CldsUser user = usersArray[0];
+ assertThat(user.getUser()).isEqualTo(user1);
+ assertThat(user.getPassword()).isEqualTo(null);
+ assertThat(user.getPermissionsString()).isEmpty();
+ }
+
+ @Test
+ public void testDecodingIncompletePermissions() {
+
+ // when
+ CldsUser[] usersArray = CldsUserJsonDecoder
+ .decodeJson(this.getClass().getResourceAsStream("/clds/clds-users-incomplete-permissions.json"));
+
+ // then
+ assertThat(usersArray).hasSize(1);
+ CldsUser user = usersArray[0];
+ assertThat(user.getUser()).isEqualTo(user1);
+ assertThat(user.getPassword()).isEqualTo(password);
+ assertThat(user.getPermissionsString()).isEqualTo(incompletePermissionsArray);
+ }
+
+ @Test(expected = CldsUsersException.class)
+ public void shouldThrowCldsUsersException() {
+ // when
+ CldsUserJsonDecoder.decodeJson(this.getClass().getResourceAsStream("/clds/clds-parse-exception.json"));
+ }
+
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/config/sdc/SdcSingleControllerConfigurationTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/config/sdc/SdcSingleControllerConfigurationTest.java
new file mode 100644
index 000000000..7390b65ba
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/config/sdc/SdcSingleControllerConfigurationTest.java
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2017, 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ * Modifications copyright (c) 2018 Nokia
+ * ================================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.config.sdc;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import org.junit.Test;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcParametersException;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+
+/**
+ * This class tests the SDC Controller config.
+ */
+public class SdcSingleControllerConfigurationTest {
+
+ /**
+ * This method loads the SDC controller configuration from a file located in the resource folder.
+ *
+ * @param fileName file for sdc controller configuration.
+ * @param sdcControllerName sdc controller name.
+ * @return instance of SdcSingleControllerConfiguration.
+ */
+ public static SdcSingleControllerConfiguration loadControllerConfiguration(String fileName,
+ String sdcControllerName) {
+
+ InputStreamReader streamReader = new InputStreamReader(ResourceFileUtils.getResourceAsStream(fileName),
+ StandardCharsets.UTF_8);
+ JsonObject jsonNode = JsonUtils.GSON.fromJson(streamReader, JsonObject.class);
+
+ return new SdcSingleControllerConfiguration(jsonNode, sdcControllerName,
+ "classpath:clds/aaf/org.onap.clamp.keyfile");
+ }
+
+ @Test
+ public final void testTheInit() throws SdcParametersException, IOException {
+ SdcSingleControllerConfiguration sdcConfig = loadControllerConfiguration("clds/sdc-controller-config-TLS.json",
+ "sdc-controller1");
+ assertEquals("User", sdcConfig.getUser());
+ assertEquals("ThePassword", sdcConfig.getPassword());
+ assertEquals("consumerGroup", sdcConfig.getConsumerGroup());
+ assertEquals("consumerId", sdcConfig.getConsumerID());
+ assertEquals("environmentName", sdcConfig.getEnvironmentName());
+ assertEquals("hostname:8080", sdcConfig.getAsdcAddress());
+ assertEquals(10, sdcConfig.getPollingInterval());
+ assertEquals(30, sdcConfig.getPollingTimeout());
+
+ assertThat(SdcSingleControllerConfiguration.SUPPORTED_ARTIFACT_TYPES_LIST)
+ .hasSameSizeAs(sdcConfig.getRelevantArtifactTypes());
+ assertEquals("ThePassword", sdcConfig.getKeyStorePassword());
+ assertTrue(sdcConfig.activateServerTLSAuth());
+ assertThat(sdcConfig.getMsgBusAddress()).contains("localhost");
+ }
+
+ @Test(expected = SdcParametersException.class)
+ public final void testAllRequiredParameters() throws IOException {
+ SdcSingleControllerConfiguration sdcConfig = loadControllerConfiguration("clds/sdc-controller-config-TLS.json",
+ "sdc-controller1");
+ // No exception should be raised
+ sdcConfig.testAllRequiredParameters();
+ sdcConfig = loadControllerConfiguration("clds/sdc-controller-config-bad.json", "sdc-controller1");
+ fail("Should have raised an exception");
+ }
+
+ @Test
+ public final void testAllRequiredParametersEmptyEncrypted() throws IOException {
+ SdcSingleControllerConfiguration sdcConfig = loadControllerConfiguration(
+ "clds/sdc-controller-config-empty-encrypted.json", "sdc-controller1");
+ sdcConfig.testAllRequiredParameters();
+ assertNull(sdcConfig.getKeyStorePassword());
+ }
+
+ @Test
+ public final void testConsumerGroupWithNull() throws IOException {
+ SdcSingleControllerConfiguration sdcConfig = loadControllerConfiguration("clds/sdc-controller-config-NULL.json",
+ "sdc-controller1");
+ assertTrue(sdcConfig.getConsumerGroup() == null);
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/it/AuthorizationControllerItCase.java b/runtime/src/test/java/org/onap/policy/clamp/clds/it/AuthorizationControllerItCase.java
new file mode 100644
index 000000000..557a2e96c
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/it/AuthorizationControllerItCase.java
@@ -0,0 +1,137 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * Modifications Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.it;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Arrays;
+import java.util.Collection;
+import org.apache.camel.Exchange;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.onap.policy.clamp.authorization.AuthorizationController;
+import org.onap.policy.clamp.authorization.SecureServicePermission;
+import org.onap.policy.clamp.clds.exception.NotAuthorizedException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.test.context.junit4.SpringRunner;
+
+/**
+ * Test CldsDAO calls through CldsModel and CldsEvent. This really test the DB
+ * and stored procedures.
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class AuthorizationControllerItCase {
+
+ @Autowired
+ private AuthorizationController auth;
+
+ private static SecurityContext sc = SecurityContextHolder.getContext();
+
+ /**
+ * Setup the variable before the tests execution.
+ */
+ @BeforeClass
+ public static void setupBefore() {
+
+ sc.setAuthentication(new Authentication() {
+ @Override
+ public Collection<? extends GrantedAuthority> getAuthorities() {
+ return Arrays.asList(new SimpleGrantedAuthority(
+ new SecureServicePermission("permission-type-cl", "dev", "read").getKey()),
+ new SimpleGrantedAuthority(new SecureServicePermission("permission-type-cl-manage", "dev",
+ "DEPLOY").getKey()),
+ new SimpleGrantedAuthority(new SecureServicePermission("permission-type-filter-vf", "dev",
+ "12345-55555-55555-5555").getKey()));
+ }
+
+ @Override
+ public Object getCredentials() {
+ return null;
+ }
+
+ @Override
+ public Object getDetails() {
+ return null;
+ }
+
+ @Override
+ public Object getPrincipal() {
+ return "admin";
+ }
+
+ @Override
+ public boolean isAuthenticated() {
+ return true;
+ }
+
+ @Override
+ public void setAuthenticated(boolean authenticatedFlag) throws IllegalArgumentException {
+
+ }
+
+ @Override
+ public String getName() {
+ return "admin";
+ }
+ });
+
+ }
+
+ @AfterClass
+
+ public static void afterCleanup() {
+ sc.setAuthentication(null);
+ }
+
+ @Test
+ public void testIsUserPermitted() {
+ assertEquals(AuthorizationController.getPrincipalName(sc), "admin");
+ assertTrue(auth.isUserPermitted(new SecureServicePermission("permission-type-cl", "dev", "read")));
+ assertTrue(auth.isUserPermitted(new SecureServicePermission("permission-type-cl-manage", "dev", "DEPLOY")));
+ assertTrue(auth.isUserPermitted(
+ new SecureServicePermission("permission-type-filter-vf", "dev", "12345-55555-55555-5555")));
+ assertFalse(auth.isUserPermitted(new SecureServicePermission("permission-type-cl", "test", "read")));
+ }
+
+ @Test(expected = NotAuthorizedException.class)
+ public void testIfAuthorizeThrowException() {
+ Exchange ex = Mockito.mock(Exchange.class);
+ auth.authorize(ex, "cl", "test", "read");
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/it/CldsHealthcheckServiceItCase.java b/runtime/src/test/java/org/onap/policy/clamp/clds/it/CldsHealthcheckServiceItCase.java
new file mode 100644
index 000000000..52da63952
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/it/CldsHealthcheckServiceItCase.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ */
+
+package org.onap.policy.clamp.clds.it;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.model.CldsHealthCheck;
+import org.onap.policy.clamp.clds.service.CldsHealthcheckService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+/**
+ * Tests HealthCheck Service.
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
+public class CldsHealthcheckServiceItCase {
+
+ @Autowired
+ private CldsHealthcheckService cldsHealthcheckService;
+
+ @Test
+ public void testGetHealthCheck() {
+ CldsHealthCheck cldsHealthCheck = cldsHealthcheckService.gethealthcheck();
+ assertNotNull(cldsHealthCheck);
+ assertEquals("UP", cldsHealthCheck.getHealthCheckStatus());
+ assertEquals("CLDS-APP", cldsHealthCheck.getHealthCheckComponent());
+ assertEquals("OK", cldsHealthCheck.getDescription());
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/it/HttpsItCase.java b/runtime/src/test/java/org/onap/policy/clamp/clds/it/HttpsItCase.java
new file mode 100644
index 000000000..1a4a2ec5f
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/it/HttpsItCase.java
@@ -0,0 +1,106 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.it;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.SSLContext;
+import org.apache.commons.io.FileUtils;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.TrustStrategy;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.web.client.RestTemplate;
+
+/**
+ * Test HTTP and HTTPS settings + redirection of HTTP to HTTPS.
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
+@TestPropertySource(locations = "classpath:https/https-test.properties")
+@DirtiesContext
+public class HttpsItCase {
+
+ @Value("${server.port}")
+ private String httpsPort;
+ @Value("${server.http-to-https-redirection.port}")
+ private String httpPort;
+
+ @Test
+ public void testDesignerIndex() throws Exception {
+ ResponseEntity<String> entity =
+ new RestTemplate().getForEntity("http://localhost:" + this.httpPort + "/swagger.html",
+ String.class);
+ assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.FOUND);
+ ResponseEntity<String> httpsEntity = getRestTemplate()
+ .getForEntity("https://localhost:" + this.httpsPort + "/swagger.html", String.class);
+ assertThat(httpsEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
+ assertThat(httpsEntity.getBody()).contains("Clamp Rest API");
+ }
+
+ @Test
+ public void testSwaggerJson() throws Exception {
+ ResponseEntity<String> httpsEntity = getRestTemplate()
+ .getForEntity("https://localhost:" + this.httpsPort + "/restservices/clds/api-doc", String.class);
+ assertThat(httpsEntity.getStatusCode()).isEqualTo(HttpStatus.OK);
+ assertThat(httpsEntity.getBody()).contains("swagger");
+ FileUtils.writeStringToFile(new File("docs/swagger/swagger.json"), httpsEntity.getBody(),
+ Charset.defaultCharset());
+ }
+
+ private RestTemplate getRestTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
+ SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
+ .loadTrustMaterial(null, new TrustStrategy() {
+ @Override
+ public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
+ return true;
+ }
+ }).build();
+ SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext, new NoopHostnameVerifier());
+ CloseableHttpClient httpClient = HttpClients.custom().setSSLSocketFactory(csf).build();
+ HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
+ requestFactory.setHttpClient(httpClient);
+ RestTemplate restTemplate = new RestTemplate(requestFactory);
+ return restTemplate;
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/it/RobotItCase.java b/runtime/src/test/java/org/onap/policy/clamp/clds/it/RobotItCase.java
new file mode 100644
index 000000000..017881ba7
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/it/RobotItCase.java
@@ -0,0 +1,131 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020-2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.it;
+
+import static org.apache.commons.io.FileUtils.copyInputStreamToFile;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import com.github.dockerjava.api.DockerClient;
+import com.github.dockerjava.api.command.BuildImageResultCallback;
+import com.github.dockerjava.api.command.CreateContainerResponse;
+import com.github.dockerjava.api.command.InspectContainerResponse;
+import com.github.dockerjava.api.command.LogContainerCmd;
+import com.github.dockerjava.api.model.AccessMode;
+import com.github.dockerjava.api.model.Bind;
+import com.github.dockerjava.api.model.BuildResponseItem;
+import com.github.dockerjava.api.model.Frame;
+import com.github.dockerjava.api.model.Volume;
+import com.github.dockerjava.core.DockerClientBuilder;
+import com.github.dockerjava.core.command.LogContainerResultCallback;
+import com.github.dockerjava.netty.NettyDockerCmdExecFactory;
+import java.io.File;
+import java.util.Objects;
+import org.codehaus.plexus.util.FileUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.DirtiesContext;
+import org.springframework.test.context.TestPropertySource;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
+@TestPropertySource(locations = "classpath:robotframework/robotframework-test.properties")
+@DirtiesContext
+public class RobotItCase {
+
+ @Value("${server.port}")
+ private String httpPort;
+ private static final int TIMEOUT_S = 150;
+ protected static final EELFLogger logger = EELFManager.getInstance().getLogger(RobotItCase.class);
+
+ @Test
+ public void robotTests() throws Exception {
+ File robotFolder = new File(getClass().getClassLoader().getResource("robotframework").getFile());
+ Volume testsVolume = new Volume("/opt/robotframework/tests");
+ DockerClient client = DockerClientBuilder
+ .getInstance()
+ .withDockerCmdExecFactory(new NettyDockerCmdExecFactory())
+ .build();
+
+
+ BuildImageResultCallback callback = new BuildImageResultCallback() {
+ @Override
+ public void onNext(BuildResponseItem item) {
+ System.out.println("XXX ITEM " + item);
+ super.onNext(item);
+ }
+ };
+
+ String imageId = client.buildImageCmd(robotFolder).exec(callback).awaitImageId();
+ CreateContainerResponse createContainerResponse = client.createContainerCmd(imageId)
+ .withVolumes(testsVolume)
+ .withBinds(
+ new Bind(robotFolder.getAbsolutePath() + "/tests/", testsVolume, AccessMode.rw))
+ .withEnv("CLAMP_PORT=" + httpPort)
+ .withStopTimeout(TIMEOUT_S)
+ .withNetworkMode("host")
+ .exec();
+ String id = createContainerResponse.getId();
+ client.startContainerCmd(id).exec();
+ InspectContainerResponse exec;
+
+ int tries = 0;
+ do {
+ Thread.sleep(1000);
+ exec = client.inspectContainerCmd(id).exec();
+ tries++;
+ } while (exec.getState().getRunning() && tries < TIMEOUT_S);
+ logger.info("RobotFramework result:" + exec.getState());
+
+ LogContainerCmd logContainerCmd = client.logContainerCmd(id);
+ logContainerCmd.withStdOut(true).withStdErr(true);
+ try {
+ logContainerCmd.exec(new LogContainerResultCallback() {
+ @Override
+ public void onNext(Frame item) {
+ logger.info(item.toString());
+ }
+ }).awaitCompletion();
+ } catch (InterruptedException e) {
+ throw new Exception("Failed to retrieve logs of container " + id, e);
+ }
+
+ copyInputStreamToFile(client.copyArchiveFromContainerCmd(id, "/opt/robotframework/reports/output.xml").exec(),
+ new File("target/robotframework/output.xml"));
+ copyInputStreamToFile(client.copyArchiveFromContainerCmd(id, "/opt/robotframework/reports/log.html").exec(),
+ new File("target/robotframework/log.html"));
+ copyInputStreamToFile(client.copyArchiveFromContainerCmd(id, "/opt/robotframework/reports/report.html").exec(),
+ new File("target/robotframework/report.html"));
+ client.stopContainerCmd(id);
+
+ logger.info("RobotFramework output.xml file: " + FileUtils.fileRead("target/robotframework/output.xml"));
+
+ Assert.assertEquals(exec.getState().getError(), 0L,
+ Objects.requireNonNull(exec.getState().getExitCodeLong()).longValue());
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/it/config/CldsReferencePropertiesItCase.java b/runtime/src/test/java/org/onap/policy/clamp/clds/it/config/CldsReferencePropertiesItCase.java
new file mode 100644
index 000000000..c8b9932cc
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/it/config/CldsReferencePropertiesItCase.java
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.it.config;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.IOException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.config.ClampProperties;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+public class CldsReferencePropertiesItCase {
+
+ @Autowired
+ private ClampProperties refProp;
+
+ /**
+ * Test getting a value the properties in string.
+ */
+ @Test
+ public void testGetStringValue() {
+ assertEquals("healthcheck", refProp.getStringValue("policy.api.userName"));
+ }
+
+ /**
+ * Test getting prop value as a JSON Node / template.
+ *
+ * @throws IOException when JSON parsing fails
+ */
+ @Test
+ public void testGetFileContent() throws IOException {
+ String users = ResourceFileUtils.getResourceAsString("clds/clds-users.json");
+ assertEquals(users, refProp.getFileContent("files.cldsUsers"));
+ // Test composite key
+ assertEquals(users, refProp.getFileContent("files", "cldsUsers"));
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/it/config/SdcControllersConfigurationItCase.java b/runtime/src/test/java/org/onap/policy/clamp/clds/it/config/SdcControllersConfigurationItCase.java
new file mode 100644
index 000000000..70aeccf59
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/it/config/SdcControllersConfigurationItCase.java
@@ -0,0 +1,88 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2017, 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.clds.it.config;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import com.google.gson.JsonSyntaxException;
+import java.io.IOException;
+import java.util.Map;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.config.sdc.SdcControllersConfiguration;
+import org.onap.policy.clamp.clds.config.sdc.SdcSingleControllerConfiguration;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcParametersException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+import org.springframework.test.util.ReflectionTestUtils;
+
+/**
+ * This class tests the SDC Controller config.
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@ActiveProfiles({"clamp-default", "clamp-default-user", "clamp-sdc-controller"})
+public class SdcControllersConfigurationItCase {
+
+ @Autowired
+ private SdcControllersConfiguration sdcControllersConfiguration;
+
+ public final void loadFile(String fileName) throws IOException {
+ ReflectionTestUtils.setField(sdcControllersConfiguration, "sdcControllerFile", fileName);
+ sdcControllersConfiguration.loadConfiguration();
+ }
+
+ @Test
+ public void testGetAllDefinedControllers() throws IOException {
+ loadFile("classpath:clds/sdc-controllers-config.json");
+ Map<String, SdcSingleControllerConfiguration> mapResult = sdcControllersConfiguration
+ .getAllDefinedControllers();
+ assertTrue(mapResult.size() == 2);
+ assertEquals("sdc-controller1", mapResult.get("sdc-controller1").getSdcControllerName());
+ assertEquals("sdc-controller2", mapResult.get("sdc-controller2").getSdcControllerName());
+ }
+
+ @Test
+ public void testGetSdcSingleControllerConfiguration() throws IOException {
+ loadFile("classpath:clds/sdc-controllers-config.json");
+ assertEquals("sdc-controller1", sdcControllersConfiguration
+ .getSdcSingleControllerConfiguration("sdc-controller1").getSdcControllerName());
+ assertEquals("sdc-controller2", sdcControllersConfiguration
+ .getSdcSingleControllerConfiguration("sdc-controller2").getSdcControllerName());
+ }
+
+ @Test(expected = JsonSyntaxException.class)
+ public void testBadJsonLoading() throws IOException {
+ loadFile("classpath:clds/sdc-controllers-config-bad.json");
+ fail("Should have raised an exception");
+ }
+
+ @Test(expected = SdcParametersException.class)
+ public void testMissingParamInJsonLoading() throws IOException {
+ loadFile("classpath:clds/sdc-controllers-config-missing-param.json");
+ sdcControllersConfiguration.getAllDefinedControllers();
+ fail("Should have raised an exception");
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/it/sdc/controller/SdcSingleControllerItCase.java b/runtime/src/test/java/org/onap/policy/clamp/clds/it/sdc/controller/SdcSingleControllerItCase.java
new file mode 100644
index 000000000..787118902
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/it/sdc/controller/SdcSingleControllerItCase.java
@@ -0,0 +1,152 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.it.sdc.controller;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import org.assertj.core.api.Assertions;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.onap.policy.clamp.clds.config.ClampProperties;
+import org.onap.policy.clamp.clds.config.sdc.SdcSingleControllerConfigurationTest;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcControllerException;
+import org.onap.policy.clamp.clds.sdc.controller.SdcSingleController;
+import org.onap.policy.clamp.clds.sdc.controller.SdcSingleControllerStatus;
+import org.onap.policy.clamp.clds.sdc.controller.installer.CsarHandler;
+import org.onap.policy.clamp.loop.CsarInstaller;
+import org.onap.sdc.api.notification.IArtifactInfo;
+import org.onap.sdc.api.notification.INotificationData;
+import org.onap.sdc.api.notification.IResourceInstance;
+import org.slf4j.MDC;
+import org.slf4j.spi.MDCAdapter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest
+@ActiveProfiles({"clamp-default", "clamp-default-user", "clamp-sdc-controller"})
+public class SdcSingleControllerItCase {
+
+ private static final String CSAR_ARTIFACT_NAME = "testArtifact.csar";
+ private static final String SERVICE_UUID = "serviceUUID";
+ private static final String RESOURCE1_UUID = "resource1UUID";
+ private static final String RESOURCE1_INSTANCE_NAME = "sim-1802 0";
+
+ @Autowired
+ private ClampProperties clampProp;
+
+ private SdcSingleController sdcSingleController;
+
+ private CsarInstaller csarInstaller = mock(CsarInstaller.class);
+
+ private INotificationData buildFakeSdcNotification() {
+ // BUild what is needed for CSAR
+ IArtifactInfo serviceArtifact = mock(IArtifactInfo.class);
+ Mockito.when(serviceArtifact.getArtifactType()).thenReturn(CsarHandler.CSAR_TYPE);
+ Mockito.when(serviceArtifact.getArtifactName()).thenReturn(CSAR_ARTIFACT_NAME);
+ List<IArtifactInfo> servicesList = new ArrayList<>();
+ servicesList.add(serviceArtifact);
+ INotificationData notifData = mock(INotificationData.class);
+ Mockito.when(notifData.getServiceArtifacts()).thenReturn(servicesList);
+ // Build what is needed for UUID
+ Mockito.when(notifData.getServiceInvariantUUID()).thenReturn(SERVICE_UUID);
+ // Build fake resource with one artifact BLUEPRINT
+ IResourceInstance resource1 = mock(IResourceInstance.class);
+ Mockito.when(resource1.getResourceType()).thenReturn("VF");
+ Mockito.when(resource1.getResourceInvariantUUID()).thenReturn(RESOURCE1_UUID);
+ Mockito.when(resource1.getResourceInstanceName()).thenReturn(RESOURCE1_INSTANCE_NAME);
+ // Create a fake artifact for resource
+ IArtifactInfo blueprintArtifact = mock(IArtifactInfo.class);
+ Mockito.when(blueprintArtifact.getArtifactType()).thenReturn(CsarHandler.BLUEPRINT_TYPE);
+ List<IArtifactInfo> artifactsListForResource = new ArrayList<>();
+ artifactsListForResource.add(blueprintArtifact);
+ Mockito.when(resource1.getArtifacts()).thenReturn(artifactsListForResource);
+ List<IResourceInstance> resourcesList = new ArrayList<>();
+ resourcesList.add(resource1);
+ Mockito.when(notifData.getResources()).thenReturn(resourcesList);
+ return notifData;
+ }
+
+ /**
+ * Initialization method.
+ */
+ @Before
+ public void init() {
+ sdcSingleController = new SdcSingleController(clampProp, csarInstaller, SdcSingleControllerConfigurationTest
+ .loadControllerConfiguration("clds/sdc-controller-config-TLS.json", "sdc-controller1"), null) {
+ };
+ }
+
+ @Test
+ public void testTreatNotification() {
+ // when
+ sdcSingleController.treatNotification(buildFakeSdcNotification());
+ // then
+ Assertions.assertThat(sdcSingleController.getNbOfNotificationsOngoing()).isEqualTo(0);
+ }
+
+ @Test
+ public void testCloseSdc() throws SdcControllerException {
+ // when
+ sdcSingleController.closeSdc();
+ // then
+ assertThat(sdcSingleController.getControllerStatus()).isEqualTo(SdcSingleControllerStatus.STOPPED);
+ }
+
+ @Test
+ public void testActivateCallback() throws InvocationTargetException, IllegalAccessException, NoSuchMethodException,
+ InstantiationException, ClassNotFoundException {
+ // given
+
+ Class<?> innerClass = Class
+ .forName("org.onap.policy.clamp.clds.sdc.controller.SdcSingleController$SdcNotificationCallBack");
+ Constructor<?> constructor = innerClass.getDeclaredConstructor(SdcSingleController.class,
+ SdcSingleController.class);
+ constructor.setAccessible(true);
+ Object child = constructor.newInstance(sdcSingleController, sdcSingleController);
+ Method method = child.getClass().getDeclaredMethod("activateCallback", INotificationData.class);
+ method.setAccessible(true);
+ MDCAdapter mdcAdapter = MDC.getMDCAdapter();
+ // when
+ method.invoke(child, buildFakeSdcNotification());
+ // then
+ assertThat(mdcAdapter.get("ResponseCode")).isEqualTo("0");
+ assertThat(mdcAdapter.get("StatusCode")).isEqualTo("COMPLETE");
+ assertThat(mdcAdapter.get("ResponseDescription"))
+ .isEqualTo("SDC Notification received and processed successfully");
+ assertThat(mdcAdapter.get("ClassName")).isEqualTo(child.getClass().getName());
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryResponseCacheTestItCase.java b/runtime/src/test/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryResponseCacheTestItCase.java
new file mode 100644
index 000000000..f406e5ed2
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryResponseCacheTestItCase.java
@@ -0,0 +1,127 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.model.dcae;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertEquals;
+
+import java.util.HashSet;
+import java.util.Set;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.ExchangeBuilder;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.Application;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.http.HttpStatus;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class DcaeInventoryResponseCacheTestItCase {
+
+ public static DcaeInventoryCache inventoryCache = new DcaeInventoryCache();
+
+ @Autowired
+ CamelContext camelContext;
+
+ /**
+ * Initialize the responses.
+ */
+ @BeforeClass
+ public static void createExample() {
+ DcaeInventoryResponse response1 = new DcaeInventoryResponse();
+ response1.setAsdcServiceId("id1");
+ response1.setAsdcResourceId("0");
+ DcaeInventoryResponse response2 = new DcaeInventoryResponse();
+ response2.setAsdcServiceId("id1");
+ response2.setAsdcResourceId("1");
+ DcaeInventoryResponse response3 = new DcaeInventoryResponse();
+ response3.setAsdcServiceId("id1");
+ response3.setAsdcResourceId("2");
+ DcaeInventoryResponse response4 = new DcaeInventoryResponse();
+ response4.setAsdcServiceId("id2");
+ response4.setAsdcResourceId("0");
+ DcaeInventoryResponse response5 = new DcaeInventoryResponse();
+ response5.setAsdcServiceId("id2");
+ response5.setAsdcResourceId("1");
+
+ inventoryCache.addDcaeInventoryResponse(response1);
+ inventoryCache.addDcaeInventoryResponse(response3);
+ inventoryCache.addDcaeInventoryResponse(response2);
+ inventoryCache.addDcaeInventoryResponse(response4);
+ inventoryCache.addDcaeInventoryResponse(response5);
+ }
+
+ @Test
+ public void testGetAllLoopIds() {
+ assertThat(inventoryCache.getAllLoopIds().size()).isEqualTo(2);
+ }
+
+ @Test
+ public void testGetAllBlueprintsPerLoopId() {
+ int value = 0;
+ for (DcaeInventoryResponse inventoryResponse : inventoryCache.getAllBlueprintsPerLoopId("id1")) {
+ assertThat(Integer.valueOf(inventoryResponse.getAsdcResourceId())).isEqualTo(value++);
+ }
+
+ value = 0;
+ for (DcaeInventoryResponse inventoryResponse : inventoryCache.getAllBlueprintsPerLoopId("id2")) {
+ assertThat(Integer.valueOf(inventoryResponse.getAsdcResourceId())).isEqualTo(value++);
+ }
+ }
+
+ @Test
+ public void testDcaeInventoryResponse() {
+ Exchange exchange = ExchangeBuilder.anExchange(camelContext).build();
+ Exchange exchangeResponse = camelContext.createProducerTemplate()
+ .send("direct:get-all-dcae-blueprint-inventory", exchange);
+ assertThat(HttpStatus.valueOf((Integer) exchangeResponse.getIn().getHeader(Exchange.HTTP_RESPONSE_CODE))
+ .is2xxSuccessful()).isTrue();
+ Set<DcaeInventoryResponse> blueprint = inventoryCache.getAllBlueprintsPerLoopId("testAsdcServiceId");
+ assertThat(blueprint.size()).isEqualTo(2);
+
+ DcaeInventoryResponse response1 = new DcaeInventoryResponse();
+ response1.setAsdcResourceId("0");
+ response1.setTypeName("testTypeName");
+ response1.setAsdcServiceId("testAsdcServiceId");
+ response1.setBlueprintTemplate("testBlueprintTemplate");
+ response1.setTypeId("testtypeId");
+ DcaeInventoryResponse response2 = new DcaeInventoryResponse();
+ response2.setAsdcResourceId("1");
+ response2.setTypeName("testTypeName2");
+ response2.setAsdcServiceId("testAsdcServiceId");
+ response2.setBlueprintTemplate("testBlueprintTemplate2");
+ response2.setTypeId("testtypeId2");
+
+ Set<DcaeInventoryResponse> expectedBlueprint = new HashSet<>();
+ expectedBlueprint.add(response1);
+ expectedBlueprint.add(response2);
+
+ assertEquals(blueprint, expectedBlueprint);
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryResponseTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryResponseTest.java
new file mode 100644
index 000000000..a246e0efa
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/model/dcae/DcaeInventoryResponseTest.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.model.dcae;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.TreeSet;
+import org.junit.Test;
+
+public class DcaeInventoryResponseTest {
+
+ @Test
+ public void testComparator() {
+ DcaeInventoryResponse response1 = new DcaeInventoryResponse();
+ response1.setAsdcServiceId("id1");
+ response1.setAsdcResourceId("0");
+ DcaeInventoryResponse response2 = new DcaeInventoryResponse();
+ response2.setAsdcServiceId("id2");
+ response2.setAsdcResourceId("1");
+ DcaeInventoryResponse response3 = new DcaeInventoryResponse();
+ response3.setAsdcServiceId("id3");
+ response3.setAsdcResourceId("2");
+ DcaeInventoryResponse response4 = new DcaeInventoryResponse();
+ response4.setAsdcServiceId("id4");
+ response4.setAsdcResourceId("3");
+
+ TreeSet<DcaeInventoryResponse> responseSet = new TreeSet<>();
+ responseSet.add(response4);
+ responseSet.add(response3);
+ responseSet.add(response1);
+ responseSet.add(response2);
+
+ int value = 0;
+ for (DcaeInventoryResponse inventoryResponse : responseSet) {
+ assertThat(Integer.valueOf(inventoryResponse.getAsdcResourceId()) == value++).isTrue();
+ }
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/model/jsontype/JsonTypeDescriptorTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/model/jsontype/JsonTypeDescriptorTest.java
new file mode 100644
index 000000000..7999709c2
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/model/jsontype/JsonTypeDescriptorTest.java
@@ -0,0 +1,95 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Samsung. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.model.jsontype;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.JsonObject;
+import org.hibernate.HibernateException;
+import org.junit.Test;
+import org.onap.policy.clamp.dao.model.jsontype.JsonTypeDescriptor;
+
+public class JsonTypeDescriptorTest {
+
+ private JsonTypeDescriptor descriptor = new JsonTypeDescriptor();
+
+ @Test
+ public void testFromString() {
+ JsonObject object = new JsonObject();
+ object.addProperty("one", "oneValue");
+ JsonObject child = new JsonObject();
+ child.addProperty("two", "twoValue");
+ object.add("child", child);
+
+ JsonObject jsonResult = descriptor.fromString("{\"one\":\"oneValue\",\"child\":{\"two\":\"twoValue\"}}");
+
+ assertThat(jsonResult).isEqualTo(object);
+ }
+
+ @Test
+ public void testUnwrap() {
+ JsonObject res1 = descriptor.unwrap(null, null, null);
+ assertThat(res1).isNull();
+
+ JsonObject object = new JsonObject();
+ object.addProperty("one", "oneValue");
+ JsonObject child = new JsonObject();
+ child.addProperty("two", "twoValue");
+ object.add("child", child);
+ String res2 = descriptor.unwrap(object, String.class, null);
+ assertThat(res2.replace("\n", "").replace(" ", ""))
+ .isEqualTo("{\"one\":\"oneValue\",\"child\":{\"two\":\"twoValue\"}}");
+
+ Object res3 = descriptor.unwrap(object, JsonObject.class, null);
+ String res3Str = ((String) res3).replace(" ", "").replace("\\n", "").replace("\\", "")
+ .replace("\"{", "{").replace("}\"", "}");
+ assertThat(res3Str).isEqualTo("{\"one\":\"oneValue\",\"child\":{\"two\":\"twoValue\"}}");
+ }
+
+ @Test(expected = HibernateException.class)
+ public void testUnwrapExpectationThrown() {
+ JsonObject object = new JsonObject();
+ object.addProperty("one", "oneValue");
+
+ descriptor.unwrap(object, Integer.class, null);
+ }
+
+ @Test
+ public void testWrap() {
+ JsonObject res1 = descriptor.wrap(null, null);
+ assertThat(res1).isNull();
+
+ JsonObject object = new JsonObject();
+ object.addProperty("one", "oneValue");
+ JsonObject child = new JsonObject();
+ child.addProperty("two", "twoValue");
+ object.add("child", child);
+ JsonObject res2 = descriptor.wrap("{\"one\":\"oneValue\",\"child\":{\"two\":\"twoValue\"}}", null);
+ assertThat(res2).isEqualTo(object);
+ }
+
+ @Test(expected = HibernateException.class)
+ public void testWrapExpectationThrown() {
+ descriptor.wrap(1, null);
+ }
+} \ No newline at end of file
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintParserTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintParserTest.java
new file mode 100644
index 000000000..085b3d187
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/sdc/controller/installer/BlueprintParserTest.java
@@ -0,0 +1,208 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.sdc.controller.installer;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import org.json.JSONObject;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.clamp.clds.exception.sdc.controller.BlueprintParserException;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.yaml.snakeyaml.Yaml;
+
+public class BlueprintParserTest {
+ private static final Gson GSON = new Gson();
+ private static final String FIRST_APPP = "first_app";
+ private static final String SECOND_APPP = "second_app";
+ private static final String THIRD_APPP = "third_app";
+ private static final String MODEL_TYPE1 = "type1";
+ private static final String MODEL_TYPE_TCA = "onap.policies.monitoring.cdap.tca.hi.lo.app";
+ private static final String VERSION = "1.0.0";
+
+ private static String microServiceTheWholeBlueprintValid;
+ private static String newMicroServiceBlueprint;
+ private static JsonObject jsonObjectBlueprintInvalid;
+ private static JsonObject jsonObjectBlueprintWithoutName;
+ private static JsonObject jsonObjectBlueprintWithoutProperties;
+ private static JsonObject jsonObjectBlueprintWithoutRelationships;
+ private static JsonObject jsonObjectBlueprintValidWithVersion;
+
+ /**
+ * Method to load Blueprints before all test.
+ *
+ * @throws IOException In case of issues when opening the files
+ */
+ @BeforeClass
+ public static void loadBlueprints() throws IOException {
+ microServiceTheWholeBlueprintValid = ResourceFileUtils
+ .getResourceAsString("clds/blueprint-with-microservice-chain.yaml");
+
+ newMicroServiceBlueprint = ResourceFileUtils.getResourceAsString("clds/new-microservice.yaml");
+
+ String microServiceBlueprintInvalid = ResourceFileUtils
+ .getResourceAsString("clds/single-microservice-fragment-invalid.yaml");
+ jsonObjectBlueprintInvalid = yamlToJson(microServiceBlueprintInvalid);
+ String microServiceBlueprintWithoutName = ResourceFileUtils
+ .getResourceAsString("clds/single-microservice-fragment-without-name.yaml");
+ jsonObjectBlueprintWithoutName = yamlToJson(microServiceBlueprintWithoutName);
+ String microServiceBlueprintWithoutProperties = ResourceFileUtils
+ .getResourceAsString("clds/single-microservice-fragment-without-properties.yaml");
+ jsonObjectBlueprintWithoutProperties = yamlToJson(microServiceBlueprintWithoutProperties);
+ String microServiceBlueprintValidWithVersion = ResourceFileUtils
+ .getResourceAsString("clds/single-microservice-fragment-valid-with-version.yaml");
+ jsonObjectBlueprintValidWithVersion = yamlToJson(microServiceBlueprintValidWithVersion);
+
+ String microServiceBlueprintWithoutRelationships = ResourceFileUtils
+ .getResourceAsString("clds/single-microservice-fragment-without-relationships.yaml");
+ jsonObjectBlueprintWithoutRelationships = yamlToJson(microServiceBlueprintWithoutRelationships);
+
+ }
+
+ @Test
+ public void getNameShouldReturnDefinedName() {
+ final JsonObject jsonObject = jsonObjectBlueprintInvalid;
+ String expectedName = jsonObject.get(jsonObject.keySet().iterator().next()).getAsJsonObject().get("properties")
+ .getAsJsonObject().get("name").getAsString();
+ Entry<String, JsonElement> entry = jsonObject.entrySet().iterator().next();
+ String actualName = BlueprintParser.getName(entry);
+
+ Assert.assertEquals(expectedName, actualName);
+ }
+
+ @Test
+ public void getNameShouldReturnServiceNameWhenNoNameDefined() {
+ final JsonObject jsonObject = jsonObjectBlueprintWithoutName;
+
+ String expectedName = jsonObject.keySet().iterator().next();
+ Entry<String, JsonElement> entry = jsonObject.entrySet().iterator().next();
+ String actualName = BlueprintParser.getName(entry);
+
+ Assert.assertEquals(expectedName, actualName);
+ }
+
+ @Test
+ public void getNameShouldReturnServiceNameWhenNoPropertiesDefined() {
+ final JsonObject jsonObject = jsonObjectBlueprintWithoutProperties;
+
+ String expectedName = jsonObject.keySet().iterator().next();
+ Entry<String, JsonElement> entry = jsonObject.entrySet().iterator().next();
+ String actualName = BlueprintParser.getName(entry);
+
+ Assert.assertEquals(expectedName, actualName);
+ }
+
+ @Test
+ public void getInputShouldReturnInputWhenPresent() {
+ final JsonObject jsonObject = jsonObjectBlueprintInvalid;
+
+ String expected = FIRST_APPP;
+ Entry<String, JsonElement> entry = jsonObject.entrySet().iterator().next();
+ String actual = BlueprintParser.getInput(entry);
+
+ Assert.assertEquals(expected, actual);
+ }
+
+ @Test
+ public void getInputShouldReturnEmptyStringWhenAbsent() {
+ final JsonObject jsonObject = jsonObjectBlueprintWithoutRelationships;
+
+ String expected = "";
+ Entry<String, JsonElement> entry = jsonObject.entrySet().iterator().next();
+ String actual = BlueprintParser.getInput(entry);
+
+ Assert.assertEquals(expected, actual);
+ }
+
+ @Test(expected = BlueprintParserException.class)
+ public void getNodeRepresentationFromIncompleteYaml() throws BlueprintParserException {
+ BlueprintParser.getNodeRepresentation(jsonObjectBlueprintInvalid.entrySet().iterator().next(),
+ jsonObjectBlueprintInvalid, null);
+ }
+
+ @Test
+ public void getNodeRepresentationFromCompleteYamlWithModelVersion() throws BlueprintParserException {
+ final JsonObject jsonObject = jsonObjectBlueprintValidWithVersion;
+
+ BlueprintMicroService expected = new BlueprintMicroService(SECOND_APPP, MODEL_TYPE1, "", "10.0.0");
+ Entry<String, JsonElement> entry = jsonObject.entrySet().iterator().next();
+ BlueprintMicroService actual = BlueprintParser.getNodeRepresentation(entry, jsonObject, null);
+
+ Assert.assertEquals(expected, actual);
+ }
+
+ @Test
+ public void getMicroServicesFromBlueprintTest() throws BlueprintParserException {
+ BlueprintMicroService thirdApp = new BlueprintMicroService(THIRD_APPP, MODEL_TYPE_TCA, SECOND_APPP, VERSION);
+ BlueprintMicroService firstApp = new BlueprintMicroService(FIRST_APPP, MODEL_TYPE_TCA, "", VERSION);
+ BlueprintMicroService secondApp = new BlueprintMicroService(SECOND_APPP, MODEL_TYPE_TCA, FIRST_APPP, VERSION);
+
+ Set<BlueprintMicroService> expected = new HashSet<>(Arrays.asList(firstApp, secondApp, thirdApp));
+ Set<BlueprintMicroService> actual = BlueprintParser.getMicroServices(microServiceTheWholeBlueprintValid);
+
+ Assert.assertEquals(expected, actual);
+ }
+
+ @Test
+ public void fallBackToOneMicroServiceTcaTest() {
+ BlueprintMicroService tcaMs = new BlueprintMicroService(BlueprintParser.TCA,
+ "onap.policies.monitoring.cdap.tca.hi.lo.app", "", VERSION);
+ List<BlueprintMicroService> expected = Collections.singletonList(tcaMs);
+ List<BlueprintMicroService> actual = BlueprintParser.fallbackToOneMicroService();
+
+ Assert.assertEquals(expected, actual);
+ }
+
+ @Test
+ public void newMicroServiceTest() throws BlueprintParserException {
+ List<BlueprintMicroService> microServicesChain = new ChainGenerator()
+ .getChainOfMicroServices(BlueprintParser.getMicroServices(newMicroServiceBlueprint));
+ if (microServicesChain.isEmpty()) {
+ microServicesChain = BlueprintParser.fallbackToOneMicroService();
+ }
+ assertThat(microServicesChain.size()).isEqualTo(1);
+ assertThat(microServicesChain.get(0).getName()).isEqualTo("pmsh");
+ }
+
+ private static JsonObject yamlToJson(String yamlString) {
+ Yaml yaml = new Yaml();
+ Map<String, Object> map = yaml.load(yamlString);
+ JSONObject jsonObject = new JSONObject(map);
+ return GSON.fromJson(jsonObject.toString(), JsonObject.class);
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/sdc/controller/installer/ChainGeneratorTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/sdc/controller/installer/ChainGeneratorTest.java
new file mode 100644
index 000000000..d7a3b3823
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/sdc/controller/installer/ChainGeneratorTest.java
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.sdc.controller.installer;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ChainGeneratorTest {
+ private static final String FIRST_APPP = "first_app";
+ private static final String SECOND_APPP = "second_app";
+ private static final String THIRD_APPP = "third_app";
+ private static final String FOURTH_APPP = "fourth_app";
+ private static final String DEFAULT_VERSION = "1.0.0";
+
+ @Test
+ public void getChainOfMicroServicesTest() {
+ BlueprintMicroService ms1 = new BlueprintMicroService(FIRST_APPP, "", "", DEFAULT_VERSION);
+ BlueprintMicroService ms2 = new BlueprintMicroService(SECOND_APPP, "", FIRST_APPP, DEFAULT_VERSION);
+ BlueprintMicroService ms3 = new BlueprintMicroService(THIRD_APPP, "", SECOND_APPP, DEFAULT_VERSION);
+ BlueprintMicroService ms4 = new BlueprintMicroService(FOURTH_APPP, "", THIRD_APPP, DEFAULT_VERSION);
+
+ List<BlueprintMicroService> expectedList = Arrays.asList(ms1, ms2, ms3, ms4);
+ Set<BlueprintMicroService> inputSet = new HashSet<>(expectedList);
+
+ List<BlueprintMicroService> actualList = new ChainGenerator().getChainOfMicroServices(inputSet);
+ Assert.assertEquals(expectedList, actualList);
+ }
+
+ @Test
+ public void getChainOfMicroServicesTwiceNoInputTest() {
+ BlueprintMicroService ms1 = new BlueprintMicroService(FIRST_APPP, "", "", DEFAULT_VERSION);
+ BlueprintMicroService ms2 = new BlueprintMicroService(SECOND_APPP, "", "", DEFAULT_VERSION);
+ BlueprintMicroService ms3 = new BlueprintMicroService(THIRD_APPP, "", SECOND_APPP, DEFAULT_VERSION);
+ BlueprintMicroService ms4 = new BlueprintMicroService(FOURTH_APPP, "", FIRST_APPP, DEFAULT_VERSION);
+
+ Set<BlueprintMicroService> inputSet = new HashSet<>(Arrays.asList(ms1, ms2, ms3, ms4));
+ List<BlueprintMicroService> actualList = new ChainGenerator().getChainOfMicroServices(inputSet);
+ Assert.assertTrue(actualList.isEmpty());
+ }
+
+ @Test
+ public void getChainOfMicroServicesBranchingTest() {
+ BlueprintMicroService ms1 = new BlueprintMicroService(FIRST_APPP, "", "", DEFAULT_VERSION);
+ BlueprintMicroService ms2 = new BlueprintMicroService(SECOND_APPP, "", FIRST_APPP, DEFAULT_VERSION);
+ BlueprintMicroService ms3 = new BlueprintMicroService(THIRD_APPP, "", FIRST_APPP, DEFAULT_VERSION);
+ BlueprintMicroService ms4 = new BlueprintMicroService(FOURTH_APPP, "", FIRST_APPP, DEFAULT_VERSION);
+
+ Set<BlueprintMicroService> inputSet = new HashSet<>(Arrays.asList(ms1, ms2, ms3, ms4));
+ List<BlueprintMicroService> actualList = new ChainGenerator().getChainOfMicroServices(inputSet);
+ Assert.assertTrue(actualList.isEmpty());
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/sdc/controller/installer/CsarHandlerTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/sdc/controller/installer/CsarHandlerTest.java
new file mode 100644
index 000000000..08e425abf
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/sdc/controller/installer/CsarHandlerTest.java
@@ -0,0 +1,199 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.sdc.controller.installer;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.onap.policy.clamp.clds.exception.sdc.controller.CsarHandlerException;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.sdc.api.notification.IArtifactInfo;
+import org.onap.sdc.api.notification.INotificationData;
+import org.onap.sdc.api.notification.IResourceInstance;
+import org.onap.sdc.api.results.IDistributionClientDownloadResult;
+import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;
+
+public class CsarHandlerTest {
+
+ private static final String SDC_FOLDER = "/tmp/csar-handler-tests";
+ private static final String CSAR_ARTIFACT_NAME = "testArtifact.csar";
+ private static final String SERVICE_UUID = "serviceUUID";
+ private static final String RESOURCE1_UUID = "resource1UUID";
+ private static final String RESOURCE1_INSTANCE_NAME = "sim-1802 0";
+ private static final String RESOURCE1_INSTANCE_NAME_IN_CSAR = "sim18020";
+ private static final String BLUEPRINT1_NAME = "FOI.Simfoimap223S0112.event_proc_bp.yaml";
+ private static final String BLUEPRINT2_NAME = "FOI.Simfoimap223S0112.event_proc_bp2.yaml";
+
+ @Test
+ public void testConstructor() throws CsarHandlerException {
+ IArtifactInfo serviceArtifact = Mockito.mock(IArtifactInfo.class);
+ Mockito.when(serviceArtifact.getArtifactType()).thenReturn(CsarHandler.CSAR_TYPE);
+ Mockito.when(serviceArtifact.getArtifactName()).thenReturn(CSAR_ARTIFACT_NAME);
+ List<IArtifactInfo> servicesList = new ArrayList<>();
+ servicesList.add(serviceArtifact);
+ INotificationData notifData = Mockito.mock(INotificationData.class);
+ Mockito.when(notifData.getServiceArtifacts()).thenReturn(servicesList);
+ CsarHandler csar = new CsarHandler(notifData, "test-controller", SDC_FOLDER);
+ assertEquals(SDC_FOLDER + "/test-controller" + "/" + CSAR_ARTIFACT_NAME, csar.getFilePath());
+ }
+
+ @Test(expected = CsarHandlerException.class)
+ public void testFailingConstructor() throws CsarHandlerException {
+ INotificationData notifData = Mockito.mock(INotificationData.class);
+ Mockito.when(notifData.getServiceArtifacts()).thenReturn(new ArrayList<>());
+ new CsarHandler(notifData, "test-controller", "/tmp/csar-handler-tests");
+ fail("Exception should have been raised");
+ }
+
+ private INotificationData buildFakeSdcNotification() {
+ // BUild what is needed for CSAR
+ IArtifactInfo serviceArtifact = Mockito.mock(IArtifactInfo.class);
+ Mockito.when(serviceArtifact.getArtifactType()).thenReturn(CsarHandler.CSAR_TYPE);
+ Mockito.when(serviceArtifact.getArtifactName()).thenReturn(CSAR_ARTIFACT_NAME);
+ List<IArtifactInfo> servicesList = new ArrayList<>();
+ servicesList.add(serviceArtifact);
+ INotificationData notifData = Mockito.mock(INotificationData.class);
+ Mockito.when(notifData.getServiceArtifacts()).thenReturn(servicesList);
+ // Build what is needed for UUID
+ Mockito.when(notifData.getServiceInvariantUUID()).thenReturn(SERVICE_UUID);
+ // Build fake resource with one artifact BLUEPRINT
+ IResourceInstance resource1 = Mockito.mock(IResourceInstance.class);
+ Mockito.when(resource1.getResourceType()).thenReturn("VF");
+ Mockito.when(resource1.getResourceInvariantUUID()).thenReturn(RESOURCE1_UUID);
+ Mockito.when(resource1.getResourceInstanceName()).thenReturn(RESOURCE1_INSTANCE_NAME);
+ // Create a fake artifact for resource
+ IArtifactInfo blueprintArtifact = Mockito.mock(IArtifactInfo.class);
+ Mockito.when(blueprintArtifact.getArtifactType()).thenReturn(CsarHandler.BLUEPRINT_TYPE);
+ List<IArtifactInfo> artifactsListForResource = new ArrayList<>();
+ artifactsListForResource.add(blueprintArtifact);
+ Mockito.when(resource1.getArtifacts()).thenReturn(artifactsListForResource);
+ List<IResourceInstance> resourcesList = new ArrayList<>();
+ resourcesList.add(resource1);
+ Mockito.when(notifData.getResources()).thenReturn(resourcesList);
+ return notifData;
+ }
+
+ private IDistributionClientDownloadResult buildFakeSdcResut() throws IOException {
+ IDistributionClientDownloadResult resultArtifact = Mockito.mock(IDistributionClientDownloadResult.class);
+ Mockito.when(resultArtifact.getArtifactPayload()).thenReturn(
+ IOUtils.toByteArray(ResourceFileUtils.getResourceAsStream("example/sdc/service-Simsfoimap0112.csar")));
+ return resultArtifact;
+ }
+
+ private IDistributionClientDownloadResult buildFakeSdcResultWithoutPolicyModel() throws IOException {
+ IDistributionClientDownloadResult resultArtifact = Mockito.mock(IDistributionClientDownloadResult.class);
+ Mockito.when(resultArtifact.getArtifactPayload()).thenReturn(
+ IOUtils.toByteArray(ResourceFileUtils.getResourceAsStream("example/sdc/service-without-policy.csar")));
+ return resultArtifact;
+ }
+
+ @Test
+ public void testSave()
+ throws SdcArtifactInstallerException, SdcToscaParserException, CsarHandlerException, IOException {
+ CsarHandler csar = new CsarHandler(buildFakeSdcNotification(), "test-controller", "/tmp/csar-handler-tests");
+ // Test the save
+ csar.save(buildFakeSdcResut());
+ assertTrue((new File(SDC_FOLDER + "/test-controller/" + CSAR_ARTIFACT_NAME)).exists());
+ assertEquals(CSAR_ARTIFACT_NAME, csar.getArtifactElement().getArtifactName());
+ assertNotNull(csar.getSdcCsarHelper());
+ // Test dcaeBlueprint
+ String blueprint = csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getDcaeBlueprint();
+ assertNotNull(blueprint);
+ assertTrue(!blueprint.isEmpty());
+ assertTrue(blueprint.contains("DCAE-VES-PM-EVENT-v1"));
+ // Test additional properties from Sdc notif
+ assertEquals(BLUEPRINT1_NAME, csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getBlueprintArtifactName());
+ assertEquals(RESOURCE1_UUID,
+ csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getResourceAttached().getResourceInvariantUUID());
+ assertEquals(SERVICE_UUID, csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getBlueprintInvariantServiceUuid());
+
+ // Just check the second one is there as well
+ assertEquals(BLUEPRINT2_NAME, csar.getMapOfBlueprints().get(BLUEPRINT2_NAME).getBlueprintArtifactName());
+ blueprint = csar.getMapOfBlueprints().get(BLUEPRINT2_NAME).getDcaeBlueprint();
+ assertNotNull(blueprint);
+ assertTrue(!blueprint.isEmpty());
+ assertTrue(blueprint.contains("DCAE-VES-PM-EVENT-v1"));
+ // Do some cleanup
+ Path path = Paths.get(SDC_FOLDER + "/test-controller/" + CSAR_ARTIFACT_NAME);
+ Files.deleteIfExists(path);
+
+ }
+
+ @Test
+ public void testLoadingOfPolicyModelFromCsar()
+ throws CsarHandlerException, IOException, SdcArtifactInstallerException, SdcToscaParserException {
+ CsarHandler csar = new CsarHandler(buildFakeSdcNotification(), "test-controller", "/tmp/csar-handler-tests");
+ csar.save(buildFakeSdcResut());
+ String policyModelYaml = csar.getPolicyModelYaml().get();
+ assertTrue(policyModelYaml.contains("tosca_simple_yaml_1_0_0"));
+ }
+
+ @Test
+ public void testLoadingOfNonexistentPolicyModelFromCsar()
+ throws CsarHandlerException, IOException, SdcArtifactInstallerException, SdcToscaParserException {
+ CsarHandler csar = new CsarHandler(buildFakeSdcNotification(), "test-controller", "/tmp/csar-handler-tests");
+ csar.save(buildFakeSdcResultWithoutPolicyModel());
+ assertFalse(csar.getPolicyModelYaml().isPresent());
+ }
+
+ @Test
+ public void testDoubleSave()
+ throws SdcArtifactInstallerException, SdcToscaParserException, CsarHandlerException, IOException {
+ CsarHandler csar = new CsarHandler(buildFakeSdcNotification(), "test-controller", "/tmp/csar-handler-tests");
+ // Test the save
+ csar.save(buildFakeSdcResut());
+ assertTrue((new File(SDC_FOLDER + "/test-controller/" + CSAR_ARTIFACT_NAME)).exists());
+ assertEquals(CSAR_ARTIFACT_NAME, csar.getArtifactElement().getArtifactName());
+ assertNotNull(csar.getSdcCsarHelper());
+ // Test dcaeBlueprint
+ String blueprint = csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getDcaeBlueprint();
+ assertNotNull(blueprint);
+ assertTrue(!blueprint.isEmpty());
+ assertTrue(blueprint.contains("DCAE-VES-PM-EVENT-v1"));
+ // Test additional properties from Sdc notif
+ assertEquals(BLUEPRINT1_NAME, csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getBlueprintArtifactName());
+ assertEquals(RESOURCE1_UUID,
+ csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getResourceAttached().getResourceInvariantUUID());
+ assertEquals(SERVICE_UUID, csar.getMapOfBlueprints().get(BLUEPRINT1_NAME).getBlueprintInvariantServiceUuid());
+ Path path = Paths.get(SDC_FOLDER + "/test-controller/" + CSAR_ARTIFACT_NAME);
+ // A double save should simply overwrite the existing
+ csar.save(buildFakeSdcResut());
+ // Do some cleanup
+ Files.deleteIfExists(path);
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/DictionaryRepositoriesTestItCase.java b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/DictionaryRepositoriesTestItCase.java
new file mode 100644
index 000000000..f70e74cd6
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/DictionaryRepositoriesTestItCase.java
@@ -0,0 +1,88 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.Application;
+import org.onap.policy.clamp.tosca.Dictionary;
+import org.onap.policy.clamp.tosca.DictionaryElement;
+import org.onap.policy.clamp.tosca.DictionaryRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest(classes = Application.class)
+public class DictionaryRepositoriesTestItCase {
+ @Autowired
+ private DictionaryRepository dictionaryRepository;
+
+ @Test
+ @Transactional
+ public void crudTest() {
+ // Setup
+ Dictionary dictionaryTest1 = new Dictionary();
+ dictionaryTest1.setName("testDictionary1");
+ dictionaryTest1.setSecondLevelDictionary(1);
+ dictionaryTest1.setSubDictionaryType("testType");
+
+ DictionaryElement element1 = new DictionaryElement();
+ element1.setName("element1");
+ element1.setShortName("shortName1");
+ element1.setType("type1");
+ element1.setDescription("description1");
+
+ dictionaryTest1.addDictionaryElements(element1);
+
+ Dictionary dictionaryTest2 = new Dictionary();
+ dictionaryTest2.setName("testDictionary2");
+ dictionaryTest2.setSecondLevelDictionary(1);
+ dictionaryTest2.setSubDictionaryType("testType");
+
+ DictionaryElement element2 = new DictionaryElement();
+ element2.setName("element2");
+ element2.setShortName("shortName2");
+ element2.setSubDictionary("testDictionary1");
+ element2.setType("type2");
+ element2.setDescription("description2");
+
+ dictionaryTest2.addDictionaryElements(element2);
+
+ dictionaryRepository.save(dictionaryTest1);
+ List<String> res1 = dictionaryRepository.getAllDictionaryNames();
+ assertThat(res1.size()).isGreaterThanOrEqualTo(1);
+ assertThat(res1).contains("testDictionary1");
+
+ dictionaryRepository.save(dictionaryTest2);
+ List<String> res2 = dictionaryRepository.getAllDictionaryNames();
+ assertThat(res2.size()).isGreaterThanOrEqualTo(2);
+ assertThat(res2).contains("testDictionary1");
+ assertThat(res2).contains("testDictionary2");
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ArrayFieldTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ArrayFieldTest.java
new file mode 100644
index 000000000..6f6f5c104
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ArrayFieldTest.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update;
+
+import com.google.gson.JsonArray;
+import java.io.IOException;
+import java.util.ArrayList;
+import junit.framework.TestCase;
+import org.onap.policy.clamp.clds.tosca.update.elements.ArrayField;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElement;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElementProperty;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplateManager;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+
+public class ArrayFieldTest extends TestCase {
+
+ /**
+ * Test the deploy method.
+ *
+ * @throws IOException in case of failure
+ */
+ public void testDeploy() throws IOException {
+ JsonTemplateManager jsonTemplateManager = new JsonTemplateManager(ResourceFileUtils.getResourceAsString(
+ "tosca/new-converter/sampleOperationalPoliciesEXTENTED.yaml"), ResourceFileUtils.getResourceAsString(
+ "clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ ToscaElement toscaElement = jsonTemplateManager.getToscaElements().get("onap.datatype.controlloop.Actor");
+ ToscaElementProperty toscaElementProperty = toscaElement.getProperties().get("actor");
+ ArrayField arrayParser = new ArrayField((ArrayList<Object>) toscaElementProperty.getItems().get("default"));
+ JsonArray toTest = arrayParser.deploy();
+ String reference = "[1,\"String\",5.5,true]";
+ assertEquals(reference, String.valueOf(toTest));
+ }
+} \ No newline at end of file
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ConstraintTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ConstraintTest.java
new file mode 100644
index 000000000..493ee992c
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ConstraintTest.java
@@ -0,0 +1,106 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.util.ArrayList;
+import junit.framework.TestCase;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElement;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElementProperty;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplate;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplateManager;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+
+public class ConstraintTest extends TestCase {
+
+ JsonTemplateManager jsonTemplateManager = new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("tosca/new-converter/constraints.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+
+ ToscaElement toscaElement = jsonTemplateManager.getToscaElements().get("onap.datatype.controlloop.Operation");
+
+ public ConstraintTest() throws IOException {
+ }
+
+ /**
+ * Test get value array.
+ */
+ public void testGetValuesArray() {
+ ToscaElementProperty toscaElementProperty = toscaElement.getProperties().get("timeout");
+ JsonTemplate jsonTemplate = jsonTemplateManager.getJsonSchemaTemplates().get("integer");
+ JsonObject resultProcess = new JsonObject();
+ toscaElementProperty.addConstraintsAsJson(resultProcess,
+ (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"),
+ jsonTemplate);
+ String reference = "{\"enum\":[3,4,5.5,6,10]}";
+ assertEquals(reference, String.valueOf(resultProcess));
+ toscaElementProperty = toscaElement.getProperties().get("success");
+ jsonTemplate = jsonTemplateManager.getJsonSchemaTemplates().get("string");
+ resultProcess = new JsonObject();
+ toscaElementProperty.addConstraintsAsJson(resultProcess,
+ (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"),
+ jsonTemplate);
+ reference = "{\"enum\":[\"VALID\",\"TERMINATED\"]}";
+ assertEquals(reference, String.valueOf(resultProcess));
+ }
+
+ /**
+ * Test get Specific length.
+ */
+ public void testGetSpecificLength() {
+ //Test for string type, same process for array
+ ToscaElementProperty toscaElementProperty = toscaElement.getProperties().get("id");
+ JsonTemplate jsonTemplate = jsonTemplateManager.getJsonSchemaTemplates().get("string");
+ JsonObject resultProcess = new JsonObject();
+ toscaElementProperty.addConstraintsAsJson(resultProcess,
+ (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"),
+ jsonTemplate);
+ int specificLength = 8;
+ int toTest = resultProcess.get("minLength").getAsInt();
+ assertEquals(specificLength, toTest);
+ toTest = resultProcess.get("maxLength").getAsInt();
+ assertEquals(specificLength, toTest);
+ }
+
+ /**
+ * Test get limit value.
+ */
+ public void testGetLimitValue() {
+ //Test for array type, same process for string
+ ToscaElementProperty toscaElementProperty = toscaElement.getProperties().get("description");
+ JsonTemplate jsonTemplate = jsonTemplateManager.getJsonSchemaTemplates().get("array");
+ JsonObject resultProcess = new JsonObject();
+ toscaElementProperty.addConstraintsAsJson(resultProcess,
+ (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"),
+ jsonTemplate);
+
+ int toTest = resultProcess.get("minItems").getAsInt();
+ assertEquals(5, toTest);
+ toTest = resultProcess.get("maxItems").getAsInt();
+ assertEquals(7, toTest);
+ }
+
+} \ No newline at end of file
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/JsonTemplateFieldTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/JsonTemplateFieldTest.java
new file mode 100644
index 000000000..3eaa0ce51
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/JsonTemplateFieldTest.java
@@ -0,0 +1,69 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update;
+
+import junit.framework.TestCase;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplateField;
+
+public class JsonTemplateFieldTest extends TestCase {
+
+ JsonTemplateField field1 = new JsonTemplateField("type", "testType", true, true);
+ JsonTemplateField field2 = new JsonTemplateField("type");
+ JsonTemplateField field3 = new JsonTemplateField("type", "testType1", true, true);
+ JsonTemplateField field4 = new JsonTemplateField("type", "testType", false, true);
+ JsonTemplateField field5 = new JsonTemplateField("type", "testType", true, false);
+ JsonTemplateField field6 = new JsonTemplateField("type", "testType", true, true);
+
+ /**
+ * Test fieldsEqual method.
+ */
+ public void testFieldsEqualsMethod() {
+ assertFalse(JsonTemplateField.fieldsEquals(field1, field3));
+ assertFalse(JsonTemplateField.fieldsEquals(field1, field4));
+ assertFalse(JsonTemplateField.fieldsEquals(field1, field5));
+ assertTrue(JsonTemplateField.fieldsEquals(field1, field6));
+ }
+
+ /**
+ * Test equals method.
+ */
+ public void testEqualsMethod() {
+ assertTrue(field1.equals(field2));
+ assertTrue(field1.equals(field3));
+ assertTrue(field1.equals(field4));
+ assertTrue(field1.equals(field5));
+ assertTrue(field1.equals(field6));
+ }
+
+ /**
+ * Test compareWithField method.
+ */
+ public void testCompareWithFieldMethod() {
+ assertFalse(field1.compareWithField(field2));
+ assertFalse(field1.compareWithField(field3));
+ assertFalse(field1.compareWithField(field4));
+ assertFalse(field1.compareWithField(field5));
+ assertTrue(field1.equals(field6));
+ }
+} \ No newline at end of file
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/JsonTemplateManagerTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/JsonTemplateManagerTest.java
new file mode 100644
index 000000000..2c8744f33
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/JsonTemplateManagerTest.java
@@ -0,0 +1,203 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import junit.framework.TestCase;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplate;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplateField;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplateManager;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+
+public class JsonTemplateManagerTest extends TestCase {
+
+ /**
+ * Test the launch translation wit operational policies.
+ *
+ * @throws IOException In case of failure
+ * @throws UnknownComponentException In case of failure
+ */
+ public void testLaunchTranslationTca() throws IOException, UnknownComponentException {
+ JsonTemplateManager jsonTemplateManager =
+ new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("http-cache/example/policy/api/v1/policytypes/onap"
+ + ".policies.monitoring.cdap.tca.hi.lo.app/versions/1.0.0/.file"),
+ ResourceFileUtils.getResourceAsString(
+ "clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ String componentName = "onap.policies.monitoring.cdap.tca.hi.lo.app";
+ jsonTemplateManager.getJsonSchemaForPolicyType(componentName, null, null);
+ }
+
+ /**
+ * Test the launch translation wit operational policies.
+ *
+ * @throws IOException In case of failure
+ * @throws UnknownComponentException In case of failure
+ */
+ public void testLaunchTranslationFrequencyLimiter() throws IOException, UnknownComponentException {
+ JsonTemplateManager jsonTemplateManager =
+ new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("http-cache/example/policy/api/v1/policytypes/onap"
+ + ".policies.controlloop.guard.common.FrequencyLimiter/versions/1.0.0/.file"),
+ ResourceFileUtils.getResourceAsString(
+ "clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ String componentName = "onap.policies.controlloop.guard.common.FrequencyLimiter";
+ jsonTemplateManager.getJsonSchemaForPolicyType(componentName, null, null);
+ }
+
+ /**
+ * Test the launch translation wit operational policies.
+ *
+ * @throws IOException In case of failure
+ * @throws UnknownComponentException In case of failure
+ */
+ public void testLaunchTranslationApex() throws IOException, UnknownComponentException {
+ JsonTemplateManager jsonTemplateManager =
+ new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("http-cache/example/policy/api/v1/policytypes/onap"
+ + ".policies.controlloop.operational.common.Apex/versions/1.0.0/.file"),
+ ResourceFileUtils.getResourceAsString(
+ "clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ String componentName = "onap.policies.controlloop.operational.common.Apex";
+ jsonTemplateManager.getJsonSchemaForPolicyType(componentName, null, null);
+ }
+
+ /**
+ * Test the launch translation wit operational policies.
+ *
+ * @throws IOException In case of failure
+ * @throws UnknownComponentException In case of failure
+ */
+ public void testLaunchTranslationDrools() throws IOException, UnknownComponentException {
+ JsonTemplateManager jsonTemplateManager =
+ new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("http-cache/example/policy/api/v1/policytypes/onap"
+ + ".policies.controlloop.operational.common.Drools/versions/1.0.0/.file"),
+ ResourceFileUtils.getResourceAsString(
+ "clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ String componentName = "onap.policies.controlloop.operational.common.Drools";
+ jsonTemplateManager.getJsonSchemaForPolicyType(componentName, null, null);
+ }
+
+
+ /**
+ * Test the launch translation.
+ *
+ * @throws IOException In case of failure
+ * @throws UnknownComponentException In case of failure
+ */
+ public void testLaunchTranslation() throws IOException, UnknownComponentException {
+ JsonTemplateManager jsonTemplateManager =
+ new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ String componentName = "onap.policies.controlloop.operational.common.Drools";
+ jsonTemplateManager.getJsonSchemaForPolicyType(componentName, null, null);
+ }
+
+ /**
+ * Test addTemplate.
+ *
+ * @throws IOException In case of failure
+ */
+ public void testAddTemplate() throws IOException {
+ JsonTemplateManager jsonTemplateManager =
+ new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ int count = jsonTemplateManager.getJsonSchemaTemplates().size();
+ List<JsonTemplateField>
+ jsonTemplateFields =
+ new ArrayList<>(Arrays.asList(new JsonTemplateField("type"), new JsonTemplateField("description"),
+ new JsonTemplateField(
+ "required"),
+ new JsonTemplateField("metadata"), new JsonTemplateField("constraints")));
+ jsonTemplateManager.addTemplate("test", jsonTemplateFields);
+ assertNotSame(count, jsonTemplateManager.getJsonSchemaTemplates().size());
+ }
+
+ /**
+ * test Remove template.
+ *
+ * @throws IOException In case of failure
+ */
+ public void testRemoveTemplate() throws IOException {
+ JsonTemplateManager jsonTemplateManager =
+ new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ int count = jsonTemplateManager.getJsonSchemaTemplates().size();
+ jsonTemplateManager.removeTemplate("string");
+ assertNotSame(count, jsonTemplateManager.getJsonSchemaTemplates().size());
+ }
+
+ /**
+ * Test update template.
+ *
+ * @throws IOException In case of failure
+ */
+ public void testUpdateTemplate() throws IOException {
+ JsonTemplateManager jsonTemplateManager =
+ new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ int count = jsonTemplateManager.getJsonSchemaTemplates().get("integer").getJsonTemplateFields().size();
+ jsonTemplateManager.updateTemplate("integer", new JsonTemplateField("type"), false);
+ assertNotSame(count,
+ jsonTemplateManager.getJsonSchemaTemplates().get("integer").getJsonTemplateFields().size());
+ }
+
+ /**
+ * Test has template.
+ *
+ * @throws IOException In case of failure
+ */
+ public void testHasTemplate() throws IOException {
+ JsonTemplateManager jsonTemplateManager =
+ new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ boolean has = true;
+ List<JsonTemplateField> jsonTemplateFieldsString =
+ new ArrayList<>(Arrays.asList(new JsonTemplateField("type"), new JsonTemplateField("description"),
+ new JsonTemplateField("required"),
+ new JsonTemplateField("metadata"), new JsonTemplateField("constraints")));
+ JsonTemplate jsonTemplateTest = new JsonTemplate("String", jsonTemplateFieldsString);
+ has = jsonTemplateManager.hasTemplate(jsonTemplateTest);
+ assertEquals(false, has);
+ }
+
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/JsonTemplateTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/JsonTemplateTest.java
new file mode 100644
index 000000000..dc27d8aaa
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/JsonTemplateTest.java
@@ -0,0 +1,69 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import junit.framework.TestCase;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplate;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplateField;
+
+public class JsonTemplateTest extends TestCase {
+
+ JsonTemplate toTest = new JsonTemplate("toTest");
+ List<JsonTemplateField>
+ jsonTemplateFields = new ArrayList<>(
+ Arrays.asList(new JsonTemplateField("type"), new JsonTemplateField("description"),
+ new JsonTemplateField(
+ "enum")));
+
+ /**
+ * Test check failed.
+ */
+ public void testCheckFields() {
+ toTest.setJsonTemplateFields(jsonTemplateFields);
+ JsonTemplate reference = new JsonTemplate("toTest");
+ reference.setJsonTemplateFields(jsonTemplateFields);
+ assertTrue(toTest.checkFields(reference));
+ }
+
+ /**
+ * Test other methods.
+ */
+ public void testOtherFields() {
+ toTest.setJsonTemplateFields(jsonTemplateFields);
+ toTest.addField(new JsonTemplateField("moreField"));
+ toTest.setVisibility("moreField", true);
+ toTest.setStatic("moreField", true);
+ toTest.updateValueField("moreField", "testValue");
+
+ assertTrue(toTest.isVisible("moreField"));
+ assertTrue(toTest.getSpecificField("moreField").getValue().equals("testValue"));
+ assertTrue(toTest.fieldStaticStatus("moreField"));
+ assertTrue(toTest.toString()
+ .equals(" templateFields : [type null null null, description null null null, "
+ + "enum null null null, moreField testValue true true]"));
+ }
+} \ No newline at end of file
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ToscaConverterWithDictionarySupportItCase.java b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ToscaConverterWithDictionarySupportItCase.java
new file mode 100644
index 000000000..658419d4c
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ToscaConverterWithDictionarySupportItCase.java
@@ -0,0 +1,147 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import javax.transaction.Transactional;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.Application;
+import org.onap.policy.clamp.clds.tosca.update.execution.ToscaMetadataExecutor;
+import org.onap.policy.clamp.clds.tosca.update.parser.metadata.ToscaMetadataParserWithDictionarySupport;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplateManager;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.loop.service.Service;
+import org.onap.policy.clamp.tosca.Dictionary;
+import org.onap.policy.clamp.tosca.DictionaryElement;
+import org.onap.policy.clamp.tosca.DictionaryService;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest(classes = Application.class)
+@ActiveProfiles({"clamp-default", "clamp-default-user", "default-dictionary-elements"})
+public class ToscaConverterWithDictionarySupportItCase {
+
+ @Autowired
+ private DictionaryService dictionaryService;
+
+ @Autowired
+ private ToscaMetadataParserWithDictionarySupport toscaMetadataParserWithDictionarySupport;
+
+ @Autowired
+ private ToscaMetadataExecutor toscaMetadataExecutor;
+
+ /**
+ * This Test validates Tosca yaml with metadata tag that contains policy_model_type and acronym
+ * parameters which defines the Tosca Policy name and its short name.
+ *
+ * @throws IOException In case of issue when opening the tosca yaml file and
+ * converted json file
+ */
+ @Test
+ @Transactional
+ public final void testMetadataClampPossibleValues() throws IOException, UnknownComponentException {
+
+ // Set up dictionary elements
+ Dictionary dictionaryTest = new Dictionary();
+ dictionaryTest.setName("Context");
+ dictionaryTest.setSecondLevelDictionary(0);
+
+ DictionaryElement element = new DictionaryElement();
+ element.setName("PROD");
+ element.setShortName("PROD");
+ element.setType("string");
+ element.setDescription("Production");
+ dictionaryTest.addDictionaryElements(element);
+
+ dictionaryService.saveOrUpdateDictionary(dictionaryTest);
+
+ Dictionary dictionaryTest1 = new Dictionary();
+ dictionaryTest1.setName("EventDictionary");
+ dictionaryTest1.setSecondLevelDictionary(0);
+
+ DictionaryElement element1 = new DictionaryElement();
+ element1.setName("alarmCondition");
+ element1.setShortName("alarmCondition");
+ element1.setType("string");
+ element1.setDescription("Alarm Condition");
+ dictionaryTest1.addDictionaryElements(element1);
+
+ dictionaryService.saveOrUpdateDictionary(dictionaryTest1);
+
+ Dictionary dictionaryTest2 = new Dictionary();
+ dictionaryTest2.setName("Operators");
+ dictionaryTest2.setSecondLevelDictionary(0);
+
+ DictionaryElement element2 = new DictionaryElement();
+ element2.setName("equals");
+ element2.setShortName("equals");
+ element2.setType("string");
+ element2.setDescription("equals");
+ dictionaryTest2.addDictionaryElements(element2);
+ dictionaryService.saveOrUpdateDictionary(dictionaryTest2);
+
+ JsonTemplateManager jsonTemplateManager =
+ new JsonTemplateManager(
+ ResourceFileUtils
+ .getResourceAsString("tosca/new-converter/tosca_metadata_clamp_possible_values.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+
+ JsonObject jsonSchema = jsonTemplateManager.getJsonSchemaForPolicyType(
+ "onap.policies.monitoring.cdap.tca.hi.lo.app", toscaMetadataParserWithDictionarySupport, null);
+
+ JSONAssert.assertEquals(
+ ResourceFileUtils
+ .getResourceAsString("tosca/new-converter/tca-with-metadata.json"),
+ JsonUtils.GSON.toJson(jsonSchema), true);
+ }
+
+ @Test
+ @Transactional
+ public final void testMetadataClampPossibleValueWithExecutor() throws IOException, UnknownComponentException {
+ Service service = new Service(ResourceFileUtils.getResourceAsString("tosca/service-details.json"),
+ ResourceFileUtils.getResourceAsString("tosca/resource-details-cds.json"));
+ JsonTemplateManager jsonTemplateManager =
+ new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("http-cache/example/policy/api/v1/policytypes/onap"
+ + ".policies.controlloop.operational.common.Apex/versions/1.0.0/.file"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+
+ JsonObject jsonSchema = jsonTemplateManager.getJsonSchemaForPolicyType(
+ "onap.policies.controlloop.operational.common.Apex", toscaMetadataParserWithDictionarySupport, service);
+
+ JSONAssert.assertEquals(
+ ResourceFileUtils
+ .getResourceAsString("tosca/new-converter/tosca_apex_with_metadata.json"),
+ JsonUtils.GSON.toJson(jsonSchema), true);
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ToscaElementPropertyTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ToscaElementPropertyTest.java
new file mode 100644
index 000000000..5652fa9cd
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ToscaElementPropertyTest.java
@@ -0,0 +1,79 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.util.ArrayList;
+import junit.framework.TestCase;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElement;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElementProperty;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplate;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplateManager;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+
+public class ToscaElementPropertyTest extends TestCase {
+ public ToscaElementPropertyTest() throws IOException {
+ }
+
+ /**
+ * Test Parse array.
+ *
+ * @throws IOException In case of failure
+ */
+ public void testParseArray() throws IOException {
+ JsonTemplateManager jsonTemplateManager = new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPoliciesEXTENTED.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ ToscaElement toscaElement = jsonTemplateManager.getToscaElements().get("onap.datatype.controlloop.Actor");
+ ToscaElementProperty toscaElementProperty = toscaElement.getProperties().get("actor");
+ JsonArray toTest =
+ toscaElementProperty.parseArray((ArrayList<Object>) toscaElementProperty.getItems().get("default"));
+ assertNotNull(toTest);
+ }
+
+ /**
+ * Test add constraint as json.
+ *
+ * @throws IOException In case of failure
+ */
+ public void testAddConstraintsAsJson() throws IOException {
+ JsonTemplateManager jsonTemplateManager = new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ ToscaElement toscaElement =
+ jsonTemplateManager.getToscaElements().get("onap.datatype.controlloop.operation.Failure");
+ ToscaElementProperty toscaElementProperty = toscaElement.getProperties().get("category");
+ JsonTemplate jsonTemplate = jsonTemplateManager.getJsonSchemaTemplates().get("string");
+ JsonObject toTest = new JsonObject();
+ toscaElementProperty
+ .addConstraintsAsJson(toTest, (ArrayList<Object>) toscaElementProperty.getItems().get("constraints"),
+ jsonTemplate);
+ String test = "{\"enum\":[\"error\",\"timeout\",\"retries\",\"guard\",\"exception\"]}";
+ assertEquals(test, String.valueOf(toTest));
+ }
+} \ No newline at end of file
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ToscaElementTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ToscaElementTest.java
new file mode 100644
index 000000000..0ea2146b4
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/tosca/update/ToscaElementTest.java
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.tosca.update;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import junit.framework.TestCase;
+import org.onap.policy.clamp.clds.tosca.update.elements.ToscaElement;
+import org.onap.policy.clamp.clds.tosca.update.templates.JsonTemplateManager;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+
+public class ToscaElementTest extends TestCase {
+
+ /**
+ * Test propertiesName.
+ *
+ * @throws IOException In case of failure
+ */
+ public void testPropertiesNames() throws IOException {
+ ArrayList<String> reference = new ArrayList<>(Arrays.asList("actor", "operation", "target", "payload"));
+ JsonTemplateManager jsonTemplateManager =
+ new JsonTemplateManager(
+ ResourceFileUtils.getResourceAsString("tosca/new-converter/sampleOperationalPolicies.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/default-tosca-types.yaml"),
+ ResourceFileUtils.getResourceAsString("clds/tosca-converter/templates.json"));
+ ToscaElement toscaElement = jsonTemplateManager.getToscaElements().get("onap.datatype.controlloop.Actor");
+ assertEquals(reference, toscaElement.propertiesNames());
+ }
+
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/util/JsonUtilsTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/util/JsonUtilsTest.java
new file mode 100644
index 000000000..b2c6d282a
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/util/JsonUtilsTest.java
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * Modifications copyright (c) 2019 Nokia
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.util;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.IOException;
+import org.junit.Test;
+
+public class JsonUtilsTest {
+
+ public static class TestClass extends TestObject {
+
+ String test2;
+ TestObject2 object2;
+
+ TestClass(String value1, String value2) {
+ super(value1);
+ test2 = value2;
+ }
+
+ void setObject2(TestObject2 object2) {
+ this.object2 = object2;
+ }
+ }
+
+ @Test
+ public void testGetObjectMapperInstance() {
+ assertNotNull(JsonUtils.GSON);
+ }
+
+ /**
+ * This method test that the security hole in GSON is not enabled in the default
+ * ObjectMapper.
+ */
+ @Test
+ public void testCreateBeanDeserializer() {
+ TestClass test = new TestClass("value1", "value2");
+ test.setObject2(new TestObject2("test3"));
+ Object testObject = JsonUtils.GSON.fromJson("[\"org.onap.policy.clamp.clds.util.JsonUtilsTest$TestClass\""
+ + ",{\"test\":\"value1\",\"test2\":\"value2\","
+ + "\"object2\":[\"org.onap.policy.clamp.clds.util.TestObject2\","
+ + "{\"test3\":\"test3\"}]}]", Object.class);
+ assertNotNull(testObject);
+ assertFalse(testObject instanceof TestObject);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldThrowExceptionFileNotExists() throws IOException {
+ ResourceFileUtils.getResourceAsString("example/notExist.json");
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/util/LoggingUtilsTest.java b/runtime/src/test/java/org/onap/policy/clamp/clds/util/LoggingUtilsTest.java
new file mode 100644
index 000000000..ab6a41bca
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/util/LoggingUtilsTest.java
@@ -0,0 +1,138 @@
+/*-
+* ============LICENSE_START=======================================================
+* ONAP CLAMP
+* Copyright (C) 2019 Samsung. All rights reserved.
+* ================================================================================
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+* ============LICENSE_END============================================
+* ===================================================================
+*
+*/
+
+package org.onap.policy.clamp.clds.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Arrays;
+import java.util.Map;
+import javax.net.ssl.HttpsURLConnection;
+import javax.servlet.http.HttpServletRequest;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.slf4j.event.Level;
+import org.springframework.http.HttpStatus;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContext;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
+
+/**
+ * Test Logging Utils.
+ */
+@RunWith(MockitoJUnitRunner.class)
+public class LoggingUtilsTest {
+
+ protected static final Logger logger = LoggerFactory.getLogger(LoggingUtilsTest.class);
+
+ private static final String SERVICE_NAME = "LogginUtilsTest: Test Entering method";
+
+ private LoggingUtils util;
+
+ @Before
+ public void setup() {
+ this.util = new LoggingUtils(logger);
+ }
+
+ @Test
+ public void testEnteringLoggingUtils() {
+ // given
+ final String userName = "test";
+
+ UserDetails userDetails = Mockito.mock(UserDetails.class);
+ Mockito.when(userDetails.getUsername()).thenReturn(userName);
+
+ Authentication localAuth = Mockito.mock(Authentication.class);
+ Mockito.when(localAuth.getPrincipal()).thenReturn(userDetails);
+
+ SecurityContext securityContext = Mockito.mock(SecurityContext.class);
+ Mockito.when(securityContext.getAuthentication()).thenReturn(localAuth);
+ SecurityContextHolder.setContext(securityContext);
+
+ HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
+ // when
+ util.entering(request, SERVICE_NAME);
+
+ // then
+ String[] keys = {OnapLogConstants.Mdcs.PARTNER_NAME, OnapLogConstants.Mdcs.ENTRY_TIMESTAMP,
+ OnapLogConstants.Mdcs.REQUEST_ID, OnapLogConstants.Mdcs.INVOCATION_ID,
+ OnapLogConstants.Mdcs.CLIENT_IP_ADDRESS, OnapLogConstants.Mdcs.SERVER_FQDN,
+ OnapLogConstants.Mdcs.INSTANCE_UUID, OnapLogConstants.Mdcs.SERVICE_NAME};
+ Map<String, String> mdc = MDC.getMDCAdapter().getCopyOfContextMap();
+
+ assertTrue(checkMapKeys(mdc, keys));
+ assertEquals(userName, mdc.get(OnapLogConstants.Mdcs.PARTNER_NAME));
+ }
+
+ @Test
+ public void testExistingLoggingUtils() {
+ // given
+ MDC.put(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP,
+ ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT));
+
+ // when
+ util.exiting(HttpStatus.OK.value(), SERVICE_NAME, Level.INFO,
+ OnapLogConstants.ResponseStatus.COMPLETE);
+
+ // then
+ Map<String, String> mdc = MDC.getMDCAdapter().getCopyOfContextMap();
+ assertNull(mdc);
+ }
+
+ @Test
+ public void testInvokeTestUtils() {
+ // given
+ final String targetEntity = "LoggingUtilsTest";
+ final String targetServiceName = "testInvokeTestUtils";
+ HttpsURLConnection secureConnection = Mockito.mock(HttpsURLConnection.class);
+
+ // when
+ secureConnection = util.invokeHttps(secureConnection, targetEntity, targetServiceName);
+
+ // then
+ assertNotNull(secureConnection);
+ String[] keys =
+ {OnapLogConstants.Mdcs.TARGET_ENTITY, OnapLogConstants.Mdcs.TARGET_SERVICE_NAME,
+ OnapLogConstants.Mdcs.INVOCATIONID_OUT, OnapLogConstants.Mdcs.INVOKE_TIMESTAMP};
+ Map<String, String> mdc = MDC.getMDCAdapter().getCopyOfContextMap();
+
+ assertTrue(checkMapKeys(mdc, keys));
+ assertEquals(targetEntity, mdc.get(OnapLogConstants.Mdcs.TARGET_ENTITY));
+ assertEquals(targetServiceName, mdc.get(OnapLogConstants.Mdcs.TARGET_SERVICE_NAME));
+ }
+
+ private boolean checkMapKeys(Map map, String[] keys) {
+ return Arrays.stream(keys).allMatch(key -> map.get(key) != null);
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/util/TestObject.java b/runtime/src/test/java/org/onap/policy/clamp/clds/util/TestObject.java
new file mode 100644
index 000000000..02cabd270
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/util/TestObject.java
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.util;
+
+public class TestObject {
+
+ private String test;
+
+ public String getTest() {
+ return test;
+ }
+
+ public void setTest(String test) {
+ this.test = test;
+ }
+
+ // @JsonProperty("test"), @JsonCreator
+ public TestObject(String theString) {
+ this.setTest(theString);
+ }
+
+ public TestObject() {
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/clds/util/TestObject2.java b/runtime/src/test/java/org/onap/policy/clamp/clds/util/TestObject2.java
new file mode 100644
index 000000000..d5abf41d0
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/clds/util/TestObject2.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.clds.util;
+
+public class TestObject2 {
+
+ private String test3;
+
+ public String getTest3() {
+ return test3;
+ }
+
+ public void setTest3(String test) {
+ this.test3 = test;
+ }
+
+ public TestObject2(String theString) {
+ this.setTest3(theString);
+ }
+
+ public TestObject2() {
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/flow/FlowLogOperationTest.java b/runtime/src/test/java/org/onap/policy/clamp/flow/FlowLogOperationTest.java
new file mode 100644
index 000000000..622fd5999
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/flow/FlowLogOperationTest.java
@@ -0,0 +1,102 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Samsung. All rights reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2021 AT&T
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.flow;
+
+import static junit.framework.Assert.assertEquals;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.support.DefaultExchange;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.onap.policy.clamp.clds.util.LoggingUtils;
+import org.onap.policy.clamp.clds.util.OnapLogConstants;
+import org.onap.policy.clamp.flow.log.FlowLogOperation;
+import org.slf4j.MDC;
+import org.slf4j.spi.MDCAdapter;
+import org.springframework.test.util.ReflectionTestUtils;
+
+public class FlowLogOperationTest {
+
+ private FlowLogOperation flowLogOperation = new FlowLogOperation();
+
+ @Test
+ public void testStartLog() {
+ // given
+ LoggingUtils loggingUtils = mock(LoggingUtils.class);
+ ReflectionTestUtils.setField(flowLogOperation, "util", loggingUtils);
+
+ // when
+ Mockito.when(loggingUtils.getProperties(OnapLogConstants.Mdcs.REQUEST_ID)).thenReturn("MockRequestId");
+ Mockito.when(loggingUtils.getProperties(OnapLogConstants.Mdcs.INVOCATION_ID)).thenReturn("MockInvocationId");
+ Mockito.when(loggingUtils.getProperties(OnapLogConstants.Mdcs.PARTNER_NAME)).thenReturn("MockPartnerName");
+ Exchange exchange = new DefaultExchange(mock(CamelContext.class));
+ flowLogOperation.startLog(exchange, "serviceName");
+
+ // then
+ assertThat(exchange.getProperty(OnapLogConstants.Headers.REQUEST_ID)).isEqualTo("MockRequestId");
+ assertThat(exchange.getProperty(OnapLogConstants.Headers.INVOCATION_ID)).isEqualTo("MockInvocationId");
+ assertThat(exchange.getProperty(OnapLogConstants.Headers.PARTNER_NAME)).isEqualTo("MockPartnerName");
+ }
+
+ @Test
+ public void testInvokeLog() {
+ // given
+ final String mockEntity = "mockEntity";
+ final String mockServiceName = "mockServiceName";
+ MDCAdapter mdcAdapter = MDC.getMDCAdapter();
+ // when
+ flowLogOperation.invokeLog(mockEntity, mockServiceName);
+ // then
+ String entity = mdcAdapter.get(OnapLogConstants.Mdcs.TARGET_ENTITY);
+ String serviceName = mdcAdapter.get(OnapLogConstants.Mdcs.TARGET_SERVICE_NAME);
+ assertEquals(entity, mockEntity);
+ assertEquals(serviceName, mockServiceName);
+ }
+
+ @Test
+ public void testEndLog() {
+ // given
+ MDC.put(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP, "2019-05-19T00:00:00.007Z");
+ MDCAdapter mdcAdapter = MDC.getMDCAdapter();
+ /// when
+ flowLogOperation.endLog();
+ // then
+ assertThat(mdcAdapter.get(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP)).isNull();
+ }
+
+ @Test
+ public void testErrorLog() {
+ // given
+ MDC.put(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP, "2019-05-19T00:00:00.007Z");
+ MDCAdapter mdcAdapter = MDC.getMDCAdapter();
+ // when
+ flowLogOperation.errorLog();
+ // then
+ assertThat(mdcAdapter.get(OnapLogConstants.Mdcs.ENTRY_TIMESTAMP)).isNull();
+ }
+} \ No newline at end of file
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/CsarInstallerItCase.java b/runtime/src/test/java/org/onap/policy/clamp/loop/CsarInstallerItCase.java
new file mode 100644
index 000000000..b0abf832b
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/CsarInstallerItCase.java
@@ -0,0 +1,322 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications copyright (c) 2019 Nokia
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import javax.transaction.Transactional;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.assertj.core.api.Assertions;
+import org.json.JSONException;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.onap.policy.clamp.clds.Application;
+import org.onap.policy.clamp.clds.exception.sdc.controller.BlueprintParserException;
+import org.onap.policy.clamp.clds.exception.sdc.controller.CsarHandlerException;
+import org.onap.policy.clamp.clds.exception.sdc.controller.SdcArtifactInstallerException;
+import org.onap.policy.clamp.clds.sdc.controller.installer.BlueprintArtifact;
+import org.onap.policy.clamp.clds.sdc.controller.installer.CsarHandler;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.loop.cds.CdsDataInstaller;
+import org.onap.policy.clamp.loop.service.ServicesRepository;
+import org.onap.policy.clamp.loop.template.LoopTemplate;
+import org.onap.policy.clamp.loop.template.LoopTemplateLoopElementModel;
+import org.onap.policy.clamp.loop.template.LoopTemplatesRepository;
+import org.onap.policy.clamp.loop.template.PolicyModelId;
+import org.onap.policy.clamp.loop.template.PolicyModelsRepository;
+import org.onap.sdc.api.notification.IArtifactInfo;
+import org.onap.sdc.api.notification.INotificationData;
+import org.onap.sdc.api.notification.IResourceInstance;
+import org.onap.sdc.tosca.parser.api.ISdcCsarHelper;
+import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;
+import org.onap.sdc.tosca.parser.impl.SdcToscaParserFactory;
+import org.onap.sdc.toscaparser.api.elements.Metadata;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.annotation.Commit;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+@ActiveProfiles({"clamp-default", "clamp-default-user", "clamp-sdc-controller"})
+public class CsarInstallerItCase {
+
+ private static final String CSAR_ARTIFACT_NAME_CDS = "example/sdc/service_Vloadbalancerms_cds.csar";
+ private static final String CSAR_ARTIFACT_NAME_NO_CDS = "example/sdc/service_Vloadbalancerms_no_cds.csar";
+ private static final String INVARIANT_SERVICE_UUID = "4cc5b45a-1f63-4194-8100-cd8e14248c92";
+ private static final String INVARIANT_RESOURCE1_UUID = "07e266fc-49ab-4cd7-8378-ca4676f1b9ec";
+ private static final String INVARIANT_RESOURCE2_UUID = "023a3f0d-1161-45ff-b4cf-8918a8ccf3ad";
+ private static final String RESOURCE_INSTANCE_NAME_RESOURCE1 = "ResourceInstanceName1";
+ private static final String RESOURCE_INSTANCE_NAME_RESOURCE2 = "ResourceInstanceName2";
+
+ @Autowired
+ private LoopTemplatesRepository loopTemplatesRepo;
+
+ @Autowired
+ ServicesRepository serviceRepository;
+
+ @Autowired
+ PolicyModelsRepository policyModelsRepository;
+
+ @Autowired
+ @Qualifier("csarInstaller")
+ private CsarInstaller csarInstaller;
+
+ private BlueprintArtifact buildFakeBlueprintArtifact(String instanceName, String invariantResourceUuid,
+ String blueprintFilePath, String artifactName,
+ String invariantServiceUuid) throws IOException {
+ IResourceInstance resource = Mockito.mock(IResourceInstance.class);
+ Mockito.when(resource.getResourceInstanceName()).thenReturn(instanceName);
+ Mockito.when(resource.getResourceInvariantUUID()).thenReturn(invariantResourceUuid);
+ BlueprintArtifact blueprintArtifact = Mockito.mock(BlueprintArtifact.class);
+ Mockito.when(blueprintArtifact.getDcaeBlueprint())
+ .thenReturn(ResourceFileUtils.getResourceAsString(blueprintFilePath));
+ Mockito.when(blueprintArtifact.getBlueprintArtifactName()).thenReturn(artifactName);
+ Mockito.when(blueprintArtifact.getBlueprintInvariantServiceUuid()).thenReturn(invariantServiceUuid);
+ Mockito.when(blueprintArtifact.getResourceAttached()).thenReturn(resource);
+ return blueprintArtifact;
+ }
+
+ private CsarHandler buildBadFakeCsarHandler(String generatedName, String csarFileName) throws IOException,
+ SdcToscaParserException {
+
+ // Build a Bad csar because the blueprint contains a link to a microservice that does not exist in the emulator
+ // Create fake notification
+ INotificationData notificationData = Mockito.mock(INotificationData.class);
+ Mockito.when(notificationData.getServiceVersion()).thenReturn("1.0");
+ // Create fake resource in notification
+ CsarHandler csarHandler = Mockito.mock(CsarHandler.class);
+ List<IResourceInstance> listResources = new ArrayList<>();
+ Mockito.when(notificationData.getResources()).thenReturn(listResources);
+ Map<String, BlueprintArtifact> blueprintMap = new HashMap<>();
+ Mockito.when(csarHandler.getMapOfBlueprints()).thenReturn(blueprintMap);
+ // Create fake blueprint artifact 1 on resource1
+ BlueprintArtifact blueprintArtifact = buildFakeBlueprintArtifact(RESOURCE_INSTANCE_NAME_RESOURCE1,
+ INVARIANT_RESOURCE1_UUID, "example/sdc/blueprint-dcae/tca-bad-policy.yaml", "tca-bad-policy.yaml",
+ INVARIANT_SERVICE_UUID);
+ listResources.add(blueprintArtifact.getResourceAttached());
+ blueprintMap.put(blueprintArtifact.getBlueprintArtifactName(), blueprintArtifact);
+
+ // Build fake csarhandler
+ Mockito.when(csarHandler.getSdcNotification()).thenReturn(notificationData);
+ // Build fake csar Helper
+ ISdcCsarHelper csarHelper = Mockito.mock(ISdcCsarHelper.class);
+ Metadata data = Mockito.mock(Metadata.class);
+ Mockito.when(data.getValue("name")).thenReturn(generatedName);
+ Mockito.when(notificationData.getServiceName()).thenReturn(generatedName);
+ Mockito.when(csarHelper.getServiceMetadata()).thenReturn(data);
+
+ // Create helper based on real csar to test policy yaml and global properties
+ // set
+ SdcToscaParserFactory factory = SdcToscaParserFactory.getInstance();
+ String path = Thread.currentThread().getContextClassLoader().getResource(csarFileName).getFile();
+ ISdcCsarHelper sdcHelper = factory.getSdcCsarHelper(path);
+ Mockito.when(csarHandler.getSdcCsarHelper()).thenReturn(sdcHelper);
+
+ // Mockito.when(csarHandler.getSdcCsarHelper()).thenReturn(csarHelper);
+ Mockito.when(csarHandler.getPolicyModelYaml())
+ .thenReturn(Optional.ofNullable(ResourceFileUtils.getResourceAsString("tosca/tosca_example.yaml")));
+ return csarHandler;
+ }
+
+ private CsarHandler buildFakeCsarHandler(String generatedName, String csarFileName) throws IOException,
+ SdcToscaParserException {
+ // Create fake notification
+ INotificationData notificationData = Mockito.mock(INotificationData.class);
+ Mockito.when(notificationData.getServiceVersion()).thenReturn("1.0");
+ // Create fake resource in notification
+ CsarHandler csarHandler = Mockito.mock(CsarHandler.class);
+ List<IResourceInstance> listResources = new ArrayList<>();
+ Mockito.when(notificationData.getResources()).thenReturn(listResources);
+ Map<String, BlueprintArtifact> blueprintMap = new HashMap<>();
+ Mockito.when(csarHandler.getMapOfBlueprints()).thenReturn(blueprintMap);
+ // Create fake blueprint artifact 1 on resource1
+ BlueprintArtifact blueprintArtifact = buildFakeBlueprintArtifact(RESOURCE_INSTANCE_NAME_RESOURCE1,
+ INVARIANT_RESOURCE1_UUID, "example/sdc/blueprint-dcae/tca.yaml", "tca.yaml", INVARIANT_SERVICE_UUID);
+ listResources.add(blueprintArtifact.getResourceAttached());
+ blueprintMap.put(blueprintArtifact.getBlueprintArtifactName(), blueprintArtifact);
+ // Create fake blueprint artifact 2 on resource2
+ blueprintArtifact = buildFakeBlueprintArtifact(RESOURCE_INSTANCE_NAME_RESOURCE2, INVARIANT_RESOURCE2_UUID,
+ "example/sdc/blueprint-dcae/tca_2.yaml", "tca_2.yaml", INVARIANT_SERVICE_UUID);
+ listResources.add(blueprintArtifact.getResourceAttached());
+ blueprintMap.put(blueprintArtifact.getBlueprintArtifactName(), blueprintArtifact);
+
+ // Create fake blueprint artifact 3 on resource 1 so that it's possible to
+ // test multiple CL deployment per Service/vnf
+ blueprintArtifact = buildFakeBlueprintArtifact(RESOURCE_INSTANCE_NAME_RESOURCE1, INVARIANT_RESOURCE1_UUID,
+ "example/sdc/blueprint-dcae/tca_3.yaml", "tca_3.yaml", INVARIANT_SERVICE_UUID);
+ blueprintMap.put(blueprintArtifact.getBlueprintArtifactName(), blueprintArtifact);
+
+ // Create fake blueprint artifact 3 on resource 1 so that it's possible to
+ // test multiple CL deployment per Service/vnf
+ blueprintArtifact = buildFakeBlueprintArtifact(RESOURCE_INSTANCE_NAME_RESOURCE1, INVARIANT_RESOURCE1_UUID,
+ "example/sdc/blueprint-dcae/tca-guilin.yaml", "tca-guilin.yaml", INVARIANT_SERVICE_UUID);
+ blueprintMap.put(blueprintArtifact.getBlueprintArtifactName(), blueprintArtifact);
+
+
+ // Build fake csarhandler
+ Mockito.when(csarHandler.getSdcNotification()).thenReturn(notificationData);
+ // Build fake csar Helper
+ ISdcCsarHelper csarHelper = Mockito.mock(ISdcCsarHelper.class);
+ Metadata data = Mockito.mock(Metadata.class);
+ Mockito.when(data.getValue("name")).thenReturn(generatedName);
+ Mockito.when(notificationData.getServiceName()).thenReturn(generatedName);
+ Mockito.when(csarHelper.getServiceMetadata()).thenReturn(data);
+
+ // Create helper based on real csar to test policy yaml and global properties
+ // set
+ SdcToscaParserFactory factory = SdcToscaParserFactory.getInstance();
+ String path = Thread.currentThread().getContextClassLoader().getResource(csarFileName).getFile();
+ ISdcCsarHelper sdcHelper = factory.getSdcCsarHelper(path);
+ Mockito.when(csarHandler.getSdcCsarHelper()).thenReturn(sdcHelper);
+
+ // Mockito.when(csarHandler.getSdcCsarHelper()).thenReturn(csarHelper);
+ Mockito.when(csarHandler.getPolicyModelYaml())
+ .thenReturn(Optional.ofNullable(ResourceFileUtils.getResourceAsString("tosca/tosca_example.yaml")));
+ return csarHandler;
+ }
+
+ @Test
+ @Transactional
+ public void testGetPolicyModelYaml() throws IOException, SdcToscaParserException, CsarHandlerException {
+ INotificationData notificationData = Mockito.mock(INotificationData.class);
+ IArtifactInfo serviceArtifacts = Mockito.mock(IArtifactInfo.class);
+ Mockito.when(serviceArtifacts.getArtifactType()).thenReturn("TOSCA_CSAR");
+ List<IArtifactInfo> serviceArtifactsList = new ArrayList<>();
+ serviceArtifactsList.add(serviceArtifacts);
+ Mockito.when(notificationData.getServiceArtifacts()).thenReturn(serviceArtifactsList);
+
+ CsarHandler csarHandler = new CsarHandler(notificationData, "", "");
+ csarHandler.setFilePath(Thread.currentThread().getContextClassLoader().getResource(CSAR_ARTIFACT_NAME_CDS)
+ .getFile());
+ Assert.assertEquals(csarHandler.getPolicyModelYaml(), Optional
+ .ofNullable(ResourceFileUtils.getResourceAsString("example/sdc/expected-result/policy-data.yaml")));
+ }
+
+ @Test
+ @Transactional
+ public void testIsCsarAlreadyDeployedTca() throws SdcArtifactInstallerException, SdcToscaParserException,
+ CsarHandlerException, IOException, InterruptedException, BlueprintParserException {
+ String generatedName = RandomStringUtils.randomAlphanumeric(5);
+ CsarHandler csarHandler = buildFakeCsarHandler(generatedName, CSAR_ARTIFACT_NAME_CDS);
+ assertThat(csarInstaller.isCsarAlreadyDeployed(csarHandler)).isFalse();
+ csarInstaller.installTheCsar(csarHandler);
+ assertThat(csarInstaller.isCsarAlreadyDeployed(csarHandler)).isTrue();
+ }
+
+ @Test
+ @Transactional
+ public void testWithoutCdsTca() throws SdcArtifactInstallerException, SdcToscaParserException,
+ CsarHandlerException, IOException, InterruptedException, BlueprintParserException {
+ String generatedName = RandomStringUtils.randomAlphanumeric(5);
+ CsarHandler csarHandler = buildFakeCsarHandler(generatedName, CSAR_ARTIFACT_NAME_NO_CDS);
+
+ assertThat(csarInstaller.isCsarAlreadyDeployed(csarHandler)).isFalse();
+ csarInstaller.installTheCsar(csarHandler);
+ assertThat(csarInstaller.isCsarAlreadyDeployed(csarHandler)).isTrue();
+ }
+
+ @Test(expected = SdcArtifactInstallerException.class)
+ @Transactional
+ public void testInstallTheBadCsarTca()
+ throws IOException, SdcToscaParserException, InterruptedException, BlueprintParserException,
+ SdcArtifactInstallerException {
+ // This test validates that the blueprint is well rejected because the blueprint contains a link
+ // to a policy that does not exist on the policy engine emulator.
+ String generatedName = RandomStringUtils.randomAlphanumeric(5);
+ csarInstaller.installTheCsar(buildBadFakeCsarHandler(generatedName, CSAR_ARTIFACT_NAME_NO_CDS));
+ }
+
+ @Test
+ @Transactional
+ @Commit
+ public void testInstallTheCsarTca() throws SdcArtifactInstallerException, SdcToscaParserException,
+ CsarHandlerException, IOException, JSONException, InterruptedException, BlueprintParserException {
+ String generatedName = RandomStringUtils.randomAlphanumeric(5);
+ csarInstaller.installTheCsar(buildFakeCsarHandler(generatedName, CSAR_ARTIFACT_NAME_CDS));
+
+ assertThat(serviceRepository.existsById("63cac700-ab9a-4115-a74f-7eac85e3fce0")).isTrue();
+ // We should have CDS info
+ assertThat(serviceRepository.findById("63cac700-ab9a-4115-a74f-7eac85e3fce0").get().getResourceByType("VF")
+ .getAsJsonObject("vLoadBalancerMS 0").getAsJsonObject(
+ CdsDataInstaller.CONTROLLER_PROPERTIES)).isNotNull();
+ assertThat(loopTemplatesRepo.existsById(LoopTemplate.generateLoopTemplateName(generatedName, "1.0",
+ RESOURCE_INSTANCE_NAME_RESOURCE1, "tca.yaml"))).isTrue();
+ assertThat(loopTemplatesRepo.existsById(LoopTemplate.generateLoopTemplateName(generatedName, "1.0",
+ RESOURCE_INSTANCE_NAME_RESOURCE1, "tca_3.yaml"))).isTrue();
+ assertThat(loopTemplatesRepo.existsById(LoopTemplate.generateLoopTemplateName(generatedName, "1.0",
+ RESOURCE_INSTANCE_NAME_RESOURCE2, "tca_2.yaml"))).isTrue();
+ assertThat(loopTemplatesRepo.existsById(LoopTemplate.generateLoopTemplateName(generatedName, "1.0",
+ RESOURCE_INSTANCE_NAME_RESOURCE1, "tca-guilin.yaml"))).isTrue();
+ // Verify now that policy and json representation, global properties are well
+ // set
+ LoopTemplate loopTemplate = loopTemplatesRepo.findById(LoopTemplate.generateLoopTemplateName(generatedName,
+ "1.0", RESOURCE_INSTANCE_NAME_RESOURCE1, "tca.yaml")).get();
+ assertThat(loopTemplate.getLoopElementModelsUsed()).hasSize(1);
+ Assertions.assertThat(loopTemplate.getModelService().getServiceUuid())
+ .isEqualTo("63cac700-ab9a-4115-a74f-7eac85e3fce0");
+ JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("tosca/model-properties.json"),
+ JsonUtils.GSON_JPA_MODEL.toJson(loopTemplate.getModelService()), true);
+ JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("tosca/service-details.json"),
+ JsonUtils.GSON_JPA_MODEL.toJson(loopTemplate.getModelService().getServiceDetails()), true);
+ JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("tosca/resource-details.json"),
+ JsonUtils.GSON_JPA_MODEL.toJson(loopTemplate.getModelService().getResourceDetails()), true);
+ Assertions.assertThat(((LoopTemplateLoopElementModel) (loopTemplate.getLoopElementModelsUsed().toArray()[0]))
+ .getLoopElementModel().getName()).isNotEmpty();
+
+ loopTemplate = loopTemplatesRepo.findById(LoopTemplate.generateLoopTemplateName(generatedName, "1.0",
+ RESOURCE_INSTANCE_NAME_RESOURCE1, "tca_3.yaml")).get();
+ assertThat(((LoopTemplateLoopElementModel) (loopTemplate.getLoopElementModelsUsed().toArray()[0]))
+ .getLoopElementModel().getName()).isNotEmpty();
+ assertThat(((LoopTemplateLoopElementModel) (loopTemplate.getLoopElementModelsUsed().toArray()[0]))
+ .getLoopElementModel().getName()).isNotEmpty();
+ assertThat(loopTemplate.getMaximumInstancesAllowed()).isEqualByComparingTo(Integer.valueOf(0));
+ loopTemplate = loopTemplatesRepo.findById(LoopTemplate.generateLoopTemplateName(generatedName, "1.0",
+ RESOURCE_INSTANCE_NAME_RESOURCE2, "tca_2.yaml")).get();
+ assertThat(((LoopTemplateLoopElementModel) (loopTemplate.getLoopElementModelsUsed().toArray()[0]))
+ .getLoopElementModel().getName()).isNotEmpty();
+
+ assertThat(policyModelsRepository.findAll().size()).isGreaterThanOrEqualTo(1);
+ assertThat(policyModelsRepository
+ .existsById(new PolicyModelId("onap.policies.monitoring.cdap.tca.hi.lo.app", "1.0.0"))).isTrue();
+ assertThat(policyModelsRepository
+ .getOne((new PolicyModelId("onap.policies.monitoring.cdap.tca.hi.lo.app", "1.0.0")))
+ .getPolicyModelTosca()).isNotBlank();
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/DcaeComponentTest.java b/runtime/src/test/java/org/onap/policy/clamp/loop/DcaeComponentTest.java
new file mode 100644
index 000000000..c95725457
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/DcaeComponentTest.java
@@ -0,0 +1,189 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.util.List;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.json.simple.parser.ParseException;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.onap.policy.clamp.clds.model.dcae.DcaeInventoryResponse;
+import org.onap.policy.clamp.clds.model.dcae.DcaeOperationStatusResponse;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.loop.components.external.DcaeComponent;
+import org.onap.policy.clamp.loop.components.external.ExternalComponentState;
+import org.onap.policy.clamp.loop.template.LoopTemplate;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+
+public class DcaeComponentTest {
+
+ private Loop createTestLoop() {
+ Loop loopTest = new Loop("ControlLoopTest");
+ loopTest.setGlobalPropertiesJson(
+ new Gson().fromJson(
+ "{\"dcaeDeployParameters\":{\"uniqueBlueprintParameters\": {\"policy_id\": \"name\"}}}",
+ JsonObject.class));
+ loopTest.setLastComputedState(LoopState.DESIGN);
+ loopTest.setDcaeDeploymentId("123456789");
+ loopTest.setDcaeDeploymentStatusUrl("http://localhost:8085");
+
+ MicroServicePolicy microServicePolicy = new MicroServicePolicy("configPolicyTest", new PolicyModel("policy1",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0"), true,
+ new Gson().fromJson("{\"configtype\":\"json\"}", JsonObject.class), null, null, null);
+ microServicePolicy.setConfigurationsJson(new Gson().fromJson("{\"param1\":\"value1\"}", JsonObject.class));
+
+ loopTest.addMicroServicePolicy(microServicePolicy);
+ LoopTemplate loopTemplate = new LoopTemplate("test", "yaml", 1, null);
+ loopTemplate.setDcaeBlueprintId("UUID-blueprint");
+ loopTest.setLoopTemplate(loopTemplate);
+
+ return loopTest;
+ }
+
+ /**
+ * Test the DcaeReponse roughly.
+ *
+ * @throws IOException In case of issues
+ */
+ @Test
+ public void convertDcaeResponseTest() throws IOException {
+ String dcaeFakeResponse = "{'requestId':'testId','operationType':'install','status':'state',"
+ + "'error':'errorMessage', 'links':{'self':'selfUrl','uninstall':'uninstallUrl'}}";
+ DcaeOperationStatusResponse responseObject = DcaeComponent.convertDcaeResponse(dcaeFakeResponse);
+ assertThat(responseObject.getRequestId()).isEqualTo("testId");
+ assertThat(responseObject.getOperationType()).isEqualTo("install");
+ assertThat(responseObject.getStatus()).isEqualTo("state");
+ assertThat(responseObject.getError()).isEqualTo("errorMessage");
+ assertThat(responseObject.getLinks()).isNotNull();
+ assertThat(responseObject.getLinks().getSelf()).isEqualTo("selfUrl");
+ assertThat(responseObject.getLinks().getUninstall()).isEqualTo("uninstallUrl");
+
+ assertThat(responseObject.getLinks().getStatus()).isNull();
+ }
+
+ @Test
+ public void testGetDeployPayload() throws IOException {
+ Loop loop = this.createTestLoop();
+ String deploymentPayload = DcaeComponent.getDeployPayload(loop);
+ String expectedPayload = "{\"serviceTypeId\":\"UUID-blueprint\",\"inputs\":{\"policy_id\":\"name\"}}";
+ assertThat(deploymentPayload).isEqualTo(expectedPayload);
+ }
+
+ @Test
+ public void testGetUndeployPayload() throws IOException {
+ Loop loop = this.createTestLoop();
+ String unDeploymentPayload = DcaeComponent.getUndeployPayload(loop);
+ String expectedPayload = "{\"serviceTypeId\":\"UUID-blueprint\"}";
+ assertThat(unDeploymentPayload).isEqualTo(expectedPayload);
+ }
+
+ /**
+ * Test the computeState method of the DcaeComponent roughly.
+ *
+ * @throws IOException In case of issues
+ */
+ @Test
+ public void computeStateTest() throws IOException {
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+ Exchange exchange2 = Mockito.mock(Exchange.class);
+ Mockito.when(exchange.getIn()).thenReturn(message);
+ Mockito.when(message.getExchange()).thenReturn(exchange2);
+ Mockito.when(exchange2.getProperty("dcaeResponse")).thenReturn(null);
+
+ DcaeComponent dcae = new DcaeComponent();
+
+ // initial state
+ ExternalComponentState state = dcae.computeState(exchange);
+ assertThat(state.getStateName()).isEqualTo("BLUEPRINT_DEPLOYED");
+
+ // OperationalType = install
+ DcaeOperationStatusResponse dcaeResponse = Mockito.mock(DcaeOperationStatusResponse.class);
+ Mockito.when(dcaeResponse.getOperationType()).thenReturn("install");
+
+ Mockito.when(dcaeResponse.getStatus()).thenReturn("succeeded");
+ Mockito.when(exchange2.getProperty("dcaeResponse")).thenReturn(dcaeResponse);
+ ExternalComponentState state2 = dcae.computeState(exchange);
+ assertThat(state2.getStateName()).isEqualTo("MICROSERVICE_INSTALLED_SUCCESSFULLY");
+ Mockito.when(dcaeResponse.getStatus()).thenReturn("processing");
+ ExternalComponentState state3 = dcae.computeState(exchange);
+ assertThat(state3.getStateName()).isEqualTo("PROCESSING_MICROSERVICE_INSTALLATION");
+
+ Mockito.when(dcaeResponse.getStatus()).thenReturn("failed");
+ ExternalComponentState state4 = dcae.computeState(exchange);
+ assertThat(state4.getStateName()).isEqualTo("MICROSERVICE_INSTALLATION_FAILED");
+
+ // OperationalType = uninstall
+ Mockito.when(dcaeResponse.getOperationType()).thenReturn("uninstall");
+
+ Mockito.when(dcaeResponse.getStatus()).thenReturn("succeeded");
+ Mockito.when(exchange2.getProperty("dcaeResponse")).thenReturn(dcaeResponse);
+ ExternalComponentState state5 = dcae.computeState(exchange);
+ assertThat(state5.getStateName()).isEqualTo("MICROSERVICE_UNINSTALLED_SUCCESSFULLY");
+
+ Mockito.when(dcaeResponse.getStatus()).thenReturn("processing");
+ ExternalComponentState state6 = dcae.computeState(exchange);
+ assertThat(state6.getStateName()).isEqualTo("PROCESSING_MICROSERVICE_UNINSTALLATION");
+
+ Mockito.when(dcaeResponse.getStatus()).thenReturn("failed");
+ ExternalComponentState state7 = dcae.computeState(exchange);
+ assertThat(state7.getStateName()).isEqualTo("MICROSERVICE_UNINSTALLATION_FAILED");
+
+ // error cases
+ Mockito.when(dcaeResponse.getOperationType()).thenReturn("whatever");
+ ExternalComponentState state8 = dcae.computeState(exchange);
+ assertThat(state8.getStateName()).isEqualTo("IN_ERROR");
+
+ Mockito.when(dcaeResponse.getOperationType()).thenReturn("install");
+ Mockito.when(dcaeResponse.getStatus()).thenReturn("anythingelse");
+ ExternalComponentState state9 = dcae.computeState(exchange);
+ assertThat(state9.getStateName()).isEqualTo("IN_ERROR");
+ }
+
+ /**
+ * Test the Converter to DcaeInventoryResponse method.
+ *
+ * @throws IOException In case of failure
+ * @throws ParseException In case of failure
+ */
+ @Test
+ public void convertToDcaeInventoryResponseTest() throws IOException, ParseException {
+
+ List<DcaeInventoryResponse> responseObject = DcaeComponent
+ .convertToDcaeInventoryResponse(
+ ResourceFileUtils.getResourceAsString("example/dcae/inventory-response.json"));
+ assertThat(responseObject.get(0).getAsdcResourceId()).isEqualTo("testAsdcResourceId");
+ assertThat(responseObject.get(0).getAsdcServiceId()).isEqualTo("testAsdcServiceId");
+ assertThat(responseObject.get(0).getTypeName()).isEqualTo("testTypeName");
+ assertThat(responseObject.get(0).getTypeId()).isEqualTo("testTypeId");
+ assertThat(responseObject.get(0).getBlueprintTemplate()).isEqualTo("testBlueprintTemplate");
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/DeployFlowTestItCase.java b/runtime/src/test/java/org/onap/policy/clamp/loop/DeployFlowTestItCase.java
new file mode 100644
index 000000000..4d02b10dc
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/DeployFlowTestItCase.java
@@ -0,0 +1,321 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
+import java.io.IOException;
+import java.util.Set;
+import javax.transaction.Transactional;
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.builder.ExchangeBuilder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.Application;
+import org.onap.policy.clamp.loop.template.LoopTemplate;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.loop.template.PolicyModelsService;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class DeployFlowTestItCase {
+ private Gson gson = new Gson();
+
+ @Autowired
+ CamelContext camelContext;
+
+ @Autowired
+ PolicyModelsService policyModelsService;
+
+ @Autowired
+ LoopService loopService;
+
+ @Autowired
+ LoopsRepository loopsRepository;
+
+ /**
+ * This method tests a deployment a single blueprint.
+ *
+ * @throws JsonSyntaxException In case of issues
+ * @throws IOException In case of issues
+ */
+ @Test
+ @Transactional
+ public void deployWithSingleBlueprintTest() throws JsonSyntaxException, IOException {
+ Loop loopTest = createLoop("ControlLoopTest", "yamlcontent",
+ "{\"dcaeDeployParameters\":{\"uniqueBlueprintParameters\": {\"policy_id\": \"name\"}}}",
+ "UUID-blueprint");
+ LoopTemplate template = new LoopTemplate();
+ template.setName("templateName");
+ template.setBlueprint("yamlcontent");
+ loopTest.setLoopTemplate(template);
+ MicroServicePolicy microServicePolicy = getMicroServicePolicy("configPolicyTest", "",
+ "{\"configtype\":\"json\"}", "tosca_definitions_version: tosca_simple_yaml_1_0_0",
+ "{\"param1\":\"value1\"}", true);
+ loopTest.addMicroServicePolicy(microServicePolicy);
+ loopService.saveOrUpdateLoop(loopTest);
+ Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext).withProperty("loopObject", loopTest)
+ .build();
+
+ camelContext.createProducerTemplate().send("direct:deploy-loop", myCamelExchange);
+
+ Loop loopAfterTest = loopService.getLoop("ControlLoopTest");
+ assertThat(loopAfterTest.getDcaeDeploymentStatusUrl()).isNotNull();
+ assertThat(loopAfterTest.getDcaeDeploymentId()).isNotNull();
+ }
+
+ /**
+ * This method tests the deployment of multiple separated blueprints.
+ *
+ * @throws JsonSyntaxException In case of issues
+ * @throws IOException In case of issues
+ */
+ @Test
+ @Transactional
+ public void deployWithMultipleBlueprintTest() throws JsonSyntaxException, IOException {
+ Loop loopTest2 = createLoop("ControlLoopTest2", "yamlcontent", "{\"dcaeDeployParameters\": {"
+ + "\"microService1\": {\"location_id\": \"\", \"policy_id\": \"TCA_ResourceInstanceName1_tca\"},"
+ + "\"microService2\": {\"location_id\": \"\", \"policy_id\": \"TCA_ResourceInstanceName2_tca\"}"
+ + "}}", "UUID-blueprint");
+ LoopTemplate template = new LoopTemplate();
+ template.setName("templateName");
+ loopTest2.setLoopTemplate(template);
+ MicroServicePolicy microServicePolicy1 = getMicroServicePolicy("microService1", "", "{\"configtype\":\"json\"}",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", "{\"param1\":\"value1\"}", true);
+ MicroServicePolicy microServicePolicy2 = getMicroServicePolicy("microService2", "", "{\"configtype\":\"json\"}",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", "{\"param1\":\"value1\"}", true);
+ loopTest2.addMicroServicePolicy(microServicePolicy1);
+ loopTest2.addMicroServicePolicy(microServicePolicy2);
+ loopsRepository.saveAndFlush(loopTest2);
+ Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext).withProperty("loopObject", loopTest2)
+ .build();
+
+ camelContext.createProducerTemplate().send("direct:deploy-loop", myCamelExchange);
+
+ Loop loopAfterTest = loopService.getLoop("ControlLoopTest2");
+ Set<MicroServicePolicy> policyList = loopAfterTest.getMicroServicePolicies();
+ for (MicroServicePolicy policy : policyList) {
+ assertThat(policy.getDcaeDeploymentStatusUrl()).isNotNull();
+ assertThat(policy.getDcaeDeploymentId()).isNotNull();
+ }
+ assertThat(loopAfterTest.getDcaeDeploymentStatusUrl()).isNull();
+ assertThat(loopAfterTest.getDcaeDeploymentId()).isNull();
+ }
+
+ /**
+ * This method tests the undeployment of a single blueprint.
+ *
+ * @throws JsonSyntaxException In case of issues
+ * @throws IOException In case of issues
+ */
+ @Test
+ @Transactional
+ public void undeployWithSingleBlueprintTest() throws JsonSyntaxException, IOException {
+ Loop loopTest = createLoop("ControlLoopTest", "yamlcontent", "{\"testname\":\"testvalue\"}",
+ "UUID-blueprint");
+ LoopTemplate template = new LoopTemplate();
+ template.setName("templateName");
+ template.setBlueprint("yamlcontent");
+ loopTest.setLoopTemplate(template);
+ loopTest.setDcaeDeploymentId("testDeploymentId");
+ loopTest.setDcaeDeploymentStatusUrl("testUrl");
+ MicroServicePolicy microServicePolicy = getMicroServicePolicy("configPolicyTest", "",
+ "{\"configtype\":\"json\"}", "tosca_definitions_version: tosca_simple_yaml_1_0_0",
+ "{\"param1\":\"value1\"}", true);
+ loopTest.addMicroServicePolicy(microServicePolicy);
+ loopService.saveOrUpdateLoop(loopTest);
+ Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext).withProperty("loopObject", loopTest)
+ .build();
+
+ camelContext.createProducerTemplate().send("direct:undeploy-loop", myCamelExchange);
+
+ Loop loopAfterTest = loopService.getLoop("ControlLoopTest");
+ assertThat(loopAfterTest.getDcaeDeploymentStatusUrl().contains("/uninstall")).isTrue();
+ assertThat(loopAfterTest.getDcaeDeploymentId()).isNull();
+ }
+
+ /**
+ * This method tests the undeployment of multiple separated blueprints.
+ *
+ * @throws JsonSyntaxException In case of issues
+ * @throws IOException In case of issues
+ */
+ @Test
+ @Transactional
+ public void undeployWithMultipleBlueprintTest() throws JsonSyntaxException, IOException {
+ Loop loopTest2 = createLoop("ControlLoopTest2", "yamlcontent", "{\"dcaeDeployParameters\": {"
+ + "\"microService1\": {\"location_id\": \"\", \"policy_id\": \"TCA_ResourceInstanceName1_tca\"},"
+ + "\"microService2\": {\"location_id\": \"\", \"policy_id\": \"TCA_ResourceInstanceName2_tca\"}"
+ + "}}", "UUID-blueprint");
+ LoopTemplate template = new LoopTemplate();
+ template.setName("templateName");
+ loopTest2.setLoopTemplate(template);
+ MicroServicePolicy microServicePolicy1 = getMicroServicePolicy("microService1", "", "{\"configtype\":\"json\"}",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", "{\"param1\":\"value1\"}", true,
+ "testDeploymentId1", "testDeploymentStatusUrl1");
+ MicroServicePolicy microServicePolicy2 = getMicroServicePolicy("microService2", "", "{\"configtype\":\"json\"}",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", "{\"param1\":\"value1\"}", true,
+ "testDeploymentId2", "testDeploymentStatusUrl2");
+ loopTest2.addMicroServicePolicy(microServicePolicy1);
+ loopTest2.addMicroServicePolicy(microServicePolicy2);
+ loopsRepository.saveAndFlush(loopTest2);
+ Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext).withProperty("loopObject", loopTest2)
+ .build();
+
+ camelContext.createProducerTemplate().send("direct:undeploy-loop", myCamelExchange);
+
+ Loop loopAfterTest = loopService.getLoop("ControlLoopTest2");
+ Set<MicroServicePolicy> policyList = loopAfterTest.getMicroServicePolicies();
+ for (MicroServicePolicy policy : policyList) {
+ assertThat(policy.getDcaeDeploymentStatusUrl().contains("/uninstall")).isTrue();
+ assertThat(policy.getDcaeDeploymentId()).isNull();
+
+ }
+ assertThat(loopAfterTest.getDcaeDeploymentStatusUrl()).isNull();
+ assertThat(loopAfterTest.getDcaeDeploymentId()).isNull();
+ }
+
+ /**
+ * This method tests the DCAE get status for a single blueprint.
+ *
+ * @throws JsonSyntaxException In case of issues
+ * @throws IOException In case of issues
+ */
+ @Test
+ @Transactional
+ public void getStatusWithSingleBlueprintTest() throws JsonSyntaxException, IOException {
+ Loop loopTest = createLoop("ControlLoopTest", "yamlcontent", "{\"testname\":\"testvalue\"}",
+ "UUID-blueprint");
+ LoopTemplate template = new LoopTemplate();
+ template.setName("templateName");
+ template.setBlueprint("yamlcontent");
+ loopTest.setLoopTemplate(template);
+ MicroServicePolicy microServicePolicy = getMicroServicePolicy("configPolicyTest", "",
+ "{\"configtype\":\"json\"}", "tosca_definitions_version: tosca_simple_yaml_1_0_0",
+ "{\"param1\":\"value1\"}", true);
+ loopTest.addMicroServicePolicy(microServicePolicy);
+ loopService.saveOrUpdateLoop(loopTest);
+ assertThat(loopTest.getComponents().size()).isEqualTo(2);
+ assertThat(loopTest.getComponent("DCAE")).isNotNull();
+ assertThat(loopTest.getComponent("POLICY")).isNotNull();
+ Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext).withProperty("loopObject", loopTest)
+ .build();
+
+ camelContext.createProducerTemplate().send("direct:update-dcae-status-for-loop", myCamelExchange);
+
+ assertThat(loopTest.getComponent("DCAE").getState().getStateName()).isEqualTo("BLUEPRINT_DEPLOYED");
+
+ Loop loopAfterTest = loopService.getLoop("ControlLoopTest");
+ assertThat(loopAfterTest.getComponents().size()).isEqualTo(2);
+ assertThat(loopAfterTest.getComponent("DCAE")).isNotNull();
+ assertThat(loopAfterTest.getComponent("POLICY")).isNotNull();
+ }
+
+ /**
+ * This method tests the dcae get status for multiple blueprints.
+ *
+ * @throws JsonSyntaxException In case of issues
+ * @throws IOException In case of issues
+ */
+ @Test
+ @Transactional
+ public void getStatusWithMultipleBlueprintTest() throws JsonSyntaxException, IOException {
+ Loop loopTest = createLoop("ControlLoopTest", "yamlcontent", "{\"testname\":\"testvalue\"}",
+ "UUID-blueprint");
+ LoopTemplate template = new LoopTemplate();
+ template.setName("templateName");
+ loopTest.setLoopTemplate(template);
+ MicroServicePolicy microServicePolicy = getMicroServicePolicy("configPolicyTest", "",
+ "{\"configtype\":\"json\"}", "tosca_definitions_version: tosca_simple_yaml_1_0_0",
+ "{\"param1\":\"value1\"}", true);
+ MicroServicePolicy microServicePolicy2 = getMicroServicePolicy("configPolicyTest2", "",
+ "{\"configtype\":\"json\"}", "tosca_definitions_version: tosca_simple_yaml_1_0_0",
+ "{\"param1\":\"value1\"}", true);
+ loopTest.addMicroServicePolicy(microServicePolicy);
+ loopTest.addMicroServicePolicy(microServicePolicy2);
+ loopService.saveOrUpdateLoop(loopTest);
+ assertThat(loopTest.getComponents().size()).isEqualTo(3);
+ assertThat(loopTest.getComponent("DCAE")).isNull();
+ assertThat(loopTest.getComponent("DCAE_configPolicyTest")).isNotNull();
+ assertThat(loopTest.getComponent("DCAE_configPolicyTest2")).isNotNull();
+ assertThat(loopTest.getComponent("POLICY")).isNotNull();
+ Exchange myCamelExchange = ExchangeBuilder.anExchange(camelContext).withProperty("loopObject", loopTest)
+ .build();
+
+ camelContext.createProducerTemplate().send("direct:update-dcae-status-for-loop", myCamelExchange);
+
+ assertThat(loopTest.getComponent("DCAE_configPolicyTest").getState().getStateName())
+ .isEqualTo("BLUEPRINT_DEPLOYED");
+ assertThat(loopTest.getComponent("DCAE_configPolicyTest2").getState().getStateName())
+ .isEqualTo("BLUEPRINT_DEPLOYED");
+
+ Loop loopAfterTest = loopService.getLoop("ControlLoopTest");
+ assertThat(loopAfterTest.getComponents().size()).isEqualTo(3);
+ assertThat(loopAfterTest.getComponent("DCAE")).isNull();
+ assertThat(loopAfterTest.getComponent("POLICY")).isNotNull();
+ assertThat(loopTest.getComponent("DCAE_configPolicyTest")).isNotNull();
+ assertThat(loopTest.getComponent("DCAE_configPolicyTest2")).isNotNull();
+ }
+
+ private Loop createLoop(String name, String blueprint, String globalPropertiesJson,
+ String dcaeBlueprintId) throws JsonSyntaxException, IOException {
+ Loop loop = new Loop(name);
+ loop.setGlobalPropertiesJson(new Gson().fromJson(globalPropertiesJson, JsonObject.class));
+ loop.setLastComputedState(LoopState.DESIGN);
+ return loop;
+ }
+
+ private MicroServicePolicy getMicroServicePolicy(String name, String modelType, String jsonRepresentation,
+ String policyTosca, String jsonProperties, boolean shared) {
+
+ PolicyModel policyModel = new PolicyModel(modelType, policyTosca, "1.0.0");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel);
+ MicroServicePolicy microService = new MicroServicePolicy(name, policyModel,
+ shared,
+ gson.fromJson(jsonRepresentation, JsonObject.class), null, null, null);
+
+ microService.setConfigurationsJson(new Gson().fromJson(jsonProperties, JsonObject.class));
+ return microService;
+ }
+
+ private MicroServicePolicy getMicroServicePolicy(String name, String modelType, String jsonRepresentation,
+ String policyTosca, String jsonProperties, boolean shared,
+ String deploymengId,
+ String deploymentStatusUrl) {
+ MicroServicePolicy microService = getMicroServicePolicy(name, modelType, jsonRepresentation, policyTosca,
+ jsonProperties, shared);
+
+ microService.setDcaeDeploymentId(deploymengId);
+ microService.setDcaeDeploymentStatusUrl(deploymentStatusUrl);
+ return microService;
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/ExternalComponentStateTest.java b/runtime/src/test/java/org/onap/policy/clamp/loop/ExternalComponentStateTest.java
new file mode 100644
index 000000000..a73b2784b
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/ExternalComponentStateTest.java
@@ -0,0 +1,82 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+import org.onap.policy.clamp.loop.components.external.ExternalComponentState;
+
+public class ExternalComponentStateTest {
+ private ExternalComponentState state = new ExternalComponentState("NOT_SENT",
+ "The policies defined have NOT yet been created on the policy engine", 90);
+
+ @Test
+ public void generalTest() {
+ assertThat(state.toString()).isEqualTo("NOT_SENT");
+ state.setLevel(70);
+ assertThat(state.getLevel()).isEqualTo(70);
+ }
+
+ @Test
+ public void equalsTest() {
+ assertThat(state.equals(null)).isEqualTo(false);
+
+ ExternalComponentState state2 = new ExternalComponentState("NOT_SENT",
+ "The policies defined have NOT yet been created on the policy engine", 90);
+ assertThat(state.equals(state2)).isEqualTo(true);
+
+ assertThat(state.equals(12)).isEqualTo(false);
+
+ state2.setLevel(70);
+ assertThat(state.equals(state2)).isEqualTo(true);
+
+ ExternalComponentState state3 = new ExternalComponentState("SENT",
+ "The policies defined have NOT yet been created on the policy engine", 90);
+ assertThat(state.equals(state3)).isEqualTo(false);
+
+ ExternalComponentState state4 = new ExternalComponentState(null,
+ "The policies defined have NOT yet been created on the policy engine", 90);
+ ExternalComponentState state5 = new ExternalComponentState(null,
+ "The policies defined have NOT yet been", 50);
+ assertThat(state4.equals(state3)).isEqualTo(false);
+ assertThat(state4.equals(state5)).isEqualTo(true);
+ }
+
+ @Test
+ public void compareToTest() {
+ ExternalComponentState state2 = new ExternalComponentState("NOT_SENT",
+ "The policies defined have NOT yet been created on the policy engine", 90);
+ assertThat(state.compareTo(state2)).isEqualTo(0);
+
+ ExternalComponentState state3 = new ExternalComponentState("SENT",
+ "The policies defined have NOT yet been created on the policy engine", 50);
+ assertThat(state.compareTo(state3)).isEqualTo(1);
+
+ ExternalComponentState state4 = new ExternalComponentState(null,
+ "The policies defined have NOT yet been created on the policy engine", 100);
+ assertThat(state.compareTo(state4)).isEqualTo(-1);
+
+ }
+} \ No newline at end of file
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/LoopControllerTestItCase.java b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopControllerTestItCase.java
new file mode 100644
index 000000000..6728d292c
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopControllerTestItCase.java
@@ -0,0 +1,175 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright (C) 2019 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import java.io.IOException;
+import java.util.Set;
+import javax.transaction.Transactional;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.Application;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.loop.service.Service;
+import org.onap.policy.clamp.loop.template.LoopTemplate;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.loop.template.PolicyModelsService;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicyService;
+import org.onap.policy.clamp.policy.operational.OperationalPolicy;
+import org.onap.policy.clamp.policy.operational.OperationalPolicyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class LoopControllerTestItCase {
+
+ private static final String EXAMPLE_LOOP_NAME = "ClosedLoopTest";
+ private static final String EXAMPLE_JSON = "{\"testName\":\"testValue\"}";
+
+ @Autowired
+ LoopService loopService;
+
+ @Autowired
+ LoopsRepository loopsRepository;
+
+ @Autowired
+ MicroServicePolicyService microServicePolicyService;
+
+ @Autowired
+ OperationalPolicyService operationalPolicyService;
+
+ @Autowired
+ PolicyModelsService policyModelsService;
+
+ @Autowired
+ LoopController loopController;
+
+ private void saveTestLoopToDb() {
+ Loop testLoop = createTestLoop(EXAMPLE_LOOP_NAME, "blueprint", "representation");
+ testLoop.setGlobalPropertiesJson(JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class));
+ LoopTemplate template = new LoopTemplate();
+ template.setName("testTemplate");
+ testLoop.setLoopTemplate(template);
+ Service modelService = new Service("{\"name\":\"serviceName\",\"UUID\":\"uuid\"}", "{}");
+ testLoop.setModelService(modelService);
+ loopService.saveOrUpdateLoop(testLoop);
+ }
+
+ private Loop createTestLoop(String loopName, String loopBlueprint, String loopSvg) {
+ return new Loop(loopName);
+ }
+
+ @Test
+ @Transactional
+ public void testUpdateOperationalPolicies() {
+ saveTestLoopToDb();
+ String policy = "[{\"name\":\"OPERATIONAL_CLholmes31_v1_0_vFW_PG_T10_k8s-holmes-rules\","
+ + "\"configurationsJson\":{"
+ + "\"operational_policy\":{\"controlLoop\":{\"trigger_policy\":\"unique-policy-id-1-modifyConfig\","
+ + "\"timeout\":\"3600\",\"abatement\":\"false\","
+ + "\"controlLoopName\":\"LOOP_CLholmes31_v1_0_vFW_PG_T10_k8s-holmes-rules\"},"
+ + "\"policies\":[{\"id\":\"unique-policy-id-1-modifyConfig\",\"recipe\":\"ModifyConfig\","
+ + "\"retry\":\"2\",\"timeout\":\"1200\",\"actor\":\"APPC\",\"payload\":\"{\\\"active-streams\\\":5}\","
+ + "\"success\":\"\",\"failure\":\"\",\"failure_timeout\":\"\",\"failure_retries\":\"\","
+ + "\"failure_exception\":\"\",\"failure_guard\":\"\",\"target\":{\"type\":\"VNF\","
+ + "\"resourceID\":\"vFW_PG_T1\"}}]}}}]";
+ JsonParser parser = new JsonParser();
+ JsonElement ele = parser.parse(policy);
+ JsonArray arr = ele.getAsJsonArray();
+ Loop loop = loopController.updateOperationalPolicies(EXAMPLE_LOOP_NAME, arr);
+ assertThat(loop.getOperationalPolicies()).hasSize(1);
+ Set<OperationalPolicy> opSet = loop.getOperationalPolicies();
+ OperationalPolicy op = opSet.iterator().next();
+ assertThat(op.getName()).isEqualTo("OPERATIONAL_CLholmes31_v1_0_vFW_PG_T10_k8s-holmes-rules");
+ }
+
+ @Test
+ @Transactional
+ public void testUpdateGlobalProperties() {
+ saveTestLoopToDb();
+ String policy = "{\"dcaeDeployParameters\":{\"aaiEnrichmentHost\":\"aai.onap.svc.cluster.local\","
+ + "\"aaiEnrichmentPort\":\"8443\",\"enableAAIEnrichment\":\"false\",\"dmaap_host\":\"message-router"
+ + ".onap\",\"dmaap_port\":\"3904\",\"enableRedisCaching\":\"false\",\"redisHosts\":\"dcae-redis.onap"
+ + ".svc.cluster.local:6379\",\"tag_version\":\"nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments"
+ + ".tca-cdap-container:1.1.1\",\"consul_host\":\"consul-server.onap\",\"consul_port\":\"8500\","
+ + "\"cbs_host\":\"config-binding-service\",\"cbs_port\":\"10000\",\"external_port\":\"32012\","
+ + "\"policy_model_id\":\"onap.policies.monitoring.cdap.tca.hi.lo.app\","
+ + "\"policy_id\":\"tca_k8s_CLTCA_v1_0_vFW_PG_T10_k8s-tca-clamp-policy-05162019\"}}";
+ JsonParser parser = new JsonParser();
+ JsonElement ele = parser.parse(policy);
+ JsonObject obj = ele.getAsJsonObject();
+ loopController.updateGlobalPropertiesJson(EXAMPLE_LOOP_NAME, obj);
+ Loop loop = loopController.getLoop(EXAMPLE_LOOP_NAME);
+ JsonObject globalPropertiesJson = loop.getGlobalPropertiesJson();
+ JsonObject prop = globalPropertiesJson.getAsJsonObject("dcaeDeployParameters");
+ assertThat(prop.get("aaiEnrichmentHost").getAsString()).isEqualTo("aai.onap.svc.cluster.local");
+ }
+
+ @Test
+ @Transactional
+ public void testUpdateMicroservicePolicy() {
+ saveTestLoopToDb();
+ PolicyModel policyModel = new PolicyModel("testPolicyModel",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel);
+ MicroServicePolicy policy = new MicroServicePolicy("policyName", policyModel, false,
+ JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null);
+ loopController.updateMicroservicePolicy(EXAMPLE_LOOP_NAME, policy);
+ assertThat(microServicePolicyService.isExisting("policyName")).isTrue();
+ }
+
+ @Test
+ @Transactional
+ public void testAddAndRemoveOperationalPolicies() throws IOException {
+ saveTestLoopToDb();
+ PolicyModel policyModel = new PolicyModel("testPolicyModel",
+ null, "1.0.0");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel);
+
+ loopController.addOperationalPolicy(EXAMPLE_LOOP_NAME, "testPolicyModel", "1.0.0");
+
+ Loop newLoop = loopController.getLoop(EXAMPLE_LOOP_NAME);
+ Set<OperationalPolicy> opPolicyList = newLoop.getOperationalPolicies();
+ assertThat(opPolicyList.size()).isEqualTo(1);
+ for (OperationalPolicy policy : opPolicyList) {
+ assertThat(policy.getName().contains("OPERATIONAL_serviceName")).isTrue();
+ Assertions.assertThat(policy.getPolicyModel().getPolicyModelType()).isEqualTo("testPolicyModel");
+ Assertions.assertThat(policy.getPolicyModel().getVersion()).isEqualTo("1.0.0");
+ }
+
+ loopController.removeOperationalPolicy(EXAMPLE_LOOP_NAME, "testPolicyModel", "1.0.0");
+ Loop newLoop2 = loopController.getLoop(EXAMPLE_LOOP_NAME);
+ assertThat(newLoop2.getOperationalPolicies().size()).isEqualTo(0);
+ }
+} \ No newline at end of file
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/LoopLogServiceTestItCase.java b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopLogServiceTestItCase.java
new file mode 100644
index 000000000..7b0ab8614
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopLogServiceTestItCase.java
@@ -0,0 +1,96 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Huawei Technologies Co., Ltd.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.JsonObject;
+import java.util.Set;
+import javax.transaction.Transactional;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.Application;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.loop.log.LogType;
+import org.onap.policy.clamp.loop.log.LoopLog;
+import org.onap.policy.clamp.loop.log.LoopLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class LoopLogServiceTestItCase {
+
+ private static final String EXAMPLE_LOOP_NAME = "ClosedLoopTest";
+ private static final String EXAMPLE_JSON = "{\"testName\":\"testValue\"}";
+ private static final String CLAMP_COMPONENT = "CLAMP";
+ private static final String SAMPLE_LOG_MESSAGE = "Sample log";
+ private static final String BLUEPRINT = "blueprint";
+
+ @Autowired
+ LoopService loopService;
+
+ @Autowired
+ LoopsRepository loopsRepository;
+
+ @Autowired
+ LoopLogService loopLogService;
+
+ private void saveTestLoopToDb() {
+ Loop testLoop = new Loop(EXAMPLE_LOOP_NAME);
+ testLoop.setGlobalPropertiesJson(JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class));
+ loopService.saveOrUpdateLoop(testLoop);
+ }
+
+ @Test
+ @Transactional
+ public void testAddLog() {
+ saveTestLoopToDb();
+ Loop loop = loopService.getLoop(EXAMPLE_LOOP_NAME);
+ loopLogService.addLog(SAMPLE_LOG_MESSAGE, "INFO", loop);
+ Set<LoopLog> loopLogs = loop.getLoopLogs();
+ assertThat(loopLogs).hasSize(1);
+ LoopLog loopLog = loopLogs.iterator().next();
+ assertThat(loopLog.getMessage()).isEqualTo(SAMPLE_LOG_MESSAGE);
+ }
+
+ @Test
+ @Transactional
+ public void testLoopLog() {
+ LoopLog log = new LoopLog();
+ Long id = Long.valueOf(100);
+ log.setId(id);
+ log.setLogComponent(CLAMP_COMPONENT);
+ log.setLogType(LogType.INFO);
+ log.setMessage(SAMPLE_LOG_MESSAGE);
+ Loop testLoop = new Loop(EXAMPLE_LOOP_NAME);
+ log.setLoop(testLoop);
+ assertThat(log.getMessage()).isEqualTo(SAMPLE_LOG_MESSAGE);
+ assertThat(log.getLogType()).isEqualTo(LogType.INFO);
+ assertThat(log.getLogComponent()).isEqualTo(CLAMP_COMPONENT);
+ assertThat(log.getId()).isEqualTo(id);
+ Assertions.assertThat(log.getLoop()).isEqualTo(testLoop);
+ }
+} \ No newline at end of file
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/LoopRepositoriesItCase.java b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopRepositoriesItCase.java
new file mode 100644
index 000000000..e18dd2475
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopRepositoriesItCase.java
@@ -0,0 +1,258 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import java.time.Instant;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.Application;
+import org.onap.policy.clamp.loop.log.LogType;
+import org.onap.policy.clamp.loop.log.LoopLog;
+import org.onap.policy.clamp.loop.log.LoopLogRepository;
+import org.onap.policy.clamp.loop.service.Service;
+import org.onap.policy.clamp.loop.service.ServicesRepository;
+import org.onap.policy.clamp.loop.template.LoopElementModel;
+import org.onap.policy.clamp.loop.template.LoopElementModelsRepository;
+import org.onap.policy.clamp.loop.template.LoopTemplate;
+import org.onap.policy.clamp.loop.template.LoopTemplatesRepository;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.loop.template.PolicyModelId;
+import org.onap.policy.clamp.loop.template.PolicyModelsRepository;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicyService;
+import org.onap.policy.clamp.policy.operational.OperationalPolicy;
+import org.onap.policy.clamp.policy.operational.OperationalPolicyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@SpringBootTest(classes = Application.class)
+public class LoopRepositoriesItCase {
+
+ private Gson gson = new GsonBuilder().setPrettyPrinting().excludeFieldsWithoutExposeAnnotation().create();
+
+ @Autowired
+ private LoopsRepository loopRepository;
+
+ @Autowired
+ private MicroServicePolicyService microServicePolicyService;
+
+ @Autowired
+ private OperationalPolicyService operationalPolicyService;
+
+ @Autowired
+ private LoopLogRepository loopLogRepository;
+
+ @Autowired
+ private LoopTemplatesRepository loopTemplateRepository;
+
+ @Autowired
+ private LoopElementModelsRepository microServiceModelsRepository;
+
+ @Autowired
+ private PolicyModelsRepository policyModelsRepository;
+
+ @Autowired
+ private ServicesRepository servicesRepository;
+
+ private Service getService(String serviceDetails, String resourceDetails) {
+ return new Service(serviceDetails, resourceDetails);
+ }
+
+ private OperationalPolicy getOperationalPolicy(String configJson, String name, PolicyModel policyModel) {
+ return new OperationalPolicy(name, null, new Gson().fromJson(configJson, JsonObject.class), policyModel,
+ null, null, null);
+ }
+
+ private LoopElementModel getLoopElementModel(String yaml, String name, String policyType, String createdBy,
+ PolicyModel policyModel) {
+ LoopElementModel model = new LoopElementModel(name, policyType, yaml);
+ model.addPolicyModel(policyModel);
+ return model;
+ }
+
+ private PolicyModel getPolicyModel(String policyType, String policyModelTosca, String version,
+ String policyAcronym) {
+ return new PolicyModel(policyType, policyModelTosca, version, policyAcronym);
+ }
+
+ private LoopTemplate getLoopTemplates(String name, String blueprint, String createdBy,
+ Integer maxInstancesAllowed) {
+ LoopTemplate template = new LoopTemplate(name, blueprint, maxInstancesAllowed, null);
+ template.addLoopElementModel(getLoopElementModel("yaml", "microService1", "org.onap.policy.drools", createdBy,
+ getPolicyModel("org.onap.policy.drools", "yaml", "1.0.0", "Drools")));
+ template.addLoopElementModel(getLoopElementModel("yaml", "oppolicy1", "org.onap.policy.drools.legacy",
+ createdBy, getPolicyModel("org.onap.policy.drools.legacy", "yaml", "1.0.0", "DroolsLegacy")));
+ loopTemplateRepository.save(template);
+ return template;
+ }
+
+ private Loop getLoop(String name, String blueprint, String globalPropertiesJson,
+ String dcaeId, String dcaeUrl, String dcaeBlueprintId) {
+ Loop loop = new Loop();
+ loop.setName(name);
+ loop.setGlobalPropertiesJson(new Gson().fromJson(globalPropertiesJson, JsonObject.class));
+ loop.setLastComputedState(LoopState.DESIGN);
+ loop.setDcaeDeploymentId(dcaeId);
+ loop.setDcaeDeploymentStatusUrl(dcaeUrl);
+ loop.setLoopTemplate(getLoopTemplates("templateName", "yaml", "toto", 1));
+ return loop;
+ }
+
+ private MicroServicePolicy getMicroServicePolicy(String name, String jsonRepresentation, String jsonProperties,
+ boolean shared, PolicyModel policyModel) {
+ MicroServicePolicy microService = new MicroServicePolicy(name, policyModel, shared,
+ gson.fromJson(jsonRepresentation, JsonObject.class), null, null, null);
+ microService.setConfigurationsJson(new Gson().fromJson(jsonProperties, JsonObject.class));
+ return microService;
+ }
+
+ private LoopLog getLoopLog(LogType type, String message, Loop loop) {
+ return new LoopLog(message, type, "CLAMP", loop);
+ }
+
+ /**
+ * This method does a crud test and save a loop template and a loop object in db.
+ */
+ @Test
+ @Transactional
+ public void crudTest() {
+ // Setup
+ Loop loopTest = getLoop("ControlLoopTest", "yamlcontent", "{\"testname\":\"testvalue\"}",
+ "123456789", "https://dcaetest.org", "UUID-blueprint");
+ OperationalPolicy opPolicy = this.getOperationalPolicy("{\"type\":\"GUARD\"}", "GuardOpPolicyTest",
+ getPolicyModel("org.onap.policy.drools.legacy", "yaml", "1.0.0", "DroolsLegacy"));
+ loopTest.addOperationalPolicy(opPolicy);
+ MicroServicePolicy microServicePolicy = getMicroServicePolicy("configPolicyTest", "{\"configtype\":\"json\"}",
+ "{\"param1\":\"value1\"}", true, getPolicyModel("org.onap.policy.drools", "yaml", "1.0.0", "Drools"));
+ loopTest.addMicroServicePolicy(microServicePolicy);
+ LoopLog loopLog = getLoopLog(LogType.INFO, "test message", loopTest);
+ loopTest.addLog(loopLog);
+ Service service = getService(
+ "{\"name\": \"vLoadBalancerMS\", \"UUID\": \"63cac700-ab9a-4115-a74f-7eac85e3fce0\"}", "{\"CP\": {}}");
+ loopTest.setModelService(service);
+
+ // Attempt to save into the database the entire loop
+ Loop loopInDb = loopRepository.save(loopTest);
+ assertThat(loopInDb).isNotNull();
+ assertThat(loopRepository.findById(loopInDb.getName()).get()).isNotNull();
+ assertThat(loopInDb.getCreatedDate()).isNotNull();
+ assertThat(loopInDb.getUpdatedDate()).isNotNull();
+ assertThat(loopInDb.getUpdatedDate()).isEqualTo(loopInDb.getCreatedDate());
+ assertThat(loopInDb.getName()).isEqualTo("ControlLoopTest");
+ // Autogen id so now set the ID in the previous model so that we can compare the
+ // objects
+ loopLog.setId(((LoopLog) loopInDb.getLoopLogs().toArray()[0]).getId());
+
+ assertThat(loopInDb).isEqualToIgnoringGivenFields(loopTest, "components", "createdDate", "updatedDate",
+ "createdBy", "updatedBy");
+ assertThat(loopRepository.existsById(loopTest.getName())).isEqualTo(true);
+ assertThat(operationalPolicyService.isExisting(opPolicy.getName())).isEqualTo(true);
+ assertThat(microServicePolicyService.isExisting(microServicePolicy.getName())).isEqualTo(true);
+ assertThat(loopLogRepository.existsById(loopLog.getId())).isEqualTo(true);
+ assertThat(loopTemplateRepository.existsById(loopInDb.getLoopTemplate().getName())).isEqualTo(true);
+ assertThat(loopTemplateRepository.existsById(loopInDb.getLoopTemplate().getName())).isEqualTo(true);
+ assertThat(servicesRepository.existsById(loopInDb.getModelService().getServiceUuid())).isEqualTo(true);
+ assertThat(microServiceModelsRepository.existsById(
+ loopInDb.getLoopTemplate().getLoopElementModelsUsed().first().getLoopElementModel().getName()))
+ .isEqualTo(true);
+ assertThat(policyModelsRepository.existsById(new PolicyModelId(
+ loopInDb.getLoopTemplate().getLoopElementModelsUsed().first().getLoopElementModel().getPolicyModels()
+ .first().getPolicyModelType(),
+ loopInDb.getLoopTemplate().getLoopElementModelsUsed().first().getLoopElementModel().getPolicyModels()
+ .first().getVersion()))).isEqualTo(true);
+
+ // Now attempt to read from database
+ Loop loopInDbRetrieved = loopRepository.findById(loopTest.getName()).get();
+ assertThat(loopInDbRetrieved).isEqualToIgnoringGivenFields(loopTest, "components", "createdDate", "updatedDate",
+ "createdBy", "updatedBy");
+ assertThat(loopInDbRetrieved).isEqualToComparingOnlyGivenFields(loopInDb, "createdDate", "updatedDate",
+ "createdBy", "updatedBy");
+ assertThat((LoopLog) loopInDbRetrieved.getLoopLogs().toArray()[0]).isEqualToComparingFieldByField(loopLog);
+ assertThat((OperationalPolicy) loopInDbRetrieved.getOperationalPolicies().toArray()[0])
+ .isEqualToIgnoringGivenFields(opPolicy, "createdDate", "updatedDate", "createdBy", "updatedBy");
+ Assertions.assertThat(
+ ((OperationalPolicy) loopInDbRetrieved.getOperationalPolicies().toArray()[0]).getCreatedDate())
+ .isNotNull();
+ Assertions.assertThat(
+ ((OperationalPolicy) loopInDbRetrieved.getOperationalPolicies().toArray()[0]).getUpdatedDate())
+ .isNotNull();
+ Assertions.assertThat(
+ ((OperationalPolicy) loopInDbRetrieved.getOperationalPolicies().toArray()[0]).getCreatedBy())
+ .isNotNull();
+ Assertions.assertThat(
+ ((OperationalPolicy) loopInDbRetrieved.getOperationalPolicies().toArray()[0]).getUpdatedBy())
+ .isNotNull();
+
+ assertThat((MicroServicePolicy) loopInDbRetrieved.getMicroServicePolicies().toArray()[0])
+ .isEqualToIgnoringGivenFields(microServicePolicy, "createdDate", "updatedDate", "createdBy",
+ "updatedBy");
+
+ // Attempt an update
+ ((LoopLog) loopInDbRetrieved.getLoopLogs().toArray()[0]).setLogInstant(Instant.now());
+ loopInDbRetrieved.setLastComputedState(LoopState.RUNNING);
+ Loop loopInDbRetrievedUpdated = loopRepository.saveAndFlush(loopInDbRetrieved);
+ // Loop loopInDbRetrievedUpdated =
+ // loopRepository.findById(loopTest.getName()).get();
+ assertThat((LoopLog) loopInDbRetrievedUpdated.getLoopLogs().toArray()[0])
+ .isEqualToComparingFieldByField(loopInDbRetrieved.getLoopLogs().toArray()[0]);
+ // UpdatedDate should have been changed
+ assertThat(loopInDbRetrievedUpdated.getUpdatedDate()).isNotEqualTo(loopInDbRetrievedUpdated.getCreatedDate());
+ // createdDate should have NOT been changed
+ assertThat(loopInDbRetrievedUpdated.getCreatedDate()).isEqualTo(loopInDb.getCreatedDate());
+ // other audit are the same
+ assertThat(loopInDbRetrievedUpdated.getCreatedBy()).isEqualTo("Not found");
+ assertThat(loopInDbRetrievedUpdated.getUpdatedBy()).isEqualTo("Not found");
+
+ // Attempt to delete the object and check it has well been cascaded
+
+ loopRepository.delete(loopInDbRetrieved);
+ assertThat(loopRepository.existsById(loopTest.getName())).isEqualTo(false);
+ assertThat(operationalPolicyService.isExisting(opPolicy.getName())).isEqualTo(false);
+ assertThat(microServicePolicyService.isExisting(microServicePolicy.getName())).isEqualTo(true);
+ assertThat(loopLogRepository.existsById(loopLog.getId())).isEqualTo(false);
+ assertThat(loopTemplateRepository.existsById(loopInDb.getLoopTemplate().getName())).isEqualTo(true);
+ assertThat(servicesRepository.existsById(loopInDb.getModelService().getServiceUuid())).isEqualTo(true);
+ assertThat(microServiceModelsRepository.existsById(
+ loopInDb.getLoopTemplate().getLoopElementModelsUsed().first().getLoopElementModel().getName()))
+ .isEqualTo(true);
+
+ assertThat(policyModelsRepository.existsById(new PolicyModelId(
+ loopInDb.getLoopTemplate().getLoopElementModelsUsed().first().getLoopElementModel().getPolicyModels()
+ .first().getPolicyModelType(),
+ loopInDb.getLoopTemplate().getLoopElementModelsUsed().first().getLoopElementModel().getPolicyModels()
+ .first().getVersion()))).isEqualTo(true);
+
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/LoopServiceTestItCase.java b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopServiceTestItCase.java
new file mode 100644
index 000000000..74092727c
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopServiceTestItCase.java
@@ -0,0 +1,381 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 Nokia Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.JsonObject;
+import java.util.Set;
+import java.util.stream.Collectors;
+import javax.transaction.Transactional;
+import org.assertj.core.api.Assertions;
+import org.assertj.core.util.Lists;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.Application;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.loop.log.LogType;
+import org.onap.policy.clamp.loop.log.LoopLog;
+import org.onap.policy.clamp.loop.log.LoopLogService;
+import org.onap.policy.clamp.loop.template.LoopTemplate;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.loop.template.PolicyModelsService;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicyService;
+import org.onap.policy.clamp.policy.operational.OperationalPolicy;
+import org.onap.policy.clamp.policy.operational.OperationalPolicyService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class LoopServiceTestItCase {
+
+ private static final String EXAMPLE_LOOP_NAME = "ClosedLoopTest";
+ private static final String EXAMPLE_JSON = "{\"testName\":\"testValue\"}";
+
+ @Autowired
+ LoopService loopService;
+
+ @Autowired
+ LoopsRepository loopsRepository;
+
+ @Autowired
+ MicroServicePolicyService microServicePolicyService;
+
+ @Autowired
+ OperationalPolicyService operationalPolicyService;
+
+ @Autowired
+ LoopLogService loopLogService;
+
+ @Autowired
+ PolicyModelsService policyModelsService;
+
+ @Test
+ @Transactional
+ public void shouldCreateEmptyLoop() {
+ // given
+ String loopBlueprint = "blueprint";
+ Loop testLoop = createTestLoop(EXAMPLE_LOOP_NAME, loopBlueprint);
+ testLoop.setGlobalPropertiesJson(JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class));
+ testLoop.setLastComputedState(LoopState.DESIGN);
+
+ // when
+ Loop actualLoop = loopService.saveOrUpdateLoop(testLoop);
+
+ // then
+ assertThat(actualLoop).isNotNull();
+ assertThat(actualLoop).isEqualTo(loopsRepository.findById(actualLoop.getName()).get());
+ assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+ assertThat(actualLoop.getGlobalPropertiesJson().getAsJsonPrimitive("testName").getAsString())
+ .isEqualTo("testValue");
+ }
+
+ @Test
+ @Transactional
+ public void shouldAddOperationalPolicyToLoop() {
+ // given
+ saveTestLoopToDb();
+ OperationalPolicy operationalPolicy = new OperationalPolicy("policyName", null,
+ JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null, null);
+
+ // when
+ Loop actualLoop = loopService.updateAndSaveOperationalPolicies(EXAMPLE_LOOP_NAME,
+ Lists.newArrayList(operationalPolicy));
+
+ // then
+ assertThat(actualLoop).isNotNull();
+ assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+ Set<OperationalPolicy> savedPolicies = actualLoop.getOperationalPolicies();
+ assertThat(savedPolicies).hasSize(1);
+ assertThat(savedPolicies)
+ .usingElementComparatorIgnoringFields("loop", "createdBy", "createdDate", "updatedBy", "updatedDate")
+ .contains(operationalPolicy);
+ OperationalPolicy savedPolicy = savedPolicies.iterator().next();
+ Assertions.assertThat(savedPolicy.getLoop().getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+
+ }
+
+ @Test
+ @Transactional
+ public void shouldAddMicroservicePolicyToLoop() {
+ // given
+ saveTestLoopToDb();
+ PolicyModel policyModel = new PolicyModel("org.policies.policyModel1",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "policyModel1");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel);
+ MicroServicePolicy microServicePolicy = new MicroServicePolicy("policyName", policyModel,
+ false, JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null);
+
+ // when
+ Loop actualLoop = loopService.updateAndSaveMicroservicePolicies(EXAMPLE_LOOP_NAME,
+ Lists.newArrayList(microServicePolicy));
+
+ // then
+ assertThat(actualLoop).isNotNull();
+ assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+ Set<MicroServicePolicy> savedPolicies = actualLoop.getMicroServicePolicies();
+ assertThat(savedPolicies).hasSize(1);
+ assertThat(savedPolicies).usingElementComparatorIgnoringFields("usedByLoops", "createdDate", "updatedDate",
+ "createdBy", "updatedBy").containsExactly(microServicePolicy);
+ assertThat(savedPolicies).extracting("usedByLoops").hasSize(1);
+
+ }
+
+ @Test
+ @Transactional
+ //@Commit
+ public void shouldCreateNewMicroservicePolicyAndUpdateJsonRepresentationOfOldOne() {
+ // given
+ saveTestLoopToDb();
+ PolicyModel policyModel1 = new PolicyModel("org.policies.firstPolicyName",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "firstPolicyName");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel1);
+ PolicyModel policyModel2 = new PolicyModel("org.policies.secondPolicyName",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "secondPolicyName");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel2);
+ MicroServicePolicy firstMicroServicePolicy = new MicroServicePolicy("firstPolicyName", policyModel1, false,
+ JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null);
+
+ loopService.updateAndSaveMicroservicePolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(firstMicroServicePolicy));
+ MicroServicePolicy secondMicroServicePolicy = new MicroServicePolicy("secondPolicyName", policyModel2, false,
+ JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null);
+
+ // when
+ firstMicroServicePolicy
+ .setConfigurationsJson(JsonUtils.GSON.fromJson("{\"name1\":\"value1\"}", JsonObject.class));
+ Loop actualLoop = loopService.updateAndSaveMicroservicePolicies(EXAMPLE_LOOP_NAME,
+ Lists.newArrayList(firstMicroServicePolicy, secondMicroServicePolicy));
+
+ // then
+ assertThat(actualLoop).isNotNull();
+ assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+ Set<MicroServicePolicy> savedPolicies = actualLoop.getMicroServicePolicies();
+ assertThat(savedPolicies).hasSize(2);
+ assertThat(savedPolicies).contains(firstMicroServicePolicy);
+ assertThat(savedPolicies).contains(secondMicroServicePolicy);
+ assertThat(savedPolicies).usingElementComparatorIgnoringFields("usedByLoops", "createdDate", "updatedDate",
+ "createdBy", "updatedBy").containsExactlyInAnyOrder(firstMicroServicePolicy, secondMicroServicePolicy);
+ }
+
+ private void saveTestLoopToDb() {
+ Loop testLoop = createTestLoop(EXAMPLE_LOOP_NAME, "blueprint");
+ testLoop.setGlobalPropertiesJson(JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class));
+ LoopTemplate template = new LoopTemplate();
+ template.setName("testTemplate");
+ testLoop.setLoopTemplate(template);
+ loopService.saveOrUpdateLoop(testLoop);
+ }
+
+ @Test
+ @Transactional
+ public void shouldRemoveOldMicroservicePolicyIfNotInUpdatedList() {
+ // given
+ saveTestLoopToDb();
+ PolicyModel policyModel1 = new PolicyModel("org.policies.firstPolicyName",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "firstPolicyName");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel1);
+ PolicyModel policyModel2 = new PolicyModel("org.policies.secondPolicyName",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "secondPolicyName");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel2);
+ MicroServicePolicy firstMicroServicePolicy = new MicroServicePolicy("firstPolicyName", policyModel1,
+ false, JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null);
+ loopService.updateAndSaveMicroservicePolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(firstMicroServicePolicy));
+
+ MicroServicePolicy secondMicroServicePolicy = new MicroServicePolicy("secondPolicyName", policyModel2,
+ false, JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null);
+
+ // when
+ Loop actualLoop = loopService.updateAndSaveMicroservicePolicies(EXAMPLE_LOOP_NAME,
+ Lists.newArrayList(secondMicroServicePolicy));
+
+ // then
+ assertThat(actualLoop).isNotNull();
+ assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+ Set<MicroServicePolicy> savedPolicies = actualLoop.getMicroServicePolicies();
+ assertThat(savedPolicies).hasSize(1);
+ assertThat(savedPolicies).usingElementComparatorIgnoringFields("usedByLoops", "createdDate", "updatedDate",
+ "createdBy", "updatedBy").containsExactly(secondMicroServicePolicy);
+
+ }
+
+ @Test
+ @Transactional
+ public void shouldCreateNewOperationalPolicyAndUpdateJsonRepresentationOfOldOne() {
+ // given
+ saveTestLoopToDb();
+
+ JsonObject newJsonConfiguration = JsonUtils.GSON.fromJson("{}", JsonObject.class);
+
+ OperationalPolicy firstOperationalPolicy = new OperationalPolicy("firstPolicyName", null,
+ JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null, null);
+ loopService.updateAndSaveOperationalPolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(firstOperationalPolicy));
+
+ OperationalPolicy secondOperationalPolicy = new OperationalPolicy("secondPolicyName", null,
+ newJsonConfiguration, null, null, null, null);
+
+ // when
+ firstOperationalPolicy.setConfigurationsJson(newJsonConfiguration);
+ Loop actualLoop = loopService.updateAndSaveOperationalPolicies(EXAMPLE_LOOP_NAME,
+ Lists.newArrayList(firstOperationalPolicy, secondOperationalPolicy));
+
+ // then
+ assertThat(actualLoop).isNotNull();
+ assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+ Set<OperationalPolicy> savedPolicies = actualLoop.getOperationalPolicies();
+ assertThat(savedPolicies).hasSize(2);
+ assertThat(savedPolicies)
+ .usingElementComparatorIgnoringFields("loop", "createdDate", "updatedDate", "createdBy", "updatedBy")
+ .containsExactlyInAnyOrder(firstOperationalPolicy, secondOperationalPolicy);
+ Set<String> policiesLoops = Lists.newArrayList(savedPolicies).stream().map(OperationalPolicy::getLoop)
+ .map(Loop::getName).collect(Collectors.toSet());
+ assertThat(policiesLoops).containsExactly(EXAMPLE_LOOP_NAME);
+ }
+
+ @Test
+ @Transactional
+ public void shouldRemoveOldOperationalPolicyIfNotInUpdatedList() {
+ // given
+ saveTestLoopToDb();
+
+ OperationalPolicy firstOperationalPolicy = new OperationalPolicy("firstPolicyName", null,
+ JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null, null);
+ loopService.updateAndSaveOperationalPolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(firstOperationalPolicy));
+
+ OperationalPolicy secondOperationalPolicy = new OperationalPolicy("policyName", null,
+ JsonUtils.GSON.fromJson("{}", JsonObject.class), null, null, "pdpGroup1", "pdpSubgroup1");
+
+ // when
+ Loop actualLoop = loopService.updateAndSaveOperationalPolicies(EXAMPLE_LOOP_NAME,
+ Lists.newArrayList(secondOperationalPolicy));
+
+ // then
+ assertThat(actualLoop).isNotNull();
+ assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+ Set<OperationalPolicy> savedPolicies = actualLoop.getOperationalPolicies();
+ assertThat(savedPolicies).hasSize(1);
+ assertThat(savedPolicies)
+ .usingElementComparatorIgnoringFields("loop", "createdDate", "updatedDate", "createdBy", "updatedBy")
+ .containsExactly(secondOperationalPolicy);
+ OperationalPolicy savedPolicy = savedPolicies.iterator().next();
+ Assertions.assertThat(savedPolicy.getLoop().getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+
+ }
+
+ @Test
+ @Transactional
+ public void shouldCreateModelPropertiesAndUpdateJsonRepresentationOfOldOne() {
+ // given
+ saveTestLoopToDb();
+ String expectedJson = "{\"test\":\"test\"}";
+ JsonObject baseGlobalProperites = JsonUtils.GSON.fromJson("{}", JsonObject.class);
+ JsonObject updatedGlobalProperites = JsonUtils.GSON.fromJson(expectedJson, JsonObject.class);
+ loopService.updateAndSaveGlobalPropertiesJson(EXAMPLE_LOOP_NAME, baseGlobalProperites);
+
+ // when
+ Loop actualLoop = loopService.updateAndSaveGlobalPropertiesJson(EXAMPLE_LOOP_NAME, updatedGlobalProperites);
+
+ // then
+ assertThat(actualLoop).isNotNull();
+ assertThat(actualLoop.getName()).isEqualTo(EXAMPLE_LOOP_NAME);
+ JsonObject returnedGlobalProperties = actualLoop.getGlobalPropertiesJson();
+ assertThat(returnedGlobalProperties.getAsJsonObject()).isEqualTo(updatedGlobalProperites);
+ }
+
+ @Test
+ @Transactional
+ public void deleteAttempt() {
+ saveTestLoopToDb();
+ // Add log
+ Loop loop = loopsRepository.findById(EXAMPLE_LOOP_NAME).orElse(null);
+ loop.addLog(new LoopLog("test", LogType.INFO, "CLAMP", loop));
+ LoopTemplate template = new LoopTemplate();
+ template.setName("testTemplate");
+ loop.setLoopTemplate(template);
+ loop = loopService.saveOrUpdateLoop(loop);
+ // Add op policy
+ OperationalPolicy operationalPolicy = new OperationalPolicy("opPolicy", null,
+ JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null, null);
+ loopService.updateAndSaveOperationalPolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(operationalPolicy));
+
+ PolicyModel policyModel = new PolicyModel("org.policies.microPolicy",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "microPolicy");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel);
+ // Add Micro service policy
+ MicroServicePolicy microServicePolicy = new MicroServicePolicy("microPolicy", policyModel,
+ false, JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null);
+ loopService.updateAndSaveMicroservicePolicies(EXAMPLE_LOOP_NAME, Lists.newArrayList(microServicePolicy));
+
+ // Verify it's there
+ assertThat(loopsRepository.findById(EXAMPLE_LOOP_NAME).orElse(null)).isNotNull();
+ loopService.deleteLoop(EXAMPLE_LOOP_NAME);
+ // Verify it's well deleted and has been cascaded, except for Microservice
+ assertThat(loopsRepository.findById(EXAMPLE_LOOP_NAME).orElse(null)).isNull();
+ assertThat(microServicePolicyService.isExisting("microPolicy")).isTrue();
+ assertThat(operationalPolicyService.isExisting("opPolicy")).isFalse();
+ assertThat(loopLogService.isExisting(((LoopLog) loop.getLoopLogs().toArray()[0]).getId())).isFalse();
+ }
+
+ @Test
+ @Transactional
+ public void testUpdateLoopState() {
+ saveTestLoopToDb();
+ Loop loop = loopService.getLoop(EXAMPLE_LOOP_NAME);
+ loopService.updateLoopState(loop, "SUBMITTED");
+ Loop updatedLoop = loopService.getLoop(EXAMPLE_LOOP_NAME);
+ assertThat(updatedLoop.getLastComputedState()).isEqualTo(LoopState.SUBMITTED);
+ }
+
+ @Test
+ @Transactional
+ public void testUpdateDcaeDeploymentFields() {
+ saveTestLoopToDb();
+ Loop loop = loopService.getLoop(EXAMPLE_LOOP_NAME);
+ loopService.updateDcaeDeploymentFields(loop, "CLAMP_c5ce429a-f570-48c5-a7ea-53bed8f86f85",
+ "https://deployment-handler.onap:8443");
+ loop = loopService.getLoop(EXAMPLE_LOOP_NAME);
+ assertThat(loop.getDcaeDeploymentId()).isEqualTo("CLAMP_c5ce429a-f570-48c5-a7ea-53bed8f86f85");
+ assertThat(loop.getDcaeDeploymentStatusUrl()).isEqualTo("https://deployment-handler.onap:8443");
+ }
+
+ @Test
+ @Transactional
+ public void testUpdateMicroservicePolicy() {
+ saveTestLoopToDb();
+ assertThat(microServicePolicyService.isExisting("policyName")).isFalse();
+ PolicyModel policyModel = new PolicyModel("org.policies.policyName",
+ "tosca_definitions_version: tosca_simple_yaml_1_0_0", "1.0.0", "policyName");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel);
+ MicroServicePolicy microServicePolicy = new MicroServicePolicy("policyName", policyModel,
+ false, JsonUtils.GSON.fromJson(EXAMPLE_JSON, JsonObject.class), null, null, null);
+ loopService.updateMicroservicePolicy(EXAMPLE_LOOP_NAME, microServicePolicy);
+ assertThat(microServicePolicyService.isExisting("policyName")).isTrue();
+ }
+
+ private Loop createTestLoop(String loopName, String loopBlueprint) {
+ return new Loop(loopName);
+ }
+} \ No newline at end of file
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/LoopTemplateLoopElementModelTest.java b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopTemplateLoopElementModelTest.java
new file mode 100644
index 000000000..9dcd71ef1
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopTemplateLoopElementModelTest.java
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+import org.onap.policy.clamp.loop.template.LoopElementModel;
+import org.onap.policy.clamp.loop.template.LoopTemplate;
+import org.onap.policy.clamp.loop.template.LoopTemplateLoopElementModel;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+
+
+public class LoopTemplateLoopElementModelTest {
+
+ private LoopElementModel loopElementModel = getLoopElementModel("yaml", "microService1",
+ getPolicyModel("org.onap.policy.drools", "yaml", "1.0.0", "Drools", "type1"));
+ private LoopTemplate loopTemplate = getLoopTemplate("templateName", "yaml", 1);
+
+ private LoopElementModel getLoopElementModel(String yaml, String name, PolicyModel policyModel) {
+ LoopElementModel model = new LoopElementModel();
+ model.setBlueprint(yaml);
+ model.setName(name);
+ model.addPolicyModel(policyModel);
+ model.setLoopElementType("OPERATIONAL_POLICY");
+ return model;
+ }
+
+ private PolicyModel getPolicyModel(String policyType, String policyModelTosca, String version, String policyAcronym,
+ String policyVariant) {
+ return new PolicyModel(policyType, policyModelTosca, version, policyAcronym);
+ }
+
+ private LoopTemplate getLoopTemplate(String name, String blueprint, Integer maxInstancesAllowed) {
+ LoopTemplate template = new LoopTemplate(name, blueprint, maxInstancesAllowed, null);
+ template.addLoopElementModel(loopElementModel);
+ return template;
+ }
+
+ /**
+ * This tests compareTo method.
+ */
+ @Test
+ public void compareToTest() {
+ LoopTemplateLoopElementModel model1 = new LoopTemplateLoopElementModel();
+ LoopTemplateLoopElementModel model2 = new LoopTemplateLoopElementModel();
+ assertThat(model1.compareTo(model2)).isEqualTo(1);
+
+ model1.setFlowOrder(2);
+ assertThat(model1.compareTo(model2)).isEqualTo(-1);
+
+ model2.setFlowOrder(3);
+ assertThat(model1.compareTo(model2)).isEqualTo(1);
+ }
+
+ /**
+ * This tests equals method.
+ */
+ @Test
+ public void equalsTest() {
+ LoopTemplateLoopElementModel model1 = new LoopTemplateLoopElementModel();
+ LoopTemplateLoopElementModel model2 = new LoopTemplateLoopElementModel();
+
+ assertThat(model1.equals(model2)).isTrue();
+
+ model1.setLoopTemplate(loopTemplate);
+ assertThat(model1.equals(model2)).isFalse();
+ model2.setLoopTemplate(loopTemplate);
+ assertThat(model1.equals(model2)).isTrue();
+
+ model1.setLoopElementModel(loopElementModel);
+ assertThat(model1.equals(model2)).isFalse();
+ model2.setLoopElementModel(loopElementModel);
+ assertThat(model1.equals(model2)).isTrue();
+
+ model1.setFlowOrder(1);
+ assertThat(model1.equals(model2)).isTrue();
+ model2.setFlowOrder(2);
+ assertThat(model1.equals(model2)).isTrue();
+ }
+
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/LoopTemplatesServiceItCase.java b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopTemplatesServiceItCase.java
new file mode 100644
index 000000000..dba7c39a9
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopTemplatesServiceItCase.java
@@ -0,0 +1,146 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.util.List;
+import java.util.SortedSet;
+import javax.transaction.Transactional;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.Application;
+import org.onap.policy.clamp.loop.template.LoopElementModel;
+import org.onap.policy.clamp.loop.template.LoopTemplate;
+import org.onap.policy.clamp.loop.template.LoopTemplateLoopElementModel;
+import org.onap.policy.clamp.loop.template.LoopTemplatesService;
+import org.onap.policy.clamp.loop.template.LoopType;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class LoopTemplatesServiceItCase {
+
+ @Autowired
+ LoopTemplatesService loopTemplatesService;
+
+ private static final String POLICY_MODEL_TYPE_1 = "org.onap.test";
+ private static final String VERSION = "1.0.0";
+
+ private LoopElementModel getLoopElementModel(String yaml, String name, String loopElementType,
+ String createdBy, PolicyModel policyModel) {
+ LoopElementModel model = new LoopElementModel(name, loopElementType, yaml);
+ model.setBlueprint("");
+ model.setDcaeBlueprintId("");
+ model.addPolicyModel(policyModel);
+ return model;
+ }
+
+ private PolicyModel getPolicyModel(String policyType, String policyModelTosca, String version,
+ String policyAcronym, String createdBy) {
+ return new PolicyModel(policyType, policyModelTosca, version, policyAcronym);
+ }
+
+ private LoopTemplate getLoopTemplate(String name, String blueprint, String createdBy, Integer maxInstancesAllowed) {
+ LoopTemplate template =
+ new LoopTemplate(name, blueprint, maxInstancesAllowed, null);
+ template.addLoopElementModel(getLoopElementModel("yaml", "microService1", "MicroService",
+ createdBy, getPolicyModel(POLICY_MODEL_TYPE_1, "yaml", VERSION, "MS1", createdBy)));
+ template.setAllowedLoopType(LoopType.OPEN);
+ return template;
+ }
+
+ @Test
+ @Transactional
+ public void shouldSaveOrUpdateLoopTemplate() {
+ LoopTemplate loopTemplate = getLoopTemplate("TemplateName", null, "xyz", -1);
+ LoopTemplate actualLoopTemplate =
+ loopTemplatesService.saveOrUpdateLoopTemplate(loopTemplate);
+
+ assertNotNull(actualLoopTemplate);
+ assertThat(loopTemplate.getName()).isEqualTo("TemplateName");
+ assertThat(loopTemplate.getAllowedLoopType()).isEqualTo(LoopType.OPEN);
+ }
+
+ @Test
+ @Transactional
+ public void shouldReturnAllLoopTemplates() {
+ LoopTemplate loopTemplate = getLoopTemplate("TemplateName", null, "xyz", -1);
+ loopTemplatesService.saveOrUpdateLoopTemplate(loopTemplate);
+ List<LoopTemplate> loopTemplateList = loopTemplatesService.getAllLoopTemplates();
+
+ assertNotNull(loopTemplateList);
+ }
+
+ @Test
+ @Transactional
+ public void shouldReturnLoopTemplateNames() {
+ LoopTemplate loopTemplate = getLoopTemplate("TemplateName", null, "xyz", -1);
+ loopTemplatesService.saveOrUpdateLoopTemplate(loopTemplate);
+ List<String> loopTemplateNames = loopTemplatesService.getLoopTemplateNames();
+
+ assertNotNull(loopTemplateNames);
+ assertEquals("TemplateName", loopTemplateNames.get(0));
+ }
+
+ @Test
+ @Transactional
+ public void shouldReturnLoopTemplate() {
+ LoopTemplate loopTemplate = getLoopTemplate("TemplateName", null, "xyz", -1);
+ loopTemplatesService.saveOrUpdateLoopTemplate(loopTemplate);
+ LoopTemplate actualLoopTemplate = loopTemplatesService.getLoopTemplate("TemplateName");
+
+ assertNotNull(actualLoopTemplate);
+ assertThat(loopTemplate).isEqualTo(actualLoopTemplate);
+ assertThat(loopTemplate.getName()).isEqualTo(actualLoopTemplate.getName());
+ assertThat(loopTemplate.getMaximumInstancesAllowed())
+ .isEqualTo(actualLoopTemplate.getMaximumInstancesAllowed());
+ SortedSet<LoopTemplateLoopElementModel> loopElementModelsUsed =
+ loopTemplate.getLoopElementModelsUsed();
+ LoopTemplateLoopElementModel loopTemplateLoopElementModel = loopElementModelsUsed.first();
+ assertThat(loopTemplateLoopElementModel.getLoopElementModel().getName())
+ .isEqualTo("microService1");
+ assertThat(loopTemplateLoopElementModel.getLoopTemplate().getName())
+ .isEqualTo("TemplateName");
+ assertNull(actualLoopTemplate.getBlueprint());
+ assertNull(actualLoopTemplate.getModelService());
+ }
+
+ @Test
+ @Transactional
+ public void shouldDeleteLoopTemplate() {
+ LoopTemplate loopTemplate = getLoopTemplate("TemplateName", null, "xyz", -1);
+ loopTemplatesService.saveOrUpdateLoopTemplate(loopTemplate);
+ loopTemplatesService.deleteLoopTemplate("TemplateName");
+ LoopTemplate actualLoopTemplate = loopTemplatesService.getLoopTemplate("TemplateName");
+ assertNull(actualLoopTemplate);
+ }
+
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/LoopToJsonTest.java b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopToJsonTest.java
new file mode 100644
index 000000000..0fc4b0b5c
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/LoopToJsonTest.java
@@ -0,0 +1,173 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertNotNull;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
+import java.io.IOException;
+import java.util.Random;
+import org.junit.Test;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.loop.log.LogType;
+import org.onap.policy.clamp.loop.log.LoopLog;
+import org.onap.policy.clamp.loop.service.Service;
+import org.onap.policy.clamp.loop.template.LoopElementModel;
+import org.onap.policy.clamp.loop.template.LoopTemplate;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.policy.clamp.policy.operational.OperationalPolicy;
+
+public class LoopToJsonTest {
+
+ private Gson gson = new Gson();
+
+ private OperationalPolicy getOperationalPolicy(String configJson, String name) {
+ return new OperationalPolicy(name, null, gson.fromJson(configJson, JsonObject.class),
+ getPolicyModel("org.onap.policy.drools.legacy", "yaml", "1.0.0", "Drools", "type1"), null, null, null);
+ }
+
+ private Loop getLoop(String name, String blueprint, String globalPropertiesJson,
+ String dcaeId, String dcaeUrl, String dcaeBlueprintId)
+ throws JsonSyntaxException, IOException {
+ Loop loop = new Loop(name);
+ loop.setGlobalPropertiesJson(new Gson().fromJson(globalPropertiesJson, JsonObject.class));
+ loop.setLastComputedState(LoopState.DESIGN);
+ loop.setDcaeDeploymentId(dcaeId);
+ loop.setDcaeDeploymentStatusUrl(dcaeUrl);
+ return loop;
+ }
+
+ private MicroServicePolicy getMicroServicePolicy(String name, String modelType, String jsonRepresentation,
+ String policyTosca, String jsonProperties, boolean shared) {
+ MicroServicePolicy microService = new MicroServicePolicy(name, new PolicyModel(modelType, policyTosca, "1.0.0"),
+ shared,
+ gson.fromJson(jsonRepresentation, JsonObject.class), null, null, null);
+ microService.setConfigurationsJson(new Gson().fromJson(jsonProperties, JsonObject.class));
+ return microService;
+ }
+
+ private LoopElementModel getLoopElementModel(String yaml, String name, PolicyModel policyModel) {
+ LoopElementModel model = new LoopElementModel();
+ model.setBlueprint(yaml);
+ model.setName(name);
+ model.addPolicyModel(policyModel);
+ model.setLoopElementType("OPERATIONAL_POLICY");
+ return model;
+ }
+
+ private PolicyModel getPolicyModel(String policyType, String policyModelTosca, String version, String policyAcronym,
+ String policyVariant) {
+ return new PolicyModel(policyType, policyModelTosca, version, policyAcronym);
+ }
+
+ private LoopTemplate getLoopTemplate(String name, String blueprint, Integer maxInstancesAllowed) {
+ LoopTemplate template = new LoopTemplate(name, blueprint, maxInstancesAllowed, null);
+ template.addLoopElementModel(getLoopElementModel("yaml", "microService1",
+ getPolicyModel("org.onap.policy.drools", "yaml", "1.0.0", "Drools", "type1")));
+ return template;
+ }
+
+ private LoopLog getLoopLog(LogType type, String message, Loop loop) {
+ LoopLog log = new LoopLog(message, type, "CLAMP", loop);
+ log.setId(Long.valueOf(new Random().nextInt()));
+ return log;
+ }
+
+ /**
+ * This tests a GSON encode/decode.
+ *
+ * @throws IOException In case of failure
+ */
+ @Test
+ public void loopGsonTest() throws IOException {
+ Loop loopTest = getLoop("ControlLoopTest", "yamlcontent", "{\"testname\":\"testvalue\"}",
+ "123456789", "https://dcaetest.org", "UUID-blueprint");
+ OperationalPolicy opPolicy = this.getOperationalPolicy(
+ ResourceFileUtils.getResourceAsString("tosca/operational-policy-properties.json"), "GuardOpPolicyTest");
+ loopTest.addOperationalPolicy(opPolicy);
+ MicroServicePolicy microServicePolicy = getMicroServicePolicy("configPolicyTest", "",
+ "{\"configtype\":\"json\"}", "tosca_definitions_version: tosca_simple_yaml_1_0_0",
+ "{\"param1\":\"value1\"}", true);
+ loopTest.addMicroServicePolicy(microServicePolicy);
+ LoopLog loopLog = getLoopLog(LogType.INFO, "test message", loopTest);
+ loopTest.addLog(loopLog);
+ LoopTemplate loopTemplate = getLoopTemplate("templateName", "yaml", 1);
+ loopTest.setLoopTemplate(loopTemplate);
+
+ String jsonSerialized = JsonUtils.GSON_JPA_MODEL.toJson(loopTest);
+ assertThat(jsonSerialized).isNotNull().isNotEmpty();
+ System.out.println(jsonSerialized);
+ Loop loopTestDeserialized = JsonUtils.GSON_JPA_MODEL.fromJson(jsonSerialized, Loop.class);
+ assertNotNull(loopTestDeserialized);
+ assertThat(loopTestDeserialized).isEqualToIgnoringGivenFields(loopTest, "svgRepresentation", "blueprint",
+ "components");
+ assertThat(loopTestDeserialized.getComponent("DCAE").getState())
+ .isEqualToComparingFieldByField(loopTest.getComponent("DCAE").getState());
+ assertThat(loopTestDeserialized.getComponent("POLICY").getState()).isEqualToComparingOnlyGivenFields(
+ loopTest.getComponent("POLICY").getState(), "stateName", "description");
+ // blueprint not exposed so wont be deserialized
+
+ assertThat(loopTestDeserialized.getOperationalPolicies()).containsExactly(opPolicy);
+ assertThat(loopTestDeserialized.getMicroServicePolicies()).containsExactly(microServicePolicy);
+ assertThat(loopTestDeserialized.getLoopLogs()).containsExactly(loopLog);
+ assertThat((LoopLog) loopTestDeserialized.getLoopLogs().toArray()[0]).isEqualToIgnoringGivenFields(loopLog,
+ "loop");
+
+ // Verify the loop template
+ assertThat(loopTestDeserialized.getLoopTemplate()).isEqualTo(loopTemplate);
+ }
+
+ /**
+ * This tests the service object GSON encode/decode.
+ *
+ * @throws IOException In case of issues
+ */
+ @Test
+ public void loopServiceTest() throws IOException {
+ Loop loopTest2 = getLoop("ControlLoopTest", "yamlcontent", "{\"testname\":\"testvalue\"}",
+ "123456789", "https://dcaetest.org", "UUID-blueprint");
+
+ JsonObject jsonModel = new GsonBuilder().create()
+ .fromJson(ResourceFileUtils.getResourceAsString("tosca/model-properties.json"), JsonObject.class);
+ Service service = new Service(jsonModel.get("serviceDetails").getAsJsonObject(),
+ jsonModel.get("resourceDetails").getAsJsonObject(), "1.0");
+ loopTest2.setModelService(service);
+ String jsonSerialized = JsonUtils.GSON_JPA_MODEL.toJson(loopTest2);
+ assertThat(jsonSerialized).isNotNull().isNotEmpty();
+ System.out.println(jsonSerialized);
+
+ Loop loopTestDeserialized = JsonUtils.GSON_JPA_MODEL.fromJson(jsonSerialized, Loop.class);
+ assertNotNull(loopTestDeserialized);
+ assertThat(loopTestDeserialized).isEqualToIgnoringGivenFields(loopTest2, "modelService", "svgRepresentation",
+ "blueprint", "components");
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/PolicyComponentTest.java b/runtime/src/test/java/org/onap/policy/clamp/loop/PolicyComponentTest.java
new file mode 100644
index 000000000..5b4e405bb
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/PolicyComponentTest.java
@@ -0,0 +1,296 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import org.apache.camel.Exchange;
+import org.apache.camel.Message;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.loop.components.external.ExternalComponentState;
+import org.onap.policy.clamp.loop.components.external.PolicyComponent;
+import org.onap.policy.clamp.loop.template.LoopTemplate;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.policy.clamp.policy.operational.OperationalPolicy;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+public class PolicyComponentTest {
+
+ /**
+ * Test the computeState method.
+ * oldState newState expectedFinalState
+ * NOT_SENT SENT_AND_DEPLOYED NOT_SENT
+ * NOT_SENT SENT NOT_SENT
+ * NOT_SENT NOT_SENT NOT_SENT
+ * NOT_SENT IN_ERROR IN_ERROR
+ */
+ @Test
+ public void computeStateTestOriginalStateUnknown() {
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+ Exchange exchange2 = Mockito.mock(Exchange.class);
+ Mockito.when(exchange.getIn()).thenReturn(message);
+ Mockito.when(message.getExchange()).thenReturn(exchange2);
+ // policy found + deployed
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true);
+ PolicyComponent policy = new PolicyComponent();
+
+ ExternalComponentState state = policy.computeState(exchange);
+ assertThat(state.getStateName()).isEqualTo("SENT_AND_DEPLOYED");
+ // policy found + not deployed
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false);
+ ExternalComponentState state2 = policy.computeState(exchange);
+ assertThat(state2.getStateName()).isEqualTo("SENT");
+ // policy not found + not deployed
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false);
+ ExternalComponentState state4 = policy.computeState(exchange);
+ assertThat(state4.getStateName()).isEqualTo("NOT_SENT");
+ // policy not found + deployed
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true);
+ ExternalComponentState state3 = policy.computeState(exchange);
+ assertThat(state3.getStateName()).isEqualTo("IN_ERROR");
+ }
+
+ /**
+ * Test the computeState method.
+ * oldState newState expectedFinalState
+ * NOT_SENT SENT_AND_DEPLOYED NOT_SENT
+ * NOT_SENT SENT NOT_SENT
+ * NOT_SENT NOT_SENT NOT_SENT
+ * NOT_SENT IN_ERROR IN_ERROR
+ */
+ @Test
+ public void computeStateTestOriginalStateNotSent() {
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+ Exchange exchange2 = Mockito.mock(Exchange.class);
+ Mockito.when(exchange.getIn()).thenReturn(message);
+ Mockito.when(message.getExchange()).thenReturn(exchange2);
+ // policy found + deployed
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true);
+ PolicyComponent policy = new PolicyComponent();
+ ExternalComponentState notSent = new ExternalComponentState("NOT_SENT",
+ "The policies defined have NOT yet been created on the policy engine", 90);
+ policy.setState(notSent);
+ ExternalComponentState state = policy.computeState(exchange);
+ assertThat(state.getStateName()).isEqualTo("NOT_SENT");
+ // policy found + not deployed
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false);
+ ExternalComponentState state2 = policy.computeState(exchange);
+ assertThat(state2.getStateName()).isEqualTo("NOT_SENT");
+ // policy not found + not deployed
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false);
+ ExternalComponentState state4 = policy.computeState(exchange);
+ assertThat(state4.getStateName()).isEqualTo("NOT_SENT");
+ // policy not found + deployed
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true);
+ ExternalComponentState state3 = policy.computeState(exchange);
+ assertThat(state3.getStateName()).isEqualTo("IN_ERROR");
+ }
+
+
+ /**
+ * Test the computeState method.
+ * oldState newState expectedFinalState
+ * SENT SENT SENT
+ * SENT SENT_AND_DEPLOYED SENT
+ * SENT IN_ERROR IN_ERROR
+ * SENT NOT_SENT NOT_SENT
+ */
+ @Test
+ public void computeStateTestOriginalStateSent() throws IOException {
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+ Exchange exchange2 = Mockito.mock(Exchange.class);
+ Mockito.when(exchange.getIn()).thenReturn(message);
+ Mockito.when(message.getExchange()).thenReturn(exchange2);
+ PolicyComponent policy = new PolicyComponent();
+ ExternalComponentState sent = new ExternalComponentState("SENT",
+ "The policies defined have been created but NOT deployed on the policy engine", 50);
+ policy.setState(sent);
+ // new policy state SENT
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false);
+ ExternalComponentState state = policy.computeState(exchange);
+ assertThat(state.getStateName()).isEqualTo("SENT");
+ // new policy state SENT_AND_DEPLOYED
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true);
+ ExternalComponentState state2 = policy.computeState(exchange);
+ assertThat(state2.getStateName()).isEqualTo("SENT");
+ // new policy state IN_ERROR
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true);
+ ExternalComponentState state3 = policy.computeState(exchange);
+ assertThat(state3.getStateName()).isEqualTo("IN_ERROR");
+ // new policy state NOT_SENT
+ policy.setState(sent);
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false);
+ ExternalComponentState state4 = policy.computeState(exchange);
+ assertThat(state4.getStateName()).isEqualTo("NOT_SENT");
+ }
+
+ /**
+ * Test the computeState method.
+ * oldState newState expectedFinalState
+ * SENT_AND_DEPLOYED SENT_AND_DEPLOYED SENT_AND_DEPLOYED
+ * SENT_AND_DEPLOYED SENT SENT
+ * SENT_AND_DEPLOYED IN_ERROR IN_ERROR
+ * SENT_AND_DEPLOYED NOT_SENT NOT_SENT
+ */
+ @Test
+ public void computeStateTestOriginalStateSentAndDeployed() throws IOException {
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+ Exchange exchange2 = Mockito.mock(Exchange.class);
+ Mockito.when(exchange.getIn()).thenReturn(message);
+ Mockito.when(message.getExchange()).thenReturn(exchange2);
+ PolicyComponent policy = new PolicyComponent();
+ ExternalComponentState sendDeployed = new ExternalComponentState("SENT_AND_DEPLOYED",
+ "The policies defined have been created and deployed on the policy engine", 10);
+ policy.setState(sendDeployed);
+ // new policy state SENT_AND_DEPLOYED
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true);
+ ExternalComponentState state = policy.computeState(exchange);
+ assertThat(state.getStateName()).isEqualTo("SENT_AND_DEPLOYED");
+ // new policy state SENT
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false);
+ ExternalComponentState state2 = policy.computeState(exchange);
+ assertThat(state2.getStateName()).isEqualTo("SENT");
+ // new policy state IN_ERROR
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true);
+ ExternalComponentState state3 = policy.computeState(exchange);
+ assertThat(state3.getStateName()).isEqualTo("IN_ERROR");
+ // new policy state NOT_SENT
+ policy.setState(sendDeployed);
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false);
+ ExternalComponentState state4 = policy.computeState(exchange);
+ assertThat(state4.getStateName()).isEqualTo("NOT_SENT");
+ }
+
+
+ /**
+ * Test the computeState method.
+ * oldState newState expectedFinalState
+ * IN_ERROR SENT_AND_DEPLOYED IN_ERROR
+ * IN_ERROR SENT IN_ERROR
+ * IN_ERROR IN_ERROR IN_ERROR
+ * IN_ERROR NOT_SENT IN_ERROR
+ */
+ @Test
+ public void computeStateTestOriginalStateInError() throws IOException {
+ Exchange exchange = Mockito.mock(Exchange.class);
+ Message message = Mockito.mock(Message.class);
+ Exchange exchange2 = Mockito.mock(Exchange.class);
+ Mockito.when(exchange.getIn()).thenReturn(message);
+ Mockito.when(message.getExchange()).thenReturn(exchange2);
+ PolicyComponent policy = new PolicyComponent();
+ ExternalComponentState inError = new ExternalComponentState("IN_ERROR",
+ "There was an error during the sending to policy, the policy engine may be corrupted or inconsistent",
+ 100);
+ policy.setState(inError);
+ // new policy state SENT_AND_DEPLOYED
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true);
+ ExternalComponentState state = policy.computeState(exchange);
+ assertThat(state.getStateName()).isEqualTo("IN_ERROR");
+ // new policy state SENT
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(true);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false);
+ ExternalComponentState state2 = policy.computeState(exchange);
+ assertThat(state2.getStateName()).isEqualTo("IN_ERROR");
+ // new policy state IN_ERROR
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(true);
+ ExternalComponentState state3 = policy.computeState(exchange);
+ assertThat(state3.getStateName()).isEqualTo("IN_ERROR");
+ // new policy state NOT_SENT
+ Mockito.when(exchange2.getProperty("policyFound")).thenReturn(false);
+ Mockito.when(exchange2.getProperty("policyDeployed")).thenReturn(false);
+ ExternalComponentState state4 = policy.computeState(exchange);
+
+ assertThat(state4.getStateName()).isEqualTo("IN_ERROR");
+ }
+
+ /**
+ * Test the create policies payload PdpGroup test.
+ */
+ @Test
+ public void createPoliciesPayloadPdpGroupTest() throws IOException {
+ Loop loopTest = new Loop("ControlLoopTest");
+ PolicyModel policyModel1 = new PolicyModel("onap.policies.monitoring.test", null, "1.0.0");
+
+ MicroServicePolicy microServicePolicy = new MicroServicePolicy("configPolicyTest", policyModel1, true,
+ new Gson().fromJson("{\"configtype\":\"json\"}", JsonObject.class), null, "pdpGroup1", "pdpSubgroup1");
+ loopTest.addMicroServicePolicy(microServicePolicy);
+
+ MicroServicePolicy microServicePolicy2 = new MicroServicePolicy("configPolicyTest2", policyModel1, true,
+ new Gson().fromJson("{\"configtype\":\"json\"}", JsonObject.class), null, "pdpGroup2", "pdpSubgroup1");
+ loopTest.addMicroServicePolicy(microServicePolicy2);
+
+ PolicyModel policyModel2 = new PolicyModel("onap.policies.monitoring.test2", null,
+ "1.0.0");
+ OperationalPolicy opPolicy =
+ new OperationalPolicy("opPolicy", new Gson().fromJson("{\"configtype\":\"json\"}", JsonObject.class),
+ new Gson().fromJson("{\"jsonschema\":\"schema\"}", JsonObject.class), policyModel2, null,
+ "pdpGroup2",
+ "pdpSubgroup2");
+
+ loopTest.addOperationalPolicy(opPolicy);
+ OperationalPolicy opLegacyPolicy =
+ new OperationalPolicy("opLegacyPolicy", new Gson().fromJson(
+ "{\"guard_policies\":[{\"policy-id\":\"guard1\"}]}", JsonObject.class),
+ new Gson().fromJson("{\"jsonschema\":\"schema\"}", JsonObject.class), policyModel2, null,
+ "pdpGroup2",
+ "pdpSubgroup2");
+
+ loopTest.addOperationalPolicy(opLegacyPolicy);
+
+ LoopTemplate loopTemplate = new LoopTemplate("test", "yaml", 1, null);
+ loopTemplate.setDcaeBlueprintId("UUID-blueprint");
+ loopTest.setLoopTemplate(loopTemplate);
+
+ JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("example/policy/pdp-group-policy-payload.json"),
+ PolicyComponent.createPoliciesPayloadPdpGroup(loopTest, "POST"), false);
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/PolicyModelServiceItCase.java b/runtime/src/test/java/org/onap/policy/clamp/loop/PolicyModelServiceItCase.java
new file mode 100644
index 000000000..a2563b8d3
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/PolicyModelServiceItCase.java
@@ -0,0 +1,300 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.stream.Collectors;
+import javax.transaction.Transactional;
+import org.assertj.core.api.Assertions;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.Application;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.loop.template.PolicyModelId;
+import org.onap.policy.clamp.loop.template.PolicyModelsRepository;
+import org.onap.policy.clamp.loop.template.PolicyModelsService;
+import org.onap.policy.models.pdp.concepts.PdpGroup;
+import org.onap.policy.models.pdp.concepts.PdpGroups;
+import org.onap.policy.models.pdp.concepts.PdpSubGroup;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class PolicyModelServiceItCase {
+
+ @Autowired
+ PolicyModelsService policyModelsService;
+
+ @Autowired
+ PolicyModelsRepository policyModelsRepository;
+
+ private static final String POLICY_MODEL_TYPE_1 = "org.onap.testos";
+ private static final String POLICY_MODEL_TYPE_1_VERSION_1 = "1.0.0";
+
+ private static final String POLICY_MODEL_TYPE_2 = "org.onap.testos2";
+ private static final String POLICY_MODEL_TYPE_3 = "org.onap.testos3";
+ private static final String POLICY_MODEL_TYPE_2_VERSION_1 = "1.0.0";
+ private static final String POLICY_MODEL_TYPE_3_VERSION_1 = "1.0.0";
+ private static final String POLICY_MODEL_TYPE_2_VERSION_2 = "2.0.0";
+
+ private PolicyModel getPolicyModel(String policyType, String policyModelTosca, String version,
+ String policyAcronym, String policyVariant, String createdBy) {
+ PolicyModel policyModel = new PolicyModel();
+ policyModel.setCreatedBy(createdBy);
+ policyModel.setPolicyAcronym(policyAcronym);
+ policyModel.setPolicyModelTosca(policyModelTosca);
+ policyModel.setPolicyModelType(policyType);
+ policyModel.setUpdatedBy(createdBy);
+ policyModel.setVersion(version);
+ return policyModel;
+ }
+
+ /**
+ * This test the create policy Model.
+ */
+ @Test
+ @Transactional
+ public void shouldCreatePolicyModel() {
+ // given
+ PolicyModel policyModel = getPolicyModel(POLICY_MODEL_TYPE_1, "yaml",
+ POLICY_MODEL_TYPE_1_VERSION_1, "TEST", "VARIANT", "user");
+
+ // when
+ PolicyModel actualPolicyModel = policyModelsService.saveOrUpdatePolicyModel(policyModel);
+
+ // then
+ assertThat(actualPolicyModel).isNotNull();
+ assertThat(actualPolicyModel).isEqualTo(policyModelsRepository
+ .findById(new PolicyModelId(actualPolicyModel.getPolicyModelType(),
+ actualPolicyModel.getVersion()))
+ .get());
+ assertThat(actualPolicyModel.getPolicyModelType())
+ .isEqualTo(policyModel.getPolicyModelType());
+ Assertions.assertThat(actualPolicyModel.getCreatedBy()).isEqualTo("Not found");
+ Assertions.assertThat(actualPolicyModel.getCreatedDate()).isNotNull();
+ assertThat(actualPolicyModel.getPolicyAcronym()).isEqualTo(policyModel.getPolicyAcronym());
+ assertThat(actualPolicyModel.getPolicyModelTosca())
+ .isEqualTo(policyModel.getPolicyModelTosca());
+ Assertions.assertThat(actualPolicyModel.getUpdatedBy()).isEqualTo("Not found");
+ Assertions.assertThat(actualPolicyModel.getUpdatedDate()).isNotNull();
+ assertThat(actualPolicyModel.getVersion()).isEqualTo(policyModel.getVersion());
+
+ assertThat(
+ policyModelsService.getPolicyModel(POLICY_MODEL_TYPE_1, POLICY_MODEL_TYPE_1_VERSION_1))
+ .isEqualToIgnoringGivenFields(policyModel, "createdDate", "updatedDate",
+ "createdBy", "updatedBy");
+ }
+
+ /**
+ * This tests the getPolicyModelJson. A json is expected.
+ *
+ * @throws IOException In case of failure
+ */
+ @Test
+ @Transactional
+ public void shouldGetPolicyModelInJson() throws IOException {
+ PolicyModel policyModel = getPolicyModel("onap.policies.monitoring.cdap.tca.hi.lo.app",
+ ResourceFileUtils.getResourceAsString(
+ "http-cache/example/policy/api/v1/policytypes/"
+ + "onap.policies.monitoring.cdap.tca.hi.lo.app/versions/1.0.0/.file"),
+ "1.0.0", "TEST", "VARIANT", "user");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel);
+
+ JsonObject policyTypeJson =
+ policyModelsService.getPolicyModelJson("onap.policies.monitoring.cdap.tca.hi.lo.app", "1.0.0");
+ assertThat(policyTypeJson).isNotNull();
+ JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("tosca/tca_hi_lo.json"),
+ policyTypeJson.toString(),
+ true);
+ }
+
+ /**
+ * This tests a getAllPolicyModelTypes get.
+ */
+ @Test
+ @Transactional
+ public void shouldReturnAllPolicyModelTypes() {
+ // given
+ PolicyModel policyModel1 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml",
+ POLICY_MODEL_TYPE_2_VERSION_1, "TEST", "VARIANT", "user");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel1);
+ PolicyModel policyModel2 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml",
+ POLICY_MODEL_TYPE_2_VERSION_2, "TEST", "VARIANT", "user");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel2);
+ List<String> policyModelTypesList = policyModelsService.getAllPolicyModelTypes();
+
+ assertThat(policyModelTypesList).contains(policyModel1.getPolicyModelType(),
+ policyModel2.getPolicyModelType());
+ }
+
+ /**
+ * This tests a getAllPolicyModels get.
+ */
+ @Test
+ @Transactional
+ public void shouldReturnAllPolicyModels() {
+ PolicyModel policyModel1 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml",
+ POLICY_MODEL_TYPE_2_VERSION_1, "TEST", "VARIANT", "user");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel1);
+ PolicyModel policyModel2 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml",
+ POLICY_MODEL_TYPE_2_VERSION_2, "TEST", "VARIANT", "user");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel2);
+
+ assertThat(policyModelsService.getAllPolicyModels()).contains(policyModel1, policyModel2);
+ }
+
+ /**
+ * This tests a getAllPolicyModelsByType get.
+ */
+ @Test
+ @Transactional
+ public void shouldReturnAllModelsByType() {
+ PolicyModel policyModel1 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml",
+ POLICY_MODEL_TYPE_2_VERSION_1, "TEST", "VARIANT", "user");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel1);
+ PolicyModel policyModel2 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml",
+ POLICY_MODEL_TYPE_2_VERSION_2, "TEST", "VARIANT", "user");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel2);
+
+ assertThat(policyModelsService.getAllPolicyModelsByType(POLICY_MODEL_TYPE_2))
+ .contains(policyModel1, policyModel2);
+ }
+
+ /**
+ * This tests the sorting of policyModel.
+ */
+ @Test
+ @Transactional
+ public void shouldReturnSortedSet() {
+ PolicyModel policyModel1 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml",
+ POLICY_MODEL_TYPE_2_VERSION_1, "TEST", "VARIANT", "user");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel1);
+ PolicyModel policyModel2 = getPolicyModel(POLICY_MODEL_TYPE_2, "yaml",
+ POLICY_MODEL_TYPE_2_VERSION_2, "TEST", "VARIANT", "user");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel2);
+ PolicyModel policyModel3 = getPolicyModel(POLICY_MODEL_TYPE_3, "yaml",
+ POLICY_MODEL_TYPE_3_VERSION_1, "TEST", "VARIANT", "user");
+ policyModelsService.saveOrUpdatePolicyModel(policyModel3);
+
+ SortedSet<PolicyModel> sortedSet = new TreeSet<>();
+ policyModelsService.getAllPolicyModels().forEach(sortedSet::add);
+ List<PolicyModel> listToCheck =
+ sortedSet
+ .stream().filter(policy -> policy.equals(policyModel3)
+ || policy.equals(policyModel2) || policy.equals(policyModel1))
+ .collect(Collectors.toList());
+ assertThat(listToCheck.get(0)).isEqualByComparingTo(policyModel2);
+ assertThat(listToCheck.get(1)).isEqualByComparingTo(policyModel1);
+ assertThat(listToCheck.get(2)).isEqualByComparingTo(policyModel3);
+ }
+
+ /**
+ * This tests the pdpgroup GSON encode/decode and saving.
+ */
+ @Test
+ @Transactional
+ public void shouldAddPdpGroupInfo() {
+ policyModelsService.saveOrUpdatePolicyModel(getPolicyModel(POLICY_MODEL_TYPE_1, "yaml",
+ POLICY_MODEL_TYPE_1_VERSION_1, "TEST", "VARIANT", "user"));
+ policyModelsService.saveOrUpdatePolicyModel(getPolicyModel(POLICY_MODEL_TYPE_2, "yaml",
+ POLICY_MODEL_TYPE_2_VERSION_2, "TEST", "VARIANT", "user"));
+ policyModelsService.saveOrUpdatePolicyModel(getPolicyModel(POLICY_MODEL_TYPE_3, "yaml",
+ POLICY_MODEL_TYPE_3_VERSION_1, "TEST", "VARIANT", "user"));
+
+ ToscaConceptIdentifier type1 = new ToscaConceptIdentifier("org.onap.testos", "1.0.0");
+ ToscaConceptIdentifier type2 = new ToscaConceptIdentifier("org.onap.testos2", "2.0.0");
+
+ PdpSubGroup pdpSubgroup1 = new PdpSubGroup();
+ pdpSubgroup1.setPdpType("subGroup1");
+ List<ToscaConceptIdentifier> pdpTypeList = new LinkedList<>();
+ pdpTypeList.add(type1);
+ pdpTypeList.add(type2);
+ pdpSubgroup1.setSupportedPolicyTypes(pdpTypeList);
+
+ ToscaConceptIdentifier type3 = new ToscaConceptIdentifier("org.onap.testos3", "2.0.0");
+ PdpSubGroup pdpSubgroup2 = new PdpSubGroup();
+ pdpSubgroup2.setPdpType("subGroup2");
+ List<ToscaConceptIdentifier> pdpTypeList2 = new LinkedList<>();
+ pdpTypeList2.add(type2);
+ pdpTypeList2.add(type3);
+ pdpSubgroup2.setSupportedPolicyTypes(pdpTypeList2);
+
+ List<PdpSubGroup> pdpSubgroupList = new LinkedList<>();
+ pdpSubgroupList.add(pdpSubgroup1);
+
+ PdpGroup pdpGroup1 = new PdpGroup();
+ pdpGroup1.setName("pdpGroup1");
+ pdpGroup1.setPdpGroupState(PdpState.ACTIVE);
+ pdpGroup1.setPdpSubgroups(pdpSubgroupList);
+
+ List<PdpSubGroup> pdpSubgroupList2 = new LinkedList<>();
+ pdpSubgroupList2.add(pdpSubgroup1);
+ pdpSubgroupList2.add(pdpSubgroup2);
+ PdpGroup pdpGroup2 = new PdpGroup();
+ pdpGroup2.setName("pdpGroup2");
+ pdpGroup2.setPdpGroupState(PdpState.ACTIVE);
+ pdpGroup2.setPdpSubgroups(pdpSubgroupList2);
+
+ List<PdpGroup> pdpGroupsList = new LinkedList<>();
+ pdpGroupsList.add(pdpGroup1);
+ pdpGroupsList.add(pdpGroup2);
+
+ PdpGroups pdpGroups = new PdpGroups();
+ pdpGroups.setGroups(pdpGroupsList);
+ policyModelsService.updatePdpGroupInfo(pdpGroups);
+
+ JsonObject res1 =
+ policyModelsService.getPolicyModel("org.onap.testos", "1.0.0").getPolicyPdpGroup();
+ String expectedRes1 =
+ "{\"supportedPdpGroups\":[{\"pdpGroup1\":[\"subGroup1\"]},{\"pdpGroup2\":[\"subGroup1\"]}]}";
+ JsonObject expectedJson1 = JsonUtils.GSON.fromJson(expectedRes1, JsonObject.class);
+ assertThat(res1).isEqualTo(expectedJson1);
+
+ JsonObject res2 =
+ policyModelsService.getPolicyModel("org.onap.testos2", "2.0.0").getPolicyPdpGroup();
+ String expectedRes2 =
+ "{\"supportedPdpGroups\":[{\"pdpGroup1\":[\"subGroup1\"]},"
+ + "{\"pdpGroup2\":[\"subGroup1\",\"subGroup2\"]}]}";
+ JsonObject expectedJson2 = JsonUtils.GSON.fromJson(expectedRes2, JsonObject.class);
+ assertThat(res2).isEqualTo(expectedJson2);
+
+ JsonObject res3 =
+ policyModelsService.getPolicyModel("org.onap.testos3", "1.0.0").getPolicyPdpGroup();
+ assertThat(res3).isNull();
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/ServiceTest.java b/runtime/src/test/java/org/onap/policy/clamp/loop/ServiceTest.java
new file mode 100644
index 000000000..8f28299fd
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/ServiceTest.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.JsonObject;
+import org.junit.Test;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.loop.service.Service;
+
+public class ServiceTest {
+
+ @Test
+ public void equalMethodTest() {
+ String serviceStr1 = "{\"name\": \"vLoadBalancerMS\", \"UUID\": \"63cac700-ab9a-4115-a74f-7eac85e3fce0\"}";
+ String serviceStr2 = "{\"name\": \"vLoadBalancerMS2\", \"UUID\": \"63cac700-ab9a-4115-a74f-7eac85e3fce0\"}";
+ String serviceStr3 = "{\"name\": \"vLoadBalancerMS\",\"UUID\": \"63cac700-ab9a-4115-a74f-7eac85e3fc11\"}";
+ String resourceStr = "{\"CP\": {}}";
+
+ Service service1 = new Service(JsonUtils.GSON.fromJson(serviceStr1, JsonObject.class),
+ JsonUtils.GSON.fromJson(resourceStr, JsonObject.class), "1.0");
+
+ Service service2 = new Service(JsonUtils.GSON.fromJson(serviceStr2, JsonObject.class), null, "1.0");
+
+ Service service3 = new Service(JsonUtils.GSON.fromJson(serviceStr3, JsonObject.class),
+ JsonUtils.GSON.fromJson(resourceStr, JsonObject.class), "1.0");
+
+ assertThat(service1.equals(service2)).isEqualTo(true);
+ assertThat(service1.equals(service3)).isEqualTo(false);
+ }
+
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/loop/deploy/BlueprintInputParametersTest.java b/runtime/src/test/java/org/onap/policy/clamp/loop/deploy/BlueprintInputParametersTest.java
new file mode 100644
index 000000000..f7f6baa0c
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/loop/deploy/BlueprintInputParametersTest.java
@@ -0,0 +1,125 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications copyright (c) 2019 Nokia
+ * Modifications Copyright (c) 2019 Samsung
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.loop.deploy;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.util.LinkedHashSet;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.loop.Loop;
+import org.onap.policy.clamp.loop.template.LoopElementModel;
+import org.onap.policy.clamp.loop.template.LoopTemplate;
+import org.onap.policy.clamp.policy.microservice.MicroServicePolicy;
+import org.onap.sdc.tosca.parser.exceptions.SdcToscaParserException;
+
+public class BlueprintInputParametersTest {
+
+ /**
+ * getDeploymentParametersinJsonMultiBlueprintsTest.
+ *
+ * @throws IOException in case of failure
+ * @throws SdcToscaParserException in case of failure
+ */
+ @Test
+ public void getDeploymentParametersinJsonMultiBlueprintsTest() throws IOException, SdcToscaParserException {
+
+
+ MicroServicePolicy umService1 = Mockito.mock(MicroServicePolicy.class);
+ Mockito.when(umService1.getName()).thenReturn("testName1");
+
+ LoopElementModel loopElement = Mockito.mock(LoopElementModel.class);
+ String blueprint1 = ResourceFileUtils.getResourceAsString("example/sdc/blueprint-dcae/tca.yaml");
+ Mockito.when(loopElement.getBlueprint()).thenReturn(blueprint1);
+ Mockito.when(umService1.getLoopElementModel()).thenReturn(loopElement);
+
+ MicroServicePolicy umService2 = Mockito.mock(MicroServicePolicy.class);
+ Mockito.when(umService2.getName()).thenReturn("testName2");
+
+ LoopElementModel loopElement2 = Mockito.mock(LoopElementModel.class);
+ String blueprint2 = ResourceFileUtils.getResourceAsString("example/sdc/blueprint-dcae/tca_2.yaml");
+ Mockito.when(loopElement2.getBlueprint()).thenReturn(blueprint2);
+ Mockito.when(umService2.getLoopElementModel()).thenReturn(loopElement2);
+
+ MicroServicePolicy umService3 = Mockito.mock(MicroServicePolicy.class);
+ Mockito.when(umService3.getName()).thenReturn("testName3");
+
+ LoopElementModel loopElement3 = Mockito.mock(LoopElementModel.class);
+ String blueprint3 = ResourceFileUtils.getResourceAsString("example/sdc/blueprint-dcae/tca_3.yaml");
+ Mockito.when(loopElement3.getBlueprint()).thenReturn(blueprint3);
+ Mockito.when(umService3.getLoopElementModel()).thenReturn(loopElement3);
+
+ LinkedHashSet<MicroServicePolicy> umServiceSet = new LinkedHashSet<>();
+ umServiceSet.add(umService1);
+ umServiceSet.add(umService2);
+ umServiceSet.add(umService3);
+ Loop loop = Mockito.mock(Loop.class);
+ Mockito.when(loop.getMicroServicePolicies()).thenReturn(umServiceSet);
+
+ LoopTemplate template = Mockito.mock(LoopTemplate.class);
+ Mockito.when(template.getUniqueBlueprint()).thenReturn(false);
+ Mockito.when(loop.getLoopTemplate()).thenReturn(template);
+
+ JsonObject paramJson = DcaeDeployParameters.getDcaeDeploymentParametersInJson(loop);
+
+ Assert.assertEquals(JsonUtils.GSON_JPA_MODEL.toJson(paramJson),
+ ResourceFileUtils.getResourceAsString(
+ "example/sdc/expected-result/deployment-parameters-multi-blueprints.json"));
+ }
+
+ /**
+ * getDeploymentParametersInJsonSingleBlueprintTest.
+ *
+ * @throws IOException In case of failure
+ * @throws SdcToscaParserException In case of failure
+ */
+ @Test
+ public void getDeploymentParametersInJsonSingleBlueprintTest() throws IOException, SdcToscaParserException {
+ Loop loop = Mockito.mock(Loop.class);
+
+ MicroServicePolicy umService1 = Mockito.mock(MicroServicePolicy.class);
+ Mockito.when(umService1.getName()).thenReturn("testName1");
+ LinkedHashSet<MicroServicePolicy> umServiceSet = new LinkedHashSet<MicroServicePolicy>();
+ umServiceSet.add(umService1);
+ Mockito.when(loop.getMicroServicePolicies()).thenReturn(umServiceSet);
+
+ LoopTemplate template = Mockito.mock(LoopTemplate.class);
+ Mockito.when(template.getUniqueBlueprint()).thenReturn(true);
+ String blueprint = ResourceFileUtils.getResourceAsString("example/sdc/blueprint-dcae/tca.yaml");
+ Mockito.when(template.getBlueprint()).thenReturn(blueprint);
+ Mockito.when(loop.getLoopTemplate()).thenReturn(template);
+
+ JsonObject paramJson = DcaeDeployParameters.getDcaeDeploymentParametersInJson(loop);
+
+ Assert.assertEquals(JsonUtils.GSON_JPA_MODEL.toJson(paramJson),
+ ResourceFileUtils.getResourceAsString(
+ "example/sdc/expected-result/deployment-parameters-single-blueprint.json"));
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/policy/downloader/PolicyEngineControllerTestItCase.java b/runtime/src/test/java/org/onap/policy/clamp/policy/downloader/PolicyEngineControllerTestItCase.java
new file mode 100644
index 000000000..657adf1d1
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/policy/downloader/PolicyEngineControllerTestItCase.java
@@ -0,0 +1,117 @@
+package org.onap.policy.clamp.policy.downloader;
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSyntaxException;
+import java.io.IOException;
+import java.time.Instant;
+import java.util.List;
+import javax.transaction.Transactional;
+import org.json.simple.parser.ParseException;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.Application;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.clamp.loop.template.PolicyModelId;
+import org.onap.policy.clamp.loop.template.PolicyModelsRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+@ActiveProfiles({"clamp-default", "clamp-policy-controller"})
+public class PolicyEngineControllerTestItCase {
+
+ @Autowired
+ PolicyEngineController policyController;
+
+ @Autowired
+ PolicyModelsRepository policyModelsRepository;
+
+ /**
+ * This method tests a fake synchronization with the emulator.
+ *
+ * @throws JsonSyntaxException In case of issues
+ * @throws IOException In case of issues
+ * @throws InterruptedException In case of issues
+ */
+ @Test
+ @Transactional
+ public void synchronizeAllPoliciesTest() throws JsonSyntaxException, IOException, InterruptedException {
+ policyController.synchronizeAllPolicies();
+ Instant firstExecution = policyController.getLastInstantExecuted();
+ assertThat(firstExecution).isNotNull();
+ List<PolicyModel> policyModelsList = policyModelsRepository.findAll();
+ assertThat(policyModelsList.size()).isGreaterThanOrEqualTo(5);
+ assertThat(policyModelsList).contains(new PolicyModel("onap.policies.controlloop.operational.common.Drools",
+ null, "1.0.0"));
+ assertThat(policyModelsList).contains(new PolicyModel("onap.policies.controlloop.operational.common.Apex",
+ null, "1.0.0"));
+ assertThat(policyModelsList)
+ .contains(new PolicyModel("onap.policies.controlloop.guard.common.FrequencyLimiter", null, "1.0.0"));
+ assertThat(policyModelsList)
+ .contains(new PolicyModel("onap.policies.controlloop.guard.common.Blacklist", null, "1.0.0"));
+ assertThat(policyModelsList)
+ .contains(new PolicyModel("onap.policies.controlloop.guard.common.MinMax", null, "2.0.0"));
+
+ // Re-do it to check that there is no issue with duplicate key
+ policyController.synchronizeAllPolicies();
+ Instant secondExecution = policyController.getLastInstantExecuted();
+ assertThat(secondExecution).isNotNull();
+
+ assertThat(firstExecution).isBefore(secondExecution);
+ }
+
+ @Test
+ @Transactional
+ public void downloadPdpGroupsTest() throws JsonSyntaxException, IOException, InterruptedException, ParseException {
+ PolicyModel policyModel1 = new PolicyModel("onap.policies.monitoring.test", null, "1.0.0");
+ policyModelsRepository.saveAndFlush(policyModel1);
+ PolicyModel policyModel2 = new PolicyModel("onap.policies.controlloop.Operational", null, "1.0.0");
+ policyModelsRepository.saveAndFlush(policyModel2);
+
+ policyController.downloadPdpGroups();
+
+ List<PolicyModel> policyModelsList = policyModelsRepository.findAll();
+ assertThat(policyModelsList.size()).isGreaterThanOrEqualTo(2);
+
+ PolicyModel policy1 = policyModelsRepository
+ .getOne(new PolicyModelId("onap.policies.monitoring.test", "1.0.0"));
+ PolicyModel policy2 = policyModelsRepository
+ .getOne(new PolicyModelId("onap.policies.controlloop.Operational", "1.0.0"));
+
+ String expectedRes1 = "{\"supportedPdpGroups\":[{\"monitoring\":[\"xacml\"]}]}";
+ JsonObject expectedJson1 = JsonUtils.GSON.fromJson(expectedRes1, JsonObject.class);
+ assertThat(policy1.getPolicyPdpGroup()).isEqualTo(expectedJson1);
+ String expectedRes2 = "{\"supportedPdpGroups\":[{\"controlloop\":[\"apex\",\"drools\"]}]}";
+ JsonObject expectedJson2 = JsonUtils.GSON.fromJson(expectedRes2, JsonObject.class);
+ assertThat(policy2.getPolicyPdpGroup()).isEqualTo(expectedJson2);
+
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/policy/microservice/MicroServicePayloadTest.java b/runtime/src/test/java/org/onap/policy/clamp/policy/microservice/MicroServicePayloadTest.java
new file mode 100644
index 000000000..4bb850c35
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/policy/microservice/MicroServicePayloadTest.java
@@ -0,0 +1,47 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.microservice;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import org.junit.Test;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+public class MicroServicePayloadTest {
+
+ @Test
+ public void testPayloadConstruction() throws IOException {
+ MicroServicePolicy policy = new MicroServicePolicy("testPolicy", new PolicyModel(
+ "onap.policies.monitoring.cdap.tca.hi.lo.app",
+ ResourceFileUtils.getResourceAsString("tosca/tosca_example.yaml"), "1.0.0"), false, null, null, null,
+ null);
+ policy.setConfigurationsJson(JsonUtils.GSON.fromJson(
+ ResourceFileUtils.getResourceAsString("tosca/micro-service-policy-properties.json"), JsonObject.class));
+ JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("tosca/micro-service-policy-payload.json"),
+ policy.createPolicyPayload(), false);
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/policy/operational/OperationalPolicyRepresentationBuilderTest.java b/runtime/src/test/java/org/onap/policy/clamp/policy/operational/OperationalPolicyRepresentationBuilderTest.java
new file mode 100644
index 000000000..136430c8f
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/policy/operational/OperationalPolicyRepresentationBuilderTest.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.operational;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import org.junit.Test;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.loop.service.Service;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+public class OperationalPolicyRepresentationBuilderTest {
+
+ @Test
+ public void testOperationalPolicyPayloadConstruction() throws IOException {
+ JsonObject jsonModel = new GsonBuilder().create().fromJson(ResourceFileUtils
+ .getResourceAsString("tosca/model-properties-operational-policy.json"), JsonObject.class);
+ Service service = new Service(jsonModel.get("serviceDetails").getAsJsonObject(),
+ jsonModel.get("resourceDetails").getAsJsonObject(), "1.0");
+
+ JsonObject jsonSchema = OperationalPolicyRepresentationBuilder.generateOperationalPolicySchema(service);
+
+ assertThat(jsonSchema).isNotNull();
+
+ JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("tosca/operational-policy-json-schema.json"),
+ new GsonBuilder().create().toJson(jsonSchema), false);
+ }
+
+ @Test
+ public void testOperationalPolicyPayloadConstructionForCds() throws IOException {
+ JsonObject jsonModel = new GsonBuilder().create()
+ .fromJson(ResourceFileUtils.getResourceAsString("tosca/model-properties-cds.json"), JsonObject.class);
+ Service service = new Service(jsonModel.get("serviceDetails").getAsJsonObject(),
+ jsonModel.get("resourceDetails").getAsJsonObject(),
+ "1.0");
+
+ JsonObject jsonSchema = OperationalPolicyRepresentationBuilder.generateOperationalPolicySchema(service);
+ assertThat(jsonSchema).isNotNull();
+ JSONAssert.assertEquals(
+ ResourceFileUtils.getResourceAsString("tosca/operational-policy-cds-payload-with-list.json"),
+ new GsonBuilder().create().toJson(jsonSchema), false);
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupAnalyzerTest.java b/runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupAnalyzerTest.java
new file mode 100644
index 000000000..30d4ebe28
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupAnalyzerTest.java
@@ -0,0 +1,231 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.pdpgroup;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.clamp.loop.template.PolicyModel;
+import org.onap.policy.models.pdp.concepts.PdpGroup;
+import org.onap.policy.models.pdp.concepts.PdpGroups;
+import org.onap.policy.models.pdp.concepts.PdpSubGroup;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+/**
+ * This test class validates the PdpGroupAnalyzer class.
+ */
+public class PdpGroupAnalyzerTest {
+
+ private static PdpGroups pdpGroups;
+ private static PdpGroup pdpGroup1;
+ private static PdpGroup pdpGroup2;
+ private static PdpGroup pdpGroup3;
+ private static PdpGroup pdpGroup4;
+
+ private static PdpSubGroup pdpSubgroupBad;
+ private static PdpSubGroup pdpSubgroup1;
+ private static PdpSubGroup pdpSubgroup2;
+ private static PdpSubGroup pdpSubgroup3;
+
+ /**
+ * This method preloads the pdpGroups for the tests.
+ */
+ @BeforeClass
+ public static void setupPdpGroup() {
+ // Create Pdp Groups
+ // Those that do not work first
+ pdpSubgroupBad = new PdpSubGroup();
+ pdpSubgroupBad.setPdpType("subGroupBad");
+ pdpSubgroupBad.setSupportedPolicyTypes(Arrays.asList(new ToscaConceptIdentifier("org.onap.test", "2.0.0"),
+ new ToscaConceptIdentifier("org.onap.test.*", "1.0.0"),
+ new ToscaConceptIdentifier("org.onip.testos", "1.0.0"),
+ new ToscaConceptIdentifier("org.onap.testos3", "2.0.0"),
+ new ToscaConceptIdentifier("org.onap.tes", "1.0.0"),
+ new ToscaConceptIdentifier("org.onap", "1.0.0")
+ ));
+ pdpSubgroupBad.setPolicies(Arrays.asList(new ToscaConceptIdentifier("org.onap", "1.0.0"),
+ new ToscaConceptIdentifier("org.onap.testos", "2.0.0"),
+ new ToscaConceptIdentifier("org.onap.testos", "1.0.1"),
+ new ToscaConceptIdentifier("org.onap.testos.new", "1.0.0"),
+ new ToscaConceptIdentifier("org.onap.", "1.0.0")));
+ pdpSubgroupBad.setPdpInstances(Collections.emptyList());
+
+ pdpSubgroup1 = new PdpSubGroup();
+ pdpSubgroup1.setPdpType("subGroup1");
+ pdpSubgroup1.setSupportedPolicyTypes(
+ Arrays.asList(new ToscaConceptIdentifier("org.onap.*", "1.0.0")));
+ pdpSubgroup1.setPdpInstances(Collections.emptyList());
+
+ pdpSubgroup2 = new PdpSubGroup();
+ pdpSubgroup2.setPdpType("subGroup2");
+ pdpSubgroup2.setSupportedPolicyTypes(Arrays.asList(new ToscaConceptIdentifier("org.onap.test", "1.0.0")));
+ pdpSubgroup2.setPolicies(Arrays.asList(new ToscaConceptIdentifier("org.onap.testos", "1.0.0")));
+ pdpSubgroup2.setPdpInstances(Collections.emptyList());
+
+ pdpSubgroup3 = new PdpSubGroup();
+ pdpSubgroup3.setPdpType("subGroup3");
+ pdpSubgroup3.setSupportedPolicyTypes(Arrays.asList(new ToscaConceptIdentifier("org.onap.test*", "1.0.0")));
+ pdpSubgroup3.setPolicies(Arrays.asList(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")));
+ pdpSubgroup3.setPdpInstances(Collections.emptyList());
+
+ // Should match pdpSubgroup1
+ pdpGroup1 = new PdpGroup();
+ pdpGroup1.setName("pdpGroup1");
+ pdpGroup1.setPdpGroupState(PdpState.ACTIVE);
+ pdpGroup1.setPdpSubgroups(Arrays.asList(pdpSubgroup1, pdpSubgroupBad));
+
+ // Should match pdpSubgroup1, pdpSubgroup2, pdpSubgroup3
+ // Should match also for the policy (pdpSubgroup2)
+ pdpGroup2 = new PdpGroup();
+ pdpGroup2.setName("pdpGroup2");
+ pdpGroup2.setPdpGroupState(PdpState.ACTIVE);
+ pdpGroup2.setPdpSubgroups(Arrays.asList(pdpSubgroup1, pdpSubgroup2, pdpSubgroup3, pdpSubgroupBad));
+
+ /// Should not match
+ pdpGroup3 = new PdpGroup();
+ pdpGroup3.setName("pdpGroup3");
+ pdpGroup3.setPdpGroupState(PdpState.ACTIVE);
+ pdpGroup3.setPdpSubgroups(Arrays.asList(pdpSubgroupBad));
+
+ // Should not match
+ pdpGroup4 = new PdpGroup();
+ pdpGroup4.setName("pdpGroup4");
+ pdpGroup4.setPdpGroupState(PdpState.TERMINATED);
+ pdpGroup4.setPdpSubgroups(Arrays.asList(pdpSubgroup1));
+
+ pdpGroups = new PdpGroups();
+ pdpGroups.setGroups(Arrays.asList(pdpGroup1, pdpGroup2, pdpGroup3, pdpGroup4));
+ }
+
+ @Test
+ public void testStructuresConstruction() {
+ PdpGroupsAnalyzer pdpGroupsAnalyzer = new PdpGroupsAnalyzer(pdpGroups);
+ assertThat(pdpGroupsAnalyzer).isNotNull();
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()).hasSize(6);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0"))).hasSize(3);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup1").getPdpSubgroups().size())
+ .isEqualTo(1);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup1").getPdpSubgroups())
+ .contains(pdpSubgroupBad);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup2").getPdpSubgroups().size())
+ .isEqualTo(2);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup2").getPdpSubgroups())
+ .contains(pdpSubgroup3);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup2").getPdpSubgroups())
+ .contains(pdpSubgroupBad);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup3").getPdpSubgroups().size())
+ .isEqualTo(1);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "2.0.0")).get("pdpGroup3").getPdpSubgroups())
+ .contains(pdpSubgroupBad);
+
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.0"))).hasSize(1);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.0")).get("pdpGroup2").getPdpSubgroups())
+ .hasSize(1);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.0")).get("pdpGroup2").getPdpSubgroups())
+ .contains(pdpSubgroup2);
+
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1"))).hasSize(3);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1")).get("pdpGroup1").getPdpSubgroups())
+ .hasSize(1);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1")).get("pdpGroup1").getPdpSubgroups())
+ .contains(pdpSubgroupBad);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1")).get("pdpGroup2").getPdpSubgroups())
+ .hasSize(1);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1")).get("pdpGroup2").getPdpSubgroups())
+ .contains(pdpSubgroupBad);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1")).get("pdpGroup3").getPdpSubgroups())
+ .hasSize(1);
+ assertThat(pdpGroupsAnalyzer.getPdpGroupsDeploymentPerPolicy()
+ .get(new ToscaConceptIdentifier("org.onap.testos", "1.0.1")).get("pdpGroup3").getPdpSubgroups())
+ .contains(pdpSubgroupBad);
+ }
+
+ @Test
+ public void testGetSupportedPdpGroupsForPolicy() throws IOException {
+ PolicyModel policyModel = new PolicyModel();
+ policyModel.setCreatedBy("user");
+ policyModel.setPolicyAcronym("TEST");
+ policyModel.setPolicyModelTosca("yaml");
+ policyModel.setPolicyModelType("org.onap.test");
+ policyModel.setUpdatedBy("user");
+ policyModel.setVersion("1.0.0");
+
+ PdpGroupsAnalyzer pdpGroupsAnalyzer = new PdpGroupsAnalyzer(pdpGroups);
+ assertThat(pdpGroupsAnalyzer).isNotNull();
+
+ assertThat(
+ JsonUtils.GSON.toJson(pdpGroupsAnalyzer.getPdpGroupsForPolicy("org.onap.testos", "2.0.0")))
+ .isEqualTo(ResourceFileUtils.getResourceAsString("example/policy/pdp-deployment-testos-2_0_0.json"));
+
+ assertThat(
+ JsonUtils.GSON.toJson(pdpGroupsAnalyzer.getPdpGroupsForPolicy("org.onap.testos", "1.0.0")))
+ .isEqualTo(ResourceFileUtils.getResourceAsString("example/policy/pdp-deployment-testos-1_0_0.json"));
+
+ assertThat(
+ pdpGroupsAnalyzer.getPdpGroupsForPolicy("org.onap.donotexist", "1.0.0"))
+ .isNull();
+ }
+
+ @Test
+ public void testUpdatePdpGroupOfPolicyModels() {
+ // Create policyModel
+ PolicyModel policyModel = new PolicyModel();
+ policyModel.setCreatedBy("user");
+ policyModel.setPolicyAcronym("TEST");
+ policyModel.setPolicyModelTosca("yaml");
+ policyModel.setPolicyModelType("org.onap.test");
+ policyModel.setUpdatedBy("user");
+ policyModel.setVersion("1.0.0");
+ PdpGroupsAnalyzer.updatePdpGroupOfPolicyModels(Arrays.asList(policyModel), pdpGroups);
+
+ assertThat(policyModel.getPolicyPdpGroup()).hasToString(
+ "{\"supportedPdpGroups\":[{\"pdpGroup1\":[\"subGroup1\"]},"
+ + "{\"pdpGroup2\":[\"subGroup1\",\"subGroup2\",\"subGroup3\"]}]}");
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayloadExceptionTest.java b/runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayloadExceptionTest.java
new file mode 100644
index 000000000..f3c3fc6cd
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayloadExceptionTest.java
@@ -0,0 +1,33 @@
+/*
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.policy.pdpgroup;
+
+import org.junit.Test;
+import org.onap.policy.clamp.policy.pdpgroup.PdpGroupPayloadException;
+import org.onap.policy.common.utils.test.ExceptionsTester;
+
+public class PdpGroupPayloadExceptionTest extends ExceptionsTester {
+
+ @Test
+ public void testPdpGroupPayloadException() {
+ test(PdpGroupPayloadException.class);
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayloadTest.java b/runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayloadTest.java
new file mode 100644
index 000000000..34674e3ec
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PdpGroupPayloadTest.java
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.pdpgroup;
+
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import org.junit.Test;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+/**
+ * This class tests the PdpGroupPayload features.
+ */
+public class PdpGroupPayloadTest {
+
+ @Test
+ public void testGeneratePdpGroupPayload() throws IOException, PdpGroupPayloadException {
+ JsonArray operations = new JsonArray();
+ operations.add("POST/pdpgroup1/pdpsubgroup1/policyname1/1.0.0");
+ operations.add("POST/pdpgroup1/pdpsubgroup1/policyname2/1.0.0");
+ operations.add("POST/pdpgroup1/pdpsubgroup1/policyname1/2.0.0");
+ operations.add("DELETE/pdpgroup2/pdpsubgroup2/policyname1/1.0.0");
+ operations.add("POST/pdpgroup2/pdpsubgroup2/policyname1/2.0.0");
+ operations.add("DELETE/pdpgroup2/pdpsubgroup2/policyname2/1.0.0");
+ JsonObject listOfOperations = new JsonObject();
+ listOfOperations.add(PdpGroupPayload.PDP_ACTIONS, operations);
+
+ PdpGroupPayload pdpGroupPayload = new PdpGroupPayload(listOfOperations);
+ JSONAssert.assertEquals(
+ ResourceFileUtils.getResourceAsString("example/policy/pdp-group-multi-policies-payload.json"),
+ pdpGroupPayload.generatePdpGroupPayload(), false);
+ }
+
+ @Test
+ public void testGeneratePdpGroupPayload_WithEmptyList() throws PdpGroupPayloadException {
+ JsonArray operations = new JsonArray();
+ JsonObject listOfOperations = new JsonObject();
+ listOfOperations.add(PdpGroupPayload.PDP_ACTIONS, operations);
+
+ PdpGroupPayload pdpGroupPayload = new PdpGroupPayload(listOfOperations);
+ JSONAssert.assertEquals("{}", pdpGroupPayload.generatePdpGroupPayload(), false);
+ }
+
+ @Test(expected = PdpGroupPayloadException.class)
+ public void testUpdatePdpGroupMap_WithEmptyEntry() throws PdpGroupPayloadException {
+ JsonArray operations = new JsonArray();
+ operations.add("");
+ JsonObject listOfOperations = new JsonObject();
+ listOfOperations.add(PdpGroupPayload.PDP_ACTIONS, operations);
+
+ PdpGroupPayload pdpGroupPayload = new PdpGroupPayload(listOfOperations);
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMergerTest.java b/runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMergerTest.java
new file mode 100644
index 000000000..be7a9d674
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/policy/pdpgroup/PoliciesPdpMergerTest.java
@@ -0,0 +1,102 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.policy.pdpgroup;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.gson.JsonObject;
+import java.io.IOException;
+import java.util.Arrays;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.clamp.clds.util.JsonUtils;
+import org.onap.policy.clamp.clds.util.ResourceFileUtils;
+import org.onap.policy.models.pdp.concepts.PdpGroup;
+import org.onap.policy.models.pdp.concepts.PdpGroups;
+import org.onap.policy.models.pdp.concepts.PdpSubGroup;
+import org.onap.policy.models.pdp.enums.PdpState;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+import org.skyscreamer.jsonassert.JSONAssert;
+
+/**
+ * This test class validates the PdpGroupAnalyzer class.
+ */
+public class PoliciesPdpMergerTest {
+
+ private static String pdpGroupsJson;
+
+ /**
+ * This method setups the pdpGroups required for the tests.
+ */
+ @BeforeClass
+ public static void setupPdpGroup() {
+ // Create Pdp Groups
+ PdpSubGroup pdpSubgroup1 = new PdpSubGroup();
+ pdpSubgroup1.setPdpType("subGroup1");
+ pdpSubgroup1.setSupportedPolicyTypes(
+ Arrays.asList(new ToscaConceptIdentifier("org.onap.*", "1.0.0")));
+
+ PdpSubGroup pdpSubgroup2 = new PdpSubGroup();
+ pdpSubgroup2.setPdpType("subGroup2");
+ pdpSubgroup2.setSupportedPolicyTypes(
+ Arrays.asList(new ToscaConceptIdentifier("onap.policies.monitoring.tcagen2", "1.0.0"),
+ new ToscaConceptIdentifier("onap.policies.controlloop.operational.common.Drools", "1.0.0")));
+ pdpSubgroup2.setPolicies(Arrays.asList(
+ new ToscaConceptIdentifier("MICROSERVICE_vLoadBalancerMS_v1_0_tcagen2_1_0_0_AV0", "1.0.0")));
+
+ PdpSubGroup pdpSubgroup3 = new PdpSubGroup();
+ pdpSubgroup3.setPdpType("subGroup3");
+ pdpSubgroup3.setSupportedPolicyTypes(
+ Arrays.asList(new ToscaConceptIdentifier("onap.policies.monitoring.tcagen2", "1.0.0"),
+ new ToscaConceptIdentifier("onap.policies.controlloop.operational.common.Drools", "1.0.0")));
+ pdpSubgroup3.setPolicies(Arrays.asList(new ToscaConceptIdentifier("org.onap.testos", "2.0.0"),
+ new ToscaConceptIdentifier("OPERATIONAL_vLoadBalancerMS_v1_0_Drools_1_0_0_7xd", "1.0.0")));
+
+ // Should match pdpSubgroup1
+ PdpGroup pdpGroup1 = new PdpGroup();
+ pdpGroup1.setName("pdpGroup1");
+ pdpGroup1.setPdpGroupState(PdpState.ACTIVE);
+ pdpGroup1.setPdpSubgroups(Arrays.asList(pdpSubgroup1));
+
+ // Should match pdpSubgroup1, pdpSubgroup2, pdpSubgroup3
+ // Should match also for the policy (pdpSubgroup2)
+ PdpGroup pdpGroup2 = new PdpGroup();
+ pdpGroup2.setName("pdpGroup2");
+ pdpGroup2.setPdpGroupState(PdpState.ACTIVE);
+ pdpGroup2.setPdpSubgroups(Arrays.asList(pdpSubgroup1, pdpSubgroup2, pdpSubgroup3));
+
+ PdpGroups pdpGroups = new PdpGroups();
+ pdpGroups.setGroups(Arrays.asList(pdpGroup1, pdpGroup2));
+
+ pdpGroupsJson = JsonUtils.GSON.toJson(pdpGroups);
+ }
+
+ @Test
+ public void testMergePoliciesAndPdpGroupStates() throws IOException {
+ JSONAssert.assertEquals(ResourceFileUtils.getResourceAsString("example/policy/policy-merger.json"),
+ PoliciesPdpMerger.mergePoliciesAndPdpGroupStates(
+ ResourceFileUtils.getResourceAsString("http-cache/example/policy/api/v1/policies/.file"),
+ pdpGroupsJson).toString(), true);
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/tosca/DictionaryServiceItCase.java b/runtime/src/test/java/org/onap/policy/clamp/tosca/DictionaryServiceItCase.java
new file mode 100644
index 000000000..fdde53a21
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/tosca/DictionaryServiceItCase.java
@@ -0,0 +1,247 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.tosca;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+import javax.persistence.EntityNotFoundException;
+import javax.transaction.Transactional;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.policy.clamp.clds.Application;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = Application.class)
+public class DictionaryServiceItCase {
+
+ @Autowired
+ private DictionaryService dictionaryService;
+
+ @Autowired
+ private DictionaryElementsRepository dictionaryElementsRepository;
+
+ private DictionaryElement getDictionaryElement(String shortName, String name,
+ String description, String type, String subDictionaryName) {
+
+ return new DictionaryElement(name, shortName, description, type, subDictionaryName);
+
+ }
+
+ private Dictionary getSimpleDictionaryExample() {
+
+ Dictionary dictionary = new Dictionary("Dictionary1", 0, null);
+
+ dictionary.addDictionaryElements(getDictionaryElement("DE1", "DictionaryElement1",
+ "DictionaryElement1", "string", null));
+
+ dictionary.addDictionaryElements(getDictionaryElement("DE2", "DictionaryElement2",
+ "DictionaryElement2", "number", null));
+
+ return dictionary;
+ }
+
+ private Dictionary getSecondaryDictionaryExample() {
+
+ Dictionary dictionary = new Dictionary("SecondaryDict", 1, "string");
+
+ dictionary.addDictionaryElements(getDictionaryElement("SDE1", "SecondaryDictElement1",
+ "SecondaryDictElement1", "string", null));
+
+ dictionary.addDictionaryElements(getDictionaryElement("SDE2", "SecondaryDictElement2",
+ "SecondaryDictElement2", "string", null));
+
+ return dictionary;
+ }
+
+ /**
+ * Test to validate that Dictionary is created.
+ */
+ @Test
+ @Transactional
+ public void shouldCreateDictionary() {
+ Dictionary dictionary = getSimpleDictionaryExample();
+ Dictionary actualDictionary = dictionaryService.saveOrUpdateDictionary(dictionary);
+ assertNotNull(actualDictionary);
+ assertThat(actualDictionary).isEqualTo(dictionary);
+ assertThat(actualDictionary.getName()).isEqualTo(dictionary.getName());
+
+ assertThat(actualDictionary.getDictionaryElements()).contains(
+ dictionaryElementsRepository.findById("DE1").get(),
+ dictionaryElementsRepository.findById("DE2").get());
+ }
+
+ /**
+ * Test to validate a DictionaryElement is created for a Dictionary.
+ */
+ @Test
+ @Transactional
+ public void shouldCreateorUpdateDictionaryElement() {
+ Dictionary dictionary = getSimpleDictionaryExample();
+ Dictionary actualDictionary = dictionaryService.saveOrUpdateDictionary(dictionary);
+ DictionaryElement dictionaryElement =
+ getDictionaryElement("DictionaryElement3", "DE3", "DictionaryElement3", "date", null);
+ actualDictionary.addDictionaryElements(dictionaryElement);
+ Dictionary updatedDictionary = dictionaryService
+ .saveOrUpdateDictionaryElement(actualDictionary.getName(), actualDictionary);
+ assertNotNull(updatedDictionary);
+ assertTrue(updatedDictionary.getDictionaryElements().contains(dictionaryElement));
+ assertThat(updatedDictionary.getName()).isEqualTo(actualDictionary.getName());
+ // update the dictionary element.
+ dictionaryElement.setDescription("DictionaryElement3 New Description");
+ Dictionary dictionary3 = new Dictionary("Dictionary1", 0, null);
+ dictionary3.addDictionaryElements(dictionaryElement);
+ Dictionary updatedDictionary2 =
+ dictionaryService.saveOrUpdateDictionaryElement(dictionary3.getName(), dictionary3);
+
+ assertNotNull(updatedDictionary2);
+ assertTrue(updatedDictionary2.getDictionaryElements().contains(dictionaryElement));
+ updatedDictionary2.getDictionaryElements().forEach(element -> {
+ if (element.equals(dictionaryElement)) {
+ assertTrue(element.getDescription().equals(dictionaryElement.getDescription()));
+ }
+ });
+
+ }
+
+ /**
+ * Test to validate that All Dictionaries are retrieved.
+ */
+ @Test
+ @Transactional
+ public void shouldReturnAllDictionaries() {
+ Dictionary dictionary = getSimpleDictionaryExample();
+ Dictionary secondaryDictionary = getSecondaryDictionaryExample();
+ dictionaryService.saveOrUpdateDictionary(dictionary);
+ dictionaryService.saveOrUpdateDictionary(secondaryDictionary);
+
+ List<Dictionary> list = dictionaryService.getAllDictionaries();
+ assertNotNull(list);
+ assertThat(list).contains(dictionary, secondaryDictionary);
+ }
+
+ /**
+ * Test to validate one Dictionary is returned.
+ */
+ @Test
+ @Transactional
+ public void shouldReturnOneDictionary() {
+ Dictionary dictionary = getSimpleDictionaryExample();
+ dictionaryService.saveOrUpdateDictionary(dictionary);
+
+ Dictionary returnedDictionary = dictionaryService.getDictionary("Dictionary1");
+ assertNotNull(returnedDictionary);
+ assertThat(returnedDictionary).isEqualTo(dictionary);
+ assertThat(returnedDictionary.getDictionaryElements())
+ .isEqualTo(dictionary.getDictionaryElements());
+ }
+
+ /**
+ * Test to validate one Dictionary is returned.
+ */
+ @Test
+ @Transactional
+ public void shouldReturnEntityNotFoundException() {
+ try {
+ dictionaryService.getDictionary("Test");
+ } catch (Exception e) {
+ assertThat(e).isInstanceOf(EntityNotFoundException.class);
+ assertTrue(e.getMessage().equals("Couldn't find Dictionary named: Test"));
+ }
+ }
+
+ /**
+ * Test to validate Dictionary is deleted.
+ */
+ @Test
+ @Transactional
+ public void shouldDeleteDictionaryByObject() {
+ Dictionary dictionary = getSimpleDictionaryExample();
+ Dictionary returnedDictionary = dictionaryService.saveOrUpdateDictionary(dictionary);
+
+ dictionaryService.deleteDictionary(returnedDictionary);
+ try {
+ dictionaryService.getDictionary("Dictionary1");
+ } catch (EntityNotFoundException e) {
+ assertTrue(e.getMessage().equals("Couldn't find Dictionary named: Dictionary1"));
+ }
+ }
+
+ /**
+ * Test to validate Dictionary is deleted by Name.
+ */
+ @Test
+ @Transactional
+ public void shouldDeleteDictionaryByName() {
+ Dictionary dictionary = getSimpleDictionaryExample();
+ dictionaryService.saveOrUpdateDictionary(dictionary);
+ dictionaryService.deleteDictionary(dictionary.getName());
+ try {
+ dictionaryService.getDictionary("Dictionary1");
+ } catch (EntityNotFoundException e) {
+ assertTrue(e.getMessage().equals("Couldn't find Dictionary named: Dictionary1"));
+ }
+ }
+
+ /**
+ * Test to validate DictionaryElements is deleted by Name.
+ */
+ @Test
+ @Transactional
+ public void shouldDeleteDictionaryElementsByName() {
+ Dictionary dictionary = getSimpleDictionaryExample();
+ dictionaryService.saveOrUpdateDictionary(dictionary);
+ DictionaryElement dictionaryElement =
+ dictionaryElementsRepository.findById("DE1").orElse(null);
+ assertNotNull(dictionaryElement);
+ dictionaryService.deleteDictionaryElement("Dictionary1", "DE1");
+ dictionary = dictionaryService.getDictionary("Dictionary1");
+ DictionaryElement deletedDictionaryElement =
+ dictionaryElementsRepository.findById("DE1").orElse(null);
+ assertThat(deletedDictionaryElement).isNotIn(dictionary.getDictionaryElements());
+ }
+
+ /**
+ * Test to validate all secondary level dictionary names are returned.
+ */
+ @Test
+ @Transactional
+ public void shouldReturnAllSecondaryLevelDictionaryNames() {
+ Dictionary dictionary = getSecondaryDictionaryExample();
+ dictionaryService.saveOrUpdateDictionary(dictionary);
+
+ Dictionary dictionary2 = new Dictionary("SecondaryDict2", 1, "string");
+ dictionaryService.saveOrUpdateDictionary(dictionary2);
+ List<String> secondaryDictionaryNames =
+ dictionaryService.getAllSecondaryLevelDictionaryNames();
+
+ assertNotNull(secondaryDictionaryNames);
+ assertThat(secondaryDictionaryNames).contains(dictionary.getName(), dictionary2.getName());
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/util/PassDecoderTest.java b/runtime/src/test/java/org/onap/policy/clamp/util/PassDecoderTest.java
new file mode 100644
index 000000000..7fd0cb91d
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/util/PassDecoderTest.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP POLICY-CLAMP
+ * ================================================================================
+ * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.util;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+
+public class PassDecoderTest {
+
+ private final String encrypted = "enc:WWCxchk4WGBNSvuzLq3MLjMs5ObRybJtts5AI0XD1Vc";
+
+ @Test
+ public final void testDecryptionNoKeyfile() throws Exception {
+ String decodedPass = PassDecoder.decode(encrypted, null);
+ assertEquals(decodedPass, encrypted);
+ }
+
+ @Test
+ public final void testDecryptionNoPassword() throws Exception {
+ String decodedPass = PassDecoder.decode(null, "classpath:clds/aaf/org.onap.clamp.keyfile");
+ assertNull(decodedPass);
+ }
+
+ @Test
+ public final void testDecryption() throws Exception {
+ String decodedPass = PassDecoder.decode(encrypted, "classpath:clds/aaf/org.onap.clamp.keyfile");
+ assertEquals(decodedPass, "China in the Spring");
+ assertEquals("Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U", PassDecoder
+ .decode("enc:JPV4p067JlSXt2Fet9bfuI8JpkS4ZGYVcgypcPs98gXjgjCjTze_d3JxqmlKaaakdiOjIcEC_MJh6-5pJTLgdc",
+ "classpath:clds/aaf/org.onap.clamp.keyfile"));
+ }
+}
diff --git a/runtime/src/test/java/org/onap/policy/clamp/util/SemanticVersioningTest.java b/runtime/src/test/java/org/onap/policy/clamp/util/SemanticVersioningTest.java
new file mode 100644
index 000000000..604ce55db
--- /dev/null
+++ b/runtime/src/test/java/org/onap/policy/clamp/util/SemanticVersioningTest.java
@@ -0,0 +1,91 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP CLAMP
+ * ================================================================================
+ * Copyright (C) 2020 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END============================================
+ * ===================================================================
+ *
+ */
+
+package org.onap.policy.clamp.util;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import org.junit.Test;
+
+public class SemanticVersioningTest {
+
+ /**
+ * compare test.
+ */
+ @Test
+ public void compareTest() {
+ assertThat(SemanticVersioning.compare("1.0.0", "2.0.0")).isEqualTo(-1);
+ assertThat(SemanticVersioning.compare("1.5.0", "2.0.0")).isEqualTo(-1);
+ assertThat(SemanticVersioning.compare("1.5.0", "2.1.0")).isEqualTo(-1);
+ assertThat(SemanticVersioning.compare("1.5.3", "2.0.0")).isEqualTo(-1);
+ assertThat(SemanticVersioning.compare("2.5.3", "2.6.0")).isEqualTo(-1);
+ assertThat(SemanticVersioning.compare("2.5", "2.5.1")).isEqualTo(-1);
+ assertThat(SemanticVersioning.compare("2.5.0", "2.5.1")).isEqualTo(-1);
+ assertThat(SemanticVersioning.compare("2.5.0.0", "2.5.1")).isEqualTo(-1);
+ assertThat(SemanticVersioning.compare("2.5.1.0", "2.5.1")).isEqualTo(1);
+
+ assertThat(SemanticVersioning.compare("2.0.0", "1.0.0")).isEqualTo(1);
+ assertThat(SemanticVersioning.compare("2.0.0", "1.5.0")).isEqualTo(1);
+ assertThat(SemanticVersioning.compare("2.1.0", "1.5.0")).isEqualTo(1);
+ assertThat(SemanticVersioning.compare("2.0.0", "1.5.3")).isEqualTo(1);
+ assertThat(SemanticVersioning.compare("2.6.0", "2.5.3")).isEqualTo(1);
+ assertThat(SemanticVersioning.compare("2.5.1", "2.5")).isEqualTo(1);
+ assertThat(SemanticVersioning.compare("2.5.1", "2.5.0")).isEqualTo(1);
+ assertThat(SemanticVersioning.compare("2.5.1", "2.5.0.0")).isEqualTo(1);
+ assertThat(SemanticVersioning.compare("1", "1.2.3.0")).isEqualTo(-1);
+ assertThat(SemanticVersioning.compare("1.2", "1")).isEqualTo(1);
+ }
+
+ /**
+ * Compare test.
+ */
+ @Test
+ public void compareEqualsTest() {
+ assertThat(SemanticVersioning.compare("1.0.0", "1.0.0")).isEqualTo(0);
+ assertThat(SemanticVersioning.compare("1.0.0.0", "1.0.0")).isEqualTo(1);
+ assertThat(SemanticVersioning.compare("1.2.3", "1.2.3")).isEqualTo(0);
+ assertThat(SemanticVersioning.compare("1.2.3", "1.2.3.0")).isEqualTo(-1);
+
+ }
+
+ /**
+ * Compare with null.
+ */
+ @Test
+ public void compareNullTest() {
+ assertThat(SemanticVersioning.compare(null, null)).isEqualTo(0);
+ assertThat(SemanticVersioning.compare(null, "1.0")).isEqualTo(-1);
+ assertThat(SemanticVersioning.compare("1.0", null)).isEqualTo(1);
+ }
+
+ /**
+ * Increment major version test.
+ */
+ @Test
+ public void incrementVersionTest() {
+ assertThat(SemanticVersioning.incrementMajorVersion("1.0")).isEqualTo("2.0.0");
+ assertThat(SemanticVersioning.incrementMajorVersion("1.0.0")).isEqualTo("2.0.0");
+ assertThat(SemanticVersioning.incrementMajorVersion("1")).isEqualTo("2.0.0");
+ assertThat(SemanticVersioning.incrementMajorVersion("1.2.3")).isEqualTo("2.0.0");
+ }
+}
diff --git a/runtime/src/test/resources/application.properties b/runtime/src/test/resources/application.properties
new file mode 100644
index 000000000..bc513e9e4
--- /dev/null
+++ b/runtime/src/test/resources/application.properties
@@ -0,0 +1,180 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP POLICY-CLAMP
+# ================================================================================
+# Copyright (C) 2017-2018, 2021 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+# ============LICENSE_END============================================
+# ===================================================================
+#
+###
+
+### Set the port for HTTP or HTTPS protocol (Controlled by Spring framework, only one at a time).
+### (See below for the parameter 'server.http.port' if you want to have both enabled)
+### To have only HTTP, keep the lines server.ssl.* commented
+### To have only HTTPS enabled, uncomment the server.ssl.* lines and specify a right keystore location
+server.port=${clamp.it.tests.http}
+### Settings for HTTPS (this automatically enables the HTTPS on the port 'server.port')
+#server.ssl.key-store=file:/tmp/mykey.jks
+#server.ssl.key-store-password=pass
+#server.ssl.key-password=pass
+
+clamp.config.keyFile=classpath:clds/aaf/org.onap.clamp.keyfile
+
+### In order to be user friendly when HTTPS is enabled,
+### you can add another HTTP port that will be automatically redirected to HTTPS
+### by enabling this parameter (server.http.port) and set it to another port (80 or 8080, 8090, etc ...)
+#server.http-to-https-redirection.port=8090
+
+### HTTP Example:
+###--------------
+### server.port=8080
+
+### HTTPS Example:
+### --------------
+### server.port=8443
+### server.ssl.key-store=file:/tmp/mykey.jks
+### server.ssl.key-store-password=mypass
+### server.ssl.key-password=mypass
+
+### HTTP (Redirected to HTTPS) and HTTPS Example:
+### --------------------------------------------
+### server.port=8443 <-- The HTTPS port
+### server.ssl.key-store=file:/tmp/mykey.jks
+### server.ssl.key-store-password=mypass
+### server.ssl.key-password=mypass
+### server.http-to-https-redirection.port=8090 <-- The HTTP port
+
+server.servlet.context-path=/
+#Modified engine-rest applicationpath
+spring.profiles.active=clamp-default,clamp-default-user
+spring.http.converters.preferred-json-mapper=gson
+
+#The max number of active threads in this pool
+server.tomcat.max-threads=200
+#The minimum number of threads always kept alive
+server.tomcat.min-Spare-Threads=25
+#The number of milliseconds before an idle thread shutsdown, unless the number of active threads are less or equal to minSpareThreads
+server.tomcat.max-idle-time=60000
+
+#Servlet context parameters
+server.context_parameters.p-name=value #context parameter with p-name as key and value as value.
+
+camel.springboot.consumer-template-cache-size=1000
+camel.springboot.producer-template-cache-size=1000
+# JMX enabled to have Camel Swagger runtime working
+camel.springboot.jmx-enabled=true
+camel.defaultthreadpool.poolsize=10
+camel.defaultthreadpool.maxpoolsize=20
+camel.defaultthreadpool.maxqueuesize=1000
+camel.defaultthreadpool.keepaliveTime=60
+camel.defaultthreadpool.rejectpolicy=CallerRuns
+camel.springboot.xml-routes=classpath:/clds/camel/routes/*.xml
+camel.springboot.xml-rests=classpath:/clds/camel/rest/*.xml
+camel.springboot.backlog-tracing=true
+camel.springboot.tracing=true
+camel.springboot.message-history=true
+
+#clds datasource connection details
+spring.datasource.driverClassName=org.mariadb.jdbc.Driver
+spring.datasource.url=jdbc:mariadb:sequential://localhost:3306,localhost:${docker.mariadb.port.host}/cldsdb4?autoReconnect=true&connectTimeout=10000&socketTimeout=10000&retriesAllDown=3
+spring.datasource.username=clds
+spring.datasource.password=sidnnd83K
+spring.datasource.validationQuery=SELECT 1
+spring.datasource.validationQueryTimeout=20000
+spring.datasource.validationInterval=30000
+spring.datasource.testWhileIdle = true
+spring.datasource.minIdle = 0
+spring.datasource.initialSize=0
+# Automatically test whether a connection provided is good or not
+spring.datasource.testOnBorrow=true
+spring.datasource.ignoreExceptionOnPreLoad=true
+
+spring.jpa.properties.javax.persistence.schema-generation.database.action=none
+#spring.jpa.properties.javax.persistence.schema-generation.create-source=metadata
+#spring.jpa.properties.javax.persistence.schema-generation.scripts.action=create
+#spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.sql
+# disable Hibernate DDL generation because the schema will be generated from a sql script
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
+spring.jpa.properties.hibernate.ddl-auto=validate
+spring.jpa.properties.hibernate.hbm2ddl.delimiter=;
+spring.jpa.properties.hibernate.format_sql=true
+spring.jpa.properties.hibernate.use-new-id-generator-mappings=true
+
+# Whether to enable logging of SQL statements.
+#spring.jpa.show-sql=true
+
+#Async Executor default Parameters
+async.core.pool.size=10
+async.max.pool.size=20
+async.queue.capacity=500
+
+#For EELF logback file
+#com.att.eelf.logging.path=
+clamp.config.logback.filename=logback-default.xml
+#The log folder that will be used in logback.xml file
+clamp.config.log.path=log
+clamp.config.files.systemProperties=classpath:/system.properties
+clamp.config.files.cldsUsers=classpath:/clds/clds-users.json
+clamp.config.files.globalProperties=classpath:/clds/templates/globalProperties.json
+clamp.config.files.sdcController=classpath:/clds/sdc-controllers-config.json
+
+clamp.config.httpclient.socketTimeout=20000
+clamp.config.httpclient.connectTimeout=10000
+
+#
+# Configuration Settings for Policy Engine Components
+clamp.config.policy.api.url=http://localhost:${docker.http-cache.port.host}
+clamp.config.policy.api.userName=healthcheck
+clamp.config.policy.api.password=zb!XztG34
+clamp.config.policy.pap.url=http://localhost:${docker.http-cache.port.host}
+clamp.config.policy.pap.userName=healthcheck
+clamp.config.policy.pap.password=zb!XztG34
+
+# Sdc service properties
+#
+clamp.config.sdc.csarFolder = ${project.build.directory}/sdc-tests
+
+#DCAE Inventory Url Properties
+clamp.config.dcae.inventory.url=http://localhost:${docker.http-cache.port.host}
+clamp.config.dcae.intentory.retry.interval=100
+clamp.config.dcae.intentory.retry.limit=1
+
+#DCAE Deployment Url Properties
+clamp.config.dcae.deployment.url=http://localhost:${docker.http-cache.port.host}
+clamp.config.dcae.deployment.userName=test
+clamp.config.dcae.deployment.password=test
+
+#Define user permission related parameters, the permission type can be changed but MUST be redefined in clds-users.properties in that case !
+clamp.config.security.permission.type.cl=org.onap.clamp.clds.cl
+clamp.config.security.permission.type.cl.manage=org.onap.clamp.clds.cl.manage
+clamp.config.security.permission.type.cl.event=org.onap.clamp.clds.cl.event
+clamp.config.security.permission.type.filter.vf=org.onap.clamp.clds.filter.vf
+clamp.config.security.permission.type.template=org.onap.clamp.clds.template
+clamp.config.security.permission.type.tosca=org.onap.clamp.clds.tosca
+clamp.config.security.permission.type.policies=org.onap.clamp.clds.policies
+#This one indicates the type of instances (dev|prod|perf...), this must be set accordingly in clds-users.properties
+clamp.config.security.permission.instance=dev
+clamp.config.security.authentication.class=org.onap.aaf.cadi.principal.X509Principal, org.onap.aaf.cadi.principal.CachedBasicPrincipal
+
+# Configuration settings for CDS
+clamp.config.cds.url=http://localhost:${docker.http-cache.port.host}
+clamp.config.cds.userName=ccsdkapps
+clamp.config.cds.password=ccsdkapps
+
+## Tosca converter
+clamp.config.tosca.converter.json.schema.templates=classpath:/clds/tosca-converter/templates.json
+clamp.config.tosca.converter.default.datatypes=classpath:/clds/tosca-converter/default-tosca-types.yaml
+clamp.config.tosca.converter.dictionary.support.enabled=true \ No newline at end of file
diff --git a/runtime/src/test/resources/clds/blueprint-with-microservice-chain.yaml b/runtime/src/test/resources/clds/blueprint-with-microservice-chain.yaml
new file mode 100644
index 000000000..0e9e4bc8c
--- /dev/null
+++ b/runtime/src/test/resources/clds/blueprint-with-microservice-chain.yaml
@@ -0,0 +1,202 @@
+tosca_definitions_version: cloudify_dsl_1_3
+
+description: >
+ This blueprint deploys/manages the TCA module as a Docker container
+
+imports:
+ - http://www.getcloudify.org/spec/cloudify/3.4/types.yaml
+ - https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R4/k8splugin/1.4.12/k8splugin_types.yaml
+ - https://nexus.onap.org/service/local/repositories/raw/content/org.onap.dcaegen2.platform.plugins/R4/dcaepolicyplugin/2.3.0/dcaepolicyplugin_types.yaml
+inputs:
+ aaiEnrichmentHost:
+ type: string
+ default: "aai.onap.svc.cluster.local"
+ aaiEnrichmentPort:
+ type: string
+ default: "8443"
+ enableAAIEnrichment:
+ type: string
+ default: true
+ dmaap_host:
+ type: string
+ default: message-router.onap.svc.cluster.local
+ dmaap_port:
+ type: string
+ default: "3904"
+ enableRedisCaching:
+ type: string
+ default: false
+ redisHosts:
+ type: string
+ default: dcae-redis.onap.svc.cluster.local:6379
+ tag_version:
+ type: string
+ default: "nexus3.onap.org:10001/onap/org.onap.dcaegen2.deployments.tca-cdap-container:1.1.0-STAGING-latest"
+ consul_host:
+ type: string
+ default: consul-server.onap.svc.cluster.local
+ consul_port:
+ type: string
+ default: "8500"
+ cbs_host:
+ type: string
+ default: "config-binding-service.dcae.svc.cluster.local"
+ cbs_port:
+ type: string
+ default: "10000"
+ policy_id:
+ type: string
+ default: "none"
+ external_port:
+ type: string
+ description: Kubernetes node port on which CDAPgui is exposed
+ default: "32012"
+ policy_model_id:
+ type: string
+ default: "onap.policies.monitoring.cdap.tca.hi.lo.app"
+
+node_templates:
+ first_app:
+ type: dcae.nodes.ContainerizedServiceComponent
+ properties:
+ service_component_type: 'dcaegen2-analytics-tca'
+ application_config: {}
+ docker_config: {}
+ image:
+ get_input: tag_version
+ log_info:
+ log_directory: "/opt/app/TCAnalytics/logs"
+ relationships:
+ - target: tca_policy_1
+ type: cloudify.relationships.depends_on
+ second_app:
+ type: dcae.nodes.ContainerizedServiceComponent
+ relationships:
+ - target: tca_policy_2
+ type: cloudify.relationships.depends_on
+ - type: clamp_node.relationships.gets_input_from
+ target: first_app
+ properties:
+ service_component_type: 'dcaegen2-analytics-tca'
+ application_config: {}
+ docker_config: {}
+ image:
+ get_input: tag_version