Connect to kubernetes with AWS Lambda function - node.js

I am trying to create a lambda function for an Alexa skill that will connect to an EKS cluster. I am creating the cluster using with Terraform and hosting it on AWS. I am not sure if I am correctly exporting my function correctly and would appreciate some feedback.
const Alexa = require('ask-sdk')
const Client = require('kubernetes-client').Client
const connect = require("./connect");
const LaunchRequestHandler = {
canHandle(handlerInput) {
return handlerInput.requestEnvelope.request.type === "LaunchRequest";
},
handle(handlerInput) {
console.log("Launch Request Handler Called");
let speechText =
"KubeVoice Test";
let repromptText =
"I did not receive any input. You can say, Connect to Cluster.";
return handlerInput.responseBuilder
.speak(speechText)
.reprompt(repromptText)
.getResponse();
}
};
//Handler for connecting
const KubernetesConnect = {
canHandle(handlerInput) {
return (
handlerInput.requestEnvelope.request.type === "IntentRequest" &&
handlerInput.request.intent.name === "Connect"
);
},
handle(handlerInput) {
let connectToCluster = connect.connect();
let speechText = "connected to cluster";
return handlerInput.responseBuilder.speak(speechText).getResponse();
}
};
const UnhandledHandler = {
canHandle() {
return true;
},
handle(handlerInput, error) {
console.log(`Error Handler : ${error.message}`);
return handlerInput.responseBuilder.speak(
"Sorry, I am unable to process your request, ask me to connect"
).getResponse();
}
};
exports.handler = Alexa.SkillBuilders.custom().
addRequestHandlers(
LaunchRequestHandler,
KubernetesConnect,
)
.addErrorHandlers(UnhandledHandler)
.lambda();
And the code for connecting to the eks cluster is taken from the Godaddy Kubernetes client example
const Client = require('kubernetes-client').Client
async function connect() {
try {
const client = new Client({
config: {
url: process.env.K8S_CLUSTER_HOST,
auth: {
provider: {
type: 'cmd',
config: {
'cmd-path': 'aws-iam-authenticator',
'cmd-args': 'token -i' + process.env.K8S_AUTH_TOKEN,
'cmd-env': {
AWS_PROFILE: process.env.AWS_PROFILE
},
'token-key': 'status.token'
}
}
},
insecureSkipTlsVerify: true
},
version: process.env.K8S_CLUSTER_VERSION
});
}
catch (err) {
console.error('Error: ', err);
}
}
module.exports.connect = connect;
This is the error I am getting
2021-04-10T13:45:14.982Z c1c8c985-5eb0-43dd-a041-5a077ca12b6c INFO Error Handler : Cannot read property 'type' of undefined

was missing .requestEnvelope on the line for the connect intent. The code functions now, just need to sort IAM roles for the cluster!

Related

stripe CLI webhook not reciving in firebase without firebasefuctions

It is showing no error but it is not reaching Firebase.i am using stripe CLI
console.log(success: order ${session.id} had been added to db); this line never comes in the console.
the terminal shows everything created but it does not reach Firebase database I am thinking there is an error in the code. i think the firebase is not connecting
The stripe dashboard also says connected
I am using the forward to localhost line in git terminal
webhook code
import { buffer } from "micro";
import * as admin from 'firebase-admin'
//secure a connection to Firebase from backend
const serviceAccount = require('../../../permissions.json');
const app = !admin.apps.length ? admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
})
: admin.app();
// establish connection to stripe
const stripe = require('stripe')(process.env.STRIPE_SECRET_KEY);
const endpointSecret = process.env.STRIPE_SIGNING_SECRET;
if (typeof endpointSecret !== "string") {
console.error("Unexpected value for STRIPE_SIGNING_SECRET");
// potentially throw an error here
}
const fulfillOrder = async (session) => {
//console.log('Fulfilling order', session)
return app
.firestore()
.collection("user")
.doc(session.metadata.email)
.collection("orders")
.doc(session.id)
.set({
amount: session.amount_total / 100,
amount_shipping: session.amount_total_details.amount_shipping / 100,
images: JSON.parse(session.metadata.images),
timestamp: admin.firestore.FieldValue.serverTimestamp(),
})
.then(() => {
console.log(`success: order ${session.id} had been added to db`);
});
};
export default async (req, res) =>{
if(req.method === 'post'){
const requestBuffer = await buffer(req);
const payload = requestBuffer.toString();
const sig = req.headers["stripe-signature"];
let event;
// verify that the event posted came from stripe
try{
event = stripe.webhooks.constructEvent(
payload,
sig,
endpointSecret);
} catch (err) {
console.log('ERROR', err.message)
return res.status(400).send(`Webhook error: ${err.message}`)
}
//handle the checkout event
if (event.type === 'checkout.session.completed') {
const session = event .data.object;
//fulfill the order...
return fulfillOrder(session)
.then(() => res.status(200))
.catch((err) => res.status(400).send(`Webhook error: ${err.message}`));
}
}
};
export const config = {
api: {
bodyParser: false,
externalResolver: true,
},
};
firebase rules
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow write: if false;
allow read: if true;
}
}
}

