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/11/10 17:31:57 UTC

[GitHub] csantanapr closed pull request #85: Add new features to routes methods.

csantanapr closed pull request #85: Add new features to routes methods.
URL: https://github.com/apache/incubator-openwhisk-client-js/pull/85
 
 
   

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/README.md b/README.md
index 159b3e3..089d7ed 100644
--- a/README.md
+++ b/README.md
@@ -272,6 +272,7 @@ ow.actions.delete({name: '...'})
 ow.triggers.delete({name: '...'})
 ow.rules.delete({name: '...'})
 ow.packages.delete({name: '...'})
+ow.feeds.delete({name: '...', trigger: '...'})
 ```
 
 The following optional parameters are supported:
@@ -413,11 +414,10 @@ ow.rules.disable({name: '...'})
 The following optional parameters are supported:
 - `namespace` - set custom namespace for endpoint
 
-### create & delete feeds
+### create feeds
 
 ```javascript
 ow.feeds.create({feedName: '...', trigger: '...'})
-ow.feeds.delete({feedName: '...', trigger: '...'})
 ```
 
 The following optional parameters are supported:
@@ -432,6 +432,15 @@ This client library defaults to using the platform service. If the `apigw_token`
 
 *The interface for managing routes through the library does not change between providers.*
 
+### retrieve route
+
+```javascript
+ow.routes.get({basepath: '...'})
+ow.routes.get({name: '...'})
+```
+
+*This method is a wrapper for the list method. It throws an error if the base path or name parameter is missing.*
+
 ### list routes
 
 ```javascript
@@ -441,16 +450,18 @@ ow.routes.list()
 The following optional parameters are supported to filter the result set:
 - `relpath` - relative URI path for endpoints
 - `basepath` - base URI path for endpoints
+- `name` - identifier for API
 - `operation` - HTTP methods
 - `limit` - limit result set size
 - `skip` - skip results from index
 
-*`relpath` is only valid when `basepath` is also specified.*
+*`relpath` is only valid when `basepath` is also specified. `name` and `basepath` cannot be used together.*
 
 ### delete routes
 
 ```javascript
 ow.routes.delete({basepath: '...'})
+ow.routes.delete({name: '...'})
 ```
 
 The following optional parameters are supported to filter the result set:
@@ -467,6 +478,17 @@ ow.routes.create({relpath: '...', operation: '...', action: '...'})
 The following optional parameters are supported:
 - `responsetype` - content type returned by web action, possible values: `html`, `http`, `json`, `text` and `svg` (default: `json`).
 - `basepath` - base URI path for endpoints (default: `/`)
