Repository: localstack/localstack

Issue:
When deploying a service with errors using a custom deployment bucket, lambdas appear to already exist
When trying to deploy a serverless service that does not currently deploy correctly onto localstack using a custom deployment bucket, the lambdas seems to be created regardless (???) but not as part of the stack, with localstack outputting `botocore.errorfactory.ResourceConflictException: An error occurred (ResourceConflictException) when calling the CreateFunction operation: Function already exist` .

For example, the `serverless.yml` below would currently fail to deploy due to  #1676 , but because a `deploymentBucket` was added, it will instead fail due to `Function already exist`. Subsequently removing `deploymentBucket` or even `events` from the the file will not allow it to deploy - it will fail until localstack is restarted ( or until the lambda is manually deleted?).

I've also reproduced this with services suffering from #1675. 

```yaml
service: "localtest"

provider:
  name: "aws"
  runtime: "nodejs10.x"
  deploymentBucket:
    name: "testbucket"

functions:
  hello:
    handler: "handler.hello"
    events:
      - schedule: "cron(0 * * * ? *)"

plugins:
- "serverless-localstack"

custom:
  localstack:
    stages:
      - "local"
```


Discussion:
Hi @Jaystified , can you please try with the `latest` version. When I try to deploy your sample in a fresh LocalStack instance, I get a `ServerlessError: Could not locate deployment bucket. Error: The specified bucket does not exist` (which is expected).

It does work, however, if `serverless-deployment-bucket` gets added to the list of plugins:
```
plugins:
  - serverless-localstack
  - serverless-deployment-bucket
```
I should've clarified: The deployment bucket should actually exist in localstack (I create it using `awslocal s3api create-bucket --bucket testbucket` before using `sls deploy`).

The issue is still present with the latest version (it seems to require another error to manifest). 

The following `serverless.yml` will reproduce it with today's update(using #1675):

```yaml
service: "localtest"

provider:
  name: "aws"
  runtime: "nodejs10.x"
  deploymentBucket:
    name: "testbucket"

functions:
  hello:
    handler: "handler.hello"

resources:
  Resources:
    ApiGatewayRestApi:
      Type: "AWS::ApiGateway::RestApi"
      Properties:
        Name: "${self:provider.stage}-${self:service}"
    GatewayResponseDefault400:
      Type: "AWS::ApiGateway::GatewayResponse"
      Properties:
        RestApiId:
          Ref: "ApiGatewayRestApi"
        ResponseType: "DEFAULT_4XX"
        ResponseTemplates:
          application/json: '{"errors":[{"message":"Custom text."}]}'

plugins:
  - "serverless-localstack"

custom:
  localstack:
    stages:
      - "local"
```

This issue also comes up with #1682 . 
The main problem with this issue is that is hides other problems and makes debugging difficult.
I am still experiencing this issue.

Here's another example:
```yaml
service: "localtest"

provider:
  name: "aws"
  runtime: "nodejs10.x"
  deploymentBucket:
    name: "testbucket"

functions:
  hello:
    handler: "handler.hello"
    events:
    - sns:
        arn: "arn:aws:sns:us-west-2:111111111:foo"
plugins:
  - "serverless-localstack"

custom:
  localstack:
    stages:
      - "local"
```
The `testbucket` bucket is created beforehand.
The SNS topic is **NOT** created and is left missing on purpose.

On AWS, this fails to deploy due to a validation error.
On localstack it is a generic "500" due to "Function already exist".
> On AWS, this fails to deploy due to a validation error.
> On localstack it is a generic "500" due to "Function already exist".

@Jaystified Good point, thanks. Seems to be a slightly different issue, but will be fixed shortly. Does the example above work for you now? Here is a small project that contains a few of the samples you reported. It works for the latest version under Mac - can you also run it successfully? https://github.com/localstack/localstack-pro-samples/tree/master/serverless-lambda-layers
> https://github.com/localstack/localstack-pro-samples/tree/master/serverless-lambda-layers

Does not work for me, but likely due to a different issue:
```
$ awslocal s3api create-bucket --bucket testbucket
$ deploy --stage local
Serverless: Using serverless-localstack
Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Excluding development dependencies...
Serverless: Recoverable error occurred (Attribute without value
Line: 17
Column: 106
Char: a), sleeping for 5 seconds. Try 1 of 4
...
```
Sorry for the back and forth, looks like the latest version wasn't pushed properly. Can you try again now please @Jaystified . If the problem persists, please post the the log output from LocalStack with `DEBUG=1` enabled. Thanks

Resolving patch:
diff --git a/localstack/services/cloudformation/cloudformation_starter.py b/localstack/services/cloudformation/cloudformation_starter.py
--- a/localstack/services/cloudformation/cloudformation_starter.py
+++ b/localstack/services/cloudformation/cloudformation_starter.py
@@ -240,16 +240,19 @@ def _parse_and_create_resource(logical_id, resource_json, resources_map, region_
             resource.region_name = region_name
 
         # check whether this resource needs to be deployed
+        is_updateable = False
         if not should_be_created:
             # This resource is either not deployable or already exists. Check if it can be updated
-            if not template_deployer.is_updateable(logical_id, resource_wrapped, stack_name):
+            is_updateable = template_deployer.is_updateable(logical_id, resource_wrapped, stack_name)
+            if not update or not is_updateable:
                 LOG.debug('Resource %s need not be deployed: %s %s' % (logical_id, resource_json, bool(resource)))
-                # Return if this resource already exists and cannot be updated
+                # Return if this resource already exists and can/need not be updated
                 return resource
 
         # Apply some fixes/patches to the resource names, then deploy resource in LocalStack
         update_resource_name(resource, resource_json)
-        LOG.debug('Deploying CloudFormation resource (update=%s): %s' % (update, resource_json))
+        LOG.debug('Deploying CloudFormation resource (update=%s, exists=%s, updateable=%s): %s' %
+                  (update, not should_be_created, is_updateable, resource_json))
 
         try:
             CURRENTLY_UPDATING_RESOURCES[resource_hash_key] = True


Test patch: