aws / aws-sdk-js

AWS SDK for JavaScript in the browser and Node.js
https://aws.amazon.com/developer/language/javascript/
Apache License 2.0
7.59k stars 1.55k forks source link

Small example code working, but testing or deploying the same code to Lambda does not work #1427

Closed Archetype90 closed 7 years ago

Archetype90 commented 7 years ago

I have some very simple AWS-SDK code that is meant to publish a simple message to an MQTT topic (endpoint). Here is the code:

var awsIot = require('aws-sdk');
var config = require('./config.js');

var iotdata = new awsIot.IotData(config.iotDevice);

console.log(config.iotDevice);

var params = {
  topic: 'DeviceNumber',
  payload: 'blah',
  qos: 0
};

iotdata.publish(params, function(err, data){
  if(err) {
      console.log(err);
  }
  else {
      console.log("success!");
  }
});

That works perfectly! It prints 'success!' to the console and publishes the 'blah' payload to the 'DeviceNumber' topic. But, when I change the code to use it as a test (with chai), it does not work. Here is the code...

var awsIot = require('aws-sdk');
var chai = require('chai');
var config = require('./config.js');

describe('skill', function() {
  var iotdata = new awsIot.IotData(config.iotDevice);
  console.log("Entering test...");
  console.log(config.iotDevice);

  var params = {
    topic: 'DeviceNumber',
    payload: 'blah',
    qos: 0
  };

  iotdata.publish(params, function(err, data){
    if(err) {
        console.log(err);
    }
    else {
        console.log("success!");
    }
  });
  console.log("After publish...");
}

The above code does NOT work. It will print the "Entering test..." and "After publish..." messages, but never prints error or success from the callback. The iotDevice config file looks good and prints with no problems. Both of the code samples above are using the same config file.

I have also attempted to deploy the code above to Lambda, which successfully deploys, and when testing it will return my expected results, but again, I never see "err" or "success".

Has anyone seen this behavior - or could you provide any guidance as to why I am seeing it?

Thanks!

jeskew commented 7 years ago

Most testing libraries require you to call a function to indicate when asynchronous code should be recognized as done. In the Mocha testing framework, for example, you would need to have the function passed as the second parameter to describe take a single argument in order for the function to flagged by Mocha as asynchronous. See Mocha's documentation and this StackOverflow question for more discussion.

When you deployed the code to AWS Lambda, was it wrapped in handler function as described in the Lambda docs?

Archetype90 commented 7 years ago

@jeskew Thanks so much for the reply. In regards to Mocha testing, thank you for the answer - I will test that out now. I am relatively new to those testing frameworks and passed a Mocha problem to the SDK.

Now Lambda is a little more curious for me. No, I did not wrap it in a handler function, but I am using Apex to deploy, which sets the handler in code (or at least, that is my understanding - again, new to Apex). Now, my Lambda function will execute, and return the correct response (using it for an Alexa skill). But, it does not ever hit that callback (giving me "success" or "err" to the console).

I will see the Lambda function say "Entering test..." and "After publish...", but as I said, no callback. Thsi is the one that really confuses me, as the Lambda function is clearly executing properly, but the publish will not work. Which is odd, as my understanding is it is a simple HTTP POST to the endpoint that you specify (in this case, the AWS IoT endpoint).

Archetype90 commented 7 years ago

@jeskew Ok, I just tested it as an asynchronous function and it worked like a charm. Thank you so much for answer what was clearly not an AWS-SDK problem 👍 .

Your async comments made me think that may be where my problem lies with Lambda, and as it turns out, it was. It seems like the whole key was for me to have my code like this:

    var iotdata = new awsIot.IotData(config.iotDevice);

    var params = {
      topic: 'DeviceNumber',
      payload: 'blah',
      qos: 0
    };

    return iotdata.publish(params, function(err, data){
      if(err) {
          console.log(err);
      }
      else {
          console.log("success!");
      }
    })

The "return" being the key. Ill be perfectly honest - I am not entirely sure why that is necessary. I attempted to make the code synchronous, as follows:

var iotdata = new awsIot.IotData(config.iotDevice);

var params = {
  topic: 'DeviceNumber',
  payload: 'blah',
  qos: 0
};

request = iotdata.publish(params);

request.send();

But that was not OK either. Anyway, it is working all across my code, and I did not need to change any of my packages or architecture. All it took was a good nights sleep and a great comment from you! Thanks a ton!

javiercuellar73 commented 5 years ago

Hi.

I need to publish to endpoint and use same code expose in this thread.

` var AWS = require('aws-sdk'); var iotdata = new AWS.IotData({endpoint:"xxxxxxxxxx-ats.iot.us-east-1.amazonaws.com"});

exports.handler = function(event, context, callback) {

   console.log("found iotdata",iotdata);
var params = {       
    topic: 'topic_1',        
    payload: 'blah',        
    qos: 0
    };    

iotdata.publish(params, function(err, data){        
    if(err){            
        console.log("Error occured : ",err)       
    }        
    else{            
        console.log("success.....");        
    }   
});    
callback();

}; `

The code runs, but the answer is:

Response: null Error occured : { ForbiddenException: null

any ideas? Of course, there is no message sent to IOT.

Thanks for any help.

javiercuellar73 commented 5 years ago

Nevermind.... it was a policy problem not giving enough permission. Now it is working.

This is the policy is use

`

{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "iot:", "Resource": "" } ] }`

lock[bot] commented 5 years ago

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs and link to relevant comments in this thread.