AWS-Lambda-Quick

 view release on metacpan or  search on metacpan

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

    my $parent_id;
    for ( @{ $result->{items} } ) {
        if ( $_->{path} eq '/' ) {
            $parent_id = $_->{id};
            last;
        }
    }
    unless ($parent_id) {
        die q{Can't find '/' resource to create a new resource from!};
    }
    $result = $self->aws_do(
        'apigateway',
        'create-resource',
        {
            'rest-api-id' => $self->rest_api_id,
            'parent-id'   => $parent_id,
            'path-part'   => $self->name,
        },
    );
    $self->debug('created new resource');
    return $result->{id};
};

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

    my $path = '/' . $self->name . '/{proxy+}';

    # search existing resources
    $self->debug('searching of existing greedy 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 greedy resource');
    $result = $self->aws_do(
        'apigateway',
        'create-resource',
        {
            'rest-api-id' => $self->rest_api_id,
            'parent-id'   => $self->resource_id,
            'path-part'   => '{proxy+}',
        },
    );
    $self->debug('created new greedy resource');
    return $result->{id};
};

### methods

sub upload {
    my $self = shift;

    my $function_arn = $self->_upload_function;

    for my $resource_id ( $self->resource_id, $self->greedy_resource_id ) {
        $self->_create_method($resource_id);
        $self->_create_method_response($resource_id);
        $self->_create_integration( $function_arn, $resource_id );
        $self->_create_integration_response($resource_id);
    }
    $self->_stage;

    return ();
}

sub api_url {
    my $self = shift;

    return
          'https://'
        . $self->rest_api_id
        . '.execute-api.'
        . $self->region
        . '.amazonaws.com/'
        . $self->stage_name . '/'
        . $self->name;
}

sub _stage {
    my $self = shift;

    $self->aws_do(
        'apigateway',
        'create-deployment',
        {
            'rest-api-id' => $self->rest_api_id,
            'stage-name'  => $self->stage_name,
        }
    );
}

sub _create_method {
    my $self        = shift;
    my $resource_id = shift;

    my @identifiers = (
        'rest-api-id' => $self->rest_api_id,
        'resource-id' => $resource_id,
        'http-method' => 'ANY',
    );

    $self->debug('checking for existing method');

    # get the current method
    my $result = $self->aws->apigateway(
        'get-method', {@identifiers},
    );

    if ($result) {
        $self->debug('found existing method');
        return ();
    }

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

        'get-integration', $identifiers,
    );
    if ($result) {
        $self->debug('found existing integration');
        return ();
    }

    $self->debug('putting new integration');
    $self->aws_do(
        'apigateway',
        'put-integration',
        {
            %{$identifiers},
            type                      => 'AWS_PROXY',
            'integration-http-method' => 'POST',
            'credential'              => $self->_role_arn,
            uri                       => $uri,
        }
    );
    $self->debug('new integration put');

    return ();
}

sub _create_integration_response {
    my $self        = shift;
    my $resource_id = shift;

    my $identifiers = {
        'rest-api-id' => $self->rest_api_id,
        'resource-id' => $resource_id,
        'http-method' => 'ANY',
        'status-code' => 200,
    };

    $self->debug('checking for existing integration response');

    # get the current method response
    my $result = $self->aws->apigateway(
        'get-integration-response', $identifiers,
    );
    if ($result) {
        $self->debug('found existing integration response');
        return ();
    }

    $self->debug('putting new integration');
    $self->aws_do(
        'apigateway',
        'put-integration-response',
        {
            %{$identifiers},
            'selection-pattern' => q{},
        }
    );
    $self->debug('new integration put');

    return ();
}

sub _upload_function {
    my $self = shift;

    my $update_type = $self->update_type;
    my $region      = $self->region;

    # compute the arn based on the list in the AWS::Lambda 0.0.11
    # documentation
    my $v      = $region eq 'me-south-1' ? 3 : 5;
    my $layers = [
        "arn:aws:lambda:$region:445285296882:layer:perl-5-30-runtime:$v",
    ];

    for my $layer ( @{ $self->extra_layers } ) {
        if ( $layer
            =~ /(arn:[a-zA-Z0-9-]+:lambda:[a-zA-Z0-9-]+:\d{12}:layer:[a-zA-Z0-9-_]+)/aa
        ) {
            push @{$layers}, $layer;
            next;
        }

        if ( $layer eq 'paws' ) {

            # compute the arn based on the list in the AWS::Lambda 0.0.11
            # documentation
            my $pv = $region eq 'me-south-1' ? 3 : 4;
            push @{$layers},
                "arn:aws:lambda:$region:445285296882:layer:perl-5-30-paws:$pv";
            next;
        }

        die "Layer '$layer' is neither a known named layer nor a layer arn";
    }

    if ( $update_type eq 'create-function' ) {
        $self->debug('creating new function');
        my $result = $self->aws_do(
            'lambda',
            'create-function',
            {
                'function-name' => $self->name,
                'role'          => $self->_role_arn,
                'region'        => $region,
                'runtime'       => 'provided',
                'zip-file'      => $self->zip_file_blob,
                'handler'       => 'handler.handler',
                'layers'        => $layers,
                'timeout'       => $self->timeout,
                'memory-size'   => $self->memory_size,
            }
        );
        $self->debug('new function created');
        return $result->{FunctionArn};
    }

    $self->debug('updating function code');
    my $result = $self->aws_do(
        'lambda',
        'update-function-code',
        {
            'function-name' => $self->name,

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

            'memory-size'   => $self->memory_size,
        }
    );
    $self->debug('function congifuration updated');
    return $result->{FunctionArn};
}

# just like $self->aws->$method but throws exception on error
sub aws_do {
    my $self   = shift;
    my $method = shift;

    my $aws    = $self->aws;
    my $result = $aws->$method(@_);

    return $result if defined $result;

    # uh oh, something went wrong, throw exception

    ## no critic (ProhibitPackageVars)
    my $code    = $AWS::CLIWrapper::Error->{Code};
    my $message = $AWS::CLIWrapper::Error->{Message};

    die "AWS CLI failure when calling $method $_[0] '$code': $message";
}

sub encode_json($) {
    return JSON::PP->new->ascii->canonical(1)->allow_nonref(1)->encode(shift);
}

sub debug {
    my $self = shift;
    return unless $ENV{AWS_LAMBDA_QUICK_DEBUG};
    for (@_) {
        print STDERR "$_\n" or die "Can't write to fh: $!";
    }
    return ();
}

sub just_update_function_code {
    my $self = shift;

    $self->aws_do(
        'lambda',
        'update-function-code',
        {
            'function-name' => $self->name,
            'zip-file'      => $self->zip_file_blob,
        },
    );

    return ();
}

1;

__END__

=head1 NAME

AWS::Lambda::Quick::Upload - upload for AWS::Lambda::Quick

=head1 DESCRIPTION

No user servicable parts.  See L<AWS::Lambda::Quick> for usage.

=head1 AUTHOR

Written by Mark Fowler B<mark@twoshortplanks.com>

Copyright Mark Fowler 2019.

This program is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.

=head1 SEE ALSO

L<AWS::Lambda::Quick>

=cut



( run in 0.733 second using v1.01-cache-2.11-cpan-b16cb0d3907 )