You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@openwhisk.apache.org by GitBox <gi...@apache.org> on 2017/12/22 19:53:24 UTC

[GitHub] csantanapr closed pull request #7: webDeploy package for use as web action

csantanapr closed pull request #7: webDeploy package for use as web action
URL: https://github.com/apache/incubator-openwhisk-package-deploy/pull/7
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/.gitignore b/.gitignore
index 0ffe4de..cc92890 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,6 @@
 build/
 tests/credentials.json
 openwhisk
+packages/actions/blueprints
+packages/actions/package.json
+packages/actions/deployWeb.zip
diff --git a/packages/actions/deploy.js b/packages/actions/deploy.js
index e5e7fa5..1c82dcc 100644
--- a/packages/actions/deploy.js
+++ b/packages/actions/deploy.js
@@ -3,6 +3,7 @@ const path = require('path');
 const exec = require('child_process').exec;
 const git = require('simple-git');
 const yaml = require('js-yaml');
+const common = require('./lib/common');
 
 let command = '';
 
@@ -39,11 +40,11 @@ function main(params) {
     // Extract the name of the repo for the tmp directory
     const repoSplit = params.gitUrl.split('/');
     const repoName = repoSplit[repoSplit.length - 1];
-    const localDirName = `${__dirname}/tmp/${repoName}`;
+    const localDirName = `${__dirname}/../tmp/${repoName}`;
     return git()
     .clone(gitUrl, localDirName, ['--depth', '1'], (err, data) => {
       if (err) {
-        reject('There was a problem cloning from github.  Does that github repo exist?  Does it begin with http?', err);
+        reject('There was a problem cloning from github.  Does that github repo exist?  Does it begin with http?');
       }
       resolve({
         repoDir: localDirName,
@@ -55,72 +56,22 @@ function main(params) {
       });
     });
   })
-  .then((data) => {
-    const {
-      wskAuth,
-      wskApiHost,
-      manifestPath,
-      manifestFileName,
-      repoDir,
-      envData,
-    } = data;
-
-    // Set the cwd of the command to be where the manifest/actions live
-    const execOptions = {
-      cwd: `${repoDir}/${manifestPath}`,
-    };
-
-    // If we were passed environment data (Cloudant bindings, etc.) add it to the options for `exec`
-    if (envData) {
-      execOptions.env = envData;
-    } else {
-      execOptions.env = {};
-    }
-
-    // Send 'y' to the wskdeploy command so it will actually run the deployment
-    command = `printf 'y' | ${__dirname}/wskdeploy -v -m ${manifestFileName} --auth ${wskAuth} --apihost ${wskApiHost}`;
-
+  .then((result) => {
+    return common.main(result);
+  })
+  .then((success) => {
     return new Promise((resolve, reject) => {
-      const manifestFilePath = `${repoDir}/${manifestPath}/${manifestFileName}`;
-      if (!fs.existsSync(manifestFilePath)) {
-        reject(`Error loading ${manifestFilePath}. Does a manifest file exist?`);
-      } else {
-        exec(command, execOptions, (err, stdout, stderr) => {
-          deleteFolder(repoDir);
-          if (err) {
-            reject('Error running `./wskdeploy`: ', err);
-          }
-          if (stdout) {
-            console.log('stdout from wskDeploy: ', stdout, ' type ', typeof stdout);
-
-            if (typeof stdout === 'string') {
-              try {
-                stdout = JSON.parse(stdout);
-              } catch (e) {
-                console.log('Failed to parse stdout, it wasn\'t a JSON object');
-              }
-            }
-
-            if (typeof stdout === 'object') {
-              if (stdout.error) {
-                stdout.descriptiveError = 'Could not successfully run wskdeploy. Please run again with the verbose flag, -v.';
-                reject(stdout);
-              }
-            }
-          }
-          if (stderr) {
-            console.log('stderr from wskDeploy: ', stderr);
-            reject(stderr);
-          }
-          console.log('Finished! Resolving now');
-          resolve({
-            status: 'success',
-            success: true,
-          });
-        });
-      }
+      resolve({
+        status: 'success',
+        success: true,
+      });
     });
-  });
+  })
+  .catch(
+    (err) => {
+      return ({error: err});
+    }
+  );
 }
 
 /**
@@ -148,23 +99,4 @@ function getWskApiAuth(params) {
   };
 }
 
-/**
- * recursive funciton to delete a folder, must first delete items inside.
- * @param  {string} pathToDelete    inclusive path to folder to delete
- */
-function deleteFolder(pathToDelete) {
-  if (fs.existsSync(pathToDelete)) {
-    fs.readdirSync(pathToDelete).forEach(function(file, index){
-      var curPath = path.join(pathToDelete, file);
-      if (fs.lstatSync(curPath).isDirectory()) {
-        deleteFolder(curPath);
-      } else {
-        //unlinkSync deletes files.
-        fs.unlinkSync(curPath);
-      }
-    });
-    fs.rmdirSync(pathToDelete);
-  }
-}
-
 exports.main = main;