+- `name` - identifier for API (default: `basepath`)
+
+### add route (swagger)
+
+```javascript
+ow.routes.create({swagger: '{...}'})
+```
+
+Swagger parameter must be a well-formed JSON string, containing a valid Swagger API definition, which follows the [OpenWhisk API Gateway route schema](https://github.com/apache/incubator-openwhisk-apigateway/blob/master/doc/v2/management_interface_v2.md#post-v2tenant_idapis).
+
+*No other parameters are supported when creating the route from a JSON Swagger document.*
 
 ## Debugging
 
@@ -510,7 +532,7 @@ Alternatively, you can run the `prepIntegrationTests.sh` script using guest cred
 Run the script with openwhisk credentials:  
 ```bash
 $ ./test/integration/prepIntegrationTests.sh <your key in the form of ABCD:EFGH> <openwhisk instance hostname> <openwhisk namespace> <api gatewaytoken>
-```  
+```
 The `prepIntegrationTests.sh` script is designed to give you feedback if it detects a setting that is not correct on your machine. ex: `node 6 or above is not detected`
 
 ## Code-Coverage:
diff --git a/lib/messages.js b/lib/messages.js
index 909721f..a1873f9 100644
--- a/lib/messages.js
+++ b/lib/messages.js
@@ -18,5 +18,6 @@ module.exports = {
   MISSING_PACKAGE_BODY_ERROR: 'Missing mandatory package parameter from options.',
   MISSING_NAMESPACE_ERROR: 'Missing namespace from options, please set a default namespace or pass one in the options.',
   INVALID_OPTIONS_ERROR: 'Invalid constructor options.',
-  MISSING_BASEPATH_ERROR: 'Missing mandatory basepath parameter from options.'
+  MISSING_BASEPATH_ERROR: 'Missing mandatory parameters: basepath or name.',
+  INVALID_BASEPATH_ERROR: 'Invalid parameters: use basepath or name, not both.'
 }
diff --git a/lib/routes.js b/lib/routes.js
index edb5f60..eb55026 100644
--- a/lib/routes.js
+++ b/lib/routes.js
@@ -13,8 +13,19 @@ class Routes extends BaseOperation {
     return `web/whisk.system/apimgmt/${path}.http`
   }
 
+  get (options) {
+    options = options || {}
+    options.basepath = this.basepath(options)
+
+    return this.list(this.qs(options, ['basepath']))
+  }
+
   list (options) {
     options = options || {}
+    if (this.has_basepath(options)) {
+      options.basepath = this.calculate_basepath(options)
+    }
+
     const qs = this.qs(options, ['relpath', 'basepath', 'operation', 'limit', 'skip'])
     return this.client.request('GET', this.routeMgmtApiPath('getApi'), { qs })
   }
@@ -30,26 +41,57 @@ class Routes extends BaseOperation {
     return result
   }
 
-  delete (options) {
-    if (!options || !options.hasOwnProperty('basepath')) {
+  has_basepath (options) {
+    return !!(options.name || options.basepath)
+  }
+
+  basepath (options) {
+    if (!this.has_basepath(options)) {
       throw new Error(messages.MISSING_BASEPATH_ERROR)
     }
 
+    return this.calculate_basepath(options)
+  }
+
+  calculate_basepath (options) {
+    if (options.name && options.basepath) {
+      throw new Error(messages.INVALID_BASEPATH_ERROR)
+    }
+
+    return options.basepath || options.name
+  }
+
+  missing_basepath (options) {
+    return !(options.name || options.basepath)
+  }
+
+  delete (options) {
+    options = options || {}
+    options.basepath = this.basepath(options)
+
     const qs = this.qs(options, ['relpath', 'basepath', 'operation'])
     qs.force = true
     return this.client.request('DELETE', this.routeMgmtApiPath('deleteApi'), { qs })
   }
 
   create (options) {
+    const body = this.create_body(options || {})
+    const qs = this.qs(options, ['responsetype'])
+    return this.client.request('POST', this.routeMgmtApiPath('createApi'), { body, qs })
+  }
+
+  create_body (options) {
+    if (options.swagger) {
+      return { apidoc: { namespace: '_', swagger: options.swagger } }
+    }
+
     const missing = CREATE_PARAMS.filter(param => !(options || {}).hasOwnProperty(param))
 
     if (missing.length) {
       throw new Error(`Missing mandatory parameters: ${missing.join(', ')}`)
     }
 
-    const body = this.route_swagger_definition(options)
-    const qs = this.qs(options, ['responsetype'])
-    return this.client.request('POST', this.routeMgmtApiPath('createApi'), { body, qs })
+    return this.route_swagger_definition(options)
   }
 
   route_swagger_definition (params) {
@@ -60,7 +102,11 @@ class Routes extends BaseOperation {
       gatewayMethod: params.operation,
       id: `API:_:${this.route_base_path(params)}`,
       action: this.route_swagger_action(params)
-   }
+    }
+
+    if (params.name) {
+      apidoc.apiName = params.name
+    }
 
     return { apidoc }
   }
diff --git a/test/unit/routes.test.js b/test/unit/routes.test.js
index 0d25c36..9d039e4 100644
--- a/test/unit/routes.test.js
+++ b/test/unit/routes.test.js
@@ -6,6 +6,73 @@
 const test = require('ava')
 const Routes = require('../../lib/routes')
 
+test('should retrieve routes from name', t => {
+  t.plan(3)
+  const client = { options: {} }
+  client.request = (method, path, options) => {
+    t.is(method, 'GET')
+    t.is(path, routes.routeMgmtApiPath('getApi'))
+    t.deepEqual(options.qs, { basepath: 'testing' })
+  }
+
+  const routes = new Routes(client)
+  return routes.get({name: 'testing'})
+})
+
+test('should retrieve routes from basepath', t => {
+  t.plan(3)
+  const client = { options: {} }
+  client.request = (method, path, options) => {
+    t.is(method, 'GET')
+    t.is(path, routes.routeMgmtApiPath('getApi'))
+    t.deepEqual(options.qs, { basepath: 'testing' })
+  }
+
+  const routes = new Routes(client)
+  return routes.get({basepath: 'testing'})
+})
+
+test('should retrieve routes with apigw_token and name', t => {
+  t.plan(3)
+  const client = { options: {
+    apigw_token: 'token',
+    apigw_space_guid: 'space'
+  } }
+  client.request = (method, path, options) => {
+    t.is(method, 'GET')
+    t.is(path, routes.routeMgmtApiPath('getApi'))
+    t.deepEqual(options.qs, { basepath: 'testing', spaceguid: 'space', accesstoken: 'token'})
+  }
+
+  const routes = new Routes(client)
+  return routes.get({name: 'testing'})
+})
+
+test('should retrieve routes with apigw_token and basepath', t => {
+  t.plan(3)
+  const client = { options: {
+    apigw_token: 'token',
+    apigw_space_guid: 'space'
+  } }
+  client.request = (method, path, options) => {
+    t.is(method, 'GET')
+    t.is(path, routes.routeMgmtApiPath('getApi'))
+    t.deepEqual(options.qs, { basepath: 'testing', spaceguid: 'space', accesstoken: 'token'})
+  }
+
+  const routes = new Routes(client)
+  return routes.get({basepath: 'testing'})
+})
+
+test('get routes with incorrect parameters', t => {
+  const routes = new Routes({options: {}})
+  t.throws(() => { routes.get() }, /Missing mandatory parameters: basepath or name/)
+  t.throws(() => { routes.get({}) }, /Missing mandatory parameters: basepath or name/)
+  t.throws(() => { routes.get({basepath: 'id', name: 'id'}) }, /Invalid parameters: use basepath or name, not both/)
+})
+
+// ADD NAME TO OTHER METHODS
+
 test('should list all routes', t => {
   t.plan(2)
   const client = { options: {} }
@@ -35,7 +102,7 @@ test('should list all routes with apigw_token', t => {
 })
 
 
-test('should list all routes with parameters', t => {
+test('should list all routes with parameters including basepath', t => {
   t.plan(3)
   const client = { options: {} }
   const options = {basepath: '/hello', relpath: '/foo/bar', operation: 'GET', limit: 10, skip: 10}
@@ -49,7 +116,28 @@ test('should list all routes with parameters', t => {
   return routes.list(options)
 })
 
-test('should delete a route', t => {
+test('should list all routes with parameters including name', t => {
+  t.plan(3)
+  const client = { options: {} }
+  const options = {name: '/hello', relpath: '/foo/bar', operation: 'GET', limit: 10, skip: 10}
+  const qs_options = {basepath: '/hello', relpath: '/foo/bar', operation: 'GET', limit: 10, skip: 10}
+  client.request = (method, path, _options) => {
+    t.is(method, 'GET')
+    t.is(path, routes.routeMgmtApiPath('getApi'))
+    t.deepEqual(_options.qs, qs_options)
+  }
+
+  const routes = new Routes(client)
+  return routes.list(options)
+})
+
+test('list routes providing basepath and name', t => {
+  const client = { options: {} }
+  const routes = new Routes(client)
+  return t.throws(() => { routes.list({basepath: 'bp', name: 'nm'}) }, /Invalid parameters: use basepath or name, not both/)
+})
+
+test('should delete a route with basepath', t => {
   t.plan(3)
   const client = { options: {} }
   const options = {force: true, basepath: '/hello'}
@@ -64,6 +152,21 @@ test('should delete a route', t => {
   return routes.delete({basepath: '/hello'})
 })
 
+test('should delete a route with name', t => {
+  t.plan(3)
+  const client = { options: {} }
+  const options = {force: true, basepath: '/hello'}
+
+  client.request = (method, path, _options) => {
+    t.is(method, 'DELETE')
+    t.is(path, routes.routeMgmtApiPath('deleteApi'))
+    t.deepEqual(_options.qs, options)
+  }
+
+  const routes = new Routes(client)
+  return routes.delete({name: '/hello'})
+})
+
 test('should delete a route with apigw token', t => {
   t.plan(3)
   const client = { options: {
@@ -96,10 +199,16 @@ test('should delete a route with parameters', t => {
   return routes.delete({basepath: '/hello', relpath: '/bar/1', operation: 'GET'})
 })
 
-test('delete routes without providing basepath', t => {
+test('delete routes without providing basepath or name', t => {
   const client = { options: {} }
   const routes = new Routes(client)
-  return t.throws(() => { routes.delete() }, /Missing mandatory basepath/)
+  return t.throws(() => { routes.delete() }, /Missing mandatory parameters: basepath or name/)
+})
+
+test('delete routes providing basepath and name', t => {
+  const client = { options: {} }
+  const routes = new Routes(client)
+  return t.throws(() => { routes.delete({basepath: 'bp', name: 'nm'}) }, /Invalid parameters: use basepath or name, not both/)
 })
 
 test('should create a route', t => {
@@ -136,6 +245,65 @@ test('should create a route', t => {
   return routes.create({relpath: '/hello', operation: 'GET', action: 'helloAction'})
 })
 
+test('should create a route from swagger file', t => {
+  t.plan(3)
+  const path_url = path => `https://openwhisk.ng.bluemix.net/api/v1/${path}`
+  const api_key = 'username:password'
+  const client_options = { api_key }
+  const client = { path_url, options: client_options }
+
+  const body = {
+    apidoc: {
+      namespace: '_',
+      swagger: '{"hello": "world"}'
+    }
+  }
+
+  client.request = (method, path, _options) => {
+    t.is(method, 'POST')
+    t.is(path, routes.routeMgmtApiPath('createApi'))
+    t.deepEqual(_options.body, body)
+  }
+
+  const routes = new Routes(client)
+  return routes.create({swagger: '{"hello": "world"}'})
+})
+
+test('should create a route with api name', t => {
+  t.plan(3)
+  const path_url = path => `https://openwhisk.ng.bluemix.net/api/v1/${path}`
+  const api_key = 'username:password'
+  const client_options = { api_key }
+  const client = { path_url, options: client_options }
+  const options = {force: true, basepath: '/hello', relpath: '/bar/1', operation: 'GET'}
+
+  const body = {
+    apidoc: {
+      namespace: '_',
+      apiName: 'SOME_NAME',
+      gatewayBasePath: '/',
+      gatewayPath: '/hello',
+      gatewayMethod: 'GET',
+      id: 'API:_:/',
+      action: {
+        name: 'helloAction',
+        namespace: '_',
+        backendMethod: 'GET',
+        backendUrl: 'https://openwhisk.ng.bluemix.net/api/v1/web/_/default/helloAction.http',
+        authkey: api_key }
+    }
+  }
+
+  client.request = (method, path, _options) => {
+    t.is(method, 'POST')
+    t.is(path, routes.routeMgmtApiPath('createApi'))
+    t.deepEqual(_options.body, body)
+  }
+
+  const routes = new Routes(client)
+  return routes.create({relpath: '/hello', operation: 'GET', action: 'helloAction', name: 'SOME_NAME'})
+})
+
 test('should create a route with apigw_token', t => {
   t.plan(4)
   const path_url = path => `https://openwhisk.ng.bluemix.net/api/v1/${path}`
@@ -446,7 +614,6 @@ test('should create a route using action name with ns overriding defaults', t =>
   return routes.create({relpath: '/hello', operation: 'GET', action: '/test/helloAction'})
 })
 
-
 test('create routes missing mandatory parameters', t => {
   const routes = new Routes()
   t.throws(() => { routes.create() }, /Missing mandatory parameters: relpath, operation, action/)


 

----------------------------------------------------------------
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