This is an automated email from the ASF dual-hosted git repository. csantanapr pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-openwhisk-cli.git
commit 9ca38f88b555d34a5c598069f1deebecb1723f55 Author: Mark Deuser <mdeu...@us.ibm.com> AuthorDate: Thu Apr 13 17:39:25 2017 -0400 API GW V2 - Add 'wsk api` command (#2068) * API GW V2 CLI - Add 'wsk api' command - Support both 'wsk api-experimental' and 'wsk api' commands (separate PR wil deprecate `api-experimental`) - 'wsk api' command requires that the target action exist and that it's a web action * API GW V2 CLI - 'wsk api' tests * Add "COMING SOON" label to 'wsk api' help * API update needs additional param * Reduce travis test execution time --- .../apigw/healthtests/ApiGwEndToEndTests.scala | 137 ++++- .../scala/whisk/core/cli/test/ApiGwTests.scala | 681 ++++++++++++++++++--- 2 files changed, 735 insertions(+), 83 deletions(-) diff --git a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala index 1833d43..aa918ea 100644 --- a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala +++ b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala @@ -23,6 +23,7 @@ import java.io.FileWriter import scala.concurrent.duration.DurationInt import org.junit.runner.RunWith +import org.scalatest.BeforeAndAfterAll import org.scalatest.FlatSpec import org.scalatest.Matchers import org.scalatest.junit.JUnitRunner @@ -35,6 +36,7 @@ import common.TestUtils._ import common.Wsk import common.WskAdmin import common.WskProps +import common.WskPropsV2 import common.WskTestHelpers import spray.json._ import spray.json.DefaultJsonProtocol._ @@ -44,19 +46,40 @@ import system.rest.RestUtil * Basic tests of the download link for Go CLI binaries */ @RunWith(classOf[JUnitRunner]) -class ApiGwEndToEndTests extends FlatSpec with Matchers with RestUtil with TestHelpers with WskTestHelpers { +class ApiGwEndToEndTests + extends FlatSpec + with Matchers + with RestUtil + with TestHelpers + with WskTestHelpers + with BeforeAndAfterAll { implicit val wskprops = WskProps() val wsk = new Wsk val (cliuser, clinamespace) = WskAdmin.getUser(wskprops.authKey) + // Custom CLI properties file + val cliWskPropsFile = File.createTempFile("wskprops", ".tmp") + + /* + * Create a CLI properties file for use by the tests + */ + override def beforeAll() = { + cliWskPropsFile.deleteOnExit() + val wskprops = WskPropsV2(token = "SOME TOKEN") + wskprops.writeFile(cliWskPropsFile) + println(s"wsk temporary props file created here: ${cliWskPropsFile.getCanonicalPath()}") + } + + behavior of "Wsk api-experimental" + it should s"create an API and successfully invoke that API" in { - val testName = "APIGW_HEALTHTEST1" + val testName = "APIGWe_HEALTHTEST1" val testbasepath = "/" + testName + "_bp" val testrelpath = "/path" val testurlop = "get" val testapiname = testName + " API Name" - val actionName = "echo" + val actionName = testName + "_echo" val urlqueryparam = "name" val urlqueryvalue = "test" @@ -68,7 +91,84 @@ class ApiGwEndToEndTests extends FlatSpec with Matchers with RestUtil with TestH wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT) // Create the API - var rr = wsk.api.create(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr = wsk.apiexperimental.create(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + val apiurl = rr.stdout.split("\n")(1) + println(s"apiurl: '${apiurl}'") + + // Validate the API was successfully created + // List result will look like: + // ok: APIs + // Action Verb API Name URL + // /_//whisk.system/utils/echo get APIGW_HEALTHTEST1 API Name http://172.17.0.1:9001/api/ab9082cd-ea8e-465a-8a65-b491725cc4ef/APIGW_HEALTHTEST1_bp/path + rr = wsk.apiexperimental.list(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop)) + rr.stdout should include("ok: APIs") + rr.stdout should include regex (s"${actionName}\\s+${testurlop}\\s+${testapiname}\\s+") + rr.stdout should include(testbasepath + testrelpath) + + // Recreate the API using a JSON swagger file + rr = wsk.apiexperimental.get(basepathOrApiName = Some(testbasepath)) + val swaggerfile = File.createTempFile("api", ".json") + swaggerfile.deleteOnExit() + val bw = new BufferedWriter(new FileWriter(swaggerfile)) + bw.write(rr.stdout) + bw.close() + + // Delete API to that it can be recreated again using the generated swagger file + val deleteApiResult = wsk.apiexperimental.delete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + + // Create the API again, but use the swagger file this time + rr = wsk.apiexperimental.create(swagger = Some(swaggerfile.getAbsolutePath())) + rr.stdout should include("ok: created API") + val swaggerapiurl = rr.stdout.split("\n")(1) + println(s"apiurl: '${swaggerapiurl}'") + + // Call the API URL and validate the results + val response = whisk.utils.retry({ + val response = RestAssured.given().config(sslconfig).get(s"$swaggerapiurl?$urlqueryparam=$urlqueryvalue") + response.statusCode should be(200) + response + }, 5, Some(1.second)) + val responseString = response.body.asString + println("URL invocation response: " + responseString) + responseString.parseJson.asJsObject.fields(urlqueryparam).convertTo[String] should be(urlqueryvalue) + + } finally { + println("Deleting action: " + actionName) + val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) + println("Deleting API: " + testbasepath) + val finallydeleteApiResult = wsk.apiexperimental.delete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + } + } + + behavior of "Wsk api" + + it should s"create an API and successfully invoke that API" in { + val testName = "APIGW_HEALTHTEST1" + val testbasepath = "/" + testName + "_bp" + val testrelpath = "/path" + val testurlop = "get" + val testapiname = testName + " API Name" + val actionName = testName + "_echo" + val urlqueryparam = "name" + val urlqueryvalue = "test" + + try { + println("cli user: " + cliuser + "; cli namespace: " + clinamespace) + + // Create the action for the API. It must be a "web-action" action. + val file = TestUtils.getTestActionFilename(s"echo-web-http.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, annotations = Map("web-export" -> true.toJson)) + + // Create the API + var rr = wsk.api.create( + basepath = Some(testbasepath), + relpath = Some(testrelpath), + operation = Some(testurlop), + action = Some(actionName), + apiname = Some(testapiname), + cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()) + ) rr.stdout should include("ok: created API") val apiurl = rr.stdout.split("\n")(1) println(s"apiurl: '${apiurl}'") @@ -78,13 +178,21 @@ class ApiGwEndToEndTests extends FlatSpec with Matchers with RestUtil with TestH // ok: APIs // Action Verb API Name URL // /_//whisk.system/utils/echo get APIGW_HEALTHTEST1 API Name http://172.17.0.1:9001/api/ab9082cd-ea8e-465a-8a65-b491725cc4ef/APIGW_HEALTHTEST1_bp/path - rr = wsk.api.list(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop)) + rr = wsk.api.list( + basepathOrApiName = Some(testbasepath), + relpath = Some(testrelpath), + operation = Some(testurlop), + cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()) + ) rr.stdout should include("ok: APIs") rr.stdout should include regex (s"${actionName}\\s+${testurlop}\\s+${testapiname}\\s+") rr.stdout should include(testbasepath + testrelpath) // Recreate the API using a JSON swagger file - rr = wsk.api.get(basepathOrApiName = Some(testbasepath)) + rr = wsk.api.get( + basepathOrApiName = Some(testbasepath), + cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()) + ) val swaggerfile = File.createTempFile("api", ".json") swaggerfile.deleteOnExit() val bw = new BufferedWriter(new FileWriter(swaggerfile)) @@ -92,10 +200,17 @@ class ApiGwEndToEndTests extends FlatSpec with Matchers with RestUtil with TestH bw.close() // Delete API to that it can be recreated again using the generated swagger file - val deleteApiResult = wsk.api.delete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + val deleteApiResult = wsk.api.delete( + basepathOrApiName = testbasepath, + expectedExitCode = DONTCARE_EXIT, + cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()) + ) // Create the API again, but use the swagger file this time - rr = wsk.api.create(swagger = Some(swaggerfile.getAbsolutePath())) + rr = wsk.api.create( + swagger = Some(swaggerfile.getAbsolutePath()), + cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()) + ) rr.stdout should include("ok: created API") val swaggerapiurl = rr.stdout.split("\n")(1) println(s"apiurl: '${swaggerapiurl}'") @@ -114,7 +229,11 @@ class ApiGwEndToEndTests extends FlatSpec with Matchers with RestUtil with TestH println("Deleting action: " + actionName) val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) println("Deleting API: " + testbasepath) - val finallydeleteApiResult = wsk.api.delete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + val finallydeleteApiResult = wsk.api.delete( + basepathOrApiName = testbasepath, + expectedExitCode = DONTCARE_EXIT, + cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()) + ) } } } diff --git a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala index eae638e..249292f 100644 --- a/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala +++ b/tests/src/test/scala/whisk/core/cli/test/ApiGwTests.scala @@ -16,8 +16,11 @@ package whisk.core.cli.test +import java.io.File import java.time.Instant import scala.concurrent.duration._ +import spray.json._ +import spray.json.DefaultJsonProtocol._ import org.junit.runner.RunWith import org.scalatest.BeforeAndAfterAll import org.scalatest.junit.JUnitRunner @@ -28,6 +31,7 @@ import common.WhiskProperties import common.Wsk import common.WskAdmin import common.WskProps +import common.WskPropsV2 import common.WskTestHelpers /** @@ -52,6 +56,9 @@ class ApiGwTests var clearedThrottleTime = Instant.now val maxActionsPerMin = WhiskProperties.getMaxActionInvokesPerMinute() + // Custom CLI properties file + val cliWskPropsFile = File.createTempFile("wskprops", ".tmp") + /** * Expected to be called before or after each CLI invocation * If number of CLI invocations in this suite have reached the throttle limit @@ -60,8 +67,9 @@ class ApiGwTests def checkThrottle() = { // If the # CLI calls at the throttle limit, then wait enough time to avoid the CLI being blocked cliCallCount += 1 - if ( cliCallCount > maxActionsPerMin ) { - println(s"Action invokes ${cliCallCount} exceeds per minute thottle limit of ${maxActionsPerMin}") + println(s"Action invokes ${cliCallCount}; per minute thottle limit ${maxActionsPerMin}") + if ( cliCallCount > (maxActionsPerMin - 10) ) { // Allow for some margin...10 invocations + println(s"Action invokes ${cliCallCount} close to exceeding per minute thottle limit of ${maxActionsPerMin}") val waitedAlready = Duration.fromNanos(java.time.Duration.between(clearedThrottleTime, Instant.now).toNanos) settleThrottle(waitedAlready) cliCallCount = 0 @@ -81,6 +89,17 @@ class ApiGwTests } /* + * Create a CLI properties file for use by the tests + */ + override def beforeAll() = { + //cliWskPropsFile = File.createTempFile("wskprops", ".tmp") + cliWskPropsFile.deleteOnExit() + val wskprops = WskPropsV2(token = "SOME TOKEN") + wskprops.writeFile(cliWskPropsFile) + println(s"wsk temporary props file created here: ${cliWskPropsFile.getCanonicalPath()}") + } + + /* * Forcibly clear the throttle so that downstream tests are not affected by * this test suite */ @@ -92,7 +111,7 @@ class ApiGwTests } } - def apiCreate( + def apiCreateExperimental( basepath: Option[String] = None, relpath: Option[String] = None, operation: Option[String] = None, @@ -101,10 +120,10 @@ class ApiGwTests swagger: Option[String] = None, expectedExitCode: Int = SUCCESS_EXIT): RunResult = { checkThrottle() - wsk.api.create(basepath, relpath, operation, action, apiname, swagger, expectedExitCode) + wsk.apiexperimental.create(basepath, relpath, operation, action, apiname, swagger, expectedExitCode) } - def apiList( + def apiListExperimental( basepathOrApiName: Option[String] = None, relpath: Option[String] = None, operation: Option[String] = None, @@ -113,38 +132,83 @@ class ApiGwTests full: Option[Boolean] = None, expectedExitCode: Int = SUCCESS_EXIT): RunResult = { checkThrottle() - wsk.api.list(basepathOrApiName, relpath, operation, limit, since, full, expectedExitCode) + wsk.apiexperimental.list(basepathOrApiName, relpath, operation, limit, since, full, expectedExitCode) } - def apiGet( + def apiGetExperimental( basepathOrApiName: Option[String] = None, full: Option[Boolean] = None, expectedExitCode: Int = SUCCESS_EXIT): RunResult = { checkThrottle() - wsk.api.get(basepathOrApiName, full, expectedExitCode) + wsk.apiexperimental.get(basepathOrApiName, full, expectedExitCode) } - def apiDelete( + def apiDeleteExperimental( basepathOrApiName: String, relpath: Option[String] = None, operation: Option[String] = None, expectedExitCode: Int = SUCCESS_EXIT): RunResult = { checkThrottle() - wsk.api.delete(basepathOrApiName, relpath, operation, expectedExitCode) + wsk.apiexperimental.delete(basepathOrApiName, relpath, operation, expectedExitCode) } - behavior of "Wsk api" + def apiCreate( + basepath: Option[String] = None, + relpath: Option[String] = None, + operation: Option[String] = None, + action: Option[String] = None, + apiname: Option[String] = None, + swagger: Option[String] = None, + expectedExitCode: Int = SUCCESS_EXIT, + cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = { + checkThrottle() + wsk.api.create(basepath, relpath, operation, action, apiname, swagger, expectedExitCode, cliCfgFile) + } + + def apiList( + basepathOrApiName: Option[String] = None, + relpath: Option[String] = None, + operation: Option[String] = None, + limit: Option[Int] = None, + since: Option[Instant] = None, + full: Option[Boolean] = None, + expectedExitCode: Int = SUCCESS_EXIT, + cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = { + checkThrottle() + wsk.api.list(basepathOrApiName, relpath, operation, limit, since, full, expectedExitCode, cliCfgFile) + } + + def apiGet( + basepathOrApiName: Option[String] = None, + full: Option[Boolean] = None, + expectedExitCode: Int = SUCCESS_EXIT, + cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = { + checkThrottle() + wsk.api.get(basepathOrApiName, full, expectedExitCode, cliCfgFile) + } + + def apiDelete( + basepathOrApiName: String, + relpath: Option[String] = None, + operation: Option[String] = None, + expectedExitCode: Int = SUCCESS_EXIT, + cliCfgFile: Option[String] = Some(cliWskPropsFile.getCanonicalPath())): RunResult = { + checkThrottle() + wsk.api.delete(basepathOrApiName, relpath, operation, expectedExitCode, cliCfgFile) + } + + behavior of "Wsk api-experimental" it should "reject an api commands with an invalid path parameter" in { val badpath = "badpath" - var rr = apiCreate(basepath = Some("/basepath"), relpath = Some(badpath), operation = Some("GET"), action = Some("action"), expectedExitCode = ANY_ERROR_EXIT) + var rr = apiCreateExperimental(basepath = Some("/basepath"), relpath = Some(badpath), operation = Some("GET"), action = Some("action"), expectedExitCode = ANY_ERROR_EXIT) rr.stderr should include (s"'${badpath}' must begin with '/'") - rr = apiDelete(basepathOrApiName = "/basepath", relpath = Some(badpath), operation = Some("GET"), expectedExitCode = ANY_ERROR_EXIT) + rr = apiDeleteExperimental(basepathOrApiName = "/basepath", relpath = Some(badpath), operation = Some("GET"), expectedExitCode = ANY_ERROR_EXIT) rr.stderr should include (s"'${badpath}' must begin with '/'") - rr = apiList(basepathOrApiName = Some("/basepath"), relpath = Some(badpath), operation = Some("GET"), expectedExitCode = ANY_ERROR_EXIT) + rr = apiListExperimental(basepathOrApiName = Some("/basepath"), relpath = Some(badpath), operation = Some("GET"), expectedExitCode = ANY_ERROR_EXIT) rr.stderr should include (s"'${badpath}' must begin with '/'") } @@ -159,10 +223,10 @@ class ApiGwTests try { println("cli user: " + cliuser + "; cli namespace: " + clinamespace) - var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) println("api create: " + rr.stdout) rr.stdout should include("ok: created API") - rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), full = Some(true)) + rr = apiListExperimental(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), full = Some(true)) println("api list: " + rr.stdout) rr.stdout should include("ok: APIs") rr.stdout should include regex (s"Action:\\s+/${clinamespace}/${actionName}\n") @@ -174,7 +238,7 @@ class ApiGwTests rr.stdout should include(testbasepath + testrelpath) } finally { - val deleteresult = apiDelete(basepathOrApiName = testbasepath) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath) } } @@ -189,17 +253,17 @@ class ApiGwTests try { println("cli user: "+cliuser+"; cli namespace: "+clinamespace) - var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) rr.stdout should include("ok: created API") - rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop)) + rr = apiListExperimental(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) - val deleteresult = apiDelete(basepathOrApiName = testbasepath) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath) deleteresult.stdout should include("ok: deleted API") } finally { - val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) } } @@ -212,14 +276,14 @@ class ApiGwTests val testapiname = testName+" API Name" val actionName = testName+"_action" try { - var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) rr.stdout should include("ok: created API") - rr = apiGet(basepathOrApiName = Some(testapiname)) + rr = apiGetExperimental(basepathOrApiName = Some(testapiname)) rr.stdout should include(testbasepath) rr.stdout should include(s"${actionName}") } finally { - val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) } } @@ -232,13 +296,13 @@ class ApiGwTests val testapiname = testName+" API Name" val actionName = testName+"_action" try { - var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) rr.stdout should include("ok: created API") - rr = apiDelete(basepathOrApiName = testapiname) + rr = apiDeleteExperimental(basepathOrApiName = testapiname) rr.stdout should include("ok: deleted API") } finally { - val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) } } @@ -251,13 +315,13 @@ class ApiGwTests val testapiname = testName+" API Name" val actionName = testName+"_action" try { - var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) rr.stdout should include("ok: created API") - rr = apiDelete(basepathOrApiName = testbasepath) + rr = apiDeleteExperimental(basepathOrApiName = testbasepath) rr.stdout should include("ok: deleted API") } finally { - val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) } } @@ -271,18 +335,18 @@ class ApiGwTests val actionName = testName+"_action" val newEndpoint = "/newEndpoint" try { - var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) rr.stdout should include("ok: created API") - rr = apiCreate(basepath = Some(testbasepath), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) rr.stdout should include("ok: created API") - rr = apiList(basepathOrApiName = Some(testbasepath)) + rr = apiListExperimental(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 = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) } } @@ -296,9 +360,9 @@ class ApiGwTests val actionName = testName+"_action" val swaggerPath = TestUtils.getTestApiGwFilename("testswaggerdoc1") try { - var rr = apiCreate(swagger = Some(swaggerPath)) + var rr = apiCreateExperimental(swagger = Some(swaggerPath)) rr.stdout should include("ok: created API") - rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop)) + rr = apiListExperimental(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") @@ -307,7 +371,7 @@ class ApiGwTests rr.stdout should include(testbasepath + testrelpath) } finally { - val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) } } @@ -322,32 +386,32 @@ class ApiGwTests val actionName = testName+"_action" val newEndpoint = "/newEndpoint" try { - var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) rr.stdout should include("ok: created API") - rr = apiCreate(basepath = Some(testbasepath2), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr = apiCreateExperimental(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 = apiCreate(basepath = Some(testbasepath), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName)) + rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName)) rr.stdout should include("ok: created API") - rr = apiCreate(basepath = Some(testbasepath2), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName)) + rr = apiCreateExperimental(basepath = Some(testbasepath2), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName)) rr.stdout should include("ok: created API") - rr = apiList(basepathOrApiName = Some(testbasepath)) + rr = apiListExperimental(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 = apiList(basepathOrApiName = Some(testbasepath2)) + rr = apiListExperimental(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 = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) - deleteresult = apiDelete(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT) + var deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT) } } @@ -364,17 +428,17 @@ class ApiGwTests try { println("cli user: "+cliuser+"; cli namespace: "+clinamespace) - var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) rr.stdout should include("ok: created API") - rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop)) + rr = apiListExperimental(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) - val deleteresult = apiDelete(basepathOrApiName = testbasepath) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath) deleteresult.stdout should include("ok: deleted API") } finally { - val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) } } @@ -388,12 +452,12 @@ class ApiGwTests val actionName = testName + "_action" val swaggerPath = TestUtils.getTestApiGwFilename(s"testswaggerdocinvalid") try { - var rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT) + var rr = apiCreateExperimental(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT) println("api create stdout: " + rr.stdout) println("api create stderr: " + rr.stderr) rr.stderr should include(s"Swagger file is invalid") } finally { - val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) } } @@ -406,18 +470,18 @@ class ApiGwTests val testapiname = testName + " API Name" val actionName = testName + "_action" try { - var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) rr.stdout should include("ok: created API") - var rr2 = apiCreate(basepath = Some(testbasepath), relpath = Some(testnewrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr2 = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testnewrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) rr2.stdout should include("ok: created API") - rr = apiDelete(basepathOrApiName = testbasepath, relpath = Some(testrelpath)) + rr = apiDeleteExperimental(basepathOrApiName = testbasepath, relpath = Some(testrelpath)) rr.stdout should include("ok: deleted " + testrelpath +" from "+ testbasepath) - rr2 = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testnewrelpath)) + rr2 = apiListExperimental(basepathOrApiName = Some(testbasepath), relpath = Some(testnewrelpath)) rr2.stdout should include("ok: APIs") rr2.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+") rr2.stdout should include(testbasepath + testnewrelpath) } finally { - val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) } } @@ -431,20 +495,20 @@ class ApiGwTests val testapiname = testName + " API Name" val actionName = testName + "_action" try { - var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) rr.stdout should include("ok: created API") - rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop2), action = Some(actionName), apiname = Some(testapiname)) + rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop2), action = Some(actionName), apiname = Some(testapiname)) rr.stdout should include("ok: created API") - rr = apiList(basepathOrApiName = Some(testbasepath)) + rr = apiListExperimental(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 = apiDelete(basepathOrApiName = testbasepath,relpath = Some(testrelpath), operation = Some(testurlop2)) + rr = apiDeleteExperimental(basepathOrApiName = testbasepath,relpath = Some(testrelpath), operation = Some(testurlop2)) rr.stdout should include("ok: deleted " + testrelpath + " " + "POST" +" from "+ testbasepath) - rr = apiList(basepathOrApiName = Some(testbasepath)) + rr = apiListExperimental(basepathOrApiName = Some(testbasepath)) rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+") } finally { - val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) } } @@ -458,18 +522,18 @@ class ApiGwTests val actionName = "test1a" val swaggerPath = TestUtils.getTestApiGwFilename(s"testswaggerdoc2") try { - var rr = apiCreate(swagger = Some(swaggerPath)) + var rr = apiCreateExperimental(swagger = Some(swaggerPath)) println("api create stdout: " + rr.stdout) println("api create stderror: " + rr.stderr) rr.stdout should include("ok: created API") - rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop)) + rr = apiListExperimental(basepathOrApiName = Some(testbasepath)) 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) rr.stdout should include(testbasepath + testrelpath2) } finally { - val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) } } @@ -483,29 +547,498 @@ class ApiGwTests val testapiname = testName + " API Name" val actionName = testName + "_action" try { - var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr = apiCreateExperimental(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) rr.stdout should include("ok: created API") - rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop)) + rr = apiListExperimental(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) - rr = apiCreate(basepath = Some(testbasepath2), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr = apiCreateExperimental(basepath = Some(testbasepath2), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) rr.stdout should include("ok: created API") - rr = apiList(basepathOrApiName = Some(testbasepath2), relpath = Some(testrelpath), operation = Some(testurlop)) + rr = apiListExperimental(basepathOrApiName = Some(testbasepath2), 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(testbasepath2 + testrelpath) - rr = apiDelete(basepathOrApiName = testbasepath2) + rr = apiDeleteExperimental(basepathOrApiName = testbasepath2) rr.stdout should include("ok: deleted API") - rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop)) + rr = apiListExperimental(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) - rr = apiDelete(basepathOrApiName = testbasepath) + rr = apiDeleteExperimental(basepathOrApiName = testbasepath) rr.stdout should include("ok: deleted API") } finally { - var deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) - deleteresult = apiDelete(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT) + var deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT) } } + + behavior of "Wsk api" + + it should "reject an api commands with an invalid path parameter" in { + val badpath = "badpath" + + var rr = apiCreate(basepath = Some("/basepath"), relpath = Some(badpath), operation = Some("GET"), action = Some("action"), expectedExitCode = ANY_ERROR_EXIT) + rr.stderr should include (s"'${badpath}' must begin with '/'") + + rr = apiDelete(basepathOrApiName = "/basepath", relpath = Some(badpath), operation = Some("GET"), expectedExitCode = ANY_ERROR_EXIT) + rr.stderr should include (s"'${badpath}' must begin with '/'") + + rr = apiList(basepathOrApiName = Some("/basepath"), relpath = Some(badpath), operation = Some("GET"), expectedExitCode = ANY_ERROR_EXIT) + rr.stderr should include (s"'${badpath}' must begin with '/'") + } + + it should "verify full list output" in { + val testName = "CLI_APIGWTEST_RO1" + val testbasepath = "/" + testName + "_bp" + val testrelpath = "/path" + val testnewrelpath = "/path_new" + val testurlop = "get" + val testapiname = testName + " API Name" + val actionName = testName + "_action" + try { + println("cli user: " + cliuser + "; cli namespace: " + clinamespace) + // Create the action for the API. It must be a "web-action" action. + val file = TestUtils.getTestActionFilename(s"echo.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, annotations = Map("web-export" -> true.toJson)) + + var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + println("api create: " + rr.stdout) + rr.stdout should include("ok: created API") + rr = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), full = Some(true)) + println("api list: " + rr.stdout) + rr.stdout should include("ok: APIs") + rr.stdout should include regex (s"Action:\\s+/${clinamespace}/${actionName}\n") + rr.stdout should include regex (s"Verb:\\s+${testurlop}\n") + rr.stdout should include regex (s"Base path:\\s+${testbasepath}\n") + rr.stdout should include regex (s"Path:\\s+${testrelpath}\n") + rr.stdout should include regex (s"API Name:\\s+${testapiname}\n") + rr.stdout should include regex (s"URL:\\s+") + rr.stdout should include(testbasepath + testrelpath) + } + finally { + val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDelete(basepathOrApiName = testbasepath) + } + } + + it should "verify successful creation and deletion of a new API" in { + val testName = "CLI_APIGWTEST1" + val testbasepath = "/"+testName+"_bp" + val testrelpath = "/path" + val testnewrelpath = "/path_new" + val testurlop = "get" + val testapiname = testName+" API Name" + val actionName = testName+"_action" + try { + println("cli user: "+cliuser+"; cli namespace: "+clinamespace) + + // Create the action for the API. It must be a "web-action" action. + val file = TestUtils.getTestActionFilename(s"echo.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, annotations = Map("web-export" -> true.toJson)) + + var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + rr = apiList(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) + val deleteresult = apiDelete(basepathOrApiName = testbasepath) + deleteresult.stdout should include("ok: deleted API") + } + finally { + val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + } + } + + it should "verify get API name " in { + val testName = "CLI_APIGWTEST3" + val testbasepath = "/"+testName+"_bp" + val testrelpath = "/path" + val testnewrelpath = "/path_new" + val testurlop = "get" + val testapiname = testName+" API Name" + val actionName = testName+"_action" + try { + // Create the action for the API. It must be a "web-action" action. + val file = TestUtils.getTestActionFilename(s"echo.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, annotations = Map("web-export" -> true.toJson)) + + var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + rr = apiGet(basepathOrApiName = Some(testapiname)) + rr.stdout should include(testbasepath) + rr.stdout should include(s"${actionName}") + } + finally { + val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + } + } + + 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 { + // Create the action for the API. It must be a "web-action" action. + val file = TestUtils.getTestActionFilename(s"echo.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, annotations = Map("web-export" -> true.toJson)) + + var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + rr = apiDelete(basepathOrApiName = testapiname) + rr.stdout should include("ok: deleted API") + } + finally { + val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDelete(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 { + // Create the action for the API. It must be a "web-action" action. + val file = TestUtils.getTestActionFilename(s"echo.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, annotations = Map("web-export" -> true.toJson)) + + var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + rr = apiDelete(basepathOrApiName = testbasepath) + rr.stdout should include("ok: deleted API") + } + finally { + val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDelete(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 { + // Create the action for the API. It must be a "web-action" action. + val file = TestUtils.getTestActionFilename(s"echo.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, annotations = Map("web-export" -> true.toJson)) + + var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + rr = apiCreate(basepath = Some(testbasepath), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + rr = apiList(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 finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + } + } + + it should "verify successful creation with swagger doc as input" in { + // 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("testswaggerdoc1V2") + try { + var rr = apiCreate(swagger = Some(swaggerPath)) + rr.stdout should include("ok: created API") + rr = apiList(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 = apiDelete(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 { + // Create the action for the API. It must be a "web-action" action. + val file = TestUtils.getTestActionFilename(s"echo.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, annotations = Map("web-export" -> true.toJson)) + + var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + rr = apiCreate(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 = apiCreate(basepath = Some(testbasepath), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName)) + rr.stdout should include("ok: created API") + rr = apiCreate(basepath = Some(testbasepath2), relpath = Some(newEndpoint), operation = Some(testurlop), action = Some(actionName)) + rr.stdout should include("ok: created API") + + rr = apiList(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 = apiList(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 { + val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) + var deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + deleteresult = apiDelete(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT) + } + } + + it should "verify successful creation of a new API using an action name using all allowed characters" in { + // Be aware: full action name is close to being truncated by the 'list' command + // e.g. /l...@us.ibm.com/CLI_APIGWTEST9a-c@t ion is currently at the 40 char 'list' display max + val testName = "CLI_APIGWTEST9" + val testbasepath = "/" + testName + "_bp" + val testrelpath = "/path" + val testnewrelpath = "/path_new" + val testurlop = "get" + val testapiname = testName+" API Name" + val actionName = testName+"a-c@t ion" + try { + println("cli user: "+cliuser+"; cli namespace: "+clinamespace) + // Create the action for the API. It must be a "web-action" action. + val file = TestUtils.getTestActionFilename(s"echo.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, annotations = Map("web-export" -> true.toJson)) + + var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + rr = apiList(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) + val deleteresult = apiDelete(basepathOrApiName = testbasepath) + deleteresult.stdout should include("ok: deleted API") + } + finally { + val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + } + } + + it should "verify failed creation with invalid swagger doc as input" in { + val testName = "CLI_APIGWTEST10" + 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 = TestUtils.getTestApiGwFilename(s"testswaggerdocinvalid") + try { + var rr = apiCreate(swagger = Some(swaggerPath), expectedExitCode = ANY_ERROR_EXIT) + println("api create stdout: " + rr.stdout) + println("api create stderr: " + rr.stderr) + rr.stderr should include(s"Swagger file is invalid") + } finally { + val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + } + } + + it should "verify delete basepath/path " in { + val testName = "CLI_APIGWTEST11" + val testbasepath = "/" + testName + "_bp" + val testrelpath = "/path" + val testnewrelpath = "/path_new" + val testurlop = "get" + val testapiname = testName + " API Name" + val actionName = testName + "_action" + try { + // Create the action for the API. It must be a "web-action" action. + val file = TestUtils.getTestActionFilename(s"echo.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, annotations = Map("web-export" -> true.toJson)) + + var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + var rr2 = apiCreate(basepath = Some(testbasepath), relpath = Some(testnewrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr2.stdout should include("ok: created API") + rr = apiDelete(basepathOrApiName = testbasepath, relpath = Some(testrelpath)) + rr.stdout should include("ok: deleted " + testrelpath +" from "+ testbasepath) + rr2 = apiList(basepathOrApiName = Some(testbasepath), relpath = Some(testnewrelpath)) + rr2.stdout should include("ok: APIs") + rr2.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+") + rr2.stdout should include(testbasepath + testnewrelpath) + } finally { + val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + } + } + + it should "verify delete single operation from existing API basepath/path/operation(s) " in { + val testName = "CLI_APIGWTEST12" + val testbasepath = "/" + testName + "_bp" + val testrelpath = "/path2" + val testnewrelpath = "/path_new" + val testurlop = "get" + val testurlop2 = "post" + val testapiname = testName + " API Name" + val actionName = testName + "_action" + try { + // Create the action for the API. It must be a "web-action" action. + val file = TestUtils.getTestActionFilename(s"echo.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, annotations = Map("web-export" -> true.toJson)) + + var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop2), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + rr = apiList(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 = apiDelete(basepathOrApiName = testbasepath,relpath = Some(testrelpath), operation = Some(testurlop2)) + rr.stdout should include("ok: deleted " + testrelpath + " " + "POST" +" from "+ testbasepath) + rr = apiList(basepathOrApiName = Some(testbasepath)) + rr.stdout should include regex (s"/${clinamespace}/${actionName}\\s+${testurlop}\\s+${testapiname}\\s+") + } finally { + val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) + val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + } + } + + it should "verify successful creation with complex swagger doc as input" in { + val testName = "CLI_APIGWTEST13" + val testbasepath = "/test1/v1" + val testrelpath = "/whisk_system/utils/echo" + val testrelpath2 = "/whisk_system/utils/split" + val testurlop = "get" + val testapiname = testName + " API Name" + val actionName = "test1a" + val swaggerPath = TestUtils.getTestApiGwFilename(s"testswaggerdoc2V2") + try { + var rr = apiCreate(swagger = Some(swaggerPath)) + println("api create stdout: " + rr.stdout) + println("api create stderror: " + rr.stderr) + rr.stdout should include("ok: created API") + rr = apiList(basepathOrApiName = Some(testbasepath)) + 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) + rr.stdout should include(testbasepath + testrelpath2) + } finally { + val deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + } + } + + it should "verify successful creation and deletion with multiple base paths" in { + val testName = "CLI_APIGWTEST14" + val testbasepath = "/" + testName + "_bp" + val testbasepath2 = "/" + testName + "_bp2" + val testrelpath = "/path" + val testnewrelpath = "/path_new" + val testurlop = "get" + val testapiname = testName + " API Name" + val actionName = testName + "_action" + try { + // Create the action for the API. It must be a "web-action" action. + val file = TestUtils.getTestActionFilename(s"echo.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, annotations = Map("web-export" -> true.toJson)) + + var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + rr = apiList(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) + rr = apiCreate(basepath = Some(testbasepath2), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + rr.stdout should include("ok: created API") + rr = apiList(basepathOrApiName = Some(testbasepath2), 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(testbasepath2 + testrelpath) + rr = apiDelete(basepathOrApiName = testbasepath2) + rr.stdout should include("ok: deleted API") + rr = apiList(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) + rr = apiDelete(basepathOrApiName = testbasepath) + rr.stdout should include("ok: deleted API") + } finally { + val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) + var deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + deleteresult = apiDelete(basepathOrApiName = testbasepath2, expectedExitCode = DONTCARE_EXIT) + } + } + + it should "reject an API created with a non-existent action" in { + val testName = "CLI_APIGWTEST15" + 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 = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname), expectedExitCode = ANY_ERROR_EXIT) + rr.stderr should include("API action does not exist") + } + finally { + val deleteresult = apiDeleteExperimental(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + } + } + + it should "reject an API created with an action that is not a web-action" in { + val testName = "CLI_APIGWTEST16" + val testbasepath = "/" + testName + "_bp" + val testbasepath2 = "/" + testName + "_bp2" + val testrelpath = "/path" + val testnewrelpath = "/path_new" + val testurlop = "get" + val testapiname = testName + " API Name" + val actionName = testName + "_action" + try { + // Create the action for the API. It must NOT be a "web-action" action for this test + val file = TestUtils.getTestActionFilename(s"echo.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT) + + var rr = apiCreate(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname), expectedExitCode = ANY_ERROR_EXIT) + rr.stderr should include("API action is not a web-action") + } finally { + val finallydeleteActionResult = wsk.action.delete(name = actionName, expectedExitCode = DONTCARE_EXIT) + var deleteresult = apiDelete(basepathOrApiName = testbasepath, expectedExitCode = DONTCARE_EXIT) + } + } + } -- To stop receiving notification emails like this one, please contact "commits@openwhisk.apache.org" <commits@openwhisk.apache.org>.