Repackage routemgmt actions
- As a .zip
- Use common utilities module
Refactor routemgmt actions
- No longer store API configuration in a separate database
- Use the API GW as the API configuration data store
Small updates to automated tests

Add test case to validate API GW filtering when >1 APIs exist
Fix test that creates an API from swagger

Swagger test fix for PG environments (namespace for CLI can vary)

Consistent API GW tenant instance support across all actions
- default to 'openwhisk'
diff --git a/tests/src/common/TestUtils.java b/tests/src/common/TestUtils.java
index d7cce75..3515b35 100644
--- a/tests/src/common/TestUtils.java
+++ b/tests/src/common/TestUtils.java
@@ -67,6 +67,7 @@
 
     private static final File catalogDir = WhiskProperties.getFileRelativeToWhiskHome("catalog");
     private static final File testActionsDir = WhiskProperties.getFileRelativeToWhiskHome("tests/dat/actions");
+    private static final File testApiGwDir = WhiskProperties.getFileRelativeToWhiskHome("tests/dat/apigw");
     private static final File vcapFile = WhiskProperties.getVCAPServicesFile();
     private static final String envServices = System.getenv("VCAP_SERVICES");
     private static final String loggerLevel = System.getProperty("LOG_LEVEL", Level.WARNING.toString());
@@ -92,9 +93,15 @@
      * @param name the filename of the test action
      * @return
      */
