YAML bad mapping issue - amazon-web-services

list:
handler: todos/list.list
events:
- http:
path: todos
method: 'use strict'
const AWS = require('aws-sdk');
const dynamoDb = new AWS.DynamoDB.DocumentClient();
const params = {
TableName: "StreamData",
Item: {
ID: uuid.v1(),
name: data.name,
description: data.description,
price: data.price,
imageURL: data.imageURL }, };
module.exports.list = (event, context, callback) => { dynamoDb.scan(params, (error, result) => { if (error) { console.error(error); callback(null, { statusCode: error.statusCode || 501,
headers: {
'Content-Type': 'text/plain' },
body: 'Couldn\'t fetch the todos.', });
return; }
const response = {
statusCode: 200, b
ody: JSON.stringify(result.Items), };
callback(null, response); }); };
cors: true
I am new to yaml having a issue with line 10 TableName: "StreamData", says "bad mapping"if I remove the line the error moves up or down to the following line.

The code you had written is not a YAML code. YAML is a declarative language and it does not contain commas(,) and semi-colons(;). Also, the YAML language does not use the equals symbol(=) for declaration. It only uses colons(:).
See YAML syntax here: https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html

Related

Why Does My Lambda Function Not `startExecution` My Step Function

I am looking to connect my Lambda with my Step Function, and cannot figure out why it will not startExecution.
SDK Code:
import AWS from "aws-sdk";
const stepfunctions = new AWS.StepFunctions({ apiVersion: "2016-11-23" });
interface Params {
stateMachineArn: string;
input: string;
}
export async function handler(event: any, context: object) {
console.log("event.body", event.body);
const params: Params = {
stateMachineArn: process.env.STEP_FUNCTION_ARN,
input: JSON.stringify(event.body),
name: "testNameField",
};
console.log("PARAMS", params);
stepfunctions.startExecution(params, (err: any, data: any) => {
if (err) {
console.log("THERE WAS AN ERROR", err);
console.log("ERROR STACK", err.stack);
} // an error occurred
else {
console.log("data", data);
} // successful response
});
}
Permissions:
Allow: states:DeleteStateMachine
Allow: states:StartExecution
Allow: states:CreateStateMachine
Allow: states:SendTaskSuccess
Allow: states:DeleteActivity
Allow: states:SendTaskHeartbeat
Allow: states:CreateActivity
Allow: states:SendTaskFailure
Allow: states:StopExecution
Allow: states:GetActivityTask
Allow: states:UpdateStateMachine
Allow: states:StartSyncExecution
Extra information:
I have tried doing a "test" on the console for the lambda function,
from which it succeeds. I'm not sure where else to look.
In the step function, all the columns
(Total/Running/Succeeded/Failed/Timed out/Aborted) are 0.
The params console.log offers the correct information
Are there any error messages outputted from the console.log?
Solution Code:
const AWS = require("aws-sdk");
AWS.config.update({ region: "eu-west-1" });
const stepFunction = new AWS.StepFunctions();
interface Params {
stateMachineArn: string;
input: string;
name: string;
}
exports.handler = async (event: any) => {
console.log(event);
const stepFunctionParams = {
stateMachineArn: process.env.STEP_FUNCTION_ARN,
input: JSON.stringify({
message: event.body,
}),
name: "name" + String(Date.now()),
};
try {
const stepFunctionResponse = await stepFunction
.startExecution(stepFunctionParams)
.promise();
return { statusCode: 200, body: "Success" };
} catch (e) {
console.log("Problem executing SF :", JSON.stringify(e));
return {
statusCode: 500,
body: "Problem executing step function : " + JSON.stringify(e),
headers: { "Access-Control-Allow-Origin": "*" },
};
}
};

API-gateway-lambda : Cookie not getting saved in browser

