IBM Cloud Function OpenWhisk node.js calling WIOTP over http - ibm-cloud

I am trying to use https://github.com/ibm-watson-iot/openwhisk-package-watsoniotp in an OpenWhisk sequence (containing two actions) all code is node.js
Testing the sequence using Postman. Once the action completes, the action returns the variable, payload. The variable payload is passed over to the next action in the sequence which is the openwhisk-package-watsoniotp (added via a binding in the IBM Cloud console so I am unable to modify this code, it is locked).
I can post data from postman into Watson IoT platform via the sequence. However the format of the payload is interpreted as a String, not a JSON string.
This is the body I post from Postman, one of the variants I have tried.
{"payload": "{'speed': 10}"}
My node.JS actions return the input, unmodified.
return {payload: params.payload};
The value should be a JSON string. However WIOTP is unable to interpret the payload and basically tokenizes the values. This is evident when I try to create a board and a card. The property list lets me select each value in the array.
enter image description here
The openwhisk-package-watsontiotp code as far as I can tell just takes, params.payload as is and passes it along.

I found an example in the code that answer the question,
The payload, should be nested. I missed that originally.
{
"key": "sampleInput",
"value": {
"eventType": "status",
"payload": {
"temp": 4
},
"domain": "messaging.internetofthings.ibmcloud.com",
"typeId": "xxxx",
"deviceId": "xxxx01"
}
}

Related

azure data factory - convert single value output from query into json

In azure data factory, I am getting a single record back from a database.
I need to take one column from this and pass it to a web call body.
The body takes data in this format:
["cdd-lm-54"]
I have tried multiple expressions but none of them work. appreciate any advice on how to perform this.
The data returned from the database looks like this:
"value": [
{
"RowNumber": 1,
"Tag": "cdd-lm-54",
"Val1": "val 1",
"Val2": "val b",
"LastSyncDateTime": "2022-07-26T13:14:28Z",
"LastTimeModified": "2021-07-28T10:33:47.7Z"
}
]
The below expressions are the closest i have gotten, they output the data as i expect it to be but the web call still rejects it:
#concat('[','"',pipeline().parameters.DeviceRecord[0]['Tag'], '"',']')
#concat('[','''',pipeline().parameters.DeviceRecord[0]['Tag'], '''',']')
Odd thing is if i paste the exact value from ADF into postman, it works.
is adf doing something odd to the body?
Odd thing is if I paste the exact value from ADF into postman, it works.
The reason behind this is that the value that you take from the value and give it as ["cdd-lm-54"], it indicates that the body accepts an array containing required string.
Using #concat() to build ["cdd-lm-54"] will return a just a string, which is not the required data that the body accepts.
Instead use the following dynamic content
#array(pipeline().parameters.DeviceRecord[0]['Tag'])
The above returns an array containing the required value.

How to call moodle function

I'm testing moodle function (core_user_create_users) via SoapUI. Every time i call the function via url that i have designed. i gets error of invalid parameter
https://localhost/webservice/rest/server.php?wstoken=90b089f55f481a7d6b534bbe2b848203&wsfunction=core_user_create_users&moodlewsrestformat=json&users[0][username]=ayubjamal[0][password]=li#mR0cks!&users[0][firstname]=Ayub&users[0][lastname]=Jamal&users[0][email]=ajamal#mailinator.com
I expect the output to be the JSON Response as shown
{
"id": 2,
"username": "ayubjamal"
}

Watson Conversation making programmatic calls to client

I have a node app that uses the Watson Conversation service. I am able to successfully trigger a call to another API via a dialogue node using the JSON that it uses for the reply. However after reading up it seems I am doing it wrong. I am triggering my client server to make a REST call by adding an action property to the context.
{
"context": {
"action": "lookup"
},
"output": {}
}
When I get my result I add it onto the context object and pass it back to the conversation service. This seems to work ok, but it causes some issues.
1) having to manually delete these props after I trigger the thing I want
2) In conversation I must wait for user input even though I am not actually requesting user input on the front end but rather my client app is sending a message with no input text and the results of the REST call on the context object. This message which is returned to the conversation at the node where the action was triggered is what triggers the child nodes. It seems like there is a standardized way IBM wants you to make these programmatic calls regardless of if it's to an IBM cloud function, or your own client app. https://console.bluemix.net/docs/services/conversation/dialog-actions.html#dialog-actions
docs method:
{
"context": {
"variable_name" : "variable_value"
},
"actions": [
{
"name":"<actionName>",
"type":"client | server",
"parameters": {
"<parameter_name>":"<parameter_value>",
"<parameter_name>":"<parameter_value>"
},
"result_variable": "<result_variable_name>",
"credentials": "<reference_to_credentials>"
}
],
"output": {
"text": "response text"
}
}
Is this a new feature? I was referencing sample projects for my own app and I didn't see this pattern. By using this format will it tell the parent node to wait for a response to come back before trying to process the children? Will it prevent me from needing to delete properties off the context object so that I'm not calling the same action over and over with the same parameters in further turns of the conversation?