-    public static String getTestActionFilename(String name) {
-        return new File(testActionsDir, name).toString();
-    }
+    public static String getTestActionFilename(String name) { return new File(testActionsDir, name).toString(); }
+
+    /**
+     * Gets path to test apigw file relative to test catalog directory.
+     *
+     * @param name the filename of the test action
+     * @return
+     */
+    public static String getTestApiGwFilename(String name) { return new File(testApiGwDir, name).toString(); }
 
     /**
      * Gets the value of VCAP_SERVICES.
diff --git a/tests/src/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala b/tests/src/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala
index 49fd1ba..b892aac 100644
--- a/tests/src/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala
+++ b/tests/src/whisk/core/apigw/actions/test/ApiGwRoutemgmtActionTests.scala
@@ -111,33 +111,6 @@
         expectedExitCode: Int = SUCCESS_EXIT): RunResult = {
         val parms = Map[String, JsValue]() ++
             { namespace map { n => Map("namespace" -> n.toJson) } getOrElse Map[String, JsValue]() } ++
-            { basepath map { b => Map("basepath" -> b.toJson) } getOrElse Map[String, JsValue]() } ++
-            { relpath map { r => Map("relpath" -> r.toJson) } getOrElse Map[String, JsValue]() } ++
-            { operation map { o => Map("operation" -> o.toJson) } getOrElse Map[String, JsValue]() } ++
-            { apiname map { an => Map("apiname" -> an.toJson) } getOrElse Map[String, JsValue]() } ++
-            { action map { a => Map("action" -> a.toJson) } getOrElse Map[String, JsValue]() } ++
-            { swagger map { s => Map("swagger" -> s.toJson) } getOrElse Map[String, JsValue]() }
-        val wskprops = new WskProps(authKey = systemKey)
-        val rr = wsk.action.invoke(
-            name = "routemgmt/createApi",
-            parameters = parms,
-            blocking = true,
-            result = true,
-            expectedExitCode = expectedExitCode)(wskprops)
-        return rr
-    }
-
-    def createRoute(
-        namespace: Option[String] = Some("_"),
-        basepath: Option[String] = Some("/"),
-        relpath: Option[String],
-        operation: Option[String],
-        apiname: Option[String],
-        action: Option[ApiAction],
-        swagger: Option[String] = None,
-        expectedExitCode: Int = SUCCESS_EXIT): RunResult = {
-        val parms = Map[String, JsValue]() ++
-            { namespace map { n => Map("namespace" -> n.toJson) } getOrElse Map[String, JsValue]() } ++
             { basepath map { b => Map("gatewayBasePath" -> b.toJson) } getOrElse Map[String, JsValue]() } ++
             { relpath map { r => Map("gatewayPath" -> r.toJson) } getOrElse Map[String, JsValue]() } ++
             { operation map { o => Map("gatewayMethod" -> o.toJson) } getOrElse Map[String, JsValue]() } ++
@@ -148,7 +121,7 @@
             { namespace map { n => Map("__ow_meta_namespace" -> n.toJson) } getOrElse Map[String, JsValue]() }
         val wskprops = new WskProps(authKey = systemKey)
         val rr = wsk.action.invoke(
-            name = "routemgmt/createRoute",
+            name = "routemgmt/createApi",
             parameters = parm,
             blocking = true,
             result = true,
@@ -162,10 +135,8 @@
         relpath: Option[String] = None,
         operation: Option[String] = None,
         apiname: Option[String] = None,
-        force: Boolean = true,
         expectedExitCode: Int = SUCCESS_EXIT): RunResult = {
         val parms = Map[String, JsValue]() ++
-            Map("force" -> force.toJson) ++
             { namespace map { n => Map("__ow_meta_namespace" -> n.toJson) } getOrElse Map[String, JsValue]() } ++
             { basepath map { b => Map("basepath" -> b.toJson) } getOrElse Map[String, JsValue]() } ++
             { relpath map { r => Map("relpath" -> r.toJson) } getOrElse Map[String, JsValue]() } ++
@@ -245,14 +216,14 @@
         val testaction = ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
 
         try {
-            val createResult = createRoute(namespace = Some(clinamespace), basepath = Some(testbasepath), relpath = Some(testrelpath),
+            val createResult = createApi(namespace = Some(clinamespace), basepath = Some(testbasepath), relpath = Some(testrelpath),
                 operation = Some(testurlop), apiname = Some(testapiname), action = Some(testaction))
             JsObjectHelper(createResult.stdout.parseJson.asJsObject).fieldPathExists("apidoc") should be(true)
             val apiVector = getApis(bpOrName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
             apiVector.size should be > 0
             apiMatch(apiVector, testbasepath, testrelpath, testurlop, testapiname, testaction) should be(true)
         } finally {
-            val deleteResult = deleteApi(namespace = Some(clinamespace), basepath = Some(testbasepath), force = true, expectedExitCode = DONTCARE_EXIT)
+            val deleteResult = deleteApi(namespace = Some(clinamespace), basepath = Some(testbasepath), expectedExitCode = DONTCARE_EXIT)
         }
     }
 
@@ -269,17 +240,17 @@
         val testaction = ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
 
         try {
-            val createResult = createRoute(namespace = Some(clinamespace), basepath = Some(testbasepath), relpath = Some(testrelpath),
+            val createResult = createApi(namespace = Some(clinamespace), basepath = Some(testbasepath), relpath = Some(testrelpath),
                 operation = Some(testurlop), apiname = Some(testapiname), action = Some(testaction))
             JsObjectHelper(createResult.stdout.parseJson.asJsObject).fieldPathExists("apidoc") should be(true)
             var apiVector = getApis(bpOrName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
             apiVector.size should be > 0
             apiMatch(apiVector, testbasepath, testrelpath, testurlop, testapiname, testaction) should be(true)
-            val deleteResult = deleteApi(namespace = Some(clinamespace), basepath = Some(testbasepath), force = true)
+            val deleteResult = deleteApi(namespace = Some(clinamespace), basepath = Some(testbasepath))
             apiVector = getApis(bpOrName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
             apiMatch(apiVector, testbasepath, testrelpath, testurlop, testapiname, testaction) should be(false)
         } finally {
-            val deleteResult = deleteApi(namespace = Some(clinamespace), basepath = Some(testbasepath), force = true, expectedExitCode = DONTCARE_EXIT)
+            val deleteResult = deleteApi(namespace = Some(clinamespace), basepath = Some(testbasepath), expectedExitCode = DONTCARE_EXIT)
         }
     }
 
@@ -298,9 +269,9 @@
         val testaction = ApiAction(name = actionName, namespace = actionNamespace, backendUrl = actionUrl, authkey = actionAuthKey)
 
         try {
-            var createResult = createRoute(namespace = Some(clinamespace), basepath = Some(testbasepath), relpath = Some(testrelpath),
+            var createResult = createApi(namespace = Some(clinamespace), basepath = Some(testbasepath), relpath = Some(testrelpath),
                 operation = Some(testurlop), apiname = Some(testapiname), action = Some(testaction))
-            createResult = createRoute(namespace = Some(clinamespace), basepath = Some(testbasepath), relpath = Some(testnewrelpath),
+            createResult = createApi(namespace = Some(clinamespace), basepath = Some(testbasepath), relpath = Some(testnewrelpath),
                 operation = Some(testnewurlop), apiname = Some(testapiname), action = Some(testaction))
             JsObjectHelper(createResult.stdout.parseJson.asJsObject).fieldPathExists("apidoc") should be(true)
             var apiVector = getApis(bpOrName = Some(testbasepath))
@@ -308,7 +279,7 @@
             apiMatch(apiVector, testbasepath, testrelpath, testurlop, testapiname, testaction) should be(true)
             apiMatch(apiVector, testbasepath, testnewrelpath, testnewurlop, testapiname, testaction) should be(true)
         } finally {
-            val deleteResult = deleteApi(namespace = Some(clinamespace), basepath = Some(testbasepath), force = true, expectedExitCode = DONTCARE_EXIT)
+            val deleteResult = deleteApi(namespace = Some(clinamespace), basepath = Some(testbasepath), expectedExitCode = DONTCARE_EXIT)
         }
     }
 
@@ -323,117 +294,32 @@
             ("/whisk.system/routemgmt/deleteApi", ANY_ERROR_EXIT, "When specifying an operation, the relpath is required",
                 Seq("-p", "__ow_meta_namespace", "_", "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp", "-p", "operation", "get")),
 
-            //deactivateApi
-            ("/whisk.system/routemgmt/deactivateApi", ANY_ERROR_EXIT, "namespace is required", Seq("-p", "basepath", "/ApiGwRoutemgmtActionTests_bp")),
-            ("/whisk.system/routemgmt/deactivateApi", ANY_ERROR_EXIT, "basepath is required", Seq("-p", "namespace", "_")),
-
-            //activateApi
-            ("/whisk.system/routemgmt/activateApi", ANY_ERROR_EXIT, "namespace is required", Seq("-p", "basepath", "/ApiGwRoutemgmtActionTests_bp")),
-
             //createApi
-            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "namespace is required",
-                Seq(
-                    //"-p", "namespace", "_",
-                    "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp",
-                    "-p", "relpath", "/ApiGwRoutemgmtActionTests_rp",
-                    "-p", "operation", "get",
-                    "-p", "action", """{"backendUrl":"URL","backendMethod":"get","namespace":"_","name":"myaction","authkey":"XXXXX"}""")),
-            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "basepath is required when swagger is not specified",
-                Seq(
-                    "-p", "namespace", "_",
-                    //"-p", "basepath", "/ApiGwRoutemgmtActionTests_bp",
-                    "-p", "relpath", "/ApiGwRoutemgmtActionTests_rp",
-                    "-p", "operation", "get",
-                    "-p", "action", """{"backendUrl":"URL","backendMethod":"get","namespace":"_","name":"myaction","authkey":"XXXXX"}""")),
-            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "relpath is required when swagger is not specified",
-                Seq(
-                    "-p", "namespace", "_",
-                    "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp",
-                    //"-p", "relpath", "/ApiGwRoutemgmtActionTests_rp",
-                    "-p", "operation", "get",
-                    "-p", "action", """{"backendUrl":"URL","backendMethod":"get","namespace":"_","name":"myaction","authkey":"XXXXX"}""")),
-            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "operation is required when swagger is not specified",
-                Seq(
-                    "-p", "namespace", "_",
-                    "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp",
-                    "-p", "relpath", "/ApiGwRoutemgmtActionTests_rp",
-                    //"-p", "operation", "get",
-                    "-p", "action", """{"backendUrl":"URL","backendMethod":"get","namespace":"_","name":"myaction","authkey":"XXXXX"}""")),
-            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "action is required when swagger is not specified",
-                Seq(
-                    "-p", "namespace", "_",
-                    "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp",
-                    "-p", "relpath", "/ApiGwRoutemgmtActionTests_rp",
-                    "-p", "operation", "get"
-                //"-p", "action", """{"backendUrl":"URL","backendMethod":"get","namespace":"_","name":"myaction","authkey":"XXXXX"}"""
-                )),
-            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "action is missing the backendUrl field",
-                Seq(
-                    "-p", "namespace", "_",
-                    "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp",
-                    "-p", "relpath", "/ApiGwRoutemgmtActionTests_rp",
-                    "-p", "operation", "get",
-                    "-p", "action", """{"backendMethod":"get","namespace":"_","name":"myaction","authkey":"XXXXX"}""")),
+            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "apidoc is required", Seq("-p", "__ow_meta_namespace", "_")),
+            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "apidoc is missing the namespace field",
+              Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", "{}")),
+            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "apidoc is missing the gatewayBasePath field",
+              Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_"}""")),
+            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "apidoc is missing the gatewayPath field",
+              Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp"}""")),
+            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "apidoc is missing the gatewayMethod field",
+              Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp"}""")),
+            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "apidoc is missing the action field",
+              Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get"}""")),
             ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "action is missing the backendMethod field",
-                Seq(
-                    "-p", "namespace", "_",
-                    "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp",
-                    "-p", "relpath", "/ApiGwRoutemgmtActionTests_rp",
-                    "-p", "operation", "get",
-                    "-p", "action", """{"backendUrl":"URL","namespace":"_","name":"myaction","authkey":"XXXXX"}""")),
+              Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{}}""")),
+            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "action is missing the backendUrl field",
+              Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post"}}""")),
             ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "action is missing the namespace field",
-                Seq(
-                    "-p", "namespace", "_",
-                    "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp",
-                    "-p", "relpath", "/ApiGwRoutemgmtActionTests_rp",
-                    "-p", "operation", "get",
-                    "-p", "action", """{"backendUrl":"URL","backendMethod":"get","name":"myaction","authkey":"XXXXX"}""")),
+              Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL"}}""")),
             ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "action is missing the name field",
-                Seq(
-                    "-p", "namespace", "_",
-                    "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp",
-                    "-p", "relpath", "/ApiGwRoutemgmtActionTests_rp",
-                    "-p", "operation", "get",
-                    "-p", "action", """{"backendUrl":"URL","backendMethod":"get","namespace":"_","authkey":"XXXXX"}""")),
+              Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_"}}""")),
             ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "action is missing the authkey field",
-                Seq(
-                    "-p", "namespace", "_",
-                    "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp",
-                    "-p", "relpath", "/ApiGwRoutemgmtActionTests_rp",
-                    "-p", "operation", "get",
-                    "-p", "action", """{"backendUrl":"URL","backendMethod":"get","namespace":"_","name":"myaction"}""")),
-            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "swagger field cannot be parsed. Ensure it is valid JSON",
-                Seq("-p", "namespace", "_", "-p", "swagger", "{1:[}}}")),
-            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "swagger and basepath are mutually exclusive and cannot be specified together",
-                Seq("-p", "namespace", "_", "-p", "basepath", "/ApiGwRoutemgmtActionTests_bp", "-p", "swagger", "{}")),
-
-            //createRoute
-            ("/whisk.system/routemgmt/createRoute", ANY_ERROR_EXIT, "apidoc is required", Seq("-p", "__ow_meta_namespace", "_")),
-            ("/whisk.system/routemgmt/createRoute", ANY_ERROR_EXIT, "apidoc is missing the namespace field",
-                Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", "{}")),
-            ("/whisk.system/routemgmt/createRoute", ANY_ERROR_EXIT, "apidoc is missing the gatewayBasePath field",
-                Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_"}""")),
-            ("/whisk.system/routemgmt/createRoute", ANY_ERROR_EXIT, "apidoc is missing the gatewayPath field",
-                Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp"}""")),
-            ("/whisk.system/routemgmt/createRoute", ANY_ERROR_EXIT, "apidoc is missing the gatewayMethod field",
-                Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp"}""")),
-            ("/whisk.system/routemgmt/createRoute", ANY_ERROR_EXIT, "apidoc is missing the action field",
-                Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get"}""")),
-            ("/whisk.system/routemgmt/createRoute", ANY_ERROR_EXIT, "action is missing the backendMethod field",
-                Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{}}""")),
-            ("/whisk.system/routemgmt/createRoute", ANY_ERROR_EXIT, "action is missing the backendUrl field",
-                Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post"}}""")),
-            ("/whisk.system/routemgmt/createRoute", ANY_ERROR_EXIT, "action is missing the namespace field",
-                Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL"}}""")),
-            ("/whisk.system/routemgmt/createRoute", ANY_ERROR_EXIT, "action is missing the name field",
-                Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_"}}""")),
-            ("/whisk.system/routemgmt/createRoute", ANY_ERROR_EXIT, "action is missing the authkey field",
-                Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_","name":"N"}}""")),
-            ("/whisk.system/routemgmt/createRoute", ANY_ERROR_EXIT, "swagger and gatewayBasePath are mutually exclusive and cannot be specified together",
-                Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_","name":"N","authkey":"XXXX"},"swagger":{}}""")),
-
-            ("/whisk.system/routemgmt/createRoute", ANY_ERROR_EXIT, "apidoc field cannot be parsed. Ensure it is valid JSON",
-                Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", "{1:[}}}"))
+              Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_","name":"N"}}""")),
+            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "swagger and gatewayBasePath are mutually exclusive and cannot be specified together",
+              Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", """{"namespace":"_","gatewayBasePath":"/ApiGwRoutemgmtActionTests_bp","gatewayPath":"ApiGwRoutemgmtActionTests_rp","gatewayMethod":"get","action":{"backendMethod":"post","backendUrl":"URL","namespace":"_","name":"N","authkey":"XXXX"},"swagger":{}}""")),
+            ("/whisk.system/routemgmt/createApi", ANY_ERROR_EXIT, "apidoc field cannot be parsed. Ensure it is valid JSON",
+              Seq("-p", "__ow_meta_namespace", "_", "-p", "apidoc", "{1:[}}}"))
         )
 
         invalidArgs foreach {
diff --git a/tests/src/whisk/core/cli/test/ApiGwTests.scala b/tests/src/whisk/core/cli/test/ApiGwTests.scala
index 2cab0ed..7509315 100644
--- a/tests/src/whisk/core/cli/test/ApiGwTests.scala
+++ b/tests/src/whisk/core/cli/test/ApiGwTests.scala
@@ -20,6 +20,7 @@
 import org.scalatest.junit.JUnitRunner
 import common.TestHelpers
 import common.TestUtils._
+import common.TestUtils
 import common.Wsk
 import common.WskAdmin
 import common.WskProps
@@ -69,12 +70,14 @@
             rr.stdout should include("ok: APIs")
             rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
             rr.stdout should include(testbasepath + testrelpath)
-        }
-        finally {
             val deleteresult = wsk.api.delete(basepathOrApiName = testbasepath)
             deleteresult.stdout should include("ok: deleted API")
         }
+        finally {
+            val deleteresult = wsk.api.delete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+        }
     }
+
     it should "verify get API name " in {
         val testName = "CLI_APIGWTEST3"
         val testbasepath = "/"+testName+"_bp"
@@ -91,93 +94,136 @@
             rr.stdout should include(s"${actionName}")
         }
         finally {
-            val deleteresult = wsk.api.delete(basepathOrApiName = testbasepath)
-            deleteresult.stdout should include("ok: deleted API")
-        }
-   }
-   it should "verify delete API name " in {
-        val testName = "CLI_APIGWTEST4"
-        val testbasepath = "/"+testName+"_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
-        try {
-            var rr = wsk.api.create(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = wsk.api.delete(basepathOrApiName = testapiname)
-            rr.stdout should include("ok: deleted API")
-        }
-        finally {
-            val deleteresult = wsk.api.delete(basepathOrApiName = testbasepath,expectedExitCode = DONTCARE_EXIT)
+            val deleteresult = wsk.api.delete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
         }
     }
 
-    it should "verify delete API basepath " in {
-        val testName = "CLI_APIGWTEST5"
-        val testbasepath = "/"+testName+"_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
-        try {
-            var rr = wsk.api.create(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = wsk.api.delete(basepathOrApiName = testbasepath)
-            rr.stdout should include("ok: deleted API")
-        }
-        finally {
-            val deleteresult = wsk.api.delete(basepathOrApiName = testbasepath,expectedExitCode = DONTCARE_EXIT)
-        }
-     }
-     it should "verify adding endpoints to existing api" in {
-        val testName = "CLI_APIGWTEST6"
-        val testbasepath = "/"+testName+"_bp"
-        val testrelpath = "/path2"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
-        val newEndpoint = "/newEndpoint"
-        try {
-            var rr = wsk.api.create(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = wsk.api.create(basepath = Some(testbasepath), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = wsk.api.list(basepathOrApiName = Some(testbasepath))
-            rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-            rr.stdout should include(testbasepath + newEndpoint)
-        }
-        finally {
-            val deleteresult = wsk.api.delete(basepathOrApiName = testbasepath)
-            deleteresult.stdout should include("ok: deleted API")
-        }
+    it should "verify delete API name " in {
+      val testName = "CLI_APIGWTEST4"
+      val testbasepath = "/"+testName+"_bp"
+      val testrelpath = "/path"
+      val testnewrelpath = "/path_new"
+      val testurlop = "get"
+      val testapiname = testName+" API Name"
+      val actionName = testName+"_action"
+      try {
+        var rr = wsk.api.create(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
+        rr.stdout should include("ok: created API")
+        rr = wsk.api.delete(basepathOrApiName = testapiname)
+        rr.stdout should include("ok: deleted API")
+      }
+      finally {
+        val deleteresult = wsk.api.delete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+      }
     }
+
+    it should "verify delete API basepath " in {
+      val testName = "CLI_APIGWTEST5"
+      val testbasepath = "/"+testName+"_bp"
+      val testrelpath = "/path"
+      val testnewrelpath = "/path_new"
+      val testurlop = "get"
+      val testapiname = testName+" API Name"
+      val actionName = testName+"_action"
+      try {
+        var rr = wsk.api.create(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
+        rr.stdout should include("ok: created API")
+        rr = wsk.api.delete(basepathOrApiName = testbasepath)
+        rr.stdout should include("ok: deleted API")
+      }
+      finally {
+        val deleteresult = wsk.api.delete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+      }
+    }
+
+    it should "verify adding endpoints to existing api" in {
+      val testName = "CLI_APIGWTEST6"
+      val testbasepath = "/"+testName+"_bp"
+      val testrelpath = "/path2"
+      val testnewrelpath = "/path_new"
+      val testurlop = "get"
+      val testapiname = testName+" API Name"
+      val actionName = testName+"_action"
+      val newEndpoint = "/newEndpoint"
+      try {
+        var rr = wsk.api.create(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
+        rr.stdout should include("ok: created API")
+        rr = wsk.api.create(basepath = Some(testbasepath), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
+        rr.stdout should include("ok: created API")
+        rr = wsk.api.list(basepathOrApiName = Some(testbasepath))
+        rr.stdout should include("ok: APIs")
+        rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+        rr.stdout should include(testbasepath + testrelpath)
+        rr.stdout should include(testbasepath + newEndpoint)
+      }
+      finally {
+        val deleteresult = wsk.api.delete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+      }
+    }
+
     it should "verify successful creation with swagger doc as input" in {
-        val testName = "CLI_APIGWTEST7"
-        val testbasepath = "/"+testName+"_bp"
-        val testrelpath = "/path"
-        val testnewrelpath = "/path_new"
-        val testurlop = "get"
-        val testapiname = testName+" API Name"
-        val actionName = testName+"_action"
-        val swaggerPath = "../../dat/apigwtestswaggerdoc1"
-        try {
-            var rr = wsk.api.create(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop),swagger= Some(swaggerPath), action = Some(actionName), apiname = Some(testapiname))
-            rr.stdout should include("ok: created API")
-            rr = wsk.api.list(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
-            rr.stdout should include("ok: APIs")
-            rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
-            rr.stdout should include(testbasepath + testrelpath)
-        }
-        finally {
-            val deleteresult = wsk.api.delete(basepathOrApiName = testbasepath)
-            deleteresult.stdout should include("ok: deleted API")
-        }
+      // NOTE: These values must match the swagger file contents
+      val testName = "CLI_APIGWTEST7"
+      val testbasepath = "/"+testName+"_bp"
+      val testrelpath = "/path"
+      val testurlop = "get"
+      val testapiname = testName+" API Name"
+      val actionName = testName+"_action"
+      val swaggerPath = TestUtils.getTestApiGwFilename("testswaggerdoc1")
+      try {
+        var rr = wsk.api.create(swagger = Some(swaggerPath))
+        rr.stdout should include("ok: created API")
+        rr = wsk.api.list(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop))
+        println("list stdout: "+rr.stdout)
+        println("list stderr: "+rr.stderr)
+        rr.stdout should include("ok: APIs")
+        // Actual CLI namespace will vary from local dev to automated test environments, so don't check
+        rr.stdout should include regex (s"/[@\\w._\\-]+/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+        rr.stdout should include(testbasepath + testrelpath)
+      }
+      finally {
+        val deleteresult = wsk.api.delete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+      }
+    }
+
+    it should "verify adding endpoints to two existing apis" in {
+      val testName = "CLI_APIGWTEST8"
+      val testbasepath = "/"+testName+"_bp"
+      val testbasepath2 = "/"+testName+"_bp2"
+      val testrelpath = "/path2"
+      val testnewrelpath = "/path_new"
+      val testurlop = "get"
+      val testapiname = testName+" API Name"
+      val actionName = testName+"_action"
+      val newEndpoint = "/newEndpoint"
+      try {
+        var rr = wsk.api.create(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
+        rr.stdout should include("ok: created API")
+        rr = wsk.api.create(basepath = Some(testbasepath2), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname))
+        rr.stdout should include("ok: created API")
+
+        // Update both APIs - each with a new endpoint
+        rr = wsk.api.create(basepath = Some(testbasepath), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName))
+        rr.stdout should include("ok: created API")
+        rr = wsk.api.create(basepath = Some(testbasepath2), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName))
+        rr.stdout should include("ok: created API")
+
+        rr = wsk.api.list(basepathOrApiName = Some(testbasepath))
+        rr.stdout should include("ok: APIs")
+        rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+        rr.stdout should include(testbasepath + testrelpath)
+        rr.stdout should include(testbasepath + newEndpoint)
+
+        rr = wsk.api.list(basepathOrApiName = Some(testbasepath2))
+        rr.stdout should include("ok: APIs")
+        rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+")
+        rr.stdout should include(testbasepath2 + testrelpath)
+        rr.stdout should include(testbasepath2 + newEndpoint)
+      }
+      finally {
+        var deleteresult = wsk.api.delete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT)
+        deleteresult = wsk.api.delete(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT)
+      }
     }
 }