Bad request while deploying cloud function in firebase. HTTP Error: 400

I'm trying to deploy cloud function to create push notification (chat messaging) on firebase (Firestore).
But when i'm trying to do this - i'm always getting HTTP Error: 400, The request has errors.
Looks like path of collections is good.
exports.notifyNewMessage = functions.firestore
.document('/chat/{toUserId}/chatRoom/{fromUserId}/chatItems')
.onCreate((docSnapshot, context) => {
const message = docSnapshot.data();
const recipientId = context.params.toUserId; // получатель сообщения
const senderId = context.params.fromUserId; // отправитель сообщения
const senderName = message['username'];
if (recipientId === senderId) {
} else {
return admin.forestore().doc('tokens/' + recipientId).get().then(userDoc => {
const tokens = userDoc.get('tokens')
const notificationBody = (message['type'] === "TEXT") ? message['textMessage'] : "New message with Image"
const payload = {
notification: {
title: senderName + " sent you a message",
body: notificationBody,
clickAction: "ChatActivity" // возможно, это только для андроида
},
data: {
USER_NAME: senderName,
USER_ID: message['senderId']
}
}
return admin.messaging().sendToDevice(tokens, payload).then( response => {
const stillRegisteredTokens = tokens
response.results.forEach((result, index) => {
const error = result.error
if (error) {
const failedRegistrationToken = tokens[index]
console.error('failed token', failedRegistrationToken, error)
if (error.code === 'messaging/invalid-registration-token' || error.code == 'messaging/registration-token-not-registred') {
const failedIndex = stillRegisteredTokens.indexOf(failedRegistrationToken)
if (failedIndex > -1) {
stillRegisteredTokens.splice(failedIndex, 1)
}
}
}
})
return admin.firestore().doc("tokens" + recipientId).update({
tokens: stillRegisteredTokens
})
})
})
}
})
also i would ask about line "clickAction: "ChatActivity" it only for android? how can i do same to ios?
Thx a lot!
Try to delete the function from firebase console and redeploy
or
try changing Internet Service Provider and deploy

Invoke different contract in a single Chaincode