diff --git a/packages/actions/deployWeb.js b/packages/actions/deployWeb.js
new file mode 100644
index 0000000..ccbf160
--- /dev/null
+++ b/packages/actions/deployWeb.js
@@ -0,0 +1,128 @@
+const fs = require('fs');
+const path = require('path');
+const exec = require('child_process').exec;
+const git = require('simple-git');
+const yaml = require('js-yaml');
+const common = require('./lib/common');
+
+let command = '';
+
+/**
+ * Action to deploy openwhisk elements from a compliant repository
+ *  @param {string} gitUrl - github url containing the manifest and elements to deploy
+ *  @param {string} manifestPath - (optional) the path to the manifest file, e.g. "openwhisk/src"
+ *  @param {object} envData - (optional) some specific details such as cloudant username or cloudant password
+ *  @return {object} Promise
+ */
+function main(params) {
+  // Grab optional envData and manifestPath params for wskdeploy
+  let {
+    envData,
+    manifestPath,
+    gitUrl
+  } = params;
+
+  // confirm gitUrl was provided as a parameter
+  if (!gitUrl) {
+    return sendError(400, 'Please enter the GitHub repo url in params');
+  }
+
+  if(params.__ow_method === "post") {
+    return new Promise((resolve, reject) => {
+      // if no manifestPath was provided, use current directory
+      if (!manifestPath) {
+        manifestPath = '.';
+      }
+      // Grab wsp api host and auth from params, or process.env
+      const { wskApiHost, wskAuth } = getWskApiAuth(params);
+
+      // Extract the name of the repo for the tmp directory
+      const repoSplit = params.gitUrl.split('/');
+      const repoName = repoSplit[repoSplit.length - 1];
+      const localDirName = `${__dirname}/../tmp/${repoName}`;
+      const blueprintsDirName = `${__dirname}/blueprints/${repoName}`;
+      if (repoSplit[2] === 'github.com' && repoSplit[3] === 'ibm-functions' && fs.existsSync(blueprintsDirName)) {
+        resolve({
+          repoDir: blueprintsDirName,
+          manifestPath,
+          manifestFileName: 'manifest.yaml',
+          wskAuth,
+          wskApiHost,
+          envData,
+        });
+      }
+      else {
+        return git()
+        .clone(gitUrl, localDirName, ['--depth', '1'], (err, data) => {
+          if (err) {
+            reject('There was a problem cloning from github.  Does that github repo exist?  Does it begin with http?');
+          }
+          resolve({
+            repoDir: localDirName,
+            manifestPath,
+            manifestFileName: 'manifest.yaml',
+            wskAuth,
+            wskApiHost,
+            envData,
+          });
+        });
+      }
+    })
+    .then((result) => {
+      return common.main(result);
+    })
+    .then((success) => {
+      return new Promise((resolve, reject) => {
+        resolve({
+          statusCode: 200,
+          headers: {'Content-Type': 'application/json'},
+          body: new Buffer(JSON.stringify({'status': 'success'})).toString('base64')
+        });
+      });
+    })
+    .catch(
+      (err) => {
+        return (sendError(400, err));
+      }
+    );
+  }
+}
+
+/**
+ * Checks if wsk API host and auth were provided in params, if not, gets them from process.env
+ * @param  {[Object]} params    [Params object]
+ * @return {[Object]}           [Object containing wskApiHost and wskAuth]
+ */
+function getWskApiAuth(params) {
+  let {
+    wskApiHost,
+    wskAuth,
+  } = params;
+
+  if (!wskApiHost) {
+    wskApiHost = process.env.__OW_API_HOST;
+  }
+
+  if (!wskAuth) {
+    wskAuth = process.env.__OW_API_KEY;
+  }
+
+  return {
+    wskApiHost,
+    wskAuth,
+  };
+}
+
+function sendError(statusCode, error, message) {
+  var params = {error: error};
+  if (message) {
+      params.message = message;
+  }
+  return {
+      statusCode: statusCode,
+      headers: { 'Content-Type': 'application/json' },
+      body: new Buffer(JSON.stringify(params)).toString('base64')
+  };
+}
+
+exports.main = main;
diff --git a/packages/actions/deployWeb_package.json b/packages/actions/deployWeb_package.json
new file mode 100644
index 0000000..cc1dc0f
--- /dev/null
+++ b/packages/actions/deployWeb_package.json
@@ -0,0 +1,16 @@
+{
+  "name": "deploy-action",
+  "version": "1.0.0",
+  "description": "",
+  "main": "deployWeb.js",
+  "scripts": {
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "keywords": [],
+  "author": "",
+  "license": "ISC",
+  "dependencies": {
+    "js-yaml": "^3.9.1",
+    "simple-git": "^1.74.1"
+  }
+}
diff --git a/packages/actions/package.json b/packages/actions/deploy_package.json
similarity index 100%
rename from packages/actions/package.json
rename to packages/actions/deploy_package.json
diff --git a/packages/actions/lib/common.js b/packages/actions/lib/common.js
new file mode 100644
index 0000000..48f1a74
--- /dev/null
+++ b/packages/actions/lib/common.js
@@ -0,0 +1,104 @@
+const fs = require('fs');
+const path = require('path');
+const exec = require('child_process').exec;
+const git = require('simple-git');
+const yaml = require('js-yaml');
+let command = '';
+
+/**
+ * Action to deploy openwhisk elements from a compliant repository
+ *  @param {string} gitUrl - github url containing the manifest and elements to deploy
+ *  @param {string} manifestPath - (optional) the path to the manifest file, e.g. "openwhisk/src"
+ *  @param {object} envData - (optional) some specific details such as cloudant username or cloudant password
+ *  @return {object} Promise
+ */
+function main(params) {
+  return new Promise((resolve, reject) => {
+    const {
+      wskAuth,
+      wskApiHost,
+      manifestPath,
+      manifestFileName,
+      repoDir,
+      envData,
+    } = params;
+
+    // Set the cwd of the command to be where the manifest/actions live
+    const execOptions = {
+      cwd: `${repoDir}/${manifestPath}`,
+    };
+
+    // If we were passed environment data (Cloudant bindings, etc.) add it to the options for `exec`
+    if (envData) {
+      execOptions.env = envData;
+    } else {
+      execOptions.env = {};
+    }
+
+    // Send 'y' to the wskdeploy command so it will actually run the deployment
+    command = `printf 'y' | ${__dirname}/../../wskdeploy -v -m ${manifestFileName} --auth ${wskAuth} --apihost ${wskApiHost}`;
+
+    const manifestFilePath = `${repoDir}/${manifestPath}/${manifestFileName}`;
+    if (!fs.existsSync(manifestFilePath)) {
+      deleteFolder(repoDir);
+      reject(`Error loading manifest file. Does a manifest file exist?`);
+    } else {
+      exec(command, execOptions, (err, stdout, stderr) => {
+        deleteFolder(repoDir);
+        if (err) {
+          reject('Error running `./wskdeploy`: ', err);
+        }
+        if (stdout) {
+          console.log('stdout from wskDeploy: ', stdout, ' type ', typeof stdout);
+
+          if (typeof stdout === 'string') {
+            try {
+              stdout = JSON.parse(stdout);
+            } catch (e) {
+              console.log('Failed to parse stdout, it wasn\'t a JSON object');
+            }
+          }
+
+          if (typeof stdout === 'object') {
+            if (stdout.error) {
+              stdout.descriptiveError = 'Could not successfully run wskdeploy. Please run again with the verbose flag, -v.';
+              reject(stdout);
+            }
+          }
+        }
+        if (stderr) {
+          console.log('stderr from wskDeploy: ', stderr);
+          reject(stderr);
+        }
+        console.log('Finished! Resolving now');
+        resolve({
+          status: 'success',
+          success: true,
+        });
+      });
+    }
+  });
+}
+
+/**
+ * recursive funciton to delete a folder, must first delete items inside.
+ * @param  {string} pathToDelete    inclusive path to folder to delete
+ */
+function deleteFolder(pathToDelete) {
+  if (fs.existsSync(pathToDelete)) {
+    fs.readdirSync(pathToDelete).forEach(function(file, index){
+      var curPath = path.join(pathToDelete, file);
+      if (fs.lstatSync(curPath).isDirectory()) {
+        deleteFolder(curPath);
+      } else {
+        //unlinkSync deletes files.
+        fs.unlinkSync(curPath);
+      }
+    });
+    fs.rmdirSync(pathToDelete);
+  }
+}
+
+module.exports = {
+  'main': main
+};
diff --git a/packages/installCatalog.sh b/packages/installCatalog.sh
index ebf4eba..ae1ca14 100755
--- a/packages/installCatalog.sh
+++ b/packages/installCatalog.sh
@@ -12,42 +12,95 @@ set -e
 set -x
 
 if [ $# -eq 0 ]
-then
-echo "Usage: ./installCatalog.sh <authkey> <edgehost> <pathtowskcli> <docker>"
+  then
+  echo "Usage: ./installCatalog.sh <authkey> <edgehost> <pathtowskcli> <skipdeploy> <docker>"
 fi
 
 AUTH="$1"
 EDGE_HOST="$2"
 WSK_CLI="$3"
-DOCKER="$4"
+SKIP_DEPLOY="${4:-False}"
+DOCKER="$5"
 
 # If docker is not provided, set to default version.
-if [ -z "$4" ]
+if [ -z "$5" ]
+  then
+  if [ $SKIP_DEPLOY = False ] || [ $SKIP_DEPLOY = True ]
   then
     DOCKER="openwhisk/wskdeploy:0.8.10"
+  else
+    SKIP_DEPLOY=False
+    DOCKER=$4
+  fi
 fi
 
 # If the auth key file exists, read the key in the file. Otherwise, take the
 # first argument as the key itself.
 if [ -f "$AUTH" ]; then
-    AUTH=`cat $AUTH`
+  AUTH=`cat $AUTH`
 fi
 
 PACKAGE_HOME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
 
 export WSK_CONFIG_FILE= # override local property file to avoid namespace clashes
 
-# wskdeploy actions
+#clone all Blueprints
+for bp in blueprint-hello-world blueprint-cloudant-trigger blueprint-messagehub-trigger
+do
+  if [ -e actions/blueprints/$bp ]
+    then
+    rm -rf actions/blueprints/$bp
+  fi
+  git clone --depth 1 https://github.com/ibm-functions/$bp actions/blueprints/$bp
+done
+
+# make deployWeb.zip & install
+OLD_PATH=`pwd`
+cd actions
 
-echo Installing wskdeploy package.
+if [ -e deployWeb.zip ]
+  then
+  rm -rf deployWeb.zip
+fi
 
-$WSK_CLI -i --apihost "$EDGE_HOST" package update --auth "$AUTH"  --shared yes "deploy" \
+cp -f deployWeb_package.json package.json
+zip -r deployWeb.zip package.json deployWeb.js lib/common.js blueprints/
+
+cd $OLD_PATH
+
+$WSK_CLI -i --apihost "$EDGE_HOST" package update --auth "$AUTH" --shared no "deployWeb" \
 -a description "This package offers a convenient way for you to describe and deploy any part of the OpenWhisk programming model using a Manifest file written in YAML." \
--a prettyName "Whisk Deploy"
+-a prettyName "Whisk Deploy Web"
 
-$WSK_CLI -i --apihost "$EDGE_HOST" action update --auth "$AUTH" "deploy/wskdeploy" "$PACKAGE_HOME/actions/deploy.js" \
+$WSK_CLI -i --apihost "$EDGE_HOST" action update --auth "$AUTH" "deployWeb/wskdeploy" "$PACKAGE_HOME/actions/deployWeb.zip" --web true \
 -a description 'Creates an action that allows you to run wskdeploy from OpenWhisk' \
 -a parameters '[ {"name":"gitUrl", "required":true, "bindTime":true, "description": "The URL to the GitHub repository to deploy"}, {"name":"manifestPath", "required":false, "bindTime":true, "description": "The relative path to the manifest file from the GitHub repo root"}, {"name":"envData", "required":false, "description": "Blueprint-specific environment data object"} ]' \
 -a sampleInput '{"gitUrl":"github.com/my_blueprint", "manifestPath":"runtimes/swift", "envData": "{\"ENV_VARIABLE_1\":\"VALUE_1\", \"ENV_VARIABLE_2\":\"VALUE_2\"}"}' \
 --docker "$DOCKER"
-     
\ No newline at end of file
+
+
+cd actions
+if [ $SKIP_DEPLOY = False ]
+  then
+  if [ -e deploy.zip ]
+  then
+      rm -rf deploy.zip
+  fi
+
+  cp -f deploy_package.json package.json
+  zip -r deploy.zip package.json deploy.js lib/common.js
+
+  cd $OLD_PATH
+
+  echo Installing wskdeploy package.
+
+  $WSK_CLI -i --apihost "$EDGE_HOST" package update --auth "$AUTH"  --shared yes "deploy" \
+  -a description "This package offers a convenient way for you to describe and deploy any part of the OpenWhisk programming model using a Manifest file written in YAML." \
+  -a prettyName "Whisk Deploy"
+
+  $WSK_CLI -i --apihost "$EDGE_HOST" action update --auth "$AUTH" "deploy/wskdeploy" "$PACKAGE_HOME/actions/deploy.zip" \
+  -a description 'Creates an action that allows you to run wskdeploy from OpenWhisk' \
+  -a parameters '[ {"name":"gitUrl", "required":true, "bindTime":true, "description": "The URL to the GitHub repository to deploy"}, {"name":"manifestPath", "required":false, "bindTime":true, "description": "The relative path to the manifest file from the GitHub repo root"}, {"name":"envData", "required":false, "description": "Blueprint-specific environment data object"} ]' \
+  -a sampleInput '{"gitUrl":"github.com/my_blueprint", "manifestPath":"runtimes/swift", "envData": "{\"ENV_VARIABLE_1\":\"VALUE_1\", \"ENV_VARIABLE_2\":\"VALUE_2\"}"}' \
+  --docker "$DOCKER"
+fi
diff --git a/tests/src/test/scala/packages/deployWebTests.scala b/tests/src/test/scala/packages/deployWebTests.scala
new file mode 100644
index 0000000..ee0ba92
--- /dev/null
+++ b/tests/src/test/scala/packages/deployWebTests.scala
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 packages
+
+
+import org.junit.runner.RunWith
+import org.scalatest.BeforeAndAfterAll
+import org.scalatest.junit.JUnitRunner
+import common.{TestHelpers, Wsk, WskProps, WskTestHelpers}
+import common.TestUtils.FORBIDDEN
+
+import com.jayway.restassured.RestAssured
+import com.jayway.restassured.config.SSLConfig
+
+import spray.json._
+
+@RunWith(classOf[JUnitRunner])
+class DeployWebTests extends TestHelpers
+    with WskTestHelpers
+    with BeforeAndAfterAll {
+
+    implicit val wskprops = WskProps()
+    val wsk = new Wsk()
+
+    //action and web action url
+    val deployAction = "/whisk.system/deployWeb/wskdeploy"
+    val deployActionURL = s"https://${wskprops.apihost}/api/v1/web${deployAction}.http"
+
+    //set parameters for deploy tests
+    val deployTestRepo = "https://github.com/apache/incubator-openwhisk-package-deploy"
+    val incorrectGithubRepo = "https://github.com/apache/openwhisk-package-deploy-incorrect"
+    val malformedRepoUrl = "github.com/ibm-functions/blueprint-hello-world"
+    val helloWorldPath = "tests/src/test/scala/testFixtures/helloWorld"
+    val helloWorldWithNoManifest = "tests/src/test/scala/testFixtures/helloWorldNoManifest"
+    val helloWorldPackageParam = "tests/src/test/scala/testFixtures/helloWorldPackageParam"
+    val incorrectManifestPath = "does/not/exist"
+    val helloWorldAction = "openwhisk-helloworld/helloworld"
+    val helloWorldActionPackage = "myPackage/helloworld"
+
+    // statuses from deployWeb
+    val successStatus = """{"status":"success"}"""
+    val githubNonExistentStatus = """{"error":"There was a problem cloning from github.  Does that github repo exist?  Does it begin with http?"}"""
+
+    def makePostCallWithExpectedResult(params: JsObject, expectedResult: String, expectedCode: Int) = {
+      val response = RestAssured.given()
+          .contentType("application/json\r\n")
+          .config(RestAssured.config().sslConfig(new SSLConfig().relaxedHTTPSValidation()))
+          .body(params.toString())
+          .post(deployActionURL)
+      assert(response.statusCode() == expectedCode)
+      response.body.asString shouldBe expectedResult
+    }
+
+    behavior of "deployWeb Package"
+
+    // test to ensure action not obtainable using CLI
+    it should "not be usable from the CLI" in {
+      wsk.action.get(deployAction, FORBIDDEN)
+    }
+
+    //test to create the hello world blueprint from github
+    it should "create the hello world action from github url" in {
+      makePostCallWithExpectedResult(JsObject(
+        "gitUrl" -> JsString(deployTestRepo),
+        "manifestPath" -> JsString(helloWorldPath),
+        "wskApiHost" -> JsString(wskprops.apihost),
+        "wskAuth" -> JsString(wskprops.authKey)
+      ), successStatus, 200);
+
+      // clean up after test
+      wsk.action.delete(helloWorldAction)
+    }
+
+    // test to create the hello world blueprint from github with myPackage as package name
+    it should s"create the $helloWorldActionPackage action from github url" in {
+      makePostCallWithExpectedResult(JsObject(
+        "gitUrl" -> JsString(deployTestRepo),
+        "manifestPath" -> JsString(helloWorldPackageParam),
+        "envData" -> JsObject("PACKAGE_NAME" -> JsString("myPackage")),
+        "wskApiHost" -> JsString(wskprops.apihost),
+        "wskAuth" -> JsString(wskprops.authKey)
+      ), successStatus, 200)
+
+      // clean up after test
+      wsk.action.delete(helloWorldActionPackage)
+    }
+
+    // test to create a blueprint with no github repo provided
+    it should "return error if there is no github repo provided" in {
+      makePostCallWithExpectedResult(JsObject(
+        "manifestPath" -> JsString(helloWorldPath),
+        "wskApiHost" -> JsString(wskprops.apihost),
+        "wskAuth" -> JsString(wskprops.authKey)
+      ), """{"error":"Please enter the GitHub repo url in params"}""", 400)
+    }
+
+    //test to create a blueprint with a nonexistant github repo provided
+    it should "return error if there is an nonexistant repo provided" in {
+      makePostCallWithExpectedResult(JsObject(
+        "gitUrl" -> JsString(incorrectGithubRepo),
+        "manifestPath" -> JsString(helloWorldPath),
+        "wskApiHost" -> JsString(wskprops.apihost),
+        "wskAuth" -> JsString(wskprops.authKey)
+      ), githubNonExistentStatus, 400)
+    }
+    //test to create a blueprint with a malformed github repo
+    it should "return error if there is a malformed gitUrl provided" in {
+      makePostCallWithExpectedResult(JsObject(
+        "gitUrl" -> JsString(malformedRepoUrl),
+        "manifestPath" -> JsString(helloWorldPath),
+        "wskApiHost" -> JsString(wskprops.apihost),
+        "wskAuth" -> JsString(wskprops.authKey)
+      ), githubNonExistentStatus, 400)
+    }
+
+    // test to create a blueprint with useless EnvData provided
+    it should "return succeed if useless envData is provided" in {
+      makePostCallWithExpectedResult(JsObject(
+        "gitUrl" -> JsString(deployTestRepo),
+        "manifestPath" -> JsString(helloWorldPath),
+        "envData" -> JsObject("something" -> JsString("useless")),
+        "wskApiHost" -> JsString(wskprops.apihost),
+        "wskAuth" -> JsString(wskprops.authKey)
+      ), successStatus, 200)
+
+      // clean up after test
+      wsk.action.delete(helloWorldAction)
+    }
+
+    // test to create a blueprint with an incorrect manifestPath provided
+    it should "return with failure if incorrect manifestPath is provided" in {
+      makePostCallWithExpectedResult(JsObject(
+        "gitUrl" -> JsString(deployTestRepo),
+        "manifestPath" -> JsString(incorrectManifestPath),
+        "wskApiHost" -> JsString(wskprops.apihost),
+        "wskAuth" -> JsString(wskprops.authKey)
+      ), """{"error":"Error loading manifest file. Does a manifest file exist?"}""", 400)
+    }
+
+    // test to create a blueprint with manifestPath provided, but no manifestFile existing
+    it should "return with failure if no manifest exists at manifestPath" in {
+      makePostCallWithExpectedResult(JsObject(
+        "gitUrl" -> JsString(deployTestRepo),
+        "manifestPath" -> JsString(helloWorldWithNoManifest),
+        "wskApiHost" -> JsString(wskprops.apihost),
+        "wskAuth" -> JsString(wskprops.authKey)
+      ), """{"error":"Error loading manifest file. Does a manifest file exist?"}""", 400)
+    }
+}
diff --git a/tools/travis/build.sh b/tools/travis/build.sh
index 42f3c37..9b1b61b 100755
--- a/tools/travis/build.sh
+++ b/tools/travis/build.sh
@@ -50,12 +50,18 @@ cat whisk.properties
 WSK_CLI=$WHISKDIR/bin/wsk
 AUTH_KEY=$(cat $WHISKDIR/ansible/files/auth.whisk.system)
 EDGE_HOST=$(grep '^edge.host=' $WHISKPROPS_FILE | cut -d'=' -f2)
+SKIP_DEPLOY="True"
 
 # Install Package
 
 cd $ROOTDIR/packages
-./installCatalog.sh $AUTH_KEY $EDGE_HOST $WSK_CLI
+./installCatalog.sh $AUTH_KEY $EDGE_HOST $WSK_CLI $SKIP_DEPLOY
 
 # Test
 cd $ROOTDIR
-TERM=dumb ./gradlew :tests:test
+if [ $SKIP_DEPLOY = True ]
+  then
+  TERM=dumb ./gradlew :tests:test --tests "packages.DeployWebTests"
+else
+  TERM=dumb ./gradlew :tests:test
+fi


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services