From 0d97a835fa2052ded5a31e8921baf641c8e9bb57 Mon Sep 17 00:00:00 2001 From: Kanagaraj Manickam k00365106 Date: Mon, 11 Dec 2017 20:34:44 +0530 Subject: Make Http as separate plugin Issue-ID: CLI-66 Change-Id: I8ad78f417f6dbb00e29effdd3ed8ec1939aee81d Signed-off-by: Kanagaraj Manickam k00365106 --- .../fw/http/auth/OnapCommandHttpAuthClient.java | 160 ++++++++ .../cli/fw/http/auth/OnapCommandHttpService.java | 101 +++++ .../cli/fw/http/cmd/BasicAuthLoginCommand.java | 48 +++ .../cli/fw/http/cmd/BasicAuthLogoutCommand.java | 29 ++ .../org/onap/cli/fw/http/cmd/CatalogCommand.java | 28 ++ .../org/onap/cli/fw/http/cmd/OnapHttpCommand.java | 203 ++++++++++ .../cli/fw/http/conf/OnapCommandHttpConstants.java | 90 +++++ .../org/onap/cli/fw/http/connect/HttpInput.java | 139 +++++++ .../org/onap/cli/fw/http/connect/HttpResult.java | 77 ++++ .../cli/fw/http/connect/OnapHttpConnection.java | 349 +++++++++++++++++ .../http/error/OnapCommandFailedMocoGenerate.java | 41 ++ .../cli/fw/http/error/OnapCommandHttpFailure.java | 46 +++ .../http/error/OnapCommandHttpHeaderNotFound.java | 32 ++ .../error/OnapCommandHttpInvalidResponseBody.java | 39 ++ .../error/OnapCommandHttpInvalidResultMap.java | 34 ++ .../cli/fw/http/error/OnapCommandLoginFailed.java | 43 +++ .../cli/fw/http/error/OnapCommandLogoutFailed.java | 42 ++ .../fw/http/error/OnapCommandServiceNotFound.java | 32 ++ .../http/schema/OnapCommandSchemaHttpLoader.java | 427 +++++++++++++++++++++ .../cli/fw/http/utils/OnapCommandHttpUtils.java | 233 +++++++++++ .../services/org.onap.cli.fw.cmd.OnapCommand | 4 + .../src/main/resources/open-cli-http.properties | 18 + .../open-cli-schema/http/basic-login.yaml | 19 + .../open-cli-schema/http/basic-logout.yaml | 19 + .../resources/open-cli-schema/http/catalog.yaml | 44 +++ .../http/default_input_parameters_http.yaml | 36 ++ .../org/onap/cli/fw/cmd/OnapHttpCommandTest.java | 80 ++++ .../org/onap/cli/fw/http/HttpInputOutputTest.java | 69 ++++ .../onap/cli/fw/http/OnapHttpConnectionTest.java | 208 ++++++++++ .../http/auth/OnapAuthClientCommandBasedTest.java | 121 ++++++ .../org/onap/cli/fw/http/auth/OnapServiceTest.java | 38 ++ .../cli/fw/http/error/OnapCommandErrorTest.java | 84 ++++ .../cli/fw/http/schema/ValidateSchemaTest.java | 39 ++ .../cli/fw/http/utils/OnapCommandUtilsTest.java | 139 +++++++ .../services/org.onap.cli.fw.cmd.OnapCommand | 0 .../open-cli-schema/sample-test1-schema-http.yaml | 95 +++++ .../resources/open-cli-schema/testauth-login.yaml | 28 ++ .../resources/open-cli-schema/testauth-logout.yaml | 19 + .../http/src/test/resources/open-cli.properties | 31 ++ .../sample-test-schema-auth-required.yaml | 16 + .../test/resources/sample-test-schema-http.yaml | 92 +++++ .../sample-test-schema-no-auth-no-catalog.yaml | 26 ++ .../sample-test-schema-no-auth-yes-catalog.yaml | 28 ++ .../test/resources/sample-test-schema-swagger.yaml | 28 ++ .../sample-test-schema-yes-auth-no-catalog.yaml | 26 ++ ...yes-auth-with-additional-params-no-catalog.yaml | 28 ++ .../sample-test-schema-yes-auth-yes-catalog.yaml | 28 ++ .../src/test/resources/schema-validate-http.yaml | 98 +++++ 48 files changed, 3654 insertions(+) create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/auth/OnapCommandHttpAuthClient.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/auth/OnapCommandHttpService.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/cmd/BasicAuthLoginCommand.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/cmd/BasicAuthLogoutCommand.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/cmd/CatalogCommand.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/cmd/OnapHttpCommand.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/conf/OnapCommandHttpConstants.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/connect/HttpInput.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/connect/HttpResult.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/connect/OnapHttpConnection.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandFailedMocoGenerate.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpFailure.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpHeaderNotFound.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpInvalidResponseBody.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpInvalidResultMap.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandLoginFailed.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandLogoutFailed.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandServiceNotFound.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/schema/OnapCommandSchemaHttpLoader.java create mode 100644 profiles/http/src/main/java/org/onap/cli/fw/http/utils/OnapCommandHttpUtils.java create mode 100644 profiles/http/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand create mode 100644 profiles/http/src/main/resources/open-cli-http.properties create mode 100644 profiles/http/src/main/resources/open-cli-schema/http/basic-login.yaml create mode 100644 profiles/http/src/main/resources/open-cli-schema/http/basic-logout.yaml create mode 100644 profiles/http/src/main/resources/open-cli-schema/http/catalog.yaml create mode 100644 profiles/http/src/main/resources/open-cli-schema/http/default_input_parameters_http.yaml create mode 100644 profiles/http/src/test/java/org/onap/cli/fw/cmd/OnapHttpCommandTest.java create mode 100644 profiles/http/src/test/java/org/onap/cli/fw/http/HttpInputOutputTest.java create mode 100644 profiles/http/src/test/java/org/onap/cli/fw/http/OnapHttpConnectionTest.java create mode 100644 profiles/http/src/test/java/org/onap/cli/fw/http/auth/OnapAuthClientCommandBasedTest.java create mode 100644 profiles/http/src/test/java/org/onap/cli/fw/http/auth/OnapServiceTest.java create mode 100644 profiles/http/src/test/java/org/onap/cli/fw/http/error/OnapCommandErrorTest.java create mode 100644 profiles/http/src/test/java/org/onap/cli/fw/http/schema/ValidateSchemaTest.java create mode 100644 profiles/http/src/test/java/org/onap/cli/fw/http/utils/OnapCommandUtilsTest.java create mode 100644 profiles/http/src/test/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand create mode 100644 profiles/http/src/test/resources/open-cli-schema/sample-test1-schema-http.yaml create mode 100644 profiles/http/src/test/resources/open-cli-schema/testauth-login.yaml create mode 100644 profiles/http/src/test/resources/open-cli-schema/testauth-logout.yaml create mode 100644 profiles/http/src/test/resources/open-cli.properties create mode 100644 profiles/http/src/test/resources/sample-test-schema-auth-required.yaml create mode 100644 profiles/http/src/test/resources/sample-test-schema-http.yaml create mode 100644 profiles/http/src/test/resources/sample-test-schema-no-auth-no-catalog.yaml create mode 100644 profiles/http/src/test/resources/sample-test-schema-no-auth-yes-catalog.yaml create mode 100644 profiles/http/src/test/resources/sample-test-schema-swagger.yaml create mode 100644 profiles/http/src/test/resources/sample-test-schema-yes-auth-no-catalog.yaml create mode 100644 profiles/http/src/test/resources/sample-test-schema-yes-auth-with-additional-params-no-catalog.yaml create mode 100644 profiles/http/src/test/resources/sample-test-schema-yes-auth-yes-catalog.yaml create mode 100644 profiles/http/src/test/resources/schema-validate-http.yaml (limited to 'profiles/http/src') diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/auth/OnapCommandHttpAuthClient.java b/profiles/http/src/main/java/org/onap/cli/fw/http/auth/OnapCommandHttpAuthClient.java new file mode 100644 index 00000000..af02afdd --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/auth/OnapCommandHttpAuthClient.java @@ -0,0 +1,160 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.auth; + +import java.util.HashMap; +import java.util.Map; + +import org.onap.cli.fw.cmd.OnapCommand; +import org.onap.cli.fw.conf.OnapCommandConfig; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandInvalidParameterValue; +import org.onap.cli.fw.http.cmd.OnapHttpCommand; +import org.onap.cli.fw.http.conf.OnapCommandHttpConstants; +import org.onap.cli.fw.http.connect.HttpInput; +import org.onap.cli.fw.http.connect.HttpResult; +import org.onap.cli.fw.http.connect.OnapHttpConnection; +import org.onap.cli.fw.http.error.OnapCommandHttpFailure; +import org.onap.cli.fw.http.schema.OnapCommandSchemaHttpLoader; +import org.onap.cli.fw.output.OnapCommandResultAttribute; +import org.onap.cli.fw.registrar.OnapCommandRegistrar; +import org.onap.cli.fw.utils.OnapCommandUtils; + +/** + * Oclip Auth client helps to do login and logout. + * + */ +public class OnapCommandHttpAuthClient { + + private OnapHttpCommand cmd = null; + + private OnapHttpConnection http = null; + + public OnapCommandHttpAuthClient(OnapHttpCommand cmd, boolean debug) throws OnapCommandHttpFailure, OnapCommandInvalidParameterValue { + this.cmd = cmd; + this.http = new OnapHttpConnection(debug); + } + + /** + * Login. + * + * @throws OnapCommandException + * exception + */ + public void login() throws OnapCommandException { + + // For development purpose, its introduced and is not supported for production + if (Boolean.parseBoolean(OnapCommandConfig.getPropertyValue(OnapCommandHttpConstants.OPEN_IGNORE_AUTH))) { + return; + } + + OnapCommand login = OnapCommandSchemaHttpLoader.findAuthCommand(this.cmd, "login"); + + OnapCommandUtils.copyParamsFrom(this.cmd, login); + login.execute(); + + //It is safely assumed that all outputs are considered as common http headers. + Map headers = new HashMap<>(); + for (OnapCommandResultAttribute attr: login.getResult().getRecords()) { + String headerValue = attr.getValues().get(0); + if (headerValue != null && !headerValue.isEmpty()) { + headers.put(attr.getName(), attr.getValues().get(0)); + } + } + + this.http.setCommonHeaders(headers); + } + + /** + * Logout. + * + * @throws OnapCommandException + * exception + */ + public void logout() throws OnapCommandException { + // For development purpose, its introduced and is not supported for production + if (Boolean.parseBoolean(OnapCommandConfig.getPropertyValue(OnapCommandHttpConstants.OPEN_IGNORE_AUTH))) { + return; + } + + OnapCommand logout = OnapCommandSchemaHttpLoader.findAuthCommand(this.cmd, "logout"); + + OnapCommandUtils.copyParamsFrom(this.cmd, logout); + + logout.execute(); + + this.http.close(); + } + + /** + * Find given service base path. + * + * @throws OnapCommandException + * exception + */ + public String getServiceUrl() throws OnapCommandException { + return this.getServiceUrl(this.cmd); + } + + private String getServiceUrl(OnapHttpCommand cmd) throws OnapCommandException { + if (cmd.getService().isModeDirect()){ + return cmd.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_HOST_URL).getValue().toString(); + } else { //Catalog mode + OnapCommand catalog = OnapCommandRegistrar.getRegistrar().get("catalog"); + + Map paramsOverrides = new HashMap<>(); + paramsOverrides.put(OnapCommandHttpConstants.CATALOG_SERVICE_NAME, cmd.getService().getName()); + paramsOverrides.put(OnapCommandHttpConstants.CATALOG_SERVICE_VERSION, cmd.getService().getVersion()); + + OnapCommandUtils.copyParamsFrom(cmd, catalog, paramsOverrides); + + catalog.execute(); + + String hostUrl = catalog.getResult().getRecordsMap().get(OnapCommandHttpConstants.CATALOG_SERVICE_HOST_URL).getValues().get(0); + hostUrl = hostUrl.trim(); + if (hostUrl.endsWith("/")) { + hostUrl = hostUrl.substring(0, hostUrl.length()-1); + } + + String basePath = catalog.getResult().getRecordsMap().get(OnapCommandHttpConstants.CATALOG_SERVICE_BASE_PATH).getValues().get(0); + basePath = basePath.trim(); + if (basePath.startsWith("/")) { + basePath = basePath.substring(1); + } + + return hostUrl + "/" + basePath; + } + } + + + public String getDebugInfo() { + return this.http.getDebugInfo(); + } + + /** + * Http call to external service. + * + * @param input + * http input + * @return http result + * @throws OnapCommandHttpFailure + * exception + */ + public HttpResult run(HttpInput input) throws OnapCommandHttpFailure { + return this.http.request(input); + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/auth/OnapCommandHttpService.java b/profiles/http/src/main/java/org/onap/cli/fw/http/auth/OnapCommandHttpService.java new file mode 100644 index 00000000..e2c8007d --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/auth/OnapCommandHttpService.java @@ -0,0 +1,101 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.auth; + +import org.onap.cli.fw.http.conf.OnapCommandHttpConstants; + +/** + * Oclip Service as reported in api catalog. + */ +public class OnapCommandHttpService { + /* + * Oclip Service name like aai. + */ + private String serviceName; + + /* + * Oclip Service API version like v1, v2, etc + */ + private String serviceVersion; + + private String basePath; + + /** + * Mode of service consideration. By default, it goes with + * 'catalog' mode, where basePath will be discovered by + * the framework using serviceName and serviceVersion + * Another mode is 'direct', in which bastPath will be + * same as OnapCredentails.ServiceUrl. + */ + private String mode = OnapCommandHttpConstants.MODE_DIRECT; + + private String authType = OnapCommandHttpConstants.AUTH_NONE; + + public String getMode() { + return mode; + } + + public void setMode(String mode) { + this.mode = mode; + } + + public boolean isModeDirect() { + return this.getMode().equals(OnapCommandHttpConstants.MODE_DIRECT); + } + + public String getAuthType() { + return this.authType; + } + + public void setAuthType(String auth) { + this.authType = auth; + } + + public boolean isNoAuth() { + return this.authType.equalsIgnoreCase(OnapCommandHttpConstants.AUTH_NONE); + } + + public String getName() { + return serviceName; + } + + public void setName(String name) { + this.serviceName = name; + } + + public String getVersion() { + return serviceVersion; + } + + public void setVersion(String version) { + this.serviceVersion = version; + } + + public String getBasePath() { + return basePath; + } + + public void setBasePath(String basePath) { + this.basePath = basePath; + } + + @Override + public String toString() { + return this.getName() + " " + this.getVersion(); + } + +} \ No newline at end of file diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/cmd/BasicAuthLoginCommand.java b/profiles/http/src/main/java/org/onap/cli/fw/http/cmd/BasicAuthLoginCommand.java new file mode 100644 index 00000000..afab750d --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/cmd/BasicAuthLoginCommand.java @@ -0,0 +1,48 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.cmd; + +import java.util.Map; + +import org.apache.http.auth.UsernamePasswordCredentials; +import org.apache.http.impl.auth.BasicScheme; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.http.conf.OnapCommandHttpConstants; +import org.onap.cli.fw.input.OnapCommandParameter; +import org.onap.cli.fw.schema.OnapCommandSchema; + +@OnapCommandSchema(schema = "basic-login.yaml") +public class BasicAuthLoginCommand extends OnapHttpCommand { + + @Override + protected void run() throws OnapCommandException { + + //get the input arguments + Map paramMap = getParametersMap(); + OnapCommandParameter usernameParam = paramMap.get(OnapCommandHttpConstants.DEAFULT_PARAMETER_USERNAME); + String username = usernameParam.getValue().toString(); + OnapCommandParameter usernamePassword = paramMap.get(OnapCommandHttpConstants.DEAFULT_PARAMETER_PASSWORD); + String password = usernamePassword.getValue().toString(); + + //Execute the command to get token + String authToken = BasicScheme.authenticate(new UsernamePasswordCredentials( + username, password), "UTF-8", false).getValue(); + + //Fill out the result part + this.getResult().getRecordsMap().get(OnapCommandHttpConstants.AUTH_SERVICE_AUTHORIZATION).getValues().add(authToken); + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/cmd/BasicAuthLogoutCommand.java b/profiles/http/src/main/java/org/onap/cli/fw/http/cmd/BasicAuthLogoutCommand.java new file mode 100644 index 00000000..6b54b3e0 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/cmd/BasicAuthLogoutCommand.java @@ -0,0 +1,29 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.cmd; + +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.schema.OnapCommandSchema; + +@OnapCommandSchema(schema = "basic-logout.yaml") +public class BasicAuthLogoutCommand extends OnapHttpCommand { + + @Override + protected void run() throws OnapCommandException { + //do nothing // NOSONAR + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/cmd/CatalogCommand.java b/profiles/http/src/main/java/org/onap/cli/fw/http/cmd/CatalogCommand.java new file mode 100644 index 00000000..2393fe82 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/cmd/CatalogCommand.java @@ -0,0 +1,28 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.cmd; + +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.schema.OnapCommandSchema; + +@OnapCommandSchema(schema = "catalog.yaml") +public class CatalogCommand extends OnapHttpCommand { + + @Override + protected void run() throws OnapCommandException { + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/cmd/OnapHttpCommand.java b/profiles/http/src/main/java/org/onap/cli/fw/http/cmd/OnapHttpCommand.java new file mode 100644 index 00000000..09ba7449 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/cmd/OnapHttpCommand.java @@ -0,0 +1,203 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.cmd; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.onap.cli.fw.cmd.OnapCommand; +import org.onap.cli.fw.cmd.OnapCommandType; +import org.onap.cli.fw.conf.OnapCommandConfig; +import org.onap.cli.fw.conf.OnapCommandConstants; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandExecutionFailed; +import org.onap.cli.fw.http.auth.OnapCommandHttpAuthClient; +import org.onap.cli.fw.http.auth.OnapCommandHttpService; +import org.onap.cli.fw.http.conf.OnapCommandHttpConstants; +import org.onap.cli.fw.http.connect.HttpInput; +import org.onap.cli.fw.http.connect.HttpResult; +import org.onap.cli.fw.http.error.OnapCommandFailedMocoGenerate; +import org.onap.cli.fw.http.schema.OnapCommandSchemaHttpLoader; +import org.onap.cli.fw.http.utils.OnapCommandHttpUtils; +import org.onap.cli.fw.output.OnapCommandResultAttribute; +import org.onap.cli.fw.schema.OnapCommandSchema; +import org.onap.cli.fw.utils.OnapCommandUtils; +import org.onap.cli.http.mock.MockJsonGenerator; +import org.onap.cli.http.mock.MockRequest; +import org.onap.cli.http.mock.MockResponse; + +/** + * Oclip http Command. + * + */ +@OnapCommandSchema(type = OnapCommandHttpConstants.HTTP_SCHEMA_PROFILE) +public class OnapHttpCommand extends OnapCommand { + + private HttpInput input = new HttpInput(); + + private List successStatusCodes = new ArrayList<>(); + + private Map resultMap = new HashMap<>(); + + protected OnapCommandHttpAuthClient authClient; + + private OnapCommandHttpService oclipService = new OnapCommandHttpService(); + + public void setInput(HttpInput input) { + this.input = input; + } + + @Override + public String getSchemaVersion() { + return OnapCommandConstants.OPEN_CLI_SCHEMA_VERSION_VALUE_1_0; + } + + public void setSuccessStatusCodes(List successStatusCodes) { + this.successStatusCodes = successStatusCodes; + } + + public void setResultMap(Map resultMap) { + this.resultMap = resultMap; + } + + public HttpInput getInput() { + return input; + } + + public List getSuccessStatusCodes() { + return successStatusCodes; + } + + public Map getResultMap() { + return resultMap; + } + + /* + * Oclip service, this command uses to execute it. + */ + public OnapCommandHttpService getService() { + return this.oclipService; + } + + public void setService(OnapCommandHttpService service) { + this.oclipService = service; + } + + @Override + protected List initializeProfileSchema() throws OnapCommandException { + return OnapCommandSchemaHttpLoader.loadHttpSchema(this, this.getSchemaName(), true, false); + } + + @Override + protected void validate() throws OnapCommandException { + if (! this.isAuthRequired()) { + if (this.getParametersMap().containsKey(OnapCommandHttpConstants.DEAFULT_PARAMETER_USERNAME)) { + this.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_USERNAME).setOptional(true); + } + if (this.getParametersMap().containsKey(OnapCommandHttpConstants.DEAFULT_PARAMETER_PASSWORD)) { + this.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_PASSWORD).setOptional(true); + } + } + + super.validate(); + } + + private boolean isAuthRequired() { + return !this.getService().isNoAuth() + && "false".equals(this.getParametersMap().get(OnapCommandHttpConstants.DEFAULT_PARAMETER_NO_AUTH).getValue()) + && this.getInfo().getCommandType().equals(OnapCommandType.CMD); + } + + @Override + protected void run() throws OnapCommandException { + try { + // For auth/catalog type commands, login and logout logic is not required + boolean isAuthRequired = this.isAuthRequired(); + + this.authClient = new OnapCommandHttpAuthClient( + this, + this.getResult().isDebug()); + + if (isAuthRequired) { + this.authClient.login(); + } + + this.processRequest(); + + if (isAuthRequired) { + this.authClient.logout(); + } + + if (this.getResult().isDebug() && authClient != null) { + this.getResult().setDebugInfo(this.authClient.getDebugInfo()); + } + } catch (OnapCommandException e) { + if (this.getResult().isDebug() && authClient != null) { + this.getResult().setDebugInfo(this.authClient.getDebugInfo()); + } + throw e; + } + } + + protected void processRequest() throws OnapCommandException { + + HttpInput httpInput = OnapCommandHttpUtils.populateParameters(this.getParametersMap(), this.getInput()); + httpInput.setUri(this.authClient.getServiceUrl() + httpInput.getUri()); + + HttpResult output = this.authClient.run(httpInput); + + this.getResult().setOutput(output); + if (!this.getSuccessStatusCodes().contains(output.getStatus())) { + throw new OnapCommandExecutionFailed(this.getName(), output.getBody(), output.getStatus()); + } + + Map> results = OnapCommandHttpUtils.populateOutputs(this.getResultMap(), output); + results = OnapCommandUtils.populateOutputsFromInputParameters(results, this.getParametersMap()); + + for (OnapCommandResultAttribute attr : this.getResult().getRecords()) { + attr.setValues(results.get(attr.getName())); + } + generateJsonMock(httpInput, output, this.getSchemaName()); + } + + private void generateJsonMock(HttpInput httpInput, HttpResult httpResult, String schemaName) + throws OnapCommandFailedMocoGenerate { + + if (Boolean.parseBoolean(OnapCommandConfig.getPropertyValue(OnapCommandConstants.SAMPLE_GEN_ENABLED))) { + try { + MockRequest mockRequest = new MockRequest(); + mockRequest.setMethod(httpInput.getMethod()); + mockRequest.setUri(httpInput.getUri()); + mockRequest.setHeaders(httpInput.getReqHeaders()); + mockRequest.setJson(httpInput.getBody()); + + MockResponse mockResponse = new MockResponse(); + mockResponse.setStatus(httpResult.getStatus()); + mockResponse.setJson(httpResult.getBody()); + + MockJsonGenerator.generateMocking(mockRequest, mockResponse, + OnapCommandConfig.getPropertyValue(OnapCommandConstants.SAMPLE_GEN_TARGET_FOLDER) + + "/" + schemaName.replace(".yaml", "") + "-moco.json"); + } catch (IOException error) { + throw new OnapCommandFailedMocoGenerate(schemaName, error); + } + } + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/conf/OnapCommandHttpConstants.java b/profiles/http/src/main/java/org/onap/cli/fw/http/conf/OnapCommandHttpConstants.java new file mode 100644 index 00000000..c33d2f27 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/conf/OnapCommandHttpConstants.java @@ -0,0 +1,90 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.conf; + +/** + * OnapCommandHttpConstants. + * + */ +public class OnapCommandHttpConstants { + public static final String CONF = "open-cli-http.properties"; + public static final String OPEN_IGNORE_AUTH = "cli.ignore_auth"; + public static final String HTTP_API_KEY_USE_COOKIES = "cli.http.api_key_use_cookies"; + public static final String HTTP_SECTIONS = "cli.schema.http_sections"; + public static final String HTTP_MANDATORY_SECTIONS = "cli.schema.http_mandatory_sections"; + public static final String HTTP_REQUEST_PARAMS = "cli.schema.http_request_params"; + public static final String HTTP_REQUEST_MANDATORY_PARAMS = "cli.schema.http_request_mandatory_params"; + public static final String HTTP_METHODS = "cli.schema.http_methods"; + //http connection + public static final String SSLCONTEST_TLS = "TLSV1.2"; + public static final String APPLICATION_JSON = "application/json"; + public static final String DEFAULT_PARAMETER_HTTP_FILE_NAME = "default_input_parameters_http.yaml"; + public static final String DEAFULT_PARAMETER_USERNAME = "host-username"; + public static final String DEAFULT_PARAMETER_PASSWORD = "host-password"; + public static final String DEAFULT_PARAMETER_HOST_URL = "host-url"; + public static final String DEFAULT_PARAMETER_NO_AUTH = "no-auth"; + public static final String HTTP_SCHEMA_PROFILE = "http"; + //http + public static final String HTTP = "http"; + public static final String METHOD = "method"; + public static final String SERVICE = "service"; + public static final String VERSION = "version"; + public static final String BASE_PATH = "base_path"; + public static final String AUTH = "auth"; + public static final String AUTH_NONE = "none"; + public static final String AUTH_BASIC = "basic"; + public static final String MODE = "mode"; + public static final String MODE_DIRECT = "direct"; + public static final String MODE_CATALOG = "catalog"; + public static final String REQUEST = "request"; + public static final String URI = "uri"; + public static final String BODY = "body"; + public static final String METHOD_TYPE = "method"; + public static final String POST = "post"; + public static final String GET = "get"; + public static final String DELETE = "delete"; + public static final String PUT = "put"; + public static final String HEAD = "delete"; + public static final String HEADERS = "headers"; + public static final String QUERIES = "queries"; + public static final String COOKIES = "cookies"; + public static final String SUCCESS_CODES = "success_codes"; + public static final String RESULT_MAP = "result_map"; + public static final String SAMPLE_RESPONSE = "sample_response"; + public static final String MULTIPART_ENTITY_NAME = "multipart_entity_name"; + public static final String HTTP_SECTION_EMPTY = "Http Section cann't be null or empty"; + public static final String HTTP_BODY_SECTION_EMPTY = "http body section under 'request:' cann't be null or empty"; + public static final String HTTP_BODY_FAILED_PARSING = "The http body json is failed to parse"; + public static final String HTTP_BODY_JSON_EMPTY = "The http body json cann't be null or empty"; + public static final String HTTP_SUCCESS_CODE_INVALID = "Invalid http success code."; + public static final String HTTP_SAMPLE_RESPONSE_EMPTY = "Sample response cann't be null or empty"; + public static final String HTTP_SAMPLE_RESPONSE_FAILED_PARSING = "The http Sample response json is failed to parse."; + //auth plugin + public static final String AUTH_SERVICE_AUTHORIZATION = "Authorization"; + //catalog plugin + public static final String CATALOG_SERVICE_NAME = "catalog-service-name"; + public static final String CATALOG_SERVICE_VERSION = "catalog-service-version"; + public static final String CATALOG_SERVICE_BASE_PATH = "catalog-service-base-path"; + public static final String CATALOG_SERVICE_HOST_URL = "catalog-service-host-url"; + + public static final String AUTH_VALUES = "cli.schema.auth_values"; + public static final String MODE_VALUES = "cli.schema.mode_values"; + public static final String SERVICE_PARAMS_LIST = "cli.schema.service_params_list"; + public static final String SERVICE_PARAMS_MANDATORY_LIST = "cli.schema.service_params_mandatory_list"; +} + + diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/connect/HttpInput.java b/profiles/http/src/main/java/org/onap/cli/fw/http/connect/HttpInput.java new file mode 100644 index 00000000..722dd12e --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/connect/HttpInput.java @@ -0,0 +1,139 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.connect; + +import java.util.HashMap; +import java.util.Map; + +/** + * Captures HTTP request URI, body and request &query parameters.
+ */ +public class HttpInput { + + private String reqUri = ""; + + private String reqBody = ""; + + private String reqMethod = ""; + + private String multipartEntityName = ""; + + private Map reqHeaders = new HashMap<>(); + + private Map reqQueries = new HashMap<>(); + + private Map reqCookies = new HashMap<>(); + + private boolean binaryData; + + public String getUri() { + return this.reqUri; + } + + public HttpInput setUri(String uri) { + this.reqUri = uri; + return this; + } + + public String getBody() { + return this.reqBody; + } + + public HttpInput setBody(String body) { + this.reqBody = body; + return this; + } + + public Map getReqHeaders() { + return this.reqHeaders; + } + + /** + * header parameter setter. + * + * @param reqHeaders + * header map + * @return HttpInput + */ + public HttpInput setReqHeaders(Map reqHeaders) { + if (reqHeaders != null) { + this.reqHeaders = reqHeaders; + } + return this; + } + + public String getMethod() { + return this.reqMethod; + } + + public HttpInput setMethod(String method) { + this.reqMethod = method; + return this; + } + + public String getMultipartEntityName() { + return this.multipartEntityName; + } + + public HttpInput setMultipartEntityName(String multipartEntityName) { + this.multipartEntityName = multipartEntityName; + return this; + } + + public Map getReqQueries() { + return reqQueries; + } + + /** + * Request query parameters. + * + * @param reqQueries + * request queries + * @return HttpInput + */ + public HttpInput setReqQueries(Map reqQueries) { + if (reqQueries != null) { + this.reqQueries = reqQueries; + } + return this; + } + + public Map getReqCookies() { + return reqCookies; + } + + public HttpInput setReqCookies(Map reqCookies) { + this.reqCookies = reqCookies; + return this; + } + + public boolean isBinaryData() { + return binaryData; + } + + public void setBinaryData(boolean binaryData) { + this.binaryData = binaryData; + } + + @Override + public String toString() { + return "\nURL: " + this.getUri() + "\nMethod: " + this.getMethod() + "\nRequest Queries: " + + this.getReqQueries() + "\nRequest Body: " + this.getBody() + "\nRequest Headers: " + + this.getReqHeaders().toString() + "\nRequest Cookies: " + this.getReqCookies().toString() + + "\nbinaryData=" + this.binaryData; + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/connect/HttpResult.java b/profiles/http/src/main/java/org/onap/cli/fw/http/connect/HttpResult.java new file mode 100644 index 00000000..42c636c0 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/connect/HttpResult.java @@ -0,0 +1,77 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.connect; + +import java.util.HashMap; +import java.util.Map; + +/** + * Captures HTTP response status, body and headers.
+ * + */ +public class HttpResult { + + private int status; + + private String resBody; + + private Map respHeaders = new HashMap<>(); + + private Map respCookies = new HashMap<>(); + + public int getStatus() { + return this.status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getBody() { + return this.resBody; + } + + public void setBody(String body) { + this.resBody = body; + } + + public void setRespHeaders(Map respHeaders) { + this.respHeaders = respHeaders; + } + + public Map getRespHeaders() { + return this.respHeaders; + } + + public Map getRespCookies() { + return respCookies; + } + + public void setRespCookies(Map respCookies) { + this.respCookies = respCookies; + } + + public boolean isSuccess() { + return this.getStatus() >= 200 && this.getStatus() <= 300; + } + + @Override + public String toString() { + return "\nHTTP Status: " + this.getStatus() + "\nResponse Body: " + this.getBody() + "\nResponse Headers: " + + this.getRespHeaders() + "\nResponse Cookies: " + this.getRespCookies(); + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/connect/OnapHttpConnection.java b/profiles/http/src/main/java/org/onap/cli/fw/http/connect/OnapHttpConnection.java new file mode 100644 index 00000000..a5a75e11 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/connect/OnapHttpConnection.java @@ -0,0 +1,349 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.connect; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.nio.charset.StandardCharsets; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; + +import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpResponse; +import org.apache.http.ParseException; +import org.apache.http.client.CookieStore; +import org.apache.http.client.HttpClient; +import org.apache.http.client.methods.HttpDelete; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.client.methods.HttpPut; +import org.apache.http.client.methods.HttpRequestBase; +import org.apache.http.client.protocol.ClientContext; +import org.apache.http.config.Registry; +import org.apache.http.config.RegistryBuilder; +import org.apache.http.conn.HttpClientConnectionManager; +import org.apache.http.conn.socket.ConnectionSocketFactory; +import org.apache.http.conn.ssl.AllowAllHostnameVerifier; +import org.apache.http.conn.ssl.SSLConnectionSocketFactory; +import org.apache.http.conn.ssl.X509HostnameVerifier; +import org.apache.http.cookie.Cookie; +import org.apache.http.entity.StringEntity; +import org.apache.http.entity.mime.MultipartEntity; +import org.apache.http.entity.mime.content.FileBody; +import org.apache.http.impl.client.BasicCookieStore; +import org.apache.http.impl.client.HttpClients; +import org.apache.http.impl.client.LaxRedirectStrategy; +import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; +import org.apache.http.impl.cookie.BasicClientCookie; +import org.apache.http.protocol.BasicHttpContext; +import org.apache.http.protocol.HttpContext; +import org.apache.http.util.EntityUtils; +import org.onap.cli.fw.http.conf.OnapCommandHttpConstants; +import org.onap.cli.fw.http.error.OnapCommandHttpFailure; + +/** + * Helps to make http connection.
+ */ +public class OnapHttpConnection { + + private HttpClient httpClient = null; + + Map mapCommonHeaders = new HashMap (); + + protected boolean debug = false; + + private String debugDetails = ""; + + public static class TrustAllX509TrustManager implements X509TrustManager { + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + + @Override + public void checkClientTrusted(java.security.cert.X509Certificate[] certs, String authType) { + // No need to implement. + } + + @Override + public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) { + // No need to implement. + } + } + + /** + * OnapHttpConnection Constructor. + * + * @param debug + * boolean + * @throws OnapCommandHttpFailure + * exception + */ + public OnapHttpConnection(boolean debug) throws OnapCommandHttpFailure { + this.debug = debug; + } + + private void initHttpClient(boolean isSecured) throws OnapCommandHttpFailure { + if (this.httpClient == null) { + try { + if (isSecured) { + SSLContext sslContext = SSLContext.getInstance(OnapCommandHttpConstants.SSLCONTEST_TLS); + sslContext.init(null, new TrustManager[] { new TrustAllX509TrustManager() }, + new java.security.SecureRandom()); + X509HostnameVerifier hostnameVerifier = new AllowAllHostnameVerifier(); + Registry socketFactoryRegistry = RegistryBuilder + .create() + .register("https", new SSLConnectionSocketFactory(sslContext, hostnameVerifier)).build(); + HttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry); + + this.httpClient = HttpClients.custom().setConnectionManager(connManager) + .setRedirectStrategy(new LaxRedirectStrategy()).build(); + } else { + this.httpClient = HttpClients.createDefault(); + } + } catch (Exception e) { + throw new OnapCommandHttpFailure(e); + } + } + } + + public String getDebugInfo() { + return this.debugDetails; + } + + private Map getHttpHeaders(HttpResponse resp) { + Map result = new HashMap<>(); + + Header[] hs = resp.getAllHeaders(); + for (int i = 0; i < hs.length; i++) { + result.put(hs[i].getName(), hs[i].getValue()); + } + + return result; + } + + private String getResponseBody(HttpResponse resp) throws OnapCommandHttpFailure { + if (resp.getEntity() == null) { + return null; + } + try { + String body = EntityUtils.toString(resp.getEntity(), StandardCharsets.UTF_8); + EntityUtils.consume(resp.getEntity()); + return body; + } catch (IOException e) { + throw new OnapCommandHttpFailure(e); + } + } + + private StringEntity getStringEntity(HttpInput input) { + return new StringEntity(input.getBody(), StandardCharsets.UTF_8); + } + + /** + * Post.
+ * + * @param input + * HttpInput Obj + * @return HttpResult + * @throws OnapCommandHttpFailure + * http failure + */ + public HttpResult post(final HttpInput input) throws OnapCommandHttpFailure { + input.setMethod("post"); + return this.request(input); + } + + /** + * Get.
+ * + * @param input + * input request + * @return HttpResult + * @throws OnapCommandHttpFailure + * excpetion + */ + public HttpResult get(final HttpInput input) throws OnapCommandHttpFailure { + input.setMethod("get"); + return this.request(input); + } + + /** + * Put.
+ * + * @param input + * input request + * @return HttpResult + * @throws OnapCommandHttpFailure + * Exception + */ + public HttpResult put(final HttpInput input) throws OnapCommandHttpFailure { + input.setMethod("put"); + return this.request(input); + } + + /** + * Delete.
+ * + * @param input + * input request + * @return HttpResult + * @throws OnapCommandHttpFailure + * exception + */ + public HttpResult delete(final HttpInput input) throws OnapCommandHttpFailure { + input.setMethod("delete"); + return this.request(input); + } + + public void setCommonHeaders(Map headers) { + this.mapCommonHeaders = headers; + } + + private void addCommonHeaders(HttpInput input) { + if (!input.isBinaryData()) { + input.getReqHeaders().put("Content-Type", OnapCommandHttpConstants.APPLICATION_JSON); + } + input.getReqHeaders().put("Accept", OnapCommandHttpConstants.APPLICATION_JSON); + + for (String headerName : this.mapCommonHeaders.keySet()) { + input.getReqHeaders().put(headerName, this.mapCommonHeaders.get(headerName)); + } + } + + private void addCommonCookies(CookieStore cookieStore) { + for (String headerName : this.mapCommonHeaders.keySet()) { + Cookie cookie = new BasicClientCookie(headerName, this.mapCommonHeaders.get(headerName)); + cookieStore.addCookie(cookie); + } + } + + private void updateResultFromCookies(HttpResult result, List cookies) { + for (Cookie cookie : cookies) { + result.getRespCookies().put(cookie.getName(), cookie.getValue()); + } + } + + private String getDomain(String url) { + try { + return new URL(url).getHost(); + } catch (MalformedURLException e) { + // url is always proper !! + return url; + } + } + + private void updateInputFromCookies(HttpInput input, CookieStore cookieStore) { + addCommonCookies(cookieStore); + for (String cookieName : input.getReqCookies().keySet()) { + BasicClientCookie cookie = new BasicClientCookie(cookieName, input.getReqCookies().get(cookieName)); + cookie.setDomain(this.getDomain(input.getUri())); + cookieStore.addCookie(cookie); + } + + } + + /** + * Handles http method requests. + * + * @param input + * HttpInput + * @return HttpResult + * @throws OnapCommandHttpFailure + * exception + */ + public HttpResult request(HttpInput input) throws OnapCommandHttpFailure { + this.addCommonHeaders(input); + + HttpRequestBase requestBase = null; + if ("post".equals(input.getMethod())) { + HttpPost httpPost = new HttpPost(); + if (input.isBinaryData()) { + httpPost.setEntity(getMultipartEntity(input)); + } else { + httpPost.setEntity(this.getStringEntity(input)); + } + requestBase = httpPost; + } else if ("put".equals(input.getMethod())) { + HttpPut httpPut = new HttpPut(); + httpPut.setEntity(this.getStringEntity(input)); + requestBase = httpPut; + } else if ("get".equals(input.getMethod())) { + requestBase = new HttpGet(); + } else if ("delete".equals(input.getMethod())) { + requestBase = new HttpDelete(); + } else { + throw new IllegalArgumentException("Invalid HTTP method"); + } + + requestBase.setURI(URI.create(input.getUri())); + + for (Entry h : input.getReqHeaders().entrySet()) { + requestBase.addHeader(h.getKey(), h.getValue()); + } + + HttpResult result = new HttpResult(); + + try { + this.debugDetails = ""; + CookieStore cookieStore = new BasicCookieStore(); + updateInputFromCookies(input, cookieStore); + HttpContext localContext = new BasicHttpContext(); + localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); + + this.initHttpClient(input.getUri().startsWith("https")); + + HttpResponse resp = this.httpClient.execute(requestBase, localContext); + String respContent = this.getResponseBody(resp); + result.setBody(respContent); + result.setStatus(resp.getStatusLine().getStatusCode()); + result.setRespHeaders(this.getHttpHeaders(resp)); + this.updateResultFromCookies(result, cookieStore.getCookies()); + } catch (ParseException | IOException e) { + throw new OnapCommandHttpFailure(e); + } finally { + if (this.debug) { + this.debugDetails = input + "" + result; + } + } + + return result; + } + + public void close() { + this.mapCommonHeaders.clear(); + } + + private HttpEntity getMultipartEntity(HttpInput input) { + FileBody fileBody = new FileBody(new File(input.getBody().trim())); + MultipartEntity multipartEntity = new MultipartEntity(); + String fileName = input.getMultipartEntityName() != "" ? input.getMultipartEntityName() : "upload"; + multipartEntity.addPart(fileName, fileBody); + return multipartEntity; + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandFailedMocoGenerate.java b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandFailedMocoGenerate.java new file mode 100644 index 00000000..12a645c4 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandFailedMocoGenerate.java @@ -0,0 +1,41 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.error; + +import org.onap.cli.fw.error.OnapCommandException; + +/** + * Invalid data for generating moco json . + * + */ +public class OnapCommandFailedMocoGenerate extends OnapCommandException { + + private static final long serialVersionUID = -5386652726982792831L; + + private static final String ERROR_CODE = "0xf002"; + + private static final String ERROR_MSG = "Failed to generate moco json "; + + public OnapCommandFailedMocoGenerate(String cmdName, String error) { + super(ERROR_CODE, ERROR_MSG + cmdName + ", " + error); + } + + public OnapCommandFailedMocoGenerate(String cmdName, Throwable throwable) { + super(ERROR_CODE, ERROR_MSG + cmdName , throwable); + } + +} \ No newline at end of file diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpFailure.java b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpFailure.java new file mode 100644 index 00000000..f40ebf45 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpFailure.java @@ -0,0 +1,46 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.error; + +import org.onap.cli.fw.error.OnapCommandException; + +/** + * Command execution failed. + * + */ +public class OnapCommandHttpFailure extends OnapCommandException { + private static final long serialVersionUID = 488775545436993345L; + + private static final String ERROR_CODE = "0x3001"; + + public OnapCommandHttpFailure(String error, long httpStatus) { + super(ERROR_CODE, error, httpStatus); + } + + public OnapCommandHttpFailure(String error) { + super(ERROR_CODE, error); + } + + public OnapCommandHttpFailure(Throwable throwable) { + super(ERROR_CODE, throwable); + } + + public OnapCommandHttpFailure(Throwable throwable, long httpStatus) { + super(ERROR_CODE, throwable, httpStatus); + } + +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpHeaderNotFound.java b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpHeaderNotFound.java new file mode 100644 index 00000000..27330fcb --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpHeaderNotFound.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.error; + +import org.onap.cli.fw.error.OnapCommandException; + +/** + * OnapCommandParameterNotFound. + * + */ +public class OnapCommandHttpHeaderNotFound extends OnapCommandException { + + private static final long serialVersionUID = 6676137916079057963L; + + public OnapCommandHttpHeaderNotFound(String name) { + super("0x3003", "Http header " + name + " is not returned from the service"); + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpInvalidResponseBody.java b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpInvalidResponseBody.java new file mode 100644 index 00000000..90527250 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpInvalidResponseBody.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.error; + +import org.onap.cli.fw.error.OnapCommandException; + +/** + * OnapCommandParameterNotFound. + * + */ +public class OnapCommandHttpInvalidResponseBody extends OnapCommandException { + + private static final long serialVersionUID = 6676137916079057963L; + + private static final String ERROR_CODE = "0x3004"; + private static final String ERR_MSG = "Http response body does not have json entry "; + + public OnapCommandHttpInvalidResponseBody(String name, String error) { + super(ERROR_CODE, ERR_MSG + name + ", " + error); + } + + public OnapCommandHttpInvalidResponseBody(String name, Throwable throwable) { + super(ERROR_CODE, ERR_MSG + name, throwable); + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpInvalidResultMap.java b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpInvalidResultMap.java new file mode 100644 index 00000000..ae1a113f --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandHttpInvalidResultMap.java @@ -0,0 +1,34 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.error; + +import java.util.List; + +import org.onap.cli.fw.error.OnapCommandException; + +/** + * Invalid result map in HTTP section. + * + */ +public class OnapCommandHttpInvalidResultMap extends OnapCommandException { + + private static final long serialVersionUID = 6676137916023457963L; + + public OnapCommandHttpInvalidResultMap(List invalidParams) { + super("0x3005", "Invalide result map parameters : " + invalidParams.toString()); + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandLoginFailed.java b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandLoginFailed.java new file mode 100644 index 00000000..0701dbf2 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandLoginFailed.java @@ -0,0 +1,43 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.error; + +import org.onap.cli.fw.error.OnapCommandException; + +/** + * Login failed. + * + */ +public class OnapCommandLoginFailed extends OnapCommandException { + + private static final long serialVersionUID = 5518154493762956959L; + + private static final String ERROR_CODE = "0x4001"; + private static final String ERROR_MESSAGE1 = "Login failed"; + + public OnapCommandLoginFailed(String error) { + super(ERROR_CODE, ERROR_MESSAGE1 + ", " + error); + } + + public OnapCommandLoginFailed(String error, int httpStatus) { + super(ERROR_CODE, ERROR_MESSAGE1 + ", " + error, httpStatus); + } + + public OnapCommandLoginFailed(Throwable throwable) { + super(ERROR_CODE, ERROR_MESSAGE1, throwable); + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandLogoutFailed.java b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandLogoutFailed.java new file mode 100644 index 00000000..53a58a25 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandLogoutFailed.java @@ -0,0 +1,42 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.error; + +import org.onap.cli.fw.error.OnapCommandException; + +/** + * Logout failed. + * + */ +public class OnapCommandLogoutFailed extends OnapCommandException { + + private static final long serialVersionUID = 1150649507734289032L; + private static final String ERROR_CODE = "0x4002"; + private static final String ERROR_MESSAGE1 = "Logout failed"; + + public OnapCommandLogoutFailed(String error) { + super(ERROR_CODE, ERROR_MESSAGE1 +", " + error); + } + + public OnapCommandLogoutFailed(Throwable throwable) { + super(ERROR_CODE, ERROR_MESSAGE1, throwable); + } + + public OnapCommandLogoutFailed(int statusCode) { + super(ERROR_CODE, ERROR_MESSAGE1, statusCode); + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandServiceNotFound.java b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandServiceNotFound.java new file mode 100644 index 00000000..30833019 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/error/OnapCommandServiceNotFound.java @@ -0,0 +1,32 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.error; + +import org.onap.cli.fw.error.OnapCommandException; + +/** + * Command not registered in MSB. + * + */ +public class OnapCommandServiceNotFound extends OnapCommandException { + + private static final long serialVersionUID = 8580121615330415065L; + + public OnapCommandServiceNotFound(String service) { + super("0xd001", "Service " + service + " is not found in MSB"); + } +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/schema/OnapCommandSchemaHttpLoader.java b/profiles/http/src/main/java/org/onap/cli/fw/http/schema/OnapCommandSchemaHttpLoader.java new file mode 100644 index 00000000..a7424732 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/schema/OnapCommandSchemaHttpLoader.java @@ -0,0 +1,427 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.schema; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Set; +import java.util.stream.Collectors; + +import org.onap.cli.fw.cmd.OnapCommand; +import org.onap.cli.fw.conf.OnapCommandConfig; +import org.onap.cli.fw.conf.OnapCommandConstants; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandInvalidSchema; +import org.onap.cli.fw.error.OnapCommandNotFound; +import org.onap.cli.fw.http.auth.OnapCommandHttpService; +import org.onap.cli.fw.http.cmd.OnapHttpCommand; +import org.onap.cli.fw.http.conf.OnapCommandHttpConstants; +import org.onap.cli.fw.http.error.OnapCommandHttpInvalidResultMap; +import org.onap.cli.fw.registrar.OnapCommandRegistrar; +import org.onap.cli.fw.schema.OnapCommandSchemaLoader; +import org.onap.cli.fw.utils.OnapCommandUtils; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import net.minidev.json.JSONObject; + +public class OnapCommandSchemaHttpLoader { + + public static List loadHttpSchema(OnapHttpCommand cmd, String schemaName, boolean includeDefault, + boolean validateSchema) throws OnapCommandException { + try { + List errors = new ArrayList<>(); + if (includeDefault) { + Map defaultParameterMap = includeDefault ? + OnapCommandSchemaLoader.validateSchemaVersion(OnapCommandHttpConstants.DEFAULT_PARAMETER_HTTP_FILE_NAME, cmd.getSchemaVersion()) : new HashMap<>(); + + //mrkanag default_parameter is supported only for parameters. + if (defaultParameterMap.containsKey(OnapCommandConstants.INFO)) { + defaultParameterMap.remove(OnapCommandConstants.INFO); + } + + errors.addAll(OnapCommandSchemaLoader.parseSchema(cmd, defaultParameterMap, validateSchema)); + } + + Map>> commandYamlMap = + (Map>>)OnapCommandSchemaLoader.validateSchemaVersion(schemaName, cmd.getSchemaVersion()); + + errors.addAll(parseHttpSchema(cmd, commandYamlMap, validateSchema)); + + return errors; + + } catch (OnapCommandException e) { + throw e; + } catch (Exception e) { + throw new OnapCommandInvalidSchema(schemaName, e); + } + } + + /** + * Load the schema. + * + * @param cmd + * OnapHttpCommand + * @param schemaName + * schema name + * @throws OnapCommandException + * on error + */ + static ArrayList parseHttpSchema(OnapHttpCommand cmd, + final Map values, + boolean validate) throws OnapCommandException { + ArrayList errorList = new ArrayList<>(); + try { + Map valMap = (Map) values.get(OnapCommandHttpConstants.HTTP); + + if (valMap != null) { + if (validate) { + OnapCommandUtils.validateTags(errorList, valMap, OnapCommandConfig.getCommaSeparatedList(OnapCommandHttpConstants.HTTP_SECTIONS), + OnapCommandConfig.getCommaSeparatedList(OnapCommandHttpConstants.HTTP_MANDATORY_SECTIONS), OnapCommandConstants.PARAMETERS); + errorList.addAll(validateHttpSchemaSection(values)); + } + for (Map.Entry entry1 : valMap.entrySet()) { + String key1 = entry1.getKey(); + + switch (key1) { + case OnapCommandHttpConstants.REQUEST: + Map map = (Map) valMap.get(key1); + + for (Map.Entry entry2 : map.entrySet()) { + try { + String key2 = entry2.getKey(); + + switch (key2) { + case OnapCommandHttpConstants.URI: + Object obj = map.get(key2); + cmd.getInput().setUri(obj.toString()); + break; + case OnapCommandHttpConstants.METHOD_TYPE: + Object method = map.get(key2); + cmd.getInput().setMethod(method.toString()); + break; + case OnapCommandHttpConstants.BODY: + Object body = map.get(key2); + cmd.getInput().setBody(body.toString()); + break; + case OnapCommandHttpConstants.HEADERS: + Map head = (Map) map.get(key2); + cmd.getInput().setReqHeaders(head); + break; + case OnapCommandHttpConstants.QUERIES: + Map query = (Map) map.get(key2); + + cmd.getInput().setReqQueries(query); + break; + case OnapCommandHttpConstants.MULTIPART_ENTITY_NAME: + Object multipartEntityName = map.get(key2); + cmd.getInput().setMultipartEntityName(multipartEntityName.toString()); + break; + } + }catch (Exception ex) { + OnapCommandUtils.throwOrCollect(new OnapCommandInvalidSchema(cmd.getSchemaName(), ex), errorList, validate); + } + } + break; + + case OnapCommandHttpConstants.SERVICE: + Map serviceMap = (Map) valMap.get(key1); + + if (serviceMap != null) { + if (validate) { + OnapCommandUtils.validateTags(errorList, (Map) valMap.get(key1), + OnapCommandConfig.getCommaSeparatedList(OnapCommandHttpConstants.SERVICE_PARAMS_LIST), + OnapCommandConfig.getCommaSeparatedList(OnapCommandHttpConstants.SERVICE_PARAMS_MANDATORY_LIST), OnapCommandHttpConstants.SERVICE); + + HashMap validationMap = new HashMap<>(); + validationMap.put(OnapCommandHttpConstants.AUTH, OnapCommandHttpConstants.AUTH_VALUES); + validationMap.put(OnapCommandHttpConstants.MODE, OnapCommandHttpConstants.MODE_VALUES); + + for (String secKey : validationMap.keySet()) { + if (serviceMap.containsKey(secKey)) { + Object obj = serviceMap.get(secKey); + if (obj == null) { + errorList.add("Attribute '" + secKey + "' under '" + OnapCommandHttpConstants.SERVICE + "' is empty"); + } else { + String value = String.valueOf(obj); + if (!OnapCommandConfig.getCommaSeparatedList(validationMap.get(secKey)).contains(value)) { + errorList.add("Attribute '" + secKey + "' contains invalid value. Valide values are " + + OnapCommandConfig.getCommaSeparatedList(validationMap.get(key1))); // + } + } + } + } + } + + OnapCommandHttpService srv = new OnapCommandHttpService(); + + for (Map.Entry entry : serviceMap.entrySet()) { + String key = entry.getKey(); + + switch (key) { + case OnapCommandConstants.NAME: + srv.setName(serviceMap.get(key)); + break; + + case OnapCommandHttpConstants.VERSION: + srv.setVersion(serviceMap.get(key).toString()); + break; + + case OnapCommandHttpConstants.AUTH: + Object obj = serviceMap.get(key); + srv.setAuthType(obj.toString()); + + //On None type, username, password and no_auth are invalid + if (srv.isNoAuth()) { + cmd.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_USERNAME).setInclude(false); + cmd.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_PASSWORD).setInclude(false); + cmd.getParametersMap().get(OnapCommandHttpConstants.DEFAULT_PARAMETER_NO_AUTH).setInclude(false); + } + break; + + //mrkanag: from auth command, add the parameters to the command's parameters list + + case OnapCommandHttpConstants.MODE: + Object mode = serviceMap.get(key); + srv.setMode(mode.toString()); + break; + } + } + cmd.setService(srv); + } + break; + + case OnapCommandHttpConstants.SUCCESS_CODES: + if (validate) { + validateHttpSccessCodes(errorList, (List) valMap.get(key1)); + } + cmd.setSuccessStatusCodes((ArrayList) valMap.get(key1)); + break; + + case OnapCommandHttpConstants.RESULT_MAP: + if (validate) { + validateHttpResultMap(errorList, values); + } + cmd.setResultMap((Map) valMap.get(key1)); + break; + + case OnapCommandHttpConstants.SAMPLE_RESPONSE: + // (mrkanag) implement sample response handling + break; + } + } + } + }catch (OnapCommandException e) { + OnapCommandUtils.throwOrCollect(e, errorList, validate); + } + + //Handle the parameters for auth + if (!cmd.getService().isNoAuth()) { + OnapCommand login = OnapCommandSchemaHttpLoader.findAuthCommand(cmd, "login"); + OnapCommandUtils.copyParamSchemasFrom(login, cmd); + } + + return errorList; + } + + public static ArrayList validateHttpSchemaSection(Map values) { + ArrayList errorList = new ArrayList<>(); + Map map = (Map) values.get(OnapCommandHttpConstants.HTTP); + Map requestMap = (Map) map.get(OnapCommandHttpConstants.REQUEST); + + if (requestMap != null && !requestMap.isEmpty()) { + OnapCommandUtils.validateTags(errorList, requestMap, OnapCommandConfig.getCommaSeparatedList(OnapCommandHttpConstants.HTTP_REQUEST_PARAMS), + OnapCommandConfig.getCommaSeparatedList(OnapCommandHttpConstants.HTTP_REQUEST_MANDATORY_PARAMS), OnapCommandHttpConstants.REQUEST); + String method = (String) requestMap.get(OnapCommandHttpConstants.METHOD); + if (method != null && !method.isEmpty()) { + if (!OnapCommandConfig.getCommaSeparatedList(OnapCommandHttpConstants.HTTP_METHODS).contains(method.toLowerCase())) { + errorList.add("Attribute '" + OnapCommandHttpConstants.METHOD + "' under '" + OnapCommandHttpConstants.REQUEST + "' is invalid, correct types are " + + OnapCommandConfig.getCommaSeparatedList(OnapCommandHttpConstants.HTTP_METHODS).toString()); + } + } else { + errorList.add("Http request method cann't be null or empty"); + } + + Set requestParams = getRequestParams(values); + + Set uriParams = validateHttpUri(errorList, requestMap); + + Set bodyParams = validateHttpBody(errorList, requestMap); + + Set headerParams = validateHttpHeaders(requestMap); + + Set queryParams = validateHttpQueries(requestMap); + + HashSet totoalParams = new HashSet<>(uriParams); + totoalParams.addAll(bodyParams); + totoalParams.addAll(headerParams); + totoalParams.addAll(queryParams); + + List nonDeclaredParams = totoalParams.stream().filter(param -> !requestParams.contains(param)) + .collect(Collectors.toList()); + + nonDeclaredParams.stream().forEach(p -> errorList.add("The parameter '" + p + + "' declared under 'parameters:' section is not mapped into request section.")); + } else { + errorList.add(OnapCommandUtils.emptySection(OnapCommandHttpConstants.REQUEST)); + } + return errorList; + } + + public static void validateHttpSccessCodes(List errorList, List requestSuccessCodes) { + + if (requestSuccessCodes == null || requestSuccessCodes.isEmpty()) { + errorList.add(OnapCommandHttpConstants.HTTP_SUCCESS_CODE_INVALID); + return; + } + + for (Object successCode : requestSuccessCodes) { + Integer code = (Integer) successCode; + if (code < 200 || code >= 300) { + if ( code != 404) { + errorList.add(OnapCommandHttpConstants.HTTP_SUCCESS_CODE_INVALID); + } + } + } + + } + + public static void validateHttpResultMap(List errorList, Map values) throws OnapCommandException { + Map valMap = (Map) values.get(OnapCommandHttpConstants.HTTP); + List> attributes = (List>) ((Map)values.get(OnapCommandConstants.RESULTS)).get(OnapCommandConstants.ATTRIBUTES); + Set resultMapParams = ((Map) valMap.get(OnapCommandHttpConstants.RESULT_MAP)).keySet(); + + Set resultAttNames = attributes.stream().map(map -> map.get(OnapCommandConstants.NAME)) + .collect(Collectors.toSet()); + + List invaliResultMapParams = resultMapParams.stream() + .filter(p -> !resultAttNames.contains(p)).collect(Collectors.toList()); + + if (!invaliResultMapParams.isEmpty()) { + OnapCommandUtils.throwOrCollect(new OnapCommandHttpInvalidResultMap(invaliResultMapParams), errorList, true); + } + } + + public static Set validateHttpQueries(Map requestMap) { + Map queries = (Map) requestMap.get(OnapCommandHttpConstants.QUERIES); + Set queryParamNames = new HashSet<>(); + if (queries != null) { + for (Entry entry : queries.entrySet()) { + OnapCommandUtils.parseParameters(String.valueOf(entry.getValue()), queryParamNames); + } + } + return queryParamNames; + } + + public static Set validateHttpHeaders(Map requestMap) { + + Map headers = (Map) requestMap.get(OnapCommandHttpConstants.HEADERS); + Set headerParamNames = new HashSet<>(); + if (headers != null) { + for (Entry entry : headers.entrySet()) { + OnapCommandUtils.parseParameters(String.valueOf(entry.getValue()), headerParamNames); + } + } + return headerParamNames; + } + + public static Set validateHttpBody(List errorList, Map requestMap) { + Set bodyParamNames = new HashSet<>(); + Object bodyString = requestMap.get(OnapCommandHttpConstants.BODY); + if (bodyString == null) { + return bodyParamNames; + } + + String body = String.valueOf(bodyString); + JSONObject obj = null; + try { + obj = new ObjectMapper().readValue(body, JSONObject.class); + } catch (IOException e1) { // NOSONAR + errorList.add(OnapCommandHttpConstants.HTTP_BODY_FAILED_PARSING); + } + if (obj == null || "".equals(obj.toString())) { + errorList.add(OnapCommandHttpConstants.HTTP_BODY_JSON_EMPTY); + } + OnapCommandUtils.parseParameters(body, bodyParamNames); + + return bodyParamNames; + } + + public static Set validateHttpUri(List errorList, Map requestMap) { + Set uriParamNames = new HashSet<>(); + String uri = (String) requestMap.get(OnapCommandHttpConstants.URI); + if (uri == null || uri.isEmpty()) { + errorList.add(OnapCommandUtils.emptySection(OnapCommandHttpConstants.URI)); + return uriParamNames; + } + OnapCommandUtils.parseParameters(uri, uriParamNames); + return uriParamNames; + } + + public static Set getRequestParams(Map yamlMap) { + + Set set = new HashSet<>(); + + @SuppressWarnings("unchecked") + List> inputParams = (List>) yamlMap.get(OnapCommandConstants.PARAMETERS); + + if (inputParams != null) { + for (Map map : inputParams) { + for (Entry entry : map.entrySet()) { + Object key = entry.getKey(); + + if (OnapCommandConstants.NAME.equals(key)) { + set.add(String.valueOf(entry.getValue())); + break; + } + } + } + } + + return set; + } + + /** + * + * @param authAction login/logout + * @return + * @throws OnapCommandException + */ + public static OnapCommand findAuthCommand(OnapHttpCommand forCmd, String authAction) throws OnapCommandException { + OnapCommand auth = null; + try { + //mrkanag: fix this to discover the auth command by matching info->product & service + auth = OnapCommandRegistrar.getRegistrar().get( + forCmd.getInfo().getService() + "-" + + forCmd.getService().getAuthType() + "-" + authAction, + forCmd.getInfo().getProduct()); + } catch (OnapCommandNotFound e) { + auth = OnapCommandRegistrar.getRegistrar().get( + forCmd.getService().getAuthType() + "-" + authAction, + forCmd.getInfo().getProduct()); + } + + return auth; + } + + +} diff --git a/profiles/http/src/main/java/org/onap/cli/fw/http/utils/OnapCommandHttpUtils.java b/profiles/http/src/main/java/org/onap/cli/fw/http/utils/OnapCommandHttpUtils.java new file mode 100644 index 00000000..e4d2cf06 --- /dev/null +++ b/profiles/http/src/main/java/org/onap/cli/fw/http/utils/OnapCommandHttpUtils.java @@ -0,0 +1,233 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.utils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandInvalidParameterValue; +import org.onap.cli.fw.error.OnapCommandParameterNotFound; +import org.onap.cli.fw.error.OnapCommandResultEmpty; +import org.onap.cli.fw.error.OnapCommandResultMapProcessingFailed; +import org.onap.cli.fw.http.connect.HttpInput; +import org.onap.cli.fw.http.connect.HttpResult; +import org.onap.cli.fw.http.error.OnapCommandHttpHeaderNotFound; +import org.onap.cli.fw.http.error.OnapCommandHttpInvalidResponseBody; +import org.onap.cli.fw.input.OnapCommandParameter; +import org.onap.cli.fw.input.OnapCommandParameterType; +import org.onap.cli.fw.utils.OnapCommandUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.jayway.jsonpath.JsonPath; + +import net.minidev.json.JSONArray; + +public class OnapCommandHttpUtils { + + static Logger LOG = LoggerFactory.getLogger(OnapCommandHttpUtils.class); + + /** + * Set argument to param value. + * + * @param params + * map + * @param input + * HttpInput + * @return HttpInput + * @throws OnapCommandParameterNotFound + * exception + * @throws OnapCommandInvalidParameterValue + * exception + */ + public static HttpInput populateParameters(Map params, HttpInput input) + throws OnapCommandException { + HttpInput inp = new HttpInput(); + for (OnapCommandParameter param : params.values()) { + if (OnapCommandParameterType.BINARY.equals(param.getParameterType())) { + inp.setBinaryData(true); + break; + } + } + inp.setBody(OnapCommandUtils.replaceLineFromInputParameters(input.getBody(), params)); + inp.setUri(OnapCommandUtils.replaceLineFromInputParameters(input.getUri(), params)); + inp.setMethod(input.getMethod().toLowerCase()); + for (String h : input.getReqHeaders().keySet()) { + String value = input.getReqHeaders().get(h); + inp.getReqHeaders().put(h, OnapCommandUtils.replaceLineFromInputParameters(value, params)); + } + + for (String h : input.getReqQueries().keySet()) { + String value = input.getReqQueries().get(h); + inp.getReqQueries().put(h, OnapCommandUtils.replaceLineFromInputParameters(value, params)); + } + + return inp; + } + + /** + * Populate result. + * + * @param resultMap + * map + * @param resultHttp + * HttpResult + * @return map + * @throws OnapCommandHttpHeaderNotFound + * header not found exception + * @throws OnapCommandHttpInvalidResponseBody + * invalid response body exception + * @throws OnapCommandResultMapProcessingFailed + * map processing failed exception + */ + public static Map> populateOutputs(Map resultMap, HttpResult resultHttp) + throws OnapCommandException { + Map> resultsProcessed = new HashMap<>(); + + for (Entry entry : resultMap.entrySet()) { + String key = entry.getKey(); + try { + resultsProcessed.put(key, OnapCommandHttpUtils.replaceLineFromOutputResults(resultMap.get(key), resultHttp)); + } catch(OnapCommandResultEmpty e) { + // pass // NOSONAR + } + } + + return resultsProcessed; + } + + public static ArrayList replaceLineFromOutputResults(String line, HttpResult resultHttp) + throws OnapCommandHttpHeaderNotFound, OnapCommandHttpInvalidResponseBody, + OnapCommandResultMapProcessingFailed, OnapCommandResultEmpty { + String headerProcessedLine = ""; + + ArrayList result = new ArrayList<>(); + if (!line.contains("$b{") && !line.contains("$h{")) { + result.add(line); + return result; + } + + /** + * In case of empty response body [] or {} + **/ + if (resultHttp.getBody().length() <= 2) { + return result; + } + + /** + * Process headers macros : line: $h{abc}-$b{$.[*].xyz} , After processing line will be [abc's + * value]-$b{$.[*].xyz} + **/ + int currentIdx = 0; + while (currentIdx < line.length()) { + int idxS = line.indexOf("$h{", currentIdx); + if (idxS == -1) { + headerProcessedLine += line.substring(currentIdx); + break; + } + int idxE = line.indexOf("}", idxS); + String headerName = line.substring(idxS + 3, idxE); + headerName = headerName.trim(); + if (!resultHttp.getRespHeaders().containsKey(headerName)) { + throw new OnapCommandHttpHeaderNotFound(headerName); + } + String value = resultHttp.getRespHeaders().get(headerName); + + headerProcessedLine += line.substring(currentIdx, idxS) + value; + currentIdx = idxE + 1; + } + + // Process body jsonpath macros + List values = new ArrayList<>(); + String bodyProcessedPattern = ""; + currentIdx = 0; + int maxRows = 1; // in normal case, only one row will be there + while (currentIdx < headerProcessedLine.length()) { + int idxS = headerProcessedLine.indexOf("$b{", currentIdx); + if (idxS == -1) { + bodyProcessedPattern += headerProcessedLine.substring(currentIdx); + break; + } + int idxE = headerProcessedLine.indexOf("}", idxS); + String jsonPath = headerProcessedLine.substring(idxS + 3, idxE); + jsonPath = jsonPath.trim(); + try { + // JSONArray or String + Object value = JsonPath.read(resultHttp.getBody(), jsonPath); + if (value instanceof JSONArray) { + JSONArray arr = (JSONArray) value; + if (arr.size() > maxRows) { + maxRows = arr.size(); + } + } + bodyProcessedPattern += headerProcessedLine.substring(currentIdx, idxS) + "%s"; + values.add(value); + currentIdx = idxE + 1; + } catch (Exception e) { + throw new OnapCommandHttpInvalidResponseBody(jsonPath, e); + } + } + + if (bodyProcessedPattern.isEmpty()) { + result.add(headerProcessedLine); + return result; + } else { + for (int i = 0; i < maxRows; i++) { + currentIdx = 0; + String bodyProcessedLine = ""; + int positionalIdx = 0; // %s positional idx + while (currentIdx < bodyProcessedPattern.length()) { + int idxS = bodyProcessedPattern.indexOf("%s", currentIdx); + if (idxS == -1) { + bodyProcessedLine += bodyProcessedPattern.substring(currentIdx); + break; + } + int idxE = idxS + 2; // %s + try { + Object value = values.get(positionalIdx); + String valueS = String.valueOf(value); + if (value instanceof JSONArray) { + JSONArray arr = (JSONArray) value; + if (!arr.isEmpty()) { + valueS = arr.get(i).toString(); + } else { + throw new OnapCommandResultEmpty(); + } + } + + bodyProcessedLine += bodyProcessedPattern.substring(currentIdx, idxS) + valueS; + currentIdx = idxE; + positionalIdx++; + } catch (OnapCommandResultEmpty e) { + throw e; + } catch (Exception e) { + throw new OnapCommandResultMapProcessingFailed(line, e); + } + } + result.add(bodyProcessedLine); + } + + return result; + } + } + +} + diff --git a/profiles/http/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand b/profiles/http/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand new file mode 100644 index 00000000..5ce19e66 --- /dev/null +++ b/profiles/http/src/main/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand @@ -0,0 +1,4 @@ +org.onap.cli.fw.http.cmd.BasicAuthLoginCommand +org.onap.cli.fw.http.cmd.BasicAuthLogoutCommand +org.onap.cli.fw.http.cmd.CatalogCommand +org.onap.cli.fw.http.cmd.OnapHttpCommand \ No newline at end of file diff --git a/profiles/http/src/main/resources/open-cli-http.properties b/profiles/http/src/main/resources/open-cli-http.properties new file mode 100644 index 00000000..caeb4a95 --- /dev/null +++ b/profiles/http/src/main/resources/open-cli-http.properties @@ -0,0 +1,18 @@ +cli.ignore_auth=false +cli.http.api_key_use_cookies=true + +#schema validation +#http +cli.schema.http_sections=request,service,success_codes,result_map,sample_response +cli.schema.http_mandatory_sections=request, success_codes + +cli.schema.http_request_params=uri,method,body,headers,queries,multipart_entity_name +cli.schema.http_request_mandatory_params=uri,method + +cli.schema.service_params_list=name,version,auth,mode +cli.schema.service_params_mandatory_list=auth,mode + +cli.schema.http_methods=post,get,delete,put,head + +cli.schema.auth_values=none,basic +cli.schema.mode_values=direct,catalog diff --git a/profiles/http/src/main/resources/open-cli-schema/http/basic-login.yaml b/profiles/http/src/main/resources/open-cli-schema/http/basic-login.yaml new file mode 100644 index 00000000..36473df7 --- /dev/null +++ b/profiles/http/src/main/resources/open-cli-schema/http/basic-login.yaml @@ -0,0 +1,19 @@ +open_cli_schema_version: 1.0 + +name: basic-login + +description: basic login auth command + +info: + product: open-cli + service: basic-auth + type: auth + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com + +results: + direction: portrait + attributes: + - name: Authorization + description: Authorization + scope: short + type: string diff --git a/profiles/http/src/main/resources/open-cli-schema/http/basic-logout.yaml b/profiles/http/src/main/resources/open-cli-schema/http/basic-logout.yaml new file mode 100644 index 00000000..f4acc0ae --- /dev/null +++ b/profiles/http/src/main/resources/open-cli-schema/http/basic-logout.yaml @@ -0,0 +1,19 @@ +open_cli_schema_version: 1.0 + +name: basic-logout + +description: basic logout auth command + +info: + product: open-cli + service: basic-auth + type: auth + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com + +parameters: + - name: host-username + is_include: false + - name: host-password + is_include: false + - name: no-auth + is_include: false \ No newline at end of file diff --git a/profiles/http/src/main/resources/open-cli-schema/http/catalog.yaml b/profiles/http/src/main/resources/open-cli-schema/http/catalog.yaml new file mode 100644 index 00000000..508955f5 --- /dev/null +++ b/profiles/http/src/main/resources/open-cli-schema/http/catalog.yaml @@ -0,0 +1,44 @@ +open_cli_schema_version: 1.0 + +name: catalog + +description: cli catalog command to find the base path for service. + +info: + product: open-cli + service: catalog + type: catalog + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com + +parameters: + - name: catalog-service-name + type: string + description: service name registered in catalog service + short_option: l + long_option: catalog-service-name + is_optional: false + - name: catalog-service-version + type: string + description: service version registered in catalog service + short_option: i + long_option: catalog-service-version + is_optional: false + - name: host-username + is_include: false + - name: host-password + is_include: false + - name: no-auth + is_include: false +results: + direction: portrait + attributes: + - name: catalog-service-host-url + description: Service connection url + scope: short + type: string + default_value: ${host-url} + - name: catalog-service-base-path + description: service base path, to append with host-url for connecting the service. + scope: short + type: string + default_value: / \ No newline at end of file diff --git a/profiles/http/src/main/resources/open-cli-schema/http/default_input_parameters_http.yaml b/profiles/http/src/main/resources/open-cli-schema/http/default_input_parameters_http.yaml new file mode 100644 index 00000000..d7fbe03c --- /dev/null +++ b/profiles/http/src/main/resources/open-cli-schema/http/default_input_parameters_http.yaml @@ -0,0 +1,36 @@ +open_cli_schema_version: 1.0 + +info: + product: open-cli + service: default-param + ignore: true + +parameters: + - name: host-username + type: string + description: Host user name + short_option: u + long_option: host-username + default_value: $s{env:OPEN_CLI_HOST_USERNAME} + is_optional: false + - name: host-password + type: string + description: Host user password + short_option: p + long_option: host-password + default_value: $s{env:OPEN_CLI_HOST_PASSWORD} + is_secured: true + is_optional: false + - name: host-url + type: url + description: host url in http(s) + short_option: m + long_option: host-url + is_optional: false + default_value: $s{env:OPEN_CLI_HOST_URL} + - name: no-auth + type: bool + description: whether to authenticate user or not + short_option: a + long_option: no-auth + default_value: false \ No newline at end of file diff --git a/profiles/http/src/test/java/org/onap/cli/fw/cmd/OnapHttpCommandTest.java b/profiles/http/src/test/java/org/onap/cli/fw/cmd/OnapHttpCommandTest.java new file mode 100644 index 00000000..bb318e1f --- /dev/null +++ b/profiles/http/src/test/java/org/onap/cli/fw/cmd/OnapHttpCommandTest.java @@ -0,0 +1,80 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.cmd; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; + +import org.junit.Test; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.http.cmd.OnapHttpCommand; +import org.onap.cli.fw.http.connect.HttpInput; +import org.onap.cli.fw.input.OnapCommandParameter; +import org.onap.cli.fw.input.OnapCommandParameterType; + +public class OnapHttpCommandTest { + + @Test(expected = OnapCommandException.class) + public void runTest() throws OnapCommandException { + OnapCommandParameter param1 = new OnapCommandParameter(); + param1.setLongOption("host-username"); + param1.setName("host-username"); + param1.setParameterType(OnapCommandParameterType.STRING); + OnapCommandParameter param2 = new OnapCommandParameter(); + param2.setLongOption("host-password"); + param2.setName("host-password"); + param2.setParameterType(OnapCommandParameterType.STRING); + OnapCommandParameter param3 = new OnapCommandParameter(); + param3.setLongOption("host-url"); + param3.setName("host-url"); + param3.setParameterType(OnapCommandParameterType.STRING); + OnapCommandParameter param4 = new OnapCommandParameter(); + param4.setLongOption("string-param"); + param4.setName("string-param"); + param4.setParameterType(OnapCommandParameterType.STRING); + OnapCommandParameter param5 = new OnapCommandParameter(); + param5.setLongOption("long-opt"); + param5.setName("long-opt"); + param5.setParameterType(OnapCommandParameterType.STRING); + + Set paramslist = new HashSet<>(); + paramslist.add(param1); + paramslist.add(param2); + paramslist.add(param3); + paramslist.add(param4); + paramslist.add(param5); + + HttpInput inp = new HttpInput(); + inp.setBody("body"); + inp.setMethod("method"); + inp.setReqCookies(new HashMap()); + inp.setReqHeaders(new HashMap()); + inp.setReqQueries(new HashMap()); + inp.setUri("uri"); + + OnapHttpCommand com = new OnapHttpCommand(); + com.setParameters(paramslist); + com.getParameters(); + com.getParametersMap(); + com.setInput(inp); + com.initializeSchema("sample-test-schema.yaml"); + com.execute(); + + } + +} diff --git a/profiles/http/src/test/java/org/onap/cli/fw/http/HttpInputOutputTest.java b/profiles/http/src/test/java/org/onap/cli/fw/http/HttpInputOutputTest.java new file mode 100644 index 00000000..99ee3d34 --- /dev/null +++ b/profiles/http/src/test/java/org/onap/cli/fw/http/HttpInputOutputTest.java @@ -0,0 +1,69 @@ +/* + * Copyright 2016-17 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. + */ + +package org.onap.cli.fw.http; + +import static org.junit.Assert.assertTrue; + +import java.util.HashMap; + +import org.junit.Test; +import org.onap.cli.fw.http.connect.HttpInput; +import org.onap.cli.fw.http.connect.HttpResult; + +public class HttpInputOutputTest { + + @Test + public void httpInputTest() { + HttpInput inp = new HttpInput(); + inp.setBody("body"); + inp.setMethod("method"); + inp.setReqCookies(null); + inp.setReqHeaders(null); + inp.setReqQueries(null); + inp.setUri("uri"); + + assertTrue("body".equals(inp.getBody()) && "method".equals(inp.getMethod()) && null == inp.getReqCookies() + && inp.getReqHeaders().isEmpty() && inp.getReqQueries().isEmpty() && "uri".equals(inp.getUri())); + + inp.setReqCookies(new HashMap()); + inp.setReqHeaders(new HashMap()); + inp.setReqQueries(new HashMap()); + + assertTrue( + "\nURL: uri\nMethod: method\nRequest Queries: {}\nRequest Body: body\nRequest Headers: {}\nRequest Cookies: {}\nbinaryData=false" + .equals(inp.toString())); + } + + @Test + public void httpResultTest() { + HttpResult out = new HttpResult(); + out.setBody("body"); + out.setRespCookies(null); + out.setRespHeaders(null); + out.setStatus(205); + + assertTrue("body".equals(out.getBody()) && null == out.getRespCookies() && null == out.getRespHeaders() + && 205 == out.getStatus()); + + out.setRespCookies(new HashMap()); + out.setRespHeaders(new HashMap()); + out.setStatus(200); + assertTrue("\nHTTP Status: 200\nResponse Body: body\nResponse Headers: {}\nResponse Cookies: {}" + .equals(out.toString())); + } + +} diff --git a/profiles/http/src/test/java/org/onap/cli/fw/http/OnapHttpConnectionTest.java b/profiles/http/src/test/java/org/onap/cli/fw/http/OnapHttpConnectionTest.java new file mode 100644 index 00000000..fe29936a --- /dev/null +++ b/profiles/http/src/test/java/org/onap/cli/fw/http/OnapHttpConnectionTest.java @@ -0,0 +1,208 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.protocol.HttpContext; +import org.junit.Before; +import org.junit.Test; +import org.onap.cli.fw.http.connect.HttpInput; +import org.onap.cli.fw.http.connect.HttpResult; +import org.onap.cli.fw.http.connect.OnapHttpConnection; +import org.onap.cli.fw.http.error.OnapCommandHttpFailure; + +import mockit.Invocation; +import mockit.Mock; +import mockit.MockUp; + +public class OnapHttpConnectionTest { + HttpInput inp = null; + OnapHttpConnection con = null; + + @Before + public void setup() { + mockHttpRequest(null); + inp = new HttpInput(); + inp.setMethod("get"); + inp.setBody("body"); + Map map1 = new HashMap<>(); + map1.put("header1", "value1"); + inp.setReqHeaders(map1); + Map map2 = new HashMap<>(); + map2.put("query1", "value1"); + inp.setReqQueries(map2); + Map map = new HashMap<>(); + map.put("cookie1", "value1"); + inp.setReqCookies(map); + inp.setUri("http://192.168.99.10:80"); + } + + @Test(expected = OnapCommandHttpFailure.class) + public void httpUnSecuredGetExceptionTest() throws OnapCommandHttpFailure { + new MockUp() { + @Mock + public CloseableHttpResponse execute(HttpUriRequest request, HttpContext context) + throws IOException, ClientProtocolException { + + throw new IOException("IO Exception"); + } + }; + inp.setMethod("get"); + con = new OnapHttpConnection(true); + con.getDebugInfo(); + con.get(inp); + + } + + @Test(expected = OnapCommandHttpFailure.class) + public void httpUnSecuredPostExceptionTest() throws OnapCommandHttpFailure { + new MockUp() { + @Mock + public CloseableHttpResponse execute(HttpUriRequest request, HttpContext context) + throws IOException, ClientProtocolException { + + throw new IOException("IO Exception"); + } + }; + + inp.setMethod("post"); + con = new OnapHttpConnection(true); + con.post(inp); + } + + + @Test(expected = OnapCommandHttpFailure.class) + public void httpUnSecuredPostExceptionTest1() throws OnapCommandHttpFailure { + new MockUp() { + @Mock + public CloseableHttpResponse execute(HttpUriRequest request, HttpContext context) + throws IOException, ClientProtocolException { + + throw new IOException("IO Exception"); + } + }; + + inp.setMethod("post"); + inp.setBinaryData(true); + con = new OnapHttpConnection(true); + con.post(inp); + } + + @Test(expected = OnapCommandHttpFailure.class) + public void httpUnSecuredPutExceptionTest() throws OnapCommandHttpFailure { + new MockUp() { + @Mock + public CloseableHttpResponse execute(HttpUriRequest request, HttpContext context) + throws IOException, ClientProtocolException { + + throw new IOException("IO Exception"); + } + }; + inp.setMethod("put"); + con = new OnapHttpConnection(true); + con.put(inp); + } + + @Test(expected = OnapCommandHttpFailure.class) + public void httpUnSecuredDeleteExceptionTest() throws OnapCommandHttpFailure { + new MockUp() { + @Mock + public CloseableHttpResponse execute(HttpUriRequest request, HttpContext context) + throws IOException, ClientProtocolException { + + throw new IOException("IO Exception"); + } + }; + inp.setMethod("delete"); + con = new OnapHttpConnection(true); + con.delete(inp); + } + + @Test(expected = IllegalArgumentException.class) + public void httpUnSecuredOtherExceptionTest() throws OnapCommandHttpFailure { + new MockUp() { + @Mock + public CloseableHttpResponse execute(HttpUriRequest request, HttpContext context) + throws IOException, ClientProtocolException { + + throw new IOException("IO Exception"); + } + }; + inp.setMethod("other"); + con = new OnapHttpConnection(true); + con.request(inp); + } + + @Test() + public void httpUnSecuredCloseExceptionTest() throws OnapCommandHttpFailure { + inp.setMethod("other"); + con = new OnapHttpConnection(true); + con.close(); + } + + @Test + public void httpSecuredGetExceptionTest() { + + // ProtocolVersion p = new ProtocolVersion("http",1,0); + // HttpResponse hr = DefaultHttpResponseFactory.INSTANCE.newHttpResponse(p, 200 , null) ; + + new MockUp() { + @Mock + public CloseableHttpResponse execute(HttpUriRequest request, HttpContext context) + throws IOException, ClientProtocolException { + + throw new IOException("IO Exception"); + } + }; + try { + HttpInput inp = new HttpInput(); + inp.setMethod("get"); + inp.setBody("body"); + inp.setReqHeaders(new HashMap()); + inp.setReqQueries(new HashMap()); + inp.setUri("https://192.168.99.10:80"); + OnapHttpConnection con = new OnapHttpConnection(false); + con.get(inp); + } catch (OnapCommandHttpFailure e) { + assertEquals("0x3001::IO Exception", e.getMessage()); + } + } + + private static void mockHttpRequest(HttpResult result) { + new MockUp() { + boolean isMock = false; + + @Mock + public HttpResult request(Invocation inv, HttpInput input) throws OnapCommandHttpFailure { + if (isMock) { + return result; + } else { + return inv.proceed(input); + } + } + }; + } +} diff --git a/profiles/http/src/test/java/org/onap/cli/fw/http/auth/OnapAuthClientCommandBasedTest.java b/profiles/http/src/test/java/org/onap/cli/fw/http/auth/OnapAuthClientCommandBasedTest.java new file mode 100644 index 00000000..d3059449 --- /dev/null +++ b/profiles/http/src/test/java/org/onap/cli/fw/http/auth/OnapAuthClientCommandBasedTest.java @@ -0,0 +1,121 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.auth; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.junit.Before; +import org.junit.Test; +import org.onap.cli.fw.conf.OnapCommandConfig; +import org.onap.cli.fw.conf.OnapCommandConstants; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandProductVersionInvalid; +import org.onap.cli.fw.http.cmd.OnapHttpCommand; +import org.onap.cli.fw.http.conf.OnapCommandHttpConstants; +import org.onap.cli.fw.registrar.OnapCommandRegistrar; + +public class OnapAuthClientCommandBasedTest { + + @Before + public void setup() throws OnapCommandProductVersionInvalid, OnapCommandException { + OnapCommandRegistrar.getRegistrar().setEnabledProductVersion(OnapCommandConfig.getPropertyValue(OnapCommandConstants.OPEN_CLI_PRODUCT_NAME)); + } + + @Test + public void yesCatalogYesAuthTest() throws OnapCommandException { + try { + OnapHttpCommand cmd = getCommand("sample-test-schema-yes-auth-yes-catalog.yaml"); + cmd.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_HOST_URL).setValue("http://localhost:8080"); + cmd.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_USERNAME).setValue("test"); + cmd.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_PASSWORD).setValue("password"); + + cmd.execute(); + } catch (OnapCommandException e) { + fail("External command Yes Auth Yes Catalog failed to run"); + e.printStackTrace(System.out); + } + } + + @Test + public void yesCatalogNoAuthTest() throws OnapCommandException { + try { + OnapHttpCommand cmd = getCommand("sample-test-schema-no-auth-yes-catalog.yaml"); + cmd.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_HOST_URL).setValue("http://localhost:8080"); + + cmd.execute(); + } catch (OnapCommandException e) { + fail("External command Yes Auth No Catalog failed to run " + e.getMessage()); + e.printStackTrace(System.out); + } + } + + @Test + public void noCatalogYesAuthTest() throws OnapCommandException { + try { + OnapHttpCommand cmd = getCommand("sample-test-schema-yes-auth-no-catalog.yaml"); + cmd.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_HOST_URL).setValue("http://localhost:8080"); + cmd.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_USERNAME).setValue("test"); + cmd.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_PASSWORD).setValue("password"); + + cmd.execute(); + } catch (OnapCommandException e) { + fail("External command Yes Auth No Catalog failed to run"); + e.printStackTrace(System.out); + } + } + + @Test + public void noCatalogYesAuthWithAdditionalParamsTest() throws OnapCommandException { + try { + OnapHttpCommand cmd = getCommand("sample-test-schema-yes-auth-with-additional-params-no-catalog.yaml"); + assertTrue(cmd.getParametersMap().containsKey("string-param")); + } catch (OnapCommandException e) { + fail("External command Yes Auth No Catalog failed to run"); + e.printStackTrace(System.out); + } + } + + @Test + public void noCatalogNoAuthTest() throws OnapCommandException { + try { + OnapHttpCommand cmd = getCommand("sample-test-schema-no-auth-no-catalog.yaml"); + cmd.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_HOST_URL).setValue("http://localhost:8080"); + + cmd.execute(); + } catch (OnapCommandException e) { + fail("External command No Auth No Catalog failed to run"); + e.printStackTrace(System.out); + } + } + + private OnapHttpCommand getCommand(String yaml) throws OnapCommandException { + OnapHttpCommand cmd = new OnapHttpCommand() { + @Override + protected void processRequest() throws OnapCommandException { + if (!this.getService().isModeDirect()) { + String url = this.authClient.getServiceUrl(); + assert url.equals(this.getParametersMap().get(OnapCommandHttpConstants.DEAFULT_PARAMETER_HOST_URL).getValue() + "/"); + } + } + }; + + cmd.initializeSchema(yaml); + + return cmd; + } + } diff --git a/profiles/http/src/test/java/org/onap/cli/fw/http/auth/OnapServiceTest.java b/profiles/http/src/test/java/org/onap/cli/fw/http/auth/OnapServiceTest.java new file mode 100644 index 00000000..8501150e --- /dev/null +++ b/profiles/http/src/test/java/org/onap/cli/fw/http/auth/OnapServiceTest.java @@ -0,0 +1,38 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.auth; + +import static org.junit.Assert.assertTrue; + +import org.junit.Test; +import org.onap.cli.fw.http.conf.OnapCommandHttpConstants; + +public class OnapServiceTest { + + @Test + public void serviceTest() { + OnapCommandHttpService ser = new OnapCommandHttpService(); + ser.setName("name"); + ser.setVersion("1.0"); + ser.setBasePath("basePath"); + ser.setAuthType(OnapCommandHttpConstants.AUTH_NONE); + assertTrue(ser.getName().equals("name") && ser.getVersion().equals("1.0") + && ser.getBasePath().equals("basePath") && ser.isNoAuth()); + + } + +} diff --git a/profiles/http/src/test/java/org/onap/cli/fw/http/error/OnapCommandErrorTest.java b/profiles/http/src/test/java/org/onap/cli/fw/http/error/OnapCommandErrorTest.java new file mode 100644 index 00000000..cd2131e9 --- /dev/null +++ b/profiles/http/src/test/java/org/onap/cli/fw/http/error/OnapCommandErrorTest.java @@ -0,0 +1,84 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.error; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.onap.cli.fw.error.OnapCommandResultMapProcessingFailed; + +public class OnapCommandErrorTest { + @Test + public void oclipCommandResultMapProcessingFailedTest() { + OnapCommandResultMapProcessingFailed failed = new OnapCommandResultMapProcessingFailed("name", + new Exception("failed")); + assertEquals("0x3002::Failed to parse the result format of command name, failed", failed.getMessage()); + } + + @Test + public void oclipCommandHttpHeaderNotFoundTest() { + OnapCommandHttpHeaderNotFound failed = new OnapCommandHttpHeaderNotFound("name"); + assertEquals("0x3003::Http header name is not returned from the service", failed.getMessage()); + } + + @Test + public void oclipCommandHttpFailureTest1() { + OnapCommandHttpFailure failed = new OnapCommandHttpFailure("Failed"); + assertEquals("0x3001::Failed", failed.getMessage()); + + failed = new OnapCommandHttpFailure(new Exception("failed"), 201); + assertEquals("201::0x3001::failed", failed.getMessage()); + } + + @Test + public void oclipCommandHttpFailureTest2() { + OnapCommandHttpFailure failed = new OnapCommandHttpFailure("Failed", 203); + + assertEquals("203::0x3001::Failed", failed.getMessage()); + } + + @Test + public void oclipCommandLoginFailedTest1() { + OnapCommandLoginFailed failed = new OnapCommandLoginFailed(new Exception("Failed")); + + assertEquals("0x4001::Login failed, Failed", failed.getMessage()); + } + + @Test + public void oclipCommandLoginFailedTest2() { + OnapCommandLoginFailed failed = new OnapCommandLoginFailed("Failed", 201); + + assertEquals("201::0x4001::Login failed, Failed", failed.getMessage()); + } + + @Test + public void oclipCommandLogoutFailedTest() { + OnapCommandLogoutFailed failed = new OnapCommandLogoutFailed(new Exception("Failed")); + assertEquals("0x4002::Logout failed, Failed", failed.getMessage()); + + failed = new OnapCommandLogoutFailed(200); + assertEquals("200::0x4002::Logout failed", failed.getMessage()); + } + + @Test + public void oclipCommandServiceNotFoundTest() { + OnapCommandServiceNotFound failed = new OnapCommandServiceNotFound("Service"); + + assertEquals("0xd001::Service Service is not found in MSB", failed.getMessage()); + } + +} diff --git a/profiles/http/src/test/java/org/onap/cli/fw/http/schema/ValidateSchemaTest.java b/profiles/http/src/test/java/org/onap/cli/fw/http/schema/ValidateSchemaTest.java new file mode 100644 index 00000000..ddf30ba7 --- /dev/null +++ b/profiles/http/src/test/java/org/onap/cli/fw/http/schema/ValidateSchemaTest.java @@ -0,0 +1,39 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.schema; + +import static org.junit.Assert.assertTrue; + +import java.util.List; + +import org.junit.Test; +import org.onap.cli.fw.cmd.OnapCommand; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.schema.OnapCommandSchemaLoader; + +public class ValidateSchemaTest { + @Test + public void validateTest() throws OnapCommandException { + + OnapCommand cmd1 = new OnapCommand() { + @Override + protected void run() throws OnapCommandException {} + }; + List errorList1 = OnapCommandSchemaLoader.loadSchema(cmd1, "schema-validate-http.yaml", true, true); + assertTrue(errorList1.size() > 0); + } +} diff --git a/profiles/http/src/test/java/org/onap/cli/fw/http/utils/OnapCommandUtilsTest.java b/profiles/http/src/test/java/org/onap/cli/fw/http/utils/OnapCommandUtilsTest.java new file mode 100644 index 00000000..12920515 --- /dev/null +++ b/profiles/http/src/test/java/org/onap/cli/fw/http/utils/OnapCommandUtilsTest.java @@ -0,0 +1,139 @@ +/* + * Copyright 2017 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. + */ + +package org.onap.cli.fw.http.utils; + + + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; + +import org.junit.FixMethodOrder; +import org.junit.Test; +import org.junit.runners.MethodSorters; +import org.onap.cli.fw.cmd.OnapCommand; +import org.onap.cli.fw.error.OnapCommandException; +import org.onap.cli.fw.error.OnapCommandInvalidParameterType; +import org.onap.cli.fw.error.OnapCommandInvalidPrintDirection; +import org.onap.cli.fw.error.OnapCommandInvalidResultAttributeScope; +import org.onap.cli.fw.error.OnapCommandInvalidSchema; +import org.onap.cli.fw.error.OnapCommandInvalidSchemaVersion; +import org.onap.cli.fw.error.OnapCommandParameterNameConflict; +import org.onap.cli.fw.error.OnapCommandParameterOptionConflict; +import org.onap.cli.fw.error.OnapCommandSchemaNotFound; +import org.onap.cli.fw.http.cmd.OnapHttpCommand; +import org.onap.cli.fw.http.connect.HttpResult; +import org.onap.cli.fw.http.error.OnapCommandHttpHeaderNotFound; +import org.onap.cli.fw.http.error.OnapCommandHttpInvalidResponseBody; +import org.onap.cli.fw.http.schema.OnapCommandSchemaHttpLoader; +import org.onap.cli.fw.input.OnapCommandParameter; +import org.onap.cli.fw.schema.OnapCommandSchema; +import org.onap.cli.fw.schema.OnapCommandSchemaLoader; +import org.onap.cli.fw.utils.OnapCommandUtils; + +@FixMethodOrder(MethodSorters.NAME_ASCENDING) +public class OnapCommandUtilsTest { + + @Test(expected = OnapCommandInvalidSchema.class) + public void oclipCommandUtilsInputStreamNullTest() throws OnapCommandException { + OnapCommandSchemaLoader.validateSchemaVersion("sample-test1-schema-http1.yaml", "1.0"); + } + + @Test + public void oclipCommandUtilsInputStreamNotNullTest() throws OnapCommandException { + Map map = OnapCommandSchemaLoader.validateSchemaVersion("sample-test1-schema-http.yaml", "1.0"); + assertTrue(map != null); + } + + @Test + public void loadHttpBasedSchemaTest() throws OnapCommandException { + OnapHttpCommand cmd = new OnapHttpCommandSample(); + cmd.setName("sample-create-http"); + try { + OnapCommandSchemaHttpLoader.loadHttpSchema(cmd, "sample-test-schema-http.yaml", true, true); + assertTrue(cmd.getSuccessStatusCodes().size() == 2); + } catch (OnapCommandParameterNameConflict | OnapCommandParameterOptionConflict + | OnapCommandInvalidParameterType | OnapCommandInvalidPrintDirection + | OnapCommandInvalidResultAttributeScope | OnapCommandSchemaNotFound | OnapCommandInvalidSchema + | OnapCommandInvalidSchemaVersion e) { + fail("Test should not have thrown this exception : " + e.getMessage()); + } + } + + + @Test + public void loadOnapCommandSchemaAuthRequiredTest() throws OnapCommandException { + OnapCommand cmd = new OnapCommand() { + + @Override + protected void run() throws OnapCommandException { + // TODO Auto-generated method stub + + } + }; + OnapCommandSchemaLoader.loadSchema(cmd, "sample-test-schema-auth-required.yaml", true, false); + assertTrue("sample-test".equals(cmd.getName())); + + Map map = OnapCommandUtils.getInputMap(cmd.getParameters()); + assertTrue(map.size() == 7); + } + + @Test(expected = OnapCommandHttpHeaderNotFound.class) + public void populateOutputsTest() throws OnapCommandException { + HttpResult output = new HttpResult(); + output.setBody( + "{\"serviceName\":\"test\",\"version\":\"v1\",\"url\":\"/api/test/v1\",\"protocol\":\"REST\",\"visualRange\":\"1\",\"lb_policy\":\"hash\",\"nodes\":[{\"ip\":\"127.0.0.1\",\"port\":\"8012\",\"ttl\":0,\"nodeId\":\"test_127.0.0.1_8012\",\"expiration\":\"2017-02-10T05:33:25Z\",\"created_at\":\"2017-02-10T05:33:25Z\",\"updated_at\":\"2017-02-10T05:33:25Z\"}],\"status\":\"1\"}"); + Map mapHead = new HashMap<>(); + mapHead.put("head1", "value1"); + output.setRespHeaders(mapHead); + output.setStatus(0); + + Map params = new HashMap<>(); + params.put("head", "$h{head1}"); + params.put("body", "$b{$.serviceName}"); + params.put("key", "value"); + + Map> input1 = OnapCommandHttpUtils.populateOutputs(params, output); + assertEquals("{head=[value1], body=[test], key=[value]}", input1.toString()); + + params.put("body", "$b{{$.serviceName}"); + try { + input1 = OnapCommandHttpUtils.populateOutputs(params, output); + } catch (OnapCommandHttpInvalidResponseBody e) { + assertEquals( + "0x3004::Http response body does not have json entry {$.serviceName, Missing property in path $['{$']", + e.getMessage()); + } + output.setBody("{}"); + input1 = OnapCommandHttpUtils.populateOutputs(params, output); + params.put("head", "$h{head2}"); + output.setBody("{\"test\"}"); + input1 = OnapCommandHttpUtils.populateOutputs(params, output); + } + + @OnapCommandSchema(schema = "sample-test-schema-http.yaml") + class OnapHttpCommandSample extends OnapHttpCommand { + + @Override + protected void run() throws OnapCommandException { + } + } +} diff --git a/profiles/http/src/test/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand b/profiles/http/src/test/resources/META-INF/services/org.onap.cli.fw.cmd.OnapCommand new file mode 100644 index 00000000..e69de29b diff --git a/profiles/http/src/test/resources/open-cli-schema/sample-test1-schema-http.yaml b/profiles/http/src/test/resources/open-cli-schema/sample-test1-schema-http.yaml new file mode 100644 index 00000000..f162231f --- /dev/null +++ b/profiles/http/src/test/resources/open-cli-schema/sample-test1-schema-http.yaml @@ -0,0 +1,95 @@ +open_cli_schema_version: 1.0 +name: sample-test1 +description: Oclip sample command to test the command features + +info: + product: open-cli + service: test + type: cmd + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com + +parameters: + - name: bool-param + type: bool + description: Oclip boolean param, by default its always false. + short_option: b + long_option: bool + is_optional: true + default_value: false + - name: secure-param + type: string + description: Oclip secure param such as password + short_option: x + long_option: secure + is_secured: true + is_optional: false + default_Value: pass123# + - name: string-param + type: string + description: Oclip string param + long_option: string-param + short_option: c + is_optional: false + default_Value: test + - name: yaml-param + type: json + description: Oclip yaml file location param + long_option: yaml-param + short_option: y + is_optional: false + - name: json-param + type: json + description: Oclip json file location param + long_option: json-param + short_option: j + is_optional: false + - name: long-param + type: digit + description: Oclip long param + short_option: l + long_option: long-opt + is_optional: false + default_value: 10 + - name: url-param + type: url + description: Oclip url param + short_option: r + long_option: url + is_optional: false + default_value: http://localhost:8082/file.txt + - name: env-param + type: string + description: Oclip env param. + short_option: z + long_option: env + is_optional: false + default_value: ${ENV_VAR} + - name: positional-args + type: string + description: Oclip positional args, if no short option and no long option given for it + is_optional: false + default_value: http://localhost:8082/file.txt +http: + request: + uri: /vims + method: POST + body: '{"name":"${name}","vendor":"${vendor}","version":"${vim-version}","description":"${description}","type":"${type}","url":"${url}","userName":"${username}","password":"${password}","domain":"${domain}","tenant":"${tenant}"}' + headers: + success_codes: + - 201 + - 200 + result_map: + id: $b{$.vimId} + name: $b{$.name} + vendor: $b{$.vendor} + type: $b{$.type} + version: $b{$.version} + url: $b{$.url} + description: $b{$.description} + username: $b{$.userName} + password: $b{$.password} + domain: $b{$.domain} + tenant: $b{$.tenant} + create-time: $b{$.createTime} + sample_response: + body:'{"id":"string","name":"string","vendor":"string","version":"string","description":"string","type":"string","createTime":"string","url":"string","userName":"string","password":"string","domain":"string","tenant":"string"}' \ No newline at end of file diff --git a/profiles/http/src/test/resources/open-cli-schema/testauth-login.yaml b/profiles/http/src/test/resources/open-cli-schema/testauth-login.yaml new file mode 100644 index 00000000..3e9211ef --- /dev/null +++ b/profiles/http/src/test/resources/open-cli-schema/testauth-login.yaml @@ -0,0 +1,28 @@ +open_cli_schema_version: 1.0 + +name: testauth-login + +description: basic login auth command + +info: + product: open-cli + service: test + type: auth + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com + +parameters: + - name: string-param + type: string + description: Oclip string param + long_option: string-param + short_option: c + is_optional: false + default_Value: test + +# followings are dummy simulator for http command +http: + request: + uri: / + method: GET + success_codes: + - 200 diff --git a/profiles/http/src/test/resources/open-cli-schema/testauth-logout.yaml b/profiles/http/src/test/resources/open-cli-schema/testauth-logout.yaml new file mode 100644 index 00000000..dfe33638 --- /dev/null +++ b/profiles/http/src/test/resources/open-cli-schema/testauth-logout.yaml @@ -0,0 +1,19 @@ +open_cli_schema_version: 1.0 + +name: testauth-logout + +description: basic logout auth command + +info: + product: open-cli + service: test + type: auth + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com + +# followings are dummy simulator for http command +http: + request: + uri: / + method: GET + success_codes: + - 200 \ No newline at end of file diff --git a/profiles/http/src/test/resources/open-cli.properties b/profiles/http/src/test/resources/open-cli.properties new file mode 100644 index 00000000..026b1f13 --- /dev/null +++ b/profiles/http/src/test/resources/open-cli.properties @@ -0,0 +1,31 @@ +cli.product_name=open-cli +cli.version=1.0 + +cli.discover_always=false + +#schema validation +cli.schema.top_level_params_list=open_cli_schema_version,name,description,parameters,results,http,info +cli.schema.top_level_mandatory_list=open_cli_schema_version + +cli.schema.info_params_list=product,service,type,author,ignore +cli.schema.info_params_mandatory_list=product,service + +cli.schema.input_params_list=name,description,type,short_option,long_option, is_optional,default_value,is_secured,is_include +cli.schema.input_params_mandatory_list=name,description,type + +cli.schema.result_params_list=name,description,scope,type,is_secured, default_value +cli.schema.result_params_mandatory_list=name, description, type, scope + +cli.schema.boolean_values=true,false +cli.command.type=cmd,auth,catalog + +# moco properties +cli.sample.gen.enable=false +cli.sample.gen.target=. + +# mrkanag Move this to db, once exteranl command registration is supported in place of discovery +cli.schema.type.supported=http + +#other properties to load (it should be hanled when plugins are made as externally register-able +#when command plugin management support is enabled in oclip +cli.plugins-prps=open-cli-http.properties \ No newline at end of file diff --git a/profiles/http/src/test/resources/sample-test-schema-auth-required.yaml b/profiles/http/src/test/resources/sample-test-schema-auth-required.yaml new file mode 100644 index 00000000..bb919d9a --- /dev/null +++ b/profiles/http/src/test/resources/sample-test-schema-auth-required.yaml @@ -0,0 +1,16 @@ +open_cli_schema_version: 1.0 +name: sample-test +description: Oclip sample command to test the command features +info: + product: open-cli + service: test + type: cmd + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com +parameters: + - name: bool-param + type: bool + description: Oclip boolean param, by default its always false. + short_option: b + long_option: bool + is_optional: true + default_value: false \ No newline at end of file diff --git a/profiles/http/src/test/resources/sample-test-schema-http.yaml b/profiles/http/src/test/resources/sample-test-schema-http.yaml new file mode 100644 index 00000000..4ae6e9e0 --- /dev/null +++ b/profiles/http/src/test/resources/sample-test-schema-http.yaml @@ -0,0 +1,92 @@ +open_cli_schema_version: 1.0 +name: sample-create-http +description: Register microservice into Onap +info: + product: open-cli + service: test + type: cmd + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com +parameters: + - name: service-name + description: Oclip service name + type: string + short_option: x + long_option: service-name + is_optional: false + - name: service-version + description: Oclip service version + type: string + short_option: y + long_option: service-version + is_optional: false + - name: service-url + description: Oclip service base url + type: url + short_option: r + long_option: service-url + is_optional: false + - name: status + description: Oclip service status + type: digit + short_option: z + long_option: service-status + is_optional: true + default_value: 1 + - name: node-ip + description: Oclip service running node IP + type: string + - name: node-port + description: Oclip service running node port + type: string + - name: create-or-update + description: Oclip service create or update + type: bool + default_value: true +results: + direction: portrait + attributes: + - name: name + description: Oclip service name + scope: short + type: string + - name: version + description: Oclip service version + scope: short + type: string + - name: url + description: Oclip service base url + scope: short + type: url + - name: status + description: Oclip service status + scope: short + type: digit + - name: nodes + description: Oclip service running nodes + scope: long + type: string + - name: location + description: Oclip service location + scope: long + type: url +http: + request: + uri: /services + method: POST + body: '{"serviceName":"${service-name}","version":"${service-version}","url":"${service-url}","protocol":"REST","visualRange":"1","lb_policy":"hash","nodes":[{"ip":"${node-ip}","port":"${node-port}","ttl":0}]}' + headers: + queries: + createOrUpdate: ${create-or-update} + success_codes: + - 201 + - 200 + result_map: + name: $b{$.serviceName} + version: $b{$.version} + url: $b{$.url} + status: $b{$.status} + nodes: $b{$.nodes[*].ip}:$b{$.nodes[*].port} + location: $h{Location} + + sample_response: + body: {"serviceName":"test","version":"v1","url":"/api/test/v1","protocol":"REST","visualRange":"1","lb_policy":"hash","nodes":[{"ip":"127.0.0.1","port":"8012","ttl":0,"nodeId":"test_127.0.0.1_8012","expiration":"2017-02-10T05:33:25Z","created_at":"2017-02-10T05:33:25Z","updated_at":"2017-02-10T05:33:25Z"}],"status":"1"} \ No newline at end of file diff --git a/profiles/http/src/test/resources/sample-test-schema-no-auth-no-catalog.yaml b/profiles/http/src/test/resources/sample-test-schema-no-auth-no-catalog.yaml new file mode 100644 index 00000000..2629a2f9 --- /dev/null +++ b/profiles/http/src/test/resources/sample-test-schema-no-auth-no-catalog.yaml @@ -0,0 +1,26 @@ +open_cli_schema_version: 1.0 + +name: sample-cmd-no-auth-no-catalog + +description: sample + +info: + product: open-cli + service: test + type: cmd + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com + +http: + + service: + name: sample + version: v1 + auth: none + mode: direct + request: + uri: /test + method: GET + success_codes: + - 200 + result_map: + name: ${name} diff --git a/profiles/http/src/test/resources/sample-test-schema-no-auth-yes-catalog.yaml b/profiles/http/src/test/resources/sample-test-schema-no-auth-yes-catalog.yaml new file mode 100644 index 00000000..15b5bf0c --- /dev/null +++ b/profiles/http/src/test/resources/sample-test-schema-no-auth-yes-catalog.yaml @@ -0,0 +1,28 @@ +open_cli_schema_version: 1.0 + +name: sample-cmd-no-auth-no-catalog + +description: sample + + +info: + product: open-cli + service: test + type: cmd + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com + +http: + + service: + name: sample + version: v1 + auth: none + mode: catalog + + request: + uri: /test + method: GET + success_codes: + - 200 + result_map: + name: ${name} diff --git a/profiles/http/src/test/resources/sample-test-schema-swagger.yaml b/profiles/http/src/test/resources/sample-test-schema-swagger.yaml new file mode 100644 index 00000000..4108d4e6 --- /dev/null +++ b/profiles/http/src/test/resources/sample-test-schema-swagger.yaml @@ -0,0 +1,28 @@ +open_cli_schema_version: 1.0 +name: sample-test-swagger +description: Sample swagger command test. +info: + product: open-cli + service: test + type: cmd + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com +parameters: + - name: user + type: string + description: Oclip user + short_option: n + long_option: username + is_optional: false +results: + direction: portrait + attributes: + - name: name + description: Oclip user + scope: short + type: string +exec: + api: org.onap.common_services.auth.auth_service.client.api.DefaultApi + client: org.onap.common_services.auth.auth_service.client.invoker.ApiClient + entity: org.onap.common_services.auth.auth_service.client.model.User, username(userName), password, description + method: create + exception: org.onap.common_services.auth.auth_service.client.invoker.ApiException \ No newline at end of file diff --git a/profiles/http/src/test/resources/sample-test-schema-yes-auth-no-catalog.yaml b/profiles/http/src/test/resources/sample-test-schema-yes-auth-no-catalog.yaml new file mode 100644 index 00000000..bb0ae46b --- /dev/null +++ b/profiles/http/src/test/resources/sample-test-schema-yes-auth-no-catalog.yaml @@ -0,0 +1,26 @@ +open_cli_schema_version: 1.0 + +name: sample-cmd-yes-auth-no-catalog + +description: sample + +info: + product: open-cli + service: test + type: cmd + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com + +http: + + service: + name: sample + version: v1 + auth: basic + mode: direct + request: + uri: /test + method: GET + success_codes: + - 200 + result_map: + name: ${name} diff --git a/profiles/http/src/test/resources/sample-test-schema-yes-auth-with-additional-params-no-catalog.yaml b/profiles/http/src/test/resources/sample-test-schema-yes-auth-with-additional-params-no-catalog.yaml new file mode 100644 index 00000000..a5a39f92 --- /dev/null +++ b/profiles/http/src/test/resources/sample-test-schema-yes-auth-with-additional-params-no-catalog.yaml @@ -0,0 +1,28 @@ +open_cli_schema_version: 1.0 + +name: sample-cmd-yes-auth-no-catalog-extra-params + +description: sample + + +info: + product: open-cli + service: test + type: cmd + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com + +http: + + service: + name: sample + version: v1 + auth: testauth + mode: catalog + + request: + uri: /test + method: GET + success_codes: + - 200 + result_map: + name: ${name} diff --git a/profiles/http/src/test/resources/sample-test-schema-yes-auth-yes-catalog.yaml b/profiles/http/src/test/resources/sample-test-schema-yes-auth-yes-catalog.yaml new file mode 100644 index 00000000..4efd4c51 --- /dev/null +++ b/profiles/http/src/test/resources/sample-test-schema-yes-auth-yes-catalog.yaml @@ -0,0 +1,28 @@ +open_cli_schema_version: 1.0 + +name: sample-cmd-no-auth-no-catalog + +description: sample + + +info: + product: open-cli + service: test + type: cmd + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com + +http: + + service: + name: sample + version: v1 + auth: basic + mode: catalog + + request: + uri: /test + method: GET + success_codes: + - 200 + result_map: + name: ${name} diff --git a/profiles/http/src/test/resources/schema-validate-http.yaml b/profiles/http/src/test/resources/schema-validate-http.yaml new file mode 100644 index 00000000..7bdafc56 --- /dev/null +++ b/profiles/http/src/test/resources/schema-validate-http.yaml @@ -0,0 +1,98 @@ +open_cli_schema_version: 1.0 +description: Register microservice into Onap +name: schema-validate +info: + product: open-cli + service: test + type: cmd + author: Kanagaraj Manickam kanagaraj.manickam@huawei.com + +parameters: + - name: service-name1 + description: Oclip service name + type: string + short_option: x + long_option: service-name + is_optional: false + - name: service-version + description: Oclip service version + type: string + short_option: x + long_option: service-version + is_optional: false + - name: service-url + description: Oclip service base url + type: url1 + short_option: u + long_option: service-url + is_optional: false1 + - name: status + description: Oclip service status + type: digit + short_option: z + long_option: service-version + is_optional: true + default_value: 1 + - name: node-ip + description: Oclip service running node IP + type: string + - name: node-port + description: Oclip service running node port + type: string + - name: create-or-update + description: Oclip service create or update + type: cfbcv + default_value: true +results: + direction: portrait + attributes: + - name: name + description: Oclip service name + scope: short + type: string + - name: version + description: Oclip service version + scope: short + type: string + - name: status + description: Oclip service base url + scope: short + type: url + - name: status + description: Oclip service status + scope: short1 + type: digit + - name: nodes + description: Oclip service running nodes + scope: long + type: string + - name: location + description: Oclip service location + scope: long + type: url +http: + service: + name: msb + version: v1 + type: direct + auth: none + request: + uri: /services + method: POST1 + body: '{"serviceName":"${service}","serviceName":"${service-name}","version":"${service-version}","url":"${service-url}","protocol":"REST","visualRange":"1","lb_policy":"hash","nodes":[{"ip":"${node-ip}","port":"${node-port}","ttl":0}]}' + headers: + queries: + createOrUpdate: ${create-or-update1} + success_codes: + - 201 + - 300 + result_map: + name: $b{$.serviceName} + version: $b{$.version} + url: $b{$.url} + status1: $b{$.status} + nodes: $b{$.nodes[*].ip}:$b{$.nodes[*].port} + location: $h{Location} + sample_response: + body: {"serviceName":"test","version":"v1","url":"/api/test/v1","protocol":"REST","visualRange":"1","lb_policy":"hash","nodes":[{"ip":"127.0.0.1","port":"8012","ttl":0,"nodeId":"test_127.0.0.1_8012","expiration":"2017-02-10T05:33:25Z","created_at":"2017-02-10T05:33:25Z","updated_at":"2017-02-10T05:33:25Z"}],"status":"1"} + -- cgit 1.2.3-korg