I am using hyperledger-fabric 1.4 for developing a simple chaincode that saves the project information.
I am working on a existing code repository that contains chain code function calls using, facing many difficulties already in running the network. I managed to get the chaincode installed on 2 peers.
Now i am on invoking the chain code part. I know that in fabric-client two types there are bootstrap identities and then enrollment strategies for users and admins.
What I am trying to achieve is to write separate contract files say Project and Folder, install these contract files as single chaincode and then invoke these contract functions using client.
Originally the repository contain only one contract that was built using shim:
const util = require('util');
var Chaincode = class {
async Init(stub) {
return shim.success();
}
async Invoke(stub) {
let ret = stub.getFunctionAndParameters();
console.info(ret);
let method = this[ret.fcn];
if (!method) {
return shim.success();
}
try {
let payload = await method(stub, ret.params, this);
return shim.success(payload);
} catch (err) {
return shim.error(err);
}
}
async save(stub, args, thisClass) {
if (args.length != 1) {
return Buffer.from(JSON.stringify({result: 400, message: "Invalid arguments"}));
}
let transactionHash = stub.getTxID();
let timeStamp = stub
.getTxTimestamp()
.seconds
.low;
try {
let order = JSON.parse(args[0]);
order.updateLogs = [
{
transactionHash: transactionHash,
createdAt: timeStamp,
completedMilestone: order.completedMilestone
}
]
let orderAsByte = await stub.getState(order.orderId);
if (orderAsByte && orderAsByte.length > 0) {
return Buffer.from(
JSON.stringify({result: 409, message: "order already exist"})
);
}
await stub.putState(order.orderId, Buffer.from(JSON.stringify(order)));
return Buffer.from(
JSON.stringify({result: 200, message: 'successfully Save', transactionHash})
);
} catch (err) {
return Buffer.from(
JSON.stringify({result: 400, message: err.message, transactionHash})
);
}
}
//Change modified of PO
async update(stub, args, thisClass) {
// args[0] = order id, args[1] = completedMilestone
if (args.length != 2) { //
return Buffer.from(JSON.stringify({result: 400, message: "Invalid arguments"}));
}
let timeStamp = stub
.getTxTimestamp()
.seconds
.low;
let orderAsByte = await stub.getState(args[0]);
if (!orderAsByte || orderAsByte.length === 0) {
return Buffer.from(
JSON.stringify({result: 404, message: "order does not exist"})
);
}
let transactionHash = stub.getTxID();
let order = JSON.parse(orderAsByte);
order.completedMilestone = args[1];
order
.updateLogs
.push(
{completedMilestone: order.completedMilestone, transactionHash: transactionHash, createdAt: timeStamp}
)
try {
await stub.putState(args[0], Buffer.from(JSON.stringify(order)));
return Buffer.from(
JSON.stringify({result: 200, message: 'successfully update', transactionHash})
);
} catch (err) {
return Buffer.from(JSON.stringify({result: 400, message: err.message}));
}
}
async queryOrder(stub, args, thisClass) {
if (args.length < 1) {
return Buffer.from(JSON.stringify({result: 400, message: "Invalid arguments"}));
}
let queryString = args[0];
let method = thisClass['getQueryResultForQueryString'];
let queryResults = await method(stub, queryString, thisClass);
return queryResults;
}
async getQueryResultForQueryString(stub, queryString, thisClass) {
let resultsIterator = await stub.getQueryResult(queryString);
let method = thisClass['getAllResults'];
let results = await method(resultsIterator, false);
return Buffer.from(JSON.stringify(results));
}
async getAllResults(iterator) {
let allResults = [];
while (true) {
let res = await iterator.next();
if (res.value && res.value.value.toString()) {
let jsonRes = {};
jsonRes.Key = res.value.key;
try {
jsonRes.Record = JSON.parse(res.value.value.toString('utf8'));
} catch (err) {
jsonRes.Record = res
.value
.value
.toString('utf8');
}
allResults.push(jsonRes);
}
if (res.done) {
await iterator.close();
console.info(allResults);
return allResults;
}
}
}
async get(stub, args, thisClass) {
if (args.length != 1) { //
return Buffer.from(JSON.stringify({result: 400, message: "Invalid arguments"}));
}
try {
let orderAsByte = await stub.getState(args[0]);
let order = JSON.parse(orderAsByte);
console.info('GET <--> ', order);
return Buffer.from(JSON.stringify({result: 200, order: JSON.stringify(order)}));
} catch (err) {
return Buffer.from(JSON.stringify({result: 404, message: 'Order Not Found'}));
}
}
};
shim.start(new Chaincode());
and it was working flawlessly with following snippet.
async function loadAdmin() {
const adminKeystorePath = path.join(
process.cwd(),
"../",
"network",
"crypto-config",
"peerOrganizations",
"blockchain.kwiktrust.com",
"users",
"Admin#blockchain.kwiktrust.com",
"msp",
"keystore",
"509c6e0476760a3eb9a6b37b7788f2178bb708e651e7f3f89a05d10eefc48522_sk");
const keystore = fs.readFileSync(adminKeystorePath);
const adminCertPath = path.join(
process.cwd(),
"../",
"network",
"crypto-config",
"peerOrganizations",
"blockchain.kwiktrust.com",
"users",
"Admin#blockchain.kwiktrust.com",
"msp",
"signcerts",
"Admin#blockchain.kwiktrust.com-cert.pem"
);
const signCert = fs.readFileSync(adminCertPath)
console.log('fabricHelper.js.loadAdmin().adminKeystorePath => ',adminKeystorePath);
console.log('fabricHelper.js.loadAdmin().adminCertPath => ', adminCertPath);
const state_store = await Fabric_Client.newDefaultKeyValueStore(
{path: store_path}
)
fabric_client.setStateStore(state_store)
const crypto_suite = Fabric_Client.newCryptoSuite()
const crypto_store = Fabric_Client.newCryptoKeyStore({path: store_path})
crypto_suite.setCryptoKeyStore(crypto_store)
fabric_client.setCryptoSuite(crypto_suite)
let admin = await fabric_client.getUserContext("admin", true)
if (!admin) {
admin = await fabric_client.createUser({
username: "admin",
mspid: process.env.MSP,
cryptoContent: {
privateKeyPEM: keystore.toString(),
signedCertPEM: signCert.toString()
}
})
console.log('fabricHelper.js.loadAdmin.createUser =>', admin.getIdentity().toString())
fabric_client.setUserContext(admin, true)
}
else{
console.log('fabricHelper.js.loadAdmin.alreadyCreated =>', admin.getIdentity().toString())
}
}
Above loads the user context in fabric client SDK and then the saveOrder to execute contract and submit transaction
function saveOrder(orderObj) {
return new Promise(async (resolve, reject) => {
await loadAdmin()
const tx_id = fabric_client.newTransactionID()
let request = {
chaincodeId: process.env.CHAIN_CODE_ID,
fcn: "save",
args: [JSON.stringify(orderObj)],
chainId: process.env.CHANNEL,
txId: tx_id
}
const results = await channel.sendTransactionProposal(request)
const [proposalResponses,proposal] = results
if (proposalResponses && proposalResponses[0].response && proposalResponses[0].response.status === 200) {
const payload = JSON.parse(proposalResponses[0].response.payload.toString())
console.log("channel.sendTransactionProposal:proposalResponses[0].response.status =>", proposalResponses[0].response.status)
console.log("channel.sendTransactionProposal:proposalResponses[0].response.payload =>", payload.result)
if (payload.result == 200) {
request = {
proposalResponses,
proposal
}
const sendRequest = await channel.sendTransaction(request)
console.log('sendRequest.Status =>', sendRequest);
if (sendRequest && sendRequest.status === "SUCCESS") {
resolve(true)
} else {
reject(false)
}
} else {
console.log("Unable to get payload success in porposal response")
reject(false)
}
} else {
console.log("Unable to get payload success in porposal response")
reject(false)
}
})
}
Now I have changed shim to fabric-contract-api:-1.4.0 and exporting two contracts Project and Folder.
As i stated I want more then one contract files, but I have no idea how to execute the transaction the same way that I did for one contract, as channel.getContract is not any function. I tried another way that uses FileSystemWallet in fabric-sample 1.4 fabcar which required enrollAdmin and registerUser options but there i get authentication failure when I even try to enroll admin and probably because of my lack of knowledge on how to setup connections.json.
// Create a new file system based wallet for managing identities.
const walletPath = path.join(process.cwd(), 'http','utils','hfc-key-store');
const wallet = new FileSystemWallet(walletPath);
console.log(`Wallet path: ${walletPath}`);
// Check to see if we've already enrolled the user.
const userExists = await wallet.exists('user1');
if (!userExists) {
console.log('An identity for the user "admin" does not exist in the wallet');
console.log('Run the registerUser.js application before retrying');
return;
}
const gateway = new Gateway();
await gateway.connect(ccp, { wallet, identity: 'user1', discovery: { enabled: false } });
// Get the network (channel) our contract is deployed to.
const network = await gateway.getNetwork('mychannel');
// Get the contract from the network.
const contract = network.getContract('Project');
This way i get to submit transaction on contract but when i run enrollAdmin.js before running registerUser.js script it gives me unable to enroll Authentication Failure.
Its been only four days since i started working on hyper-ledger so any help is appriciated..