Security of cloudant query from OpenWhisk

I'm building an Angular SPA with a Cloudant data store on Bluemix.
Since the Bluemix implementation of OpenWhisk doesn't use VCAP services, I see 3 options to use OpenWhisk as my api provider for cloudant queries for my Angular app:
Follow the pattern of passing credentials as seen here: https://github.com/IBM-Bluemix/openwhisk-visionapp (very interesting approach btw)
Include the credentials as though I'm running locally as seen here: https://github.com/IBM-Bluemix/nodejs-cloudant/blob/master/app.js
Use the http API as seen here: https://docs.cloudant.com/api.html (which highlights the security problem passing credentials.
Since my service is not intended for publishing (it's intended for my own app) I'm thinking option 2 is my "least of all evils" choice. Am I missing something? My thinking is such that while fragile to changes it would be the most secure since credentials aren't passed in the open. The serverless infrastructure would have to be hacked...
Thanks in advance!
(lengthy) Update: (apologies in advance)
I've gotten a little farther along but still no answer - stuck in execution right now.
To clarify, my objective is for the app to flow from Angular Client -> OpenWhisk -> Cloudant.
In this simplest use case, I want to pass a startTime parameter and an endTime parameter, have OpenWhisk fetch all the records in that time range with all fields, and passing back selected fields. In my example, I have USGS earthquake data in a modified GeoJSON format.
Following information from the following articles below, I've concluded that I can invoke the wsk command line actions and use the bindings I've setup from within my Javascript function and therefore not pass my credentials to the database. This gives me a measure of security (still question the rest endpoint of my OpenWhisk action) but I figure once I get my sample running I think through that part of it.
My command line (that works):
wsk action invoke /my#orgname.com_mybluemixspace/mycfAppName/exec-query-find --blocking --result --param dbname perils --param query {\"selector\":{\"_id\":{\"$gt\":0},\"properties.time\":{\"$gt\":1484190609500,\"$lt\":1484190609700}}}
This successfully returns the following:
{
"docs": [
{
"_id": "eq1484190609589",
"_rev": "1-b4fe3de75d9c5efc0eb05df38f056a65",
"dbSaveTime": 1.484191201099e+12,
"fipsalpha": "AK",
"fipsnumer": "02",
"geometry": {
"coordinates": [
-149.3691,
62.5456,
0
],
"type": "Point"
},
"id": "ak15062242",
"properties": {
"alert": null,
"cdi": null,
"code": "15062242",
"detail": "http://earthquake.usgs.gov/earthquakes/feed/v1.0/detail/ak15062242.geojson",
"dmin": null,
"felt": null,
"gap": null,
"ids": ",ak15062242,",
"mag": 1.4,
"magType": "ml",
"mmi": null,
"net": "ak",
"nst": null,
"place": "45km ENE of Talkeetna, Alaska",
"rms": 0.5,
"sig": 30,
"sources": ",ak,",
"status": "automatic",
"time": 1.484190609589e+12,
"title": "M 1.4 - 45km ENE of Talkeetna, Alaska",
"tsunami": 0,
"type": "earthquake",
"types": ",geoserve,origin,",
"tz": -540,
"updated": 1.484191127265e+12,
"url": "http://earthquake.usgs.gov/earthquakes/eventpage/ak15062242"
},
"type": "Feature"
}
]
}
The action I created in OpenWhisk (below) returns an Internal Server Error. I'm passing the input value as
{
"startTime": "1484161200000",
"endTime": "1484190000000"
}
Here's the code for my action:
`var openWhisk = require('openwhisk');
var ow = openWhisk({
api_key:'im really a host'
});
function main(params) {
return new Promise(function(resolve, reject) {
ow.actions.invoke({
actionName:'/my#orgname.com_mybluemixspace/mycfAppName/exec-query-find',
blocking:true,
parameters:{
dbname: 'perils',
query: {
"selector": {
"_id": {
"$gt": 0
},
"properties.time": {
"$gt": params.startTime,
"$lt": params.endTime
}
}
}
}
}).then(function(res) {
//get the raw result
var raw = res.response.result.rows;
//lets make a new one
var result = [];
raw.forEach(function(c) {
result.push({id:c.docs._id, time:c.docs.properties.time, title:c.docs.properties.title});
});
resolve({result:result});
});
});
}`
Here are the links to my research:
http://infrastructuredevops.com/08-17-2016/news-openwhisk-uniq.html
Useful because of the use of the exec-query-find and selector syntax usage but also cool for the update function I need to build for populating my data!
https://www.raymondcamden.com/2016/12/23/going-serverless-with-openwhisk
The article referenced by #csantanapr
Am I overlooking something?
Thanks!
I'm assuming what you are trying to do is to access your Cloudant DB directly from your angular client side code from the Browser.
If you don't need any business logic, or you can get away by using Cloudant features (design docs, views, map, reduce, etc..) and you are generating Cloudant API keys with certain access (i.e. write vs. read), then you don't need a server or serveless middlewear/tier.
But now let's get real, most people need that tier, and if you are looking a OpenWhisk, then you are in good luck this is very easy to do.
OpenWhisk on Bluemix support VCAP service credentials, but in a different way.
Let's name you have a Bluemix Org carlos#example.com and space dev that would translate to OpenWhisk namespace carlos#example.com_dev
If you add a Cloudant service under the space dev in Bluemix, this will generate service key credentials for this Cloudant Account. This credentials give you super power access meaning you are admin.
If you want to use this Cloudant credentials in OpenWhisk, you can use the automatic binding generated with the cloudant package.
To do this using the OpenWhisk CLI run wsk package refresh this will pull the Cloudant credentials and create you a new package with the credentials binded as default parameter for all the cloudant actions under that package. This is modified version of #1 above
Another alternative is to bind the credentials manually to a package or an action as default parameters, this makes sense when you don't want to use the super power admin credentials, and you generated a Cloudant API key for a specific database. This is option #1 above.
I would not recommend to put the credentials in source code #2
For option #3, what's insecure is to pass your credentials as part of the URL like https://username:password#user.cloudant.com, but passing the username and password in the Authorization header over https is secured.
This is because even if you are using secure transport https everything in the URI/URL is not encrypted anyone can see that value, but passing secrets in body or header is standard practice as this is transfer after secure connection is established.
Then you create actions that use the credentials as parameters in your OpenWhisk actions to build your business logic for your backend.
Then how to do you access this backend from the Browser, well OpenWhisk has a API Gateway feature in experimental that allows your to expose your actions as public APIs with CORS enable.
Only a url is expose, your credentials as default parameters are never expose.
If you want to see an example on check out Raymond Camden Blog posts where he show Ionic/Angular App accessing his Cloudant Database of Cats
https://www.raymondcamden.com/2016/12/23/going-serverless-with-openwhisk

What types are available for profile variables in Watson Dialog Service?

The Watson Dialog Service on IBM Bluemix allows to create profile variables and to pass values to them. In the examples these variables always seem to have the type "TEXT" (see "myVariable" below). Are there any other types available? How would I pass a JSON object and how would I access specific values inside a dialog?
<variables>
<var_folder name="Home">
<var name="myVariable" type="TEXT"/>
</var_folder>
</variables>
I talked with the service team, and the recommendation is to use the new Watson Conversation service as it is actually possible to pass an array of name:value pairs. Below is a sample that the team came up with on the fly. Hopefully it's helpful.
Sample:
{
"client_id": 4435,
"name_values": [
{
"name": "string",
"value": "string"
}
]
}
For example, if you want to post to a context variable named JSON_object, the PUT context payload would be:
{
"client_id": 4435,
"name_values": [
{
"name": "JSON_object",
"value": "{"sample":"data"}"
}
]
}
HOWEVER, they highly recommend converting the JSON to flat XML before posting as context, since dialog has much more versatility to parse XML, using {variable_name.xmlElementName}.
More info found on the API explorer - https://watson-api-explorer.mybluemix.net/apis/dialog-v1#!/Profile/setProfile under PUT CONTEXT method.
Best to go to the documentation.
variables can be objects - consisting of many vars
http://www.ibm.com/watson/developercloud/doc/dialog/reference_elements.shtml#reference_variables
vars can be of types
http://www.ibm.com/watson/developercloud/doc/dialog/reference_elements.shtml#reference_var