Abdelrahman Shahda
Abdelrahman Shahda

Reputation: 91

My lambda function isn't working properly

Im trying to make lambda compress all the images uploaded to a certain file in my bucket so here what i did :

  1. I created a lambda function with prefix : myfile/*/

  2. I deployed my nodejs code


//Import compress module
const imagemin = require('imagemin');
const imageminMozjpeg = require('imagemin-mozjpeg');
const sharp = require('sharp');

const AWS = require('aws-sdk')

const s3 = new AWS.S3()
exports.handler = async (event) =>{
    // TODO implement
    
    const srcBucket = event.Records[0].s3.bucket.name;
    
    const srcKey    = decodeURIComponent(event.Records[0].s3.object.key.replace(/\+/g, " "));
    const dstBucket = "safarni";
    const dstKey    =  srcKey;
    
    console.log(srcKey, dstBucket, dstKey)
     // Download the image from the S3 source bucket. 
    try {
        const params = {
            Bucket: srcBucket,
            Key: srcKey
        };
        var origimage = await s3.getObject(params).promise();

    } catch (error) {
        console.log(error);
        return;
    }  
    console.log('here')
    const jpgBuffer = sharp(origimage.Body).toBuffer().jpeg().toBuffer()
    
    //Compressing the photo
        const compressedjpgBuffer = await imagemin.buffer(jpgBuffer, {
            plugins: [imageminMozjpeg({ quality: 85 })]
        })
        
    // Upload the thumbnail image to the destination bucket
    try {
        const destparams = {
            Bucket: dstBucket,
            Key: dstKey,
            Body: compressedjpgBuffer,
            ContentType: "image"
        };

        const putResult = await s3.putObject(destparams).promise(); 
        
    } catch (error) {
        console.log(error);
        return;
    } 
        
    console.log('Successfully resized ' + srcBucket + '/' + srcKey +
        ' and uploaded to ' + dstBucket + '/' + dstKey); 
    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};

  1. I added a role to lambda with the following policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:*"
            ],
            "Resource": "arn:aws:logs:*:*:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::*"
        }
    ]
}
  1. I made my source bucket public so that i can easily access it but i added a policy in my destination bucket as follow
{
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::272222288325:role/LambdaRole" //Role i assigned to my lambda function
            },
            "Action": [
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::safarni/*"
        }

Error: For some reason it isn't invoking and i can't find out why so I would really appreciate any help

Edit Lambda settings enter image description here

My role policy enter image description here

Upvotes: 0

Views: 584

Answers (3)

Chris Williams
Chris Williams

Reputation: 35146

If you have used a prefix of myfile/*/ this won't get invoked. You should have the prefix as myfile/ and not myfile/*.

This will of course also trigger for any files that exist in the myfile prefix, but it is also recursive so any object with keys that start with myfile will also be included such as:

  • myfile/test.txt
  • myfile/test/test.txt
  • myfile/test/test2/test2.txt

An S3 object name is its key, the / character just displays as if the structure of the S3 bucket contains a nested subfolder structure but in fact it is just listing objects by prefix.

Upvotes: 1

Markonick
Markonick

Reputation: 328

I might be wrong but my first guess is that you might be missing a lambda invocation action in your statement? Something like this:

"Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": "*"
        },

Upvotes: 1

AppleCiderGuy
AppleCiderGuy

Reputation: 1287

you need to provide invoke permissions to your bucket like so:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowS3ToABCFunction",
      "Effect": "Allow",
      "Action": "lambda:InvokeFunction",
      "Resource": "arn:aws:lambda:<region>:<account>:function:<function_name>"
    }
   ]
}

checkout this link for more details.

Also, in your question, I didn't see any steps to setup a trigger from s3 to lambda. you may wanna follow this link for an example.

Upvotes: 1

Related Questions