lambda with graphql and sqs send 2 messages to sqs in nodejs?

i'm working on project where i need to write a lambda function which provides AWS API to handles GraphQL query and send the payload to AWS SQS everything is working fine but when i check my AWS SQS queue it shows 2 messages every single time instead of 1 and cloud watch also shows function trigger only once. below i'm sharing my code with you any help would be very much appreciated.
index.js
const { graphql } = require("graphql");
const { schema } = require("./graphql/schema");
exports.handler = async (event) => {
// getting query from lambda event
const query = event.query;
// getting query variables from lambda event
const variables = event.variables;
return await graphql(schema, query, null, null, variables);
};
sqs.js
const AWS = require("aws-sdk");
AWS.config.update({ region: "us-east-1"});
// Create an SQS service object
const sqs = new AWS.SQS({apiVersion: '2012-11-05', "accessKeyId": process.env.ACCESS_KEY_ID, "secretAccessKey": process.env.SECRET_ACCESS_KEY});
const QueueUrl = process.env.SQS_QUEUE_URL;
const sendPayloadToSQS = message => {
const params = {
MessageBody: JSON.stringify(message),
QueueUrl
};
await sqs.sendMessage(params, function(err, data) {
if (err) {
console.log("Message sending failed : ", err);
} else {
console.log("Message queued to SQS successfully : ", data.MessageId);
}
}).promise();
};
module.exports = sendPayloadToSQS;
graphql mutation file
const { GraphQLNonNull } = require("graphql");
const { mutationWithClientMutationId } = require("../../common");
const { JobRequestEventResponse } = require("../jobRequestEventResponse");
const { JobRequestInput, JobEventMetadataInput } = require("../jobSchema");
const sendPayloadToSQS = require("../../../sqs");
const { newId } = require("../../../newId");
const JobRequestEvent = mutationWithClientMutationId({
name: "JobRequestEvent",
inputFields: {
eventMetadataInput: {
type: new GraphQLNonNull(JobEventMetadataInput),
},
eventInput: {
type: new GraphQLNonNull(JobRequestInput),
},
},
outputFields: {
JobRequestEventResponse: {
type: JobRequestEventResponse,
},
},
mutateAndGetPayload: async (params) => {
const new_id = newId();
if(params.eventInput.jobId === null || params.eventInput.jobId === undefined) {
params.eventInput.jobId = new_id;
}
const payload = {
_id: new_id,
transactionId: new_id,
name: params.eventMetadataInput.name,
userRole: params.eventMetadataInput.userRole,
date: params.eventMetadataInput.date,
languageCode: params.eventMetadataInput.languageCode,
eventInput: params.eventInput,
};
//send payload to sqs
await sendPayloadToSQS(payload);
return {
JobRequestEventResponse: {
id: payload._id,
transactionId: payload.transactionId,
status: "Success",
},
};
},
});
module.exports = {
JobRequestEvent,
};
I read the documentation again and found the callback is the root cause of my problem: if I provide a callback to sendMessage it triggers my function and after when I write promise() again it triggers my function so I remove the callback only as you can see below.
Refer : AWS Official documentation
Instead of this:
await sqs.sendMessage(params, function(err, data) {
if (err) {
console.log("Message sending failed : ", err);
} else {
console.log("Message queued to SQS successfully : ", data.MessageId);
}
}).promise();
I write this:
const request = sqs.sendMessage(params);
const result = await request.promise();
if(result) {
console.log("Message queued to SQS successfully : ", result.MessageId);
} else {
console.log("Message queued failed");
}

