AWS-Lambda-Quick

 view release on metacpan or  search on metacpan

lib/AWS/Lambda/Quick/Upload.pm  view on Meta::CPAN

package AWS::Lambda::Quick::Upload;
use Mo qw( default required );

our $VERSION = '1.0002';

use AWS::CLIWrapper;
use JSON::PP ();

### required attributes

has zip_filename => required => 1;
has name         => required => 1;

### optional attributes wrt the lambda function itself

has extra_layers => default => [];
has region       => default => 'us-east-1';
has memory_size  => default => 128;           # this is the AWS default
has timeout      => default => 3;             # this is the AWS default
has description => default => 'A Perl AWS::Lambda::Quick Lambda function.';
has stage_name  => default => 'quick';

### lambda function computed attributes

has aws => sub {
    my $self = shift;

    return AWS::CLIWrapper->new(
        region => $self->region,
    );
};

has zip_file_blob => sub { 'fileb://' . shift->zip_filename };

# should we create the function from scratch or just update it?
# by default we interogate the api to see if it exists already
has update_type => sub {
    my $self = shift;
    my $aws  = $self->aws;

    my $result = $aws->lambda(
        'get-function',
        {
            'function-name' => $self->name,
        }
    );

    return $result ? 'update-function' : 'create-function';
};

### role attributes

has role      => default => 'perl-aws-lambda-quick';
has _role_arn => sub {
    my $self = shift;

    # if whatever we were passed in role was an actual ARN then we
    # can just use that without any further lookups
    if ( $self->role
        =~ /^arn:(aws[a-zA-Z-]*)?:iam::\d{12}:role\/?[a-zA-Z_0-9+=,.@\-_\/]+$/
    ) {
        $self->debug('using passed role arn');
        return $self->role;
    }

    $self->debug('searching for existing role');
    my $aws    = $self->aws;
    my $result = $aws->iam(
        'get-role',
        {
            'role-name' => $self->role,
        }
    );
    if ($result) {
        $self->debug('found existing role');
        return $result->{Role}{Arn};
    }

    $self->debug('creating new role');
    $result = $self->aws_do(
        'iam',
        'create-role',
        {
            'role-name' => $self->role,
            'description' =>
                'Role for lambda functions created by AWS::Lambda::Quick. See https://metacpan.org/pod/AWS::Lambda::Quick for more info.',
            'assume-role-policy-document' => <<'JSON',
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "sts:AssumeRole",
            "Effect": "Allow",
            "Principal": {
                "Service": [
                    "lambda.amazonaws.com",
                    "apigateway.amazonaws.com"
                ]
            }
        }
    ]
}
JSON
        }
    );
    $self->debug('new role created');
    $self->debug('attaching permissions to role');
    $self->aws_do(
        'iam',
        'attach-role-policy',
        {
            'policy-arn' =>
                'arn:aws:iam::aws:policy/service-role/AWSLambdaRole',
            'role-name' => $self->role,
        }
    );
    $self->aws_do(
        'iam',
        'attach-role-policy',
        {
            'policy-arn' =>
                'arn:aws:iam::aws:policy/CloudWatchLogsFullAccess',
            'role-name' => $self->role,
        }
    );
    $self->debug('permissions attached to role');
    return $result->{Role}{Arn};
};

### rest api attributes

has rest_api    => default => 'perl-aws-lambda-quick';
has rest_api_id => sub {
    my $self = shift;

    # search existing apis
    $self->debug('searching for existing rest api');
    my $result = $self->aws_do(
        'apigateway',
        'get-rest-apis',
    );
    for ( @{ $result->{items} } ) {
        next unless $_->{name} eq $self->rest_api;
        $self->debug('found existing existing rest api');
        return $_->{id};
    }

    # couldn't find it.  Create a new one
    $self->debug('creating new rest api');
    $result = $self->aws_do(
        'apigateway',
        'create-rest-api',
        {
            name => $self->rest_api,
            description =>
                'Created by AWS::Lambda::Quick. See https://metacpan.org/pod/AWS::Lambda::Quick for more info.',
        },
    );
    $self->debug('created new rest api');
    return $result->{id};
};

has resource_id => sub {
    my $self = shift;

    # TODO: We shold probably make this configurable, right?
    my $path = '/' . $self->name;

    # search existing resources
    $self->debug('searching of existing resource');
    my $result = $self->aws_do(
        'apigateway',
        'get-resources',
        {
            'rest-api-id' => $self->rest_api_id,
        }
    );
    for ( @{ $result->{items} } ) {
        next unless $_->{path} eq $path;
        $self->debug('found exiting resource');
        return $_->{id};
    }

    # couldn't find it.  Create a new one
    $self->debug('creating new resource');
    my $parent_id;
    for ( @{ $result->{items} } ) {
        if ( $_->{path} eq '/' ) {
            $parent_id = $_->{id};
            last;
        }
    }



( run in 0.490 second using v1.01-cache-2.11-cpan-39bf76dae61 )