I'm trying to know how to use cookies with AWS-Lambda with the serverless framework as per this blogpost
and following is my serverless.yml code
functions:
hello:
handler: handler.hello
events:
- http:
path: /post
method: post
cors:
origin : 'https://xyz.netlify.app'
and Lambda function as per following
"use strict";
const cookie = require("cookie");
module.exports.hello = async (event) => {
const body = JSON.parse(event.body);
const name = body.name;
const value = body.value;
return {
statusCode: 200,
headers: {
"Access-Control-Allow-Origin": "https://xyz.netlify.app",
"Access-Control-Allow-Credentials": true,
"Set-Cookie": cookie.serialize(name, value, {
expires: new Date(new Date().getTime() + 10 * 1000),
}),
},
body: JSON.stringify(
{
input: event,
},
null,
2
),
};
// Use this code if you don't use the http event with the LAMBDA-PROXY integration
// return { message: 'Go Serverless v1.0! Your function executed successfully!', event };
};
As you can notice, I already have configured the code to avoid any cors issue.
While try to send a post request as per following,
const name = document.getElementById('name')
const value = document.getElementById('value')
const post_btn = document.getElementById('post_btn')
post_btn.addEventListener('click', () => {
console.log(name.value, value.value)
const post_url = 'https://abcdxyz59t9.execute-api.ap-south-1.amazonaws.com/dev/post'
const user = {
name: name.value,
value: value.value
};
// request options
const options = {
method: 'POST',
body: JSON.stringify(user),
headers: {
'Content-Type': 'application/json'
}
}
// send POST request
fetch(post_url, options)
.then(res => res.json())
.then(res => console.log(res));
})
I do get a Set-Cookie header like below
But the cookie doesn't get saved in the browser.
That's not the case when I directly try to hit a get request with that URL without the cors in the browser. Can anyone please tell me what to do?

Why is my Lambda function creating two Spot Instance Requests instead of one?

I have the following lambda function
var AWS = require('aws-sdk');
var ec2 = new AWS.EC2({
region: "eu-west-1"
});
var userData = `#!/bin/bash
echo "hello there"
`;
var userDataEncoded = new Buffer.from(userData).toString('base64');
var params = {
InstanceCount: 1,
LaunchSpecification: {
ImageId: "ami-xxxxxxxxx",
InstanceType: "c4.2xlarge",
KeyName: "xxxxxxx",
SubnetId: "subnet-xxxxxxxxxx",
Placement: {
AvailabilityZone: "eu-west-1a"
},
SecurityGroupIds: [
"sg-xxxxxxxxxx"
],
UserData: userDataEncoded
},
SpotPrice: "0.8",
BlockDurationMinutes: 180,
Type: "one-time"
};
exports.handler = async (event, context) => {
await ec2.requestSpotInstances(params, function (err, data) {
if (err) {
console.log("error");
} else {
console.log("starting instance");
context.succeed('Completed');
return {
statusCode: 200,
body: JSON.stringify('success!'),
};
}
}).promise();
};
The function is supposed to take my params and create ONE spot request, but it always starts two parallel spot requests with one instance each.
There is no error in the logs, the function is only triggered once according to Cloudwatch and has a success rate of 100%.
I set the timeout on 20 minutes so it can't be that either.
Why is it doing that? I only want one request, and not two. Any help is appreciated.
You can either use the promise-based or callback-based approach. Using both at once results in duplicate calls.
So either remove the callback and use .then and .catch for you response or do the opposite and do not call .promise on requestSpotInstances.
exports.handler = async (event, context) =>
ec2.requestSpotInstances(params).promise()
.then(() => {
console.log("starting instance");
return {
statusCode: 200,
body: 'success!'
};
}).catch((error) => {
console.error("error");
return {
statusCode: 500,
body: 'an error occurred'
}
})

Serverless framework on AWS - Post API gives Internal server error

