orangewise / s3-zip

Download selected files from an Amazon S3 bucket as a zip file

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Zipping files in S3 + localstack

mariamghalleb opened this issue · comments

Lambda function :

const AWS = require('aws-sdk')
const s3Zip = require('s3-zip')

exports.handler = function (event, context) {
    console.log('event', event)

    const region = event.region
    const bucket = event.bucket
    const folder = event.folder
    const files = event.files
    const zipFileName = event.zipFileName

    const s3Client = new aws.S3({
        signatureVersion: 'v4',
        s3ForcePathStyle: 'true',
        endpoint: 'http://localhost:4566',
    })
    
    // Create body stream
    try {

        const body = s3Zip.archive({ s3: s3Client, region: region, bucket: bucket}, folder, files)
        const zipParams = { params: { Bucket: bucket, Key: folder + zipFileName } }
        const zipFile = new AWS.S3(zipParams)
        zipFile.upload({ Body: body })
            .on('httpUploadProgress', function (evt) { console.log(evt) })
            .send(function (e, r) {
                if (e) {
                    const err = 'zipFile.upload error ' + e
                    console.log(err)
                    context.fail(err)
                }
                console.log(r)
                context.succeed(r)
            })

    } catch (e) {
        const err = 'catched error: ' + e
        console.log(err)
        context.fail(err)
    }

}

PHP (to invoke the function)

public function downloadFontsZip(array $s3Paths): StreamedResponse
    {
        $credentials = new Credentials('xxx', 'xxx');
        $client = LambdaClient::factory([
            'credentials' => $credentials,
            'version' => 'latest',
            'region' => env('AWS_DEFAULT_REGION'),
            'endpoint' => env('LOCALSTACK_ENDPOINT'),
            'use_path_style_endpoint' => true,
        ]);
        
        
        $files =   array('file.png', 'file2.png');
        $payload = [
          'region' => env('AWS_DEFAULT_REGION'),
          'bucket' => $this->bucket,
          'folder' => 'Images/',
          'files' => $files,
          'zipFileName' => 'bla.zip',
        ]; 
                
        $result = $client->invoke([
            // The name your created Lamda function
            'FunctionName' => 'functiontest',
            'Payload' => json_encode($payload),
        ]);

        var_dump(json_decode((string) $result->get('Payload'))) ; exit;

docker-composer.yml (localstack part)

Localstack Service

  localstack:
    container_name: localstack
    image: localstack/localstack:0.11.0
    hostname: localhost
    ports:
      - "4566:4566"
    environment:
      - SERVICES=s3,lambda,iam
      - DEBUG=1
      - DATA_DIR=/tmp/localstack/data
      - DOCKER_HOST=unix:///var/run/docker.sock
      - HOST_TMP_FOLDER=/tmp/localstack/data
      - DEFAULT_REGION=eu-central-1
      - LAMBDA_EXECUTOR=docker
      - LAMBDA_DOCKER_NETWORK=website-network
      - HOSTNAME_EXTERNAL=http://localstack
      - S3_PORT_EXTERNAL=4566
    volumes:
      - "../website-setup/.localstack:/tmp/localstack"
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "../website-setup/bin:/docker-entrypoint-initaws.d"
      - "../website-setup/uploads:/uploads"

localstack-entrypoint-initlaws.d (lambda part)

aws iam create-role --role-name roleforlambda \
 --assume-role-policy-document file:///uploads/functions/roles/trust.json \
 --description "roleforlambda desc" \
 --endpoint-url=http://localhost:4566

aws lambda create-function \
  --function-name functiontest \
  --endpoint-url=http://localhost:4566 \
  --runtime nodejs10.x \
  --zip-file fileb:///uploads/functions/test.zip \
  --handler index.handler \
  --role arn:aws:iam::000000000000:role/roleforlambda

trust.json (for the role)

{
  "Version": "2021-03-30",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "s3:*",
      "Resource": "arn:aws:s3:::*"
    }
  ]
}

Expected Behavior:

Zip files that already exist in S3 and save the zip in s3.

Actual Behavior:

Error executing Lambda function arn:aws:lambda:eu-central-1:000000000000:functiontest: Lambda process returned error
status code: 1. Result: {"errorType":"string","errorMessage":"zipFile.upload error CredentialsError: Missing credentials
in config, if using AWS_CONFIG_FILE, set AWS_SDK_LOAD_CONFIG=1"}. Output:
�[32mSTART RequestId: 7a105d11-ba6c-1de9-1da1-1b112d64bd11 Version: $LATEST�[0m

If I update the lambda function like follows:


    const s3Client = new AWS.S3({
        signatureVersion: 'v4',
        s3ForcePathStyle: 'true',
        accessKeyId: 'xxx',
        secretAccessKey: 'xxx',
        endpoint: 'http://localhost::4566',
    })

The error becomes:

Error executing Lambda function arn:aws:lambda:eu-central-1:000000000000:function:functiontest: Lambda process returned error
status code: 1. Result: {"errorType":"string","errorMessage":"zipFile.upload error NoSuchKey: The specified key does not
exist."}. Output:
�[32mSTART RequestId: dd7e4498-64cf-185a-bff7-83b18a8b8df4 Version: $LATEST

@mariamghalleb how did you fix this, ive followed the guide exactly with the same result.