How to pass parameter to event object aws lambda functions in nodejs 8.10v

I am working project there we are creating a serverless architecture for handle computation task. How to pass parameters to event object in aws lambda function.
Is there any reference link, if any please suggest.
index.js - handler function of lambda
exports.handler = (event, context, callback) => {
context.callbackWaitsForEmptyEventLoop = false;
const mysql = require("mysql");
const pool = mysql.createPool({
host: "test_db.xxxxxxxxxxx.us-east-2.rds.amazonaws.com",
user: "root",
password: "xxxxxxxx",
database: "test_db",
port: 3306
});
pool.getConnection((err, connection) => {
if (err) throw err;
// const { fund_name, returns, aum, rating, expense_ratio } = event.body; // BODY PARAMETER REMAINING
const randomNumber = () => Math.random()*10+1;
const fund_name = 'example';
const returns = randomNumber();
const aum = randomNumber();
const rating = randomNumber();
const expense_ratio = randomNumber();
if (fund_name && returns && aum && rating && expense_ratio) {
pool.getConnection((err, connection) => {
if (err) {
throw err;
}
const query = `INSERT INTO mutual_fund_tb(fund_name, returns, aum, rating, expense_ratio) VALUES ('${fund_name}', '${returns}', '${aum}', '${rating}', '${expense_ratio}')`;
connection.query(query, (err, results, fields) => {
if (err) {
throw err;
}
if (results.affectedRows === 1) {
const response = {
data: {...event.body},
message: "Data successfully inserted",
status: "ok"
};
callback(null, response);
} else {
const response = {
data: {},
message: "Data unable to insert into database.",
status: "failed"
};
callback(null, response);
}
});
});
} else {
const response = {
data: {},
message: "Invalid arguments passed. Please pass valid arguments",
status: "failed"
};
callback(null, response);
}
});
};
IF you are using API Gateway then on the method execution diagram click on the the integration Response (Integration type Lambda Function) and under that we have Body mapping template field where in you can add application/json or txt/xml and then enter the mapping manually for e.g. in our case we use application/json
{
"abc" : $input.params('$def')
}
So abc can be accessed in you lambda function and def can be passed on the url when calling the API Gateway
As of now you can use lambda proxy integration and then you don't need to provide this mapping, and still you will be able to access the parameters
aws docs

Resources