Add test infrastructure for cloudant
diff --git a/.gitignore b/.gitignore
index c95e0ad..7f6823b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,2 @@
-/node_modules/
-*.log
+.gradle
+build/
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..4398fee
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,14 @@
+include 'tests', ':WhiskTest', ':common:scala', ':core:invoker', ':core:controller'
+
+rootProject.name = 'openwhisk-cloudant-trigger'
+def whiskhome = "$System.env.OPENWHISK_HOME"
+
+project(':WhiskTest').projectDir = new File(whiskhome, 'tests')
+project(':common:scala').projectDir = new File(whiskhome + '/common', 'scala')
+project(':core:invoker').projectDir = new File(whiskhome + '/core', 'invoker')
+project(':core:controller').projectDir = new File(whiskhome + '/core', 'controller')
+
+gradle.ext.scala = [
+ version: '2.11.8',
+ compileFlags: ['-feature', '-unchecked', '-deprecation', '-Xfatal-warnings', '-Ywarn-unused-import']
+]
\ No newline at end of file
diff --git a/tests/build.gradle b/tests/build.gradle
new file mode 100644
index 0000000..78e38eb
--- /dev/null
+++ b/tests/build.gradle
@@ -0,0 +1,69 @@
+def whiskhome = "$System.env.OPENWHISK_HOME"
+
+apply plugin: 'scala'
+apply plugin: 'eclipse'
+compileTestScala.options.encoding = 'UTF-8'
+
+repositories {
+ mavenCentral()
+ maven {
+ url 'https://oss.sonatype.org/content/repositories/snapshots/'
+ }
+}
+
+sourceSets {
+ test {
+ scala {
+ srcDirs = ['src/']
+ }
+ }
+}
+
+test {
+ systemProperty 'testthreads', System.getProperty('testthreads', '1')
+ testLogging {
+ events "passed", "skipped", "failed"
+ showStandardStreams = true
+ exceptionFormat = 'full'
+ }
+ outputs.upToDateWhen { false } // force tests to run everytime
+}
+
+dependencies {
+ testCompile "org.scala-lang:scala-library:${gradle.scala.version}"
+ testCompile 'org.apache.commons:commons-exec:1.1'
+ testCompile 'org.apache.commons:commons-lang3:3.3.2'
+ testCompile 'commons-logging:commons-logging:1.1.3'
+ testCompile 'org.codehaus.groovy:groovy:2.4.3'
+ testCompile 'org.codehaus.groovy:groovy-json:2.4.3'
+ testCompile 'org.codehaus.groovy:groovy-xml:2.4.3'
+ testCompile 'com.google.guava:guava:18.0'
+ testCompile 'org.hamcrest:hamcrest-core:1.3'
+ testCompile 'org.apache.httpcomponents:httpmime:4.3.6'
+ testCompile 'junit:junit:4.11'
+ testCompile 'com.jayway.restassured:rest-assured:2.4.1'
+ testCompile 'org.scalatest:scalatest_2.11:2.2.4'
+ testCompile 'org.seleniumhq.selenium:selenium-java:2.45.0'
+ testCompile 'io.spray:spray-testkit_2.11:1.3.3'
+ testCompile 'io.spray:spray-json_2.11:1.3.2'
+ testCompile 'com.google.code.tempus-fugit:tempus-fugit:1.2-SNAPSHOT'
+ testCompile 'com.google.code.gson:gson:2.3.1'
+ testCompile 'com.cloudant:cloudant-client:1.0.1'
+ testCompile project(':WhiskTest').sourceSets.test.output
+}
+
+tasks.withType(ScalaCompile) {
+ scalaCompileOptions.additionalParameters = gradle.scala.compileFlags
+}
+
+def keystorePath = new File(buildDir, 'classes/test/keystore')
+task deleteKeystore(type: Delete) {
+ delete keystorePath
+}
+task createKeystore(dependsOn: deleteKeystore) << {
+ Properties props = new Properties()
+ props.load(new FileInputStream(file(whiskhome+'/whisk.properties')))
+ def cmd = ['keytool', '-import', '-alias', 'Whisk', '-noprompt', '-trustcacerts', '-file', file(props['whisk.ssl.cert']), '-keystore', keystorePath, '-storepass', 'openwhisk']
+ cmd.execute().waitForProcessOutput(System.out, System.err)
+}
+compileTestScala.finalizedBy createKeystore
diff --git a/tests/dat/attach.txt b/tests/dat/attach.txt
new file mode 100644
index 0000000..630ac45
--- /dev/null
+++ b/tests/dat/attach.txt
@@ -0,0 +1 @@
+My hovercraft is full of eels!
diff --git a/tests/dat/indexdesigndoc.txt b/tests/dat/indexdesigndoc.txt
new file mode 100644
index 0000000..0ea3d2b
--- /dev/null
+++ b/tests/dat/indexdesigndoc.txt
@@ -0,0 +1,8 @@
+{
+ "ddoc":"test-query-index",
+ "name": "test-query-index",
+ "type": "json",
+ "index": {
+ "fields": ["date"]
+ }
+}
diff --git a/tests/dat/searchdesigndoc.txt b/tests/dat/searchdesigndoc.txt
new file mode 100644
index 0000000..833827c
--- /dev/null
+++ b/tests/dat/searchdesigndoc.txt
@@ -0,0 +1,15 @@
+{
+ "_id": "_design/test_design",
+ "views": {
+ "test_view": {
+ "map": "function (doc) {\n emit(doc._id, 1);\n}"
+ }
+ },
+ "language": "javascript",
+ "indexes": {
+ "test_search": {
+ "analyzer": "standard",
+ "index": "function (doc) {\n index(\"date\", doc.date);\n}"
+ }
+ }
+}
diff --git a/tests/src/catalog/CloudantUtil.java b/tests/src/catalog/CloudantUtil.java
new file mode 100755
index 0000000..e4fd188
--- /dev/null
+++ b/tests/src/catalog/CloudantUtil.java
@@ -0,0 +1,373 @@
+/*
+ * Copyright 2017 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package catalog;
+
+import com.cloudant.client.api.CloudantClient;
+import com.cloudant.client.api.Database;
+import com.google.gson.*;
+import com.jayway.restassured.response.Response;
+import common.Pair;
+import common.TestUtils;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.util.Date;
+import java.util.Map;
+import java.util.Properties;
+import java.util.UUID;
+
+import static com.jayway.restassured.RestAssured.given;
+import static org.junit.Assert.assertTrue;
+
+/**
+ * Basic tests of the cloudant trigger function.
+ */
+public class CloudantUtil {
+ public static final String USER_PROPERTY = "user";
+ public static final String PWD_PROPERTY = "password";
+ public static final String DBNAME_PROPERTY = "dbname";
+ public static final String DOC_ID = "testId";
+ public static final File ATTACHMENT_FILE_PATH = getFileRelativeToCloudantHome("tests/dat/attach.txt");
+ public static final File INDEX_DDOC_PATH = getFileRelativeToCloudantHome("tests/dat/indexdesigndoc.txt");
+ public static final File VIEW_AND_SEARCH_DDOC_PATH = getFileRelativeToCloudantHome("tests/dat/searchdesigndoc.txt");
+
+ /**
+ * The root of the Cloudant installation.
+ */
+ private static final String cloudantHome = getCloudantHome();
+ private static final String CLOUDANT_INSTALL_FILE = "installCatalog.sh";
+
+ private static Gson gson = new Gson();
+
+ public static class Credential {
+ public final String user;
+ public final String password;
+ public final String dbname;
+
+ public String host() {
+ return user + ".cloudant.com";
+ }
+
+ public Credential(String user, String password, String dbname) {
+ this.user = user;
+ this.password = password;
+ this.dbname = dbname;
+ }
+
+ public Credential(Properties props) {
+ this(props.getProperty(USER_PROPERTY), props.getProperty(PWD_PROPERTY), props.getProperty(DBNAME_PROPERTY));
+ }
+
+ public static Credential makeFromVCAPFile(String vcapService, String dbNamePrefix) {
+ // Create database name using dbNamePrefix and generated uuid
+ String uniqueSuffix = UUID.randomUUID().toString().replace("-", "");
+ String dbname = dbNamePrefix.toLowerCase() + "-" + uniqueSuffix;
+
+ Map<String,String> credentials = TestUtils.getVCAPcredentials(vcapService);
+ String username = credentials.get("username");
+ String password = credentials.get("password");
+ Properties props = new Properties();
+ props.setProperty(USER_PROPERTY, username);
+ props.setProperty(PWD_PROPERTY, password);
+ props.setProperty(DBNAME_PROPERTY, dbname);
+ return new Credential(props);
+ }
+
+ }
+
+ public static void setUp(Credential credential) throws Exception {
+ deleteTestDatabase(credential);
+ for (int i = 0; i < 5; i++) {
+ try {
+ Pair<Integer, JsonObject> response = CloudantUtil.createTestDatabase(credential, false);
+ if (response.fst == 201)
+ return;
+ // respond code is sometimes not 201 but still ok
+ // (might be 200 or 202)
+ if (response.snd.has("ok")) {
+ if (response.snd.get("ok").getAsBoolean())
+ return;
+ }
+ if (response.snd.has("reason")) {
+ String reason = response.snd.get("reason").getAsString();
+ if (reason.contains("exists"))
+ return;
+ }
+ } catch (Throwable t) {
+ Thread.sleep(1000);
+ }
+ }
+ assertTrue("failed to create database " + credential.dbname, false);
+ }
+
+ public static void unsetUp(Credential credential) throws Exception {
+ deleteTestDatabase(credential);
+ }
+
+ /**
+ * Delete a user-specific Cloudant database.
+ *
+ * @throws UnsupportedEncodingException
+ * @throws InterruptedException
+ */
+ public static JsonObject deleteTestDatabase(Credential credential) throws UnsupportedEncodingException, InterruptedException {
+ return deleteTestDatabase(credential, null);
+ }
+
+ public static JsonObject deleteTestDatabase(Credential credential, String dbName) throws UnsupportedEncodingException, InterruptedException {
+ // Use DELETE to delete the database.
+ // This could fail if the database already exists, but that's ok.
+ Response response = null;
+ String db = (dbName != null && !dbName.isEmpty()) ? dbName : credential.dbname;
+ assertTrue("failed to determine database name", db != null && !db.isEmpty());
+ response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).when().delete("/" + db);
+ System.out.format("Response of delete database %s: %s\n", db, response.asString());
+ return (JsonObject) new JsonParser().parse(response.asString());
+ }
+
+ /**
+ * Create a user-specific Cloudant database that will be used for this test.
+ *
+ * @throws UnsupportedEncodingException
+ */
+ public static Pair<Integer, JsonObject> createTestDatabase(Credential credential) throws UnsupportedEncodingException {
+ return createTestDatabase(credential, true);
+ }
+
+ private static Pair<Integer, JsonObject> createTestDatabase(Credential credential, boolean failIfCannotCreate) throws UnsupportedEncodingException {
+ // Use PUT to create the database.
+ // This could fail if the database already exists, but that's ok.
+ String dbName = credential.dbname;
+ assertTrue("failed to determine database name", dbName != null && !dbName.isEmpty());
+ Response response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).when().put("/" + dbName);
+ System.out.format("Response of create database %s: %s\n", dbName, response.asString());
+ if (failIfCannotCreate)
+ assertTrue("failed to create database " + dbName, response.statusCode() == 201 || response.statusCode() == 202);
+ return Pair.make(response.statusCode(), (JsonObject) new JsonParser().parse(response.asString()));
+ }
+
+ /**
+ * read a user-specific Cloudant database to verify database action test
+ * cases.
+ *
+ * @throws UnsupportedEncodingException
+ */
+ public static Response readTestDatabase(Credential credential) {
+ return readTestDatabase(credential, null);
+ }
+
+ public static Response readTestDatabase(Credential credential, String dbName) {
+ try {
+ Response response = null;
+ String db = (dbName != null && !dbName.isEmpty()) ? dbName : credential.dbname;
+ response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).when().get("/" + db);
+ System.out.format("Response of HTTP GET for database %s: %s\n", credential.dbname, response.asString());
+ return response;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+
+ /**
+ * create a document in the cloudant database
+ *
+ * @throws UnsupportedEncodingException
+ */
+ public static JsonObject createDocument(Credential credential, String jsonObj) throws UnsupportedEncodingException {
+ JsonObject obj = new JsonParser().parse(jsonObj).getAsJsonObject();
+
+ CloudantClient client = new CloudantClient(credential.user, credential.user, credential.password);
+ Database db = client.database(credential.dbname, false);
+ com.cloudant.client.api.model.Response res = db.post(obj);
+ client.shutdown();
+
+ JsonObject ret = new JsonObject();
+ ret.addProperty("ok", true);
+ ret.addProperty("id", res.getId());
+ ret.addProperty("rev", res.getRev());
+ return ret;
+ }
+
+ /**
+ * get a document from the cloudant database
+ *
+ * @throws UnsupportedEncodingException
+ */
+ public static JsonObject getDocument(Credential credential, String docId) throws UnsupportedEncodingException {
+ // use GET to get the document
+ Response response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).get("/" + credential.dbname + "/" + docId);
+ String responseStr = response.asString();
+ if (responseStr.length() > 500)
+ responseStr = responseStr.substring(0, 500);
+ System.out.format("Response of get document from database %s: %s\n", credential.dbname, responseStr);
+ return (JsonObject) new JsonParser().parse(response.asString());
+ }
+
+ /**
+ * delete a document from the cloudant database
+ *
+ * @throws UnsupportedEncodingException
+ */
+ public static JsonObject deleteDocument(Credential credential, String docId) throws UnsupportedEncodingException {
+ // use GET to get the document
+ Response response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).delete("/" + credential.dbname + "/" + docId);
+ System.out.format("Response of delete document in database %s: %s\n", credential.dbname, response.asString());
+ assertTrue("failed to delete document in database " + credential.dbname, response.statusCode() == 200 || response.statusCode() == 202);
+ return (JsonObject) new JsonParser().parse(response.asString());
+ }
+
+ /**
+ * Read bulk documents from the cloudant database
+ *
+ * @throws UnsupportedEncodingException
+ */
+ public static JsonArray bulkDocuments(Credential credential, JsonArray bulkDocs) throws UnsupportedEncodingException {
+ JsonObject docs = new JsonObject();
+ docs.add("docs", bulkDocs);
+ // use GET to get the document
+ String dbname = credential.dbname;
+ Response response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).contentType("application/json").body(docs).post("/" + credential.dbname + "/_bulk_docs?include_docs=true");
+ String responseStr = response.asString();
+ if (responseStr.length() > 500)
+ responseStr = responseStr.substring(0, 500);
+ System.out.format("Response of get document from database %s: %s\n", dbname, responseStr);
+ return (JsonArray) new JsonParser().parse(response.asString());
+ }
+
+ public static JsonObject createDocParameterForWhisk() {
+ return createDocParameterForWhisk(null);
+ }
+
+ public static JsonObject createDocParameterForWhisk(String doc) {
+ JsonObject cloudantDoc = new JsonObject();
+ String now = new Date().toString();
+ cloudantDoc.addProperty("_id", DOC_ID);
+ cloudantDoc.addProperty("date", now);
+ // Create JSON object that will be passed as an argument to whisk cli
+ JsonObject param = new JsonObject();
+ if (doc != null && !doc.isEmpty()) {
+ param.addProperty("doc", doc);
+ } else {
+ param.addProperty("doc", cloudantDoc.toString());
+ }
+ return param;
+ }
+
+ public static JsonArray createDocumentArray(int numDocs) {
+ // Array of docs for bulk
+ JsonArray bulkDocs = new JsonArray();
+ for (int i = 1; i <= numDocs; i++) {
+ JsonObject cloudantDoc = new JsonObject();
+ String now = new Date().toString();
+ cloudantDoc.addProperty("_id", CloudantUtil.DOC_ID + i);
+ cloudantDoc.addProperty("date", now);
+ bulkDocs.add(cloudantDoc);
+ }
+ return bulkDocs;
+ }
+
+ /**
+ * Only keep _id and _rev for each document in the JSON array.
+ */
+ public static JsonArray updateDocsWithOnlyIdAndRev(JsonArray docs) {
+ for (int i = 0; i < docs.size(); i++) {
+ JsonElement id = docs.get(i).getAsJsonObject().get("id");
+ JsonElement rev = docs.get(i).getAsJsonObject().get("rev");
+ docs.get(i).getAsJsonObject().add("_id", id);
+ docs.get(i).getAsJsonObject().add("_rev", rev);
+ }
+ return docs;
+ }
+
+ public static JsonArray addDeletedPropertyToDocs(JsonArray docs) {
+ for (int i = 0; i < docs.size(); i++) {
+ JsonElement id = docs.get(i).getAsJsonObject().get("id");
+ JsonElement rev = docs.get(i).getAsJsonObject().get("rev");
+ docs.get(i).getAsJsonObject().add("_id", id);
+ docs.get(i).getAsJsonObject().add("_rev", rev);
+ docs.get(i).getAsJsonObject().addProperty("_deleted", true);
+ }
+ return docs;
+ }
+
+ public static JsonObject createDesignFromFile(File jsonFile) throws JsonSyntaxException, IOException {
+ return gson.fromJson(readFile(jsonFile), JsonObject.class);
+ }
+
+ public static String readFile(File jsonFile) throws IOException {
+ return new String(Files.readAllBytes(jsonFile.toPath()), StandardCharsets.UTF_8);
+ }
+
+ /**
+ * Create an index in the cloudant database
+ *
+ * @throws UnsupportedEncodingException
+ */
+ public static JsonObject createIndex(Credential credential, String jsonObj) throws UnsupportedEncodingException {
+ Response response = given().port(443).baseUri(cloudantAccount(credential.user)).auth().basic(credential.user, credential.password).contentType("application/json").body(jsonObj).when().post("/" + credential.dbname + "/_index");
+ System.out.format("Response of create document in database %s: %s\n", credential.dbname, response.asString());
+ assertTrue("failed to create index in database " + credential.dbname, response.statusCode() == 200);
+ return (JsonObject) new JsonParser().parse(response.asString());
+ }
+
+ /**
+ * Create a document with attachment in a cloudant database
+ *
+ * @throws UnsupportedEncodingException
+ * @throws FileNotFoundException
+ */
+ public static com.cloudant.client.api.model.Response createDocumentWithAttachment(Credential credential, File attachmentFilePath) throws UnsupportedEncodingException, FileNotFoundException {
+ InputStream attachStream = new FileInputStream(attachmentFilePath);
+ String contentType = "text/plain";
+
+ CloudantClient client = new CloudantClient(credential.user, credential.user, credential.password);
+ Database db = client.database(credential.dbname, false);
+ return db.saveAttachment(attachStream, attachmentFilePath.getName(), contentType);
+ }
+
+ private static String cloudantAccount(String user) {
+ return "https://" + user + ".cloudant.com";
+ }
+
+ public static File getFileRelativeToCloudantHome(String name) {
+ return new File(cloudantHome, name);
+ }
+
+ private static String getCloudantHome() {
+ String dir = System.getProperty("user.dir");
+
+ if (dir != null) {
+ // Look in the directory tree recursively.
+ File propfile = findFileRecursively(dir, CLOUDANT_INSTALL_FILE);
+ return propfile != null ? propfile.getParent() : null;
+ } else return null;
+ }
+
+ private static File findFileRecursively(String dir, String needle) {
+ if (dir != null) {
+ File base = new File(dir);
+ File file = new File(base, needle);
+ if (file.exists()) {
+ return file;
+ } else {
+ return findFileRecursively(base.getParent(), needle);
+ }
+ } else return null;
+ }
+
+}
diff --git a/tests/src/catalog/cloudant/CloudantBindingTests.scala b/tests/src/catalog/cloudant/CloudantBindingTests.scala
new file mode 100644
index 0000000..812de49
--- /dev/null
+++ b/tests/src/catalog/cloudant/CloudantBindingTests.scala
@@ -0,0 +1,121 @@
+/*
+ * Copyright 2017 IBM Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package catalog.cloudant
+
+import org.junit.runner.RunWith
+import org.scalatest.FlatSpec
+import org.scalatest.junit.JUnitRunner
+
+import catalog.CloudantUtil
+import common.JsHelpers
+import common.TestHelpers
+import common.Wsk
+import common.WskProps
+import common.WskTestHelpers
+import spray.json.DefaultJsonProtocol.StringJsonFormat
+import spray.json.JsObject
+import spray.json.pimpAny
+
+@RunWith(classOf[JUnitRunner])
+class CloudantBindingTests extends FlatSpec
+ with TestHelpers
+ with WskTestHelpers
+ with JsHelpers {
+
+ val wskprops = WskProps()
+ val wsk = new Wsk
+
+ val myCloudantCreds = CloudantUtil.Credential.makeFromVCAPFile("cloudantNoSQLDB", this.getClass.getSimpleName)
+
+ behavior of "Cloudant binding"
+
+ /**
+ * Simulate bluemix package binding by supplying a "url" parameter.
+ * Additionally, leave out other key parameters (e.g. username, password)
+ * to ensure that the action uses the "url" bound parameter.
+ */
+ it should """Use "url" property if it is available""" in withAssetCleaner(wskprops) {
+ (wp, assetHelper) =>
+ implicit val wskprops = wp // shadow global props and make implicit
+ val packageName = "cloudantBindingWithURL"
+
+ try {
+ CloudantUtil.setUp(myCloudantCreds)
+
+ val packageGetResult = wsk.pkg.get("/whisk.system/cloudant")
+ println("Fetching cloudant package.")
+ packageGetResult.stdout should include("ok")
+
+ println("""Creating cloudant package binding with only a "url" parameter.""")
+ assetHelper.withCleaner(wsk.pkg, packageName) {
+ (pkg, name) =>
+ pkg.bind("/whisk.system/cloudant", name,
+ Map("url" -> s"https://${myCloudantCreds.user}:${myCloudantCreds.password}@${myCloudantCreds.host}".toJson))
+ }
+
+ println("Invoking the document-create action.")
+ withActivation(wsk.activation, wsk.action.invoke(s"${packageName}/create-document",
+ Map(
+ "dbname" -> myCloudantCreds.dbname.toJson,
+ "doc" -> JsObject("message" -> "I used the url parameter.".toJson)))) {
+ activation =>
+ activation.response.success shouldBe true
+ activation.response.result.get.fields.get("id") shouldBe defined
+ }
+ } finally {
+ CloudantUtil.unsetUp(myCloudantCreds)
+ }
+ }
+
+ /**
+ * Simulate a user creating their own binding with "username", "password", and "host".
+ * Do not include "url" in the binding to ensure the package uses the other bound properties.
+ */
+ it should """Use "username", "password", and "host" if "url" is not available""" in withAssetCleaner(wskprops) {
+ (wp, assetHelper) =>
+ implicit val wskprops = wp // shadow global props and make implicit
+ val packageName = "cloudantBindingWithoutURL"
+
+ try {
+ CloudantUtil.setUp(myCloudantCreds)
+
+ val packageGetResult = wsk.pkg.get("/whisk.system/cloudant")
+ println("Fetching cloudant package.")
+ packageGetResult.stdout should include("ok")
+
+ println("""Creating cloudant package binding with "username", "pasword" and "host".""")
+ assetHelper.withCleaner(wsk.pkg, packageName) {
+ (pkg, name) =>
+ pkg.bind("/whisk.system/cloudant", name,
+ Map("username" -> myCloudantCreds.user.toJson,
+ "password" -> myCloudantCreds.password.toJson,
+ "host" -> myCloudantCreds.host().toJson))
+ }
+
+ println("Invoking the document-create action.")
+ withActivation(wsk.activation, wsk.action.invoke(s"${packageName}/create-document",
+ Map(
+ "dbname" -> myCloudantCreds.dbname.toJson,
+ "doc" -> JsObject("message" -> "This time I didn't use the URL param.".toJson)))) {
+ activation =>
+ activation.response.success shouldBe true
+ activation.response.result.get.fields.get("id") shouldBe defined
+ }
+ } finally {
+ CloudantUtil.unsetUp(myCloudantCreds)
+ }
+ }
+}