My serverless.yml looks like this -
service: books-api-v1
provider:
name: aws
region: eu-west-1
role: arn:aws:iam::298945683355:role/lambda-vpc-role
runtime: nodejs8.10
iamRoleStatements:
- Effect: Allow
Action:
- "ec2:CreateNetworkInterface"
- "ec2:DescribeNetworkInterfaces"
- "ec2:DeleteNetworkInterface"
Resource: "*"
functions:
login:
handler: api/controllers/authController.authenticate
vpc: ${self:custom.vpc}
events:
- http:
path: /v1/users/login
method: post
cors: true
And the actual API function looks this -
'use strict';
var db = require('../../config/db'),
crypt = require('../../helper/crypt.js'),
jwt = require('jsonwebtoken');
exports.authenticate = function(event, context, callback) {
console.log(JSON.parse(event.body));
const data = IsJsonString(event.body) ? JSON.parse(event.body) : event.body;
let myEmailBuff = new Buffer(process.env.EMAIL_ENCRYPTION_KEY);
db.users.find({
where:{
username : crypt.encrypt(data.username)
}
}).then(function(user) {
try {
let res = {
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true,
},
body: JSON.stringify({
message:'ERROR!',
success: false
})
};
if (!user) {
res.body = JSON.stringify({
success: false,
message: 'Authentication failed. User not found.',
authFail:true
});
//res.status(200).json({ success: false, message: 'Authentication failed. User not found.',authFail:true, });
}else if (user) {
// check if password matches
if (crypt.decrypt(user.password) != data.password) {
res.body = JSON.stringify({
success: false,
message: 'Authentication failed. Wrong password.',
authFail:true
});
//res.status(200).json({ success: false, message: 'Authentication failed. Wrong password.',authFail:true, });
} else {
// if user is found and password is right
// create a token with only our given payload
// we don't want to pass in the entire user since that has the password
const payload = {
username: crypt.decrypt(user.username)
};
var token = jwt.sign(payload, process.env.JWT_SIGINING_KEY, {
algorithm: process.env.JWT_ALGORITHM,
expiresIn: 18000,
issuer: process.env.JWT_ISS
});
// return the information including token as JSON
// res.status(200).json({
// success: true,
// message: 'Enjoy your token!',
// token: token
// });
res.body = JSON.stringify({
success: true,
message: 'Enjoy your token!',
token: token
});
}
//callback(null, res);
}
console.log(res);
callback(null, res);
} catch (error) {
console.log('errorsssss: ');
console.log(error);
}
});
};
function IsJsonString(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
Works very well on my serverless local, but when I try it on AWS Lambda function, then it gives "Internal server error" Message.
I have looked into my cloudwatch logs and the response looks correct to me. Here is the response that I am sending back to callback.
{
statusCode: 200,
headers: {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Credentials': true
},
body: '{"success":true,"message":"Enjoy your token!","token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InNhaW1hLm5hc2lyckBnbWFpbC5jb20iLCJpYXQiOjE1NDUwNjE4OTYsImV4cCI6MTU0NTA3OTg5NiwiaXNzIjoiaWFtbm90YWdlZWsuY28udWsifQ.2HyA-wpmkrmbvrYlWOG41W-ezuLCNQnt0Tvrnsy2n3I"}'
}
Any help please?
In this case, it might because of the Api Gateway configurations. Does your api public? Because I have met such problems when the api is not public.

What is the code to tell a Lambda#Edge function to do a redirect?

So just to be clear I have spent several hours googling things and none of these work. This is not a "low effort post".
This is an example of the code I have been trying. It doesn't work. Neither does doing response like this response.headers=[{Location:"foo"}] or response.headers=[{location:"foo"}] or the other eight ways I've tried it.
exports.handler = (event, context, callback) => {
if(request.uri === "/") {
var response = {
statusCode: 301,
headers: {
"location" : [{
key: "Location",
value: "foo"
}]
},
body: null
};
callback(null, response);
}
I've tried the following links:
http://blog.ryangreen.ca/2016/01/04/how-to-http-redirects-with-api-gateway-and-lambda/
http://blog.rowanudell.com/redirects-in-serverless/
https://kennbrodhagen.net/2016/04/02/how-to-return-302-using-api-gateway-lambda/
Python AWS Lambda 301 redirect
http://www.davekonopka.com/2016/serverless-aws-lambda-api-gateway.html
You mentioned the link to this example in your question; it should work with Lambda Proxy Integration:
'use strict';
exports.handler = function(event, context, callback) {
var response = {
statusCode: 301,
headers: {
"Location" : "http://example.com"
},
body: null
};
callback(null, response);
};
source: http://blog.ryangreen.ca/2016/01/04/how-to-http-redirects-with-api-gateway-and-lambda/
Update:
Else, try using this example from this page of example functions:
'use strict';
exports.handler = (event, context, callback) => {
/*
* Generate HTTP redirect response with 302 status code and Location header.
*/
const response = {
status: '302',
statusDescription: 'Found',
headers: {
location: [{
key: 'Location',
value: 'http://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html',
}],
},
};
callback(null, response);
};