From 1aab93e765169ca70ba7c9f35c5f61e0698f7f47 Mon Sep 17 00:00:00 2001 From: Brandon Lee Underwood Date: Thu, 22 Jun 2017 21:17:46 +0000 Subject: [PATCH] Fixed empty wsk list print, renamed functions, fixed comments, and reordered tests --- .../healthtests/ApiGwEndToEndTests.scala | 219 ++++++++-------- .../scala/system/basic/WskBasicTests.scala | 239 +++++++++--------- tools/cli/go-whisk-cli/commands/action.go | 7 +- tools/cli/go-whisk-cli/commands/api.go | 60 ++--- tools/cli/go-whisk-cli/commands/package.go | 8 +- tools/cli/go-whisk-cli/commands/rule.go | 7 +- tools/cli/go-whisk-cli/commands/trigger.go | 7 +- tools/cli/go-whisk-cli/commands/util.go | 43 ++-- tools/cli/go-whisk/whisk/action.go | 4 +- tools/cli/go-whisk/whisk/api.go | 32 +-- tools/cli/go-whisk/whisk/namespace.go | 4 +- tools/cli/go-whisk/whisk/package.go | 4 +- tools/cli/go-whisk/whisk/rule.go | 4 +- tools/cli/go-whisk/whisk/trigger.go | 4 +- tools/cli/go-whisk/whisk/util.go | 5 +- 15 files changed, 299 insertions(+), 348 deletions(-) diff --git a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala index c1231b27829..6bba76d57fe 100644 --- a/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala +++ b/tests/src/test/scala/apigw/healthtests/ApiGwEndToEndTests.scala @@ -74,6 +74,74 @@ class ApiGwEndToEndTests behavior of "Wsk api-experimental" + it should s"create an API and successfully invoke that API" in { + val testName = "APIGWe_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 + val file = TestUtils.getTestActionFilename(s"echo.js") + wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT) + + // Create the API + 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) + } + } + it should "return a list of alphabetized api-experimental" in withAssetCleaner(wskprops) { (wp, assetHelper) => @@ -85,7 +153,7 @@ class ApiGwEndToEndTests val base3 = "/BaseTestPath3" try { - //Create Actions for apiexperimentals + // Create Actions for apiexperimentals val file = TestUtils.getTestActionFilename(s"echo-web-http.js") assetHelper.withCleaner(wsk.action, actionName1) { (action, name) => action.create(name, artifact = Some(file), expectedExitCode = SUCCESS_EXIT, web = Some("true")) @@ -124,7 +192,7 @@ class ApiGwEndToEndTests scalaSorted.toString shouldEqual list.toString scalaSorted.toString shouldEqual listFull.toString } finally { - //Clean up apiexperimentals + // Clean up apiexperimentals wsk.apiexperimental.delete(base1, expectedExitCode = DONTCARE_EXIT) wsk.apiexperimental.delete(base2, expectedExitCode = DONTCARE_EXIT) wsk.apiexperimental.delete(base3, expectedExitCode = DONTCARE_EXIT) @@ -188,8 +256,10 @@ class ApiGwEndToEndTests } } + behavior of "Wsk api" + it should s"create an API and successfully invoke that API" in { - val testName = "APIGWe_HEALTHTEST1" + val testName = "APIGW_HEALTHTEST1" val testbasepath = "/" + testName + "_bp" val testrelpath = "/path" val testurlop = "get" @@ -201,12 +271,20 @@ class ApiGwEndToEndTests try { println("cli user: " + cliuser + "; cli namespace: " + clinamespace) - // Create the action for the API - val file = TestUtils.getTestActionFilename(s"echo.js") - wsk.action.create(name = actionName, artifact = Some(file), expectedExitCode = SUCCESS_EXIT) + // 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.apiexperimental.create(basepath = Some(testbasepath), relpath = Some(testrelpath), operation = Some(testurlop), action = Some(actionName), apiname = Some(testapiname)) + var rr = wsk.api.create( + basepath = Some(testbasepath), + relpath = Some(testrelpath), + operation = Some(testurlop), + action = Some(actionName), + apiname = Some(testapiname), + responsetype = Some("http"), + cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()) + ) rr.stdout should include("ok: created API") val apiurl = rr.stdout.split("\n")(1) println(s"apiurl: '${apiurl}'") @@ -216,13 +294,21 @@ class ApiGwEndToEndTests // 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 = 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.apiexperimental.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)) @@ -230,10 +316,17 @@ class ApiGwEndToEndTests 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) + 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.apiexperimental.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}'") @@ -252,12 +345,14 @@ class ApiGwEndToEndTests 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) + val finallydeleteApiResult = wsk.api.delete( + basepathOrApiName = testbasepath, + expectedExitCode = DONTCARE_EXIT, + cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()) + ) } } - behavior of "Wsk api" - it should "return a list of alphabetized api" in withAssetCleaner(wskprops) { (wp, assetHelper) => @@ -379,100 +474,4 @@ class ApiGwEndToEndTests wsk.api.delete(base3, expectedExitCode = DONTCARE_EXIT, cliCfgFile = Some(cliWskPropsFile.getCanonicalPath())) } } - - - 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), - responsetype = Some("http"), - cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()) - ) - 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.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), - cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()) - ) - 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.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()), - cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()) - ) - 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.api.delete( - basepathOrApiName = testbasepath, - expectedExitCode = DONTCARE_EXIT, - cliCfgFile = Some(cliWskPropsFile.getCanonicalPath()) - ) - } - } } diff --git a/tests/src/test/scala/system/basic/WskBasicTests.scala b/tests/src/test/scala/system/basic/WskBasicTests.scala index e99c6d4e386..71c4dd8aca9 100644 --- a/tests/src/test/scala/system/basic/WskBasicTests.scala +++ b/tests/src/test/scala/system/basic/WskBasicTests.scala @@ -47,127 +47,6 @@ class WskBasicTests behavior of "Wsk CLI" - - it should "return a list of alphabetized packages" in withAssetCleaner(wskprops) { - (wp, assetHelper) => - - // Declare 4 actions, create them out of alphabetical order - val nameA = "activationBasicTestingA1" - val nameB = "activationBasicTestingA2" - val nameC = "activationBasicTestingB1" - assetHelper.withCleaner(wsk.pkg, nameB) { - (pkg, nameB) => - pkg.create(nameB) - } - assetHelper.withCleaner(wsk.pkg, nameC) { - (pkg, nameC) => - pkg.create(nameC) - } - assetHelper.withCleaner(wsk.pkg, nameA) { - (pkg, nameA) => - pkg.create(nameA) - } - - val original = wsk.pkg.list().stdout - // Create list with action names in correct order - val scalaSorted = List(nameA, nameB, nameC) - // Filter out everything not previously created - val regex = "activationBasicTesting[A,B][1,2]".r - // Retrieve action names into list as found in original - val list = (regex.findAllMatchIn(original)).toList - scalaSorted.toString shouldEqual list.toString - } - - - it should "return a list of alphabetized rules" in withAssetCleaner(wskprops) { - (wp, assetHelper) => - - val triggerName = "listRulesTrigger" - val actionName = "listRulesAction" - - assetHelper.withCleaner(wsk.trigger, triggerName) { - (trigger, name) => trigger.create(name) - } - assetHelper.withCleaner(wsk.action, actionName) { - (action, name) => action.create(name, defaultAction) - } - // Declare 4 actions, create them out of alphabetical order - val nameA = "activationBasicTestingA1" - val nameB = "activationBasicTestingA2" - val nameC = "activationBasicTestingB1" - assetHelper.withCleaner(wsk.rule, nameB) { - (rule, nameB) => - rule.create(nameB, trigger = triggerName, action = actionName) - } - assetHelper.withCleaner(wsk.rule, nameC) { - (rule, nameC) => - rule.create(nameC, trigger = triggerName, action = actionName) - } - assetHelper.withCleaner(wsk.rule, nameA) { - (rule, nameA) => - rule.create(nameA, trigger = triggerName, action = actionName) - } - - val original = wsk.rule.list().stdout - // Create list with action names in correct order - val scalaSorted = List(nameA, nameB, nameC) - // Filter out everything not previously created - val regex = "activationBasicTesting[A,B][1,2]".r - // Retrieve action names into list as found in original - val list = (regex.findAllMatchIn(original)).toList - scalaSorted.toString shouldEqual list.toString - } - - it should "return a list of alphabetized actions" in withAssetCleaner(wskprops) { - (wp, assetHelper) => - // Declare 4 actions, create them out of alphabetical order - val nameA = "activationBasicTestingA1" - val nameB = "activationBasicTestingA2" - val nameC = "activationBasicTestingB1" - assetHelper.withCleaner(wsk.action, nameB) { - (action, _) => action.create(nameB, Some(TestUtils.getTestActionFilename("empty.js"))) - } - assetHelper.withCleaner(wsk.action, nameC) { - (action, _) => action.create(nameC, Some(TestUtils.getTestActionFilename("empty.js"))) - } - assetHelper.withCleaner(wsk.action, nameA) { - (action, _) => action.create(nameA, Some(TestUtils.getTestActionFilename("empty.js"))) - } - val original = wsk.action.list().stdout - // Create list with action names in correct order - val scalaSorted = List(nameA, nameB, nameC) - // Filter out everything not previously created - val regex = "activationBasicTesting[A,B][1,2]".r - // Retrieve action names into list as found in original - val list = (regex.findAllMatchIn(original)).toList - scalaSorted.toString shouldEqual list.toString -} - -it should "return a list of alphabetized triggers" in withAssetCleaner(wskprops) { -(wp, assetHelper) => - // Declare 4 actions, create them out of alphabetical order - val nameA = "activationBasicTestingA1" - val nameB = "activationBasicTestingA2" - val nameC = "activationBasicTestingB1" - assetHelper.withCleaner(wsk.trigger, nameB) { - (trigger, _) => trigger.create(nameB) - } - assetHelper.withCleaner(wsk.trigger, nameC) { - (trigger, _) => trigger.create(nameC) - } - assetHelper.withCleaner(wsk.trigger, nameA) { - (trigger, _) => trigger.create(nameA) - } - val original = wsk.trigger.list().stdout - // Create list with action names in correct order - val scalaSorted = List(nameA, nameB, nameC) - // Filter out everything not previously created - val regex = "activationBasicTesting[A,B][1,2]".r - // Retrieve action names into list as found in original - val list = (regex.findAllMatchIn(original)).toList - scalaSorted.toString shouldEqual list.toString -} - it should "confirm wsk exists" in { Wsk.exists } @@ -331,6 +210,35 @@ it should "return a list of alphabetized triggers" in withAssetCleaner(wskprops) stderr should include regex (s"""Unable to get package '$name': The requested resource does not exist. \\(code \\d+\\)""") } + it should "return a list of alphabetized packages" in withAssetCleaner(wskprops) { + (wp, assetHelper) => + // Declare 3 packages, create them out of alphabetical order + val nameA = "activationBasicTestingA1" + val nameB = "activationBasicTestingA2" + val nameC = "activationBasicTestingB1" + assetHelper.withCleaner(wsk.pkg, nameB) { + (pkg, nameB) => + pkg.create(nameB) + } + assetHelper.withCleaner(wsk.pkg, nameC) { + (pkg, nameC) => + pkg.create(nameC) + } + assetHelper.withCleaner(wsk.pkg, nameA) { + (pkg, nameA) => + pkg.create(nameA) + } + + val original = wsk.pkg.list().stdout + // Create list with package names in correct order + val scalaSorted = List(nameA, nameB, nameC) + // Filter out everything not previously created + val regex = "activationBasicTesting[A,B][1,2]".r + // Retrieve package names into list as found in original + val list = (regex.findAllMatchIn(original)).toList + scalaSorted.toString shouldEqual list.toString + } + behavior of "Wsk Action CLI" it should "create the same action twice with different cases" in withAssetCleaner(wskprops) { @@ -613,6 +521,31 @@ it should "return a list of alphabetized triggers" in withAssetCleaner(wskprops) wsk.action.get(name).stdout should not include (""""code"""") } + it should "return a list of alphabetized actions" in withAssetCleaner(wskprops) { + (wp, assetHelper) => + // Declare 3 actions, create them out of alphabetical order + val nameA = "activationBasicTestingA1" + val nameB = "activationBasicTestingA2" + val nameC = "activationBasicTestingB1" + assetHelper.withCleaner(wsk.action, nameB) { + (action, _) => action.create(nameB, Some(TestUtils.getTestActionFilename("empty.js"))) + } + assetHelper.withCleaner(wsk.action, nameC) { + (action, _) => action.create(nameC, Some(TestUtils.getTestActionFilename("empty.js"))) + } + assetHelper.withCleaner(wsk.action, nameA) { + (action, _) => action.create(nameA, Some(TestUtils.getTestActionFilename("empty.js"))) + } + val original = wsk.action.list().stdout + // Create list with action names in correct order + val scalaSorted = List(nameA, nameB, nameC) + // Filter out everything not previously created + val regex = "activationBasicTesting[A,B][1,2]".r + // Retrieve action names into list as found in original + val list = (regex.findAllMatchIn(original)).toList + scalaSorted.toString shouldEqual list.toString + } + behavior of "Wsk Trigger CLI" it should "create, update, get, fire and list trigger" in withAssetCleaner(wskprops) { @@ -776,6 +709,31 @@ it should "return a list of alphabetized triggers" in withAssetCleaner(wskprops) stderr should include regex (s"""Unable to fire trigger '$name': The requested resource does not exist. \\(code \\d+\\)""") } + it should "return a list of alphabetized triggers" in withAssetCleaner(wskprops) { + (wp, assetHelper) => + // Declare 3 triggers, create them out of alphabetical order + val nameA = "activationBasicTestingA1" + val nameB = "activationBasicTestingA2" + val nameC = "activationBasicTestingB1" + assetHelper.withCleaner(wsk.trigger, nameB) { + (trigger, _) => trigger.create(nameB) + } + assetHelper.withCleaner(wsk.trigger, nameC) { + (trigger, _) => trigger.create(nameC) + } + assetHelper.withCleaner(wsk.trigger, nameA) { + (trigger, _) => trigger.create(nameA) + } + val original = wsk.trigger.list().stdout + // Create list with trigger names in correct order + val scalaSorted = List(nameA, nameB, nameC) + // Filter out everything not previously created + val regex = "activationBasicTesting[A,B][1,2]".r + // Retrieve trigger names into list as found in original + val list = (regex.findAllMatchIn(original)).toList + scalaSorted.toString shouldEqual list.toString + } + behavior of "Wsk Rule CLI" it should "create rule, get rule, update rule and list rule" in withAssetCleaner(wskprops) { @@ -935,6 +893,45 @@ it should "return a list of alphabetized triggers" in withAssetCleaner(wskprops) stderr should include regex (s"""Unable to get rule '$name': The requested resource does not exist. \\(code \\d+\\)""") } + it should "return a list of alphabetized rules" in withAssetCleaner(wskprops) { + (wp, assetHelper) => + + // Declare a trigger and action for rules + val triggerName = "listRulesTrigger" + val actionName = "listRulesAction" + assetHelper.withCleaner(wsk.trigger, triggerName) { + (trigger, name) => trigger.create(name) + } + assetHelper.withCleaner(wsk.action, actionName) { + (action, name) => action.create(name, defaultAction) + } + // Declare 3 rules, create them out of alphabetical order + val nameA = "activationBasicTestingA1" + val nameB = "activationBasicTestingA2" + val nameC = "activationBasicTestingB1" + assetHelper.withCleaner(wsk.rule, nameB) { + (rule, nameB) => + rule.create(nameB, trigger = triggerName, action = actionName) + } + assetHelper.withCleaner(wsk.rule, nameC) { + (rule, nameC) => + rule.create(nameC, trigger = triggerName, action = actionName) + } + assetHelper.withCleaner(wsk.rule, nameA) { + (rule, nameA) => + rule.create(nameA, trigger = triggerName, action = actionName) + } + + val original = wsk.rule.list().stdout + // Create list with rule names in correct order + val scalaSorted = List(nameA, nameB, nameC) + // Filter out everything not previously created + val regex = "activationBasicTesting[A,B][1,2]".r + // Retrieve rule names into list as found in original + val list = (regex.findAllMatchIn(original)).toList + scalaSorted.toString shouldEqual list.toString + } + behavior of "Wsk Namespace CLI" it should "return a list of exactly one namespace" in { diff --git a/tools/cli/go-whisk-cli/commands/action.go b/tools/cli/go-whisk-cli/commands/action.go index 405590ca813..71aff1ec03f 100644 --- a/tools/cli/go-whisk-cli/commands/action.go +++ b/tools/cli/go-whisk-cli/commands/action.go @@ -313,12 +313,7 @@ var actionListCmd = &cobra.Command{ return actionListError(qualifiedName.entityName, options, err) } - if (len(actions) != 0) { - whisk.Debug(whisk.DbgInfo, "Sending actions to be printed") - printList(actions) - } else { - whisk.Debug(whisk.DbgInfo, "No actions found in action list") - } + printList(actions) return nil }, } diff --git a/tools/cli/go-whisk-cli/commands/api.go b/tools/cli/go-whisk-cli/commands/api.go index f0d5376d9b0..8396df1eb7a 100644 --- a/tools/cli/go-whisk-cli/commands/api.go +++ b/tools/cli/go-whisk-cli/commands/api.go @@ -423,14 +423,9 @@ var apiListCmd = &cobra.Command{ "ok": color.GreenString("ok:"), })) for i:=0; i 0) { // Dynamically create the output format string based on the maximum size of the @@ -1230,14 +1215,9 @@ var apiListCmdV2 = &cobra.Command{ })) fmt.Printf(fmtString, "Action", "Verb", "API Name", "URL") for i:=0; i< len(retApiArray.Apis); i++ { - sortFilteredRow = append(sortFilteredRow, printFilteredListRowV2(retApiArray.Apis[i].ApiValue, apiPath, apiVerb, maxActionNameSize, maxApiNameSize, flagType)...) - } - if (len(sortFilteredRow) != 0) { - whisk.Debug(whisk.DbgInfo, "Sending sortFilteredRow to be printed") - printList(sortFilteredRow) //Sends an array of structs that contains specifed variables that are truncated - } else { - whisk.Debug(whisk.DbgInfo, "No Apis found in Api list") + sortFilteredRow = append(sortFilteredRow, parseFilteredRowV2(retApiArray.Apis[i].ApiValue, apiPath, apiVerb, maxActionNameSize, maxApiNameSize, flagType)...) } + printList(sortFilteredRow) // Sends an array of structs that contains specifed variables that are truncated } else { fmt.Fprintf(color.Output, wski18n.T("{{.ok}} APIs\n", @@ -1258,7 +1238,7 @@ var apiListCmdV2 = &cobra.Command{ * each endpoint's configuration - one line per configuration property (action name, verb, api name, api gw url) * Parses and initializes values for ApiFilteredList struct */ -func printFilteredListApiV2(resultApi *whisk.RetApiV2, apiPath string, apiVerb string,flagType string) []whisk.ApiFilteredList{ +func parseFilteredListV2(resultApi *whisk.RetApiV2, apiPath string, apiVerb string,flagType string) []whisk.ApiFilteredList{ var sortInfo whisk.ApiFilteredList var sortInfoArr []whisk.ApiFilteredList baseUrl := strings.TrimSuffix(resultApi.BaseUrl, "/") @@ -1266,13 +1246,13 @@ func printFilteredListApiV2(resultApi *whisk.RetApiV2, apiPath string, apiVerb s basePath := resultApi.Swagger.BasePath if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) { for path, _ := range resultApi.Swagger.Paths { - whisk.Debug(whisk.DbgInfo, "printFilteredListApiV2: comparing api relpath: %s\n", path) + whisk.Debug(whisk.DbgInfo, "parseFilteredListV2: comparing api relpath: %s\n", path) if ( len(apiPath) == 0 || path == apiPath) { - whisk.Debug(whisk.DbgInfo, "printFilteredListApiV2: relpath matches\n") + whisk.Debug(whisk.DbgInfo, "parseFilteredListV2: relpath matches\n") for op, opv := range resultApi.Swagger.Paths[path] { - whisk.Debug(whisk.DbgInfo, "printFilteredListApiV2: comparing operation: '%s'\n", op) + whisk.Debug(whisk.DbgInfo, "parseFilteredListV2: comparing operation: '%s'\n", op) if ( len(apiVerb) == 0 || strings.ToLower(op) == strings.ToLower(apiVerb)) { - whisk.Debug(whisk.DbgInfo, "printFilteredListApiV2: operation matches: %#v\n", opv) + whisk.Debug(whisk.DbgInfo, "parseFilteredListV2: operation matches: %#v\n", opv) var actionName string if (len(opv.XOpenWhisk.Package) > 0) { actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName @@ -1304,7 +1284,7 @@ func printFilteredListApiV2(resultApi *whisk.RetApiV2, apiPath string, apiVerb s * * NOTE: Large action name and api name value will be truncated by their associated max size parameters. */ -func printFilteredListRowV2(resultApi *whisk.RetApiV2, apiPath string, apiVerb string, maxActionNameSize int, maxApiNameSize int, flagType string) []whisk.ApiFilteredRow { +func parseFilteredRowV2(resultApi *whisk.RetApiV2, apiPath string, apiVerb string, maxActionNameSize int, maxApiNameSize int, flagType string) []whisk.ApiFilteredRow { var sortInfo whisk.ApiFilteredRow var sortInfoArr []whisk.ApiFilteredRow baseUrl := strings.TrimSuffix(resultApi.BaseUrl, "/") @@ -1312,13 +1292,13 @@ func printFilteredListRowV2(resultApi *whisk.RetApiV2, apiPath string, apiVerb s basePath := resultApi.Swagger.BasePath if (resultApi.Swagger != nil && resultApi.Swagger.Paths != nil) { for path, _ := range resultApi.Swagger.Paths { - whisk.Debug(whisk.DbgInfo, "printFilteredListRowV2: comparing api relpath: %s\n", path) + whisk.Debug(whisk.DbgInfo, "parseFilteredRowV2: comparing api relpath: %s\n", path) if ( len(apiPath) == 0 || path == apiPath) { - whisk.Debug(whisk.DbgInfo, "printFilteredListRowV2: relpath matches\n") + whisk.Debug(whisk.DbgInfo, "parseFilteredRowV2: relpath matches\n") for op, opv := range resultApi.Swagger.Paths[path] { - whisk.Debug(whisk.DbgInfo, "printFilteredListRowV2: comparing operation: '%s'\n", op) + whisk.Debug(whisk.DbgInfo, "parseFilteredRowV2: comparing operation: '%s'\n", op) if ( len(apiVerb) == 0 || strings.ToLower(op) == strings.ToLower(apiVerb)) { - whisk.Debug(whisk.DbgInfo, "printFilteredListRowV2: operation matches: %#v\n", opv) + whisk.Debug(whisk.DbgInfo, "parseFilteredRowV2: operation matches: %#v\n", opv) var actionName string if (len(opv.XOpenWhisk.Package) > 0) { actionName = "/"+opv.XOpenWhisk.Namespace+"/"+opv.XOpenWhisk.Package+"/"+opv.XOpenWhisk.ActionName diff --git a/tools/cli/go-whisk-cli/commands/package.go b/tools/cli/go-whisk-cli/commands/package.go index 0a920b70b1c..17d2dae3f62 100644 --- a/tools/cli/go-whisk-cli/commands/package.go +++ b/tools/cli/go-whisk-cli/commands/package.go @@ -417,13 +417,7 @@ var packageListCmd = &cobra.Command{ werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) return werr } - - if (len(packages) != 0) { - whisk.Debug(whisk.DbgInfo, "Sending packages to be printed") - printList(packages) - } else { - whisk.Debug(whisk.DbgInfo, "No packages found in package list") - } + printList(packages) return nil }, } diff --git a/tools/cli/go-whisk-cli/commands/rule.go b/tools/cli/go-whisk-cli/commands/rule.go index 121f8abf004..418b35bcdd1 100644 --- a/tools/cli/go-whisk-cli/commands/rule.go +++ b/tools/cli/go-whisk-cli/commands/rule.go @@ -388,12 +388,7 @@ var ruleListCmd = &cobra.Command{ werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) return werr } - if (len(rules) != 0) { - whisk.Debug(whisk.DbgInfo, "Sending rules to be printed") - printList(rules) - } else { - whisk.Debug(whisk.DbgInfo, "No rules found in rule list") - } + printList(rules) return nil }, } diff --git a/tools/cli/go-whisk-cli/commands/trigger.go b/tools/cli/go-whisk-cli/commands/trigger.go index 196fbe945d9..254c898c20e 100644 --- a/tools/cli/go-whisk-cli/commands/trigger.go +++ b/tools/cli/go-whisk-cli/commands/trigger.go @@ -456,12 +456,7 @@ var triggerListCmd = &cobra.Command{ werr := whisk.MakeWskErrorFromWskError(errors.New(errStr), err, whisk.EXITCODE_ERR_GENERAL, whisk.DISPLAY_MSG, whisk.NO_DISPLAY_USAGE) return werr } - if (len(triggers) != 0) { - whisk.Debug(whisk.DbgInfo, "Sending triggers to be printed") - printList(triggers) - } else { - whisk.Debug(whisk.DbgInfo, "No triggers found in trigger list") - } + printList(triggers) return nil }, } diff --git a/tools/cli/go-whisk-cli/commands/util.go b/tools/cli/go-whisk-cli/commands/util.go index 0ea46b1660e..cc465a6eb90 100644 --- a/tools/cli/go-whisk-cli/commands/util.go +++ b/tools/cli/go-whisk-cli/commands/util.go @@ -249,15 +249,15 @@ func isValidJSON(value string) (bool) { var boldString = color.New(color.Bold).SprintFunc() type SortCmds []whisk.Sortable -//Uses Go builtin sort to sort commands based on their compare methods -//Param: Takes in a array of Sortable interfaces which contains a specific command +// Uses Go builtin sort to sort commands based on their compare methods +// Param: Takes in a array of Sortable interfaces which contains a specific command func (s SortCmds) Len() int { return len(s) } func (s SortCmds) Less(i,j int) bool { return s[i].Compare(s[j]) } func (s SortCmds) Swap(i,j int) { s[i], s[j] = s[j], s[i] } -//Prints the parameters/list for wsk xxxx list -//Identifies type and then copies array into an array of interfaces(Sortable) to be sorted and printed -//Param: Takes in an interace which contains an array of a command(Ex: []Action) +// Prints the parameters/list for wsk xxxx list +// Identifies type and then copies array into an array of interfaces(Sortable) to be sorted and printed +// Param: Takes in an interace which contains an array of a command(Ex: []Action) func printList(collection interface{}) { var commandToSort []whisk.Sortable switch collection := collection.(type){ @@ -266,31 +266,31 @@ func printList(collection interface{}) { commandToSort = append(commandToSort, collection[i]) } sort.Sort(SortCmds(commandToSort)) - printCommandsList(commandToSort,true) + printCommandsList(commandToSort, "actions") case []whisk.Trigger: for i := range collection { commandToSort = append(commandToSort, collection[i]) } sort.Sort(SortCmds(commandToSort)) - printCommandsList(commandToSort,true) + printCommandsList(commandToSort, "triggers") case []whisk.Package: for i := range collection { commandToSort = append(commandToSort, collection[i]) } sort.Sort(SortCmds(commandToSort)) - printCommandsList(commandToSort,true) + printCommandsList(commandToSort, "packages") case []whisk.Rule: for i := range collection { commandToSort = append(commandToSort, collection[i]) } sort.Sort(SortCmds(commandToSort)) - printCommandsList(commandToSort,true) + printCommandsList(commandToSort, "rules") case []whisk.Namespace: for i := range collection { commandToSort = append(commandToSort, collection[i]) } sort.Sort(SortCmds(commandToSort)) - printCommandsList(commandToSort,true) + printCommandsList(commandToSort, "namespaces") case []whisk.Activation: printActivationList(collection) case []whisk.ApiFilteredList: @@ -298,13 +298,13 @@ func printList(collection interface{}) { commandToSort = append(commandToSort, collection[i]) } sort.Sort(SortCmds(commandToSort)) - printCommandsList(commandToSort,false) + printCommandsList(commandToSort, "") case []whisk.ApiFilteredRow: for i:= range collection { commandToSort = append(commandToSort, collection[i]) } sort.Sort(SortCmds(commandToSort)) - printCommandsList(commandToSort,false) + printCommandsList(commandToSort, "") } } @@ -342,22 +342,15 @@ func printSummary(collection interface{}) { } } // Used to print Action, Tigger, Package, and Rule lists -// Param: Takes in a array of Sortable interface -func printCommandsList(commands []whisk.Sortable, printName bool) { - commandName := reflect.TypeOf(commands[0]).Name() - - if printName { +// Param: Takes in a array of Sortable interface, and the name of the command +// being sent to it +// **Note**: The name sould be an empty string for APIs. +func printCommandsList(commands []whisk.Sortable, commandName string) { + if commandName != "" { fmt.Fprintf(color.Output, "%s\n", boldString(commandName)) } for i := range commands { - fmt.Print(commands[i].ListString()) - } -} - -func printNamespaceList(namespaces []whisk.Namespace) { - fmt.Fprintf(color.Output, "%s\n", boldString("namespaces")) - for _, namespace := range namespaces { - fmt.Printf("%s\n", namespace.Name) + fmt.Print(commands[i].InfoToString()) } } diff --git a/tools/cli/go-whisk/whisk/action.go b/tools/cli/go-whisk/whisk/action.go index 50f1f968230..89583efb34d 100644 --- a/tools/cli/go-whisk/whisk/action.go +++ b/tools/cli/go-whisk/whisk/action.go @@ -78,11 +78,11 @@ func(action Action) Compare(sortable Sortable) bool{ } /* - * ListString() returns a compound string of required parameters for printing + * InfoToString() returns a compound string of required parameters for printing * from CLI command `wsk action list`. * ***Method of type Sortable*** */ -func(action Action) ListString() string{ +func(action Action) InfoToString() string{ publishState := wski18n.T("private") var kind string diff --git a/tools/cli/go-whisk/whisk/api.go b/tools/cli/go-whisk/whisk/api.go index 281930a536b..e1bbadc3209 100644 --- a/tools/cli/go-whisk/whisk/api.go +++ b/tools/cli/go-whisk/whisk/api.go @@ -185,6 +185,7 @@ type ApiSwaggerOpXOpenWhiskV2 struct { ApiUrl string `json:"url"` } +// Used for printing individual APIs in non-truncated form type ApiFilteredList struct { ActionName string ApiName string @@ -195,16 +196,16 @@ type ApiFilteredList struct { Flag string } +// Used for printing individual APIs in truncated form type ApiFilteredRow struct { - ActionName string - ApiName string - BasePath string - RelPath string - Verb string - Url string - FmtString string - Flag string - + ActionName string + ApiName string + BasePath string + RelPath string + Verb string + Url string + FmtString string + Flag string } var ApiVerbs map[string]bool = map[string]bool { @@ -220,6 +221,7 @@ var ApiVerbs map[string]bool = map[string]bool { const ( Overwrite = true DoNotOverwrite = false + sortActionFlag = "a" ) //////////////////// @@ -241,7 +243,7 @@ func(api ApiFilteredList) Compare(sortable Sortable) bool{ // Check for flag to build proper comparison strings switch api.Flag { - case "a": + case sortActionFlag: apiString = strings.ToLower(fmt.Sprintf("%s%s%s%s", api.ActionName, api.BasePath, api.RelPath, api.Verb)) compareString = strings.ToLower(fmt.Sprintf("%s%s%s%s", apiToCompare.ActionName, @@ -257,11 +259,11 @@ func(api ApiFilteredList) Compare(sortable Sortable) bool{ } /* - * ListString() returns a compound string of required parameters for printing + * InfoToString() returns a compound string of required parameters for printing * from CLI command `wsk api list` or `wsk api-experimental list`. * ***Method of type Sortable*** */ -func(api ApiFilteredList) ListString() string { +func(api ApiFilteredList) InfoToString() string { return fmt.Sprintf("%s %s %s %s %s %s", fmt.Sprintf("%s: %s\n", wski18n.T("Action"), api.ActionName), fmt.Sprintf(" %s: %s\n", wski18n.T("API Name"), api.ApiName), @@ -286,7 +288,7 @@ func(api ApiFilteredRow) Compare(sortable Sortable) bool{ // Check for flag to build proper comparison strings switch api.Flag { - case "a": + case sortActionFlag: apiString = strings.ToLower(fmt.Sprintf("%s%s%s%s", api.ActionName, api.BasePath, api.RelPath, api.Verb)) compareString = strings.ToLower(fmt.Sprintf("%s%s%s%s", apiToCompare.ActionName, @@ -302,11 +304,11 @@ func(api ApiFilteredRow) Compare(sortable Sortable) bool{ } /* - * ListString() returns a compound string of required parameters for printing + * InfoToString() returns a compound string of required parameters for printing * from CLI command `wsk api list -f` or `wsk api-experimental list -f`. * ***Method of type Sortable*** */ -func(api ApiFilteredRow) ListString() string { +func(api ApiFilteredRow) InfoToString() string { return fmt.Sprintf(api.FmtString, api.ActionName, api.Verb, api.ApiName, api.Url) } diff --git a/tools/cli/go-whisk/whisk/namespace.go b/tools/cli/go-whisk/whisk/namespace.go index d554ee767b6..a382a7e501f 100644 --- a/tools/cli/go-whisk/whisk/namespace.go +++ b/tools/cli/go-whisk/whisk/namespace.go @@ -55,11 +55,11 @@ func(namespace Namespace) Compare(sortable Sortable) bool { } /* - * ListString() returns a compound string of required parameters for printing + * InfoToString() returns a compound string of required parameters for printing * from CLI command `wsk namespace list`. * ***Method of type Sortable*** */ -func(namespace Namespace) ListString() string { +func(namespace Namespace) InfoToString() string { return fmt.Sprintf("%s\n", namespace.Name) } diff --git a/tools/cli/go-whisk/whisk/package.go b/tools/cli/go-whisk/whisk/package.go index 7aa8034d808..a03e78a0103 100644 --- a/tools/cli/go-whisk/whisk/package.go +++ b/tools/cli/go-whisk/whisk/package.go @@ -103,11 +103,11 @@ func(xPackage Package) Compare(sortable Sortable) bool{ } /* - * ListString() returns a compound string of required parameters for printing + * InfoToString() returns a compound string of required parameters for printing * from CLI command `wsk package list`. * ***Method of type Sortable*** */ -func(xPackage Package) ListString() string{ +func(xPackage Package) InfoToString() string{ publishState := wski18n.T("private") if xPackage.Publish != nil && *xPackage.Publish { diff --git a/tools/cli/go-whisk/whisk/rule.go b/tools/cli/go-whisk/whisk/rule.go index 666d52ff749..f05b56ad66d 100644 --- a/tools/cli/go-whisk/whisk/rule.go +++ b/tools/cli/go-whisk/whisk/rule.go @@ -63,11 +63,11 @@ func(rule Rule) Compare(sortable Sortable) bool{ } /* - * ListString() returns a compound string of required parameters for printing + * InfoToString() returns a compound string of required parameters for printing * from CLI command `wsk rule list`. * ***Method of type Sortable*** */ -func(rule Rule) ListString() string{ +func(rule Rule) InfoToString() string{ publishState := wski18n.T("private") return fmt.Sprintf("%-70s %s\n", fmt.Sprintf("/%s/%s", rule.Namespace, diff --git a/tools/cli/go-whisk/whisk/trigger.go b/tools/cli/go-whisk/whisk/trigger.go index 899dde226d7..2c04071984d 100644 --- a/tools/cli/go-whisk/whisk/trigger.go +++ b/tools/cli/go-whisk/whisk/trigger.go @@ -64,11 +64,11 @@ func(trigger Trigger) Compare(sortable Sortable) bool { } /* - * ListString() returns a compound string of required parameters for printing + * InfoToString() returns a compound string of required parameters for printing * from CLI command `wsk trigger list`. * ***Method of type Sortable*** */ -func(trigger Trigger) ListString() string { +func(trigger Trigger) InfoToString() string { publishState := wski18n.T("private") return fmt.Sprintf("%-70s %s\n", fmt.Sprintf("/%s/%s", trigger.Namespace, diff --git a/tools/cli/go-whisk/whisk/util.go b/tools/cli/go-whisk/whisk/util.go index 529ebe64f98..ce252119000 100644 --- a/tools/cli/go-whisk/whisk/util.go +++ b/tools/cli/go-whisk/whisk/util.go @@ -28,9 +28,10 @@ import ( "../wski18n" ) +// Sortable items are anything that needs to be sorted, listed, and printed. type Sortable interface { - Compare(s Sortable) bool - ListString() string + Compare(s Sortable) bool // Used for defining how to sort a Sortable + InfoToString() string // Defines what information to print for a Sortable } // addOptions adds the parameters in opt as URL query parameters to s. opt