Beispiel #1
0
def test_new_scope_config_is_separate_copy():
    original = Config(chalice_stage='dev', function_name='foo')
    new_config = original.scope(chalice_stage='prod', function_name='bar')

    # The original should not have been mutated.
    assert original.chalice_stage == 'dev'
    assert original.function_name == 'foo'

    assert new_config.chalice_stage == 'prod'
    assert new_config.function_name == 'bar'
Beispiel #2
0
    def test_single_role_generated_for_default_config(self,
                                                      sample_app_lambda_only):
        # The sample_app has one lambda function.
        # We'll add a few more and verify they all share the same role.
        @sample_app_lambda_only.lambda_function()
        def second(event, context):
            pass

        @sample_app_lambda_only.lambda_function()
        def third(event, context):
            pass

        config = Config.create(chalice_app=sample_app_lambda_only,
                               project_dir='.',
                               autogen_policy=True,
                               api_gateway_stage='api')
        template = self.generate_template(config, 'dev')
        roles = [resource for resource in template['Resources'].values()
                 if resource['Type'] == 'AWS::IAM::Role']
        assert len(roles) == 1
        # The lambda functions should all reference this role.
        functions = [
            resource for resource in template['Resources'].values()
            if resource['Type'] == 'AWS::Serverless::Function'
        ]
        role_names = [
            function['Properties']['Role'] for function in functions
        ]
        assert role_names == [
            {'Fn::GetAtt': ['DefaultRole', 'Arn']},
            {'Fn::GetAtt': ['DefaultRole', 'Arn']},
            {'Fn::GetAtt': ['DefaultRole', 'Arn']},
        ]
Beispiel #3
0
def test_can_create_app_packager_with_no_autogen():
    # We can't actually observe a change here, but we want
    # to make sure the function can handle this param being
    # False.
    config = Config.create(autogen_policy=False)
    packager = package.create_app_packager(config)
    assert isinstance(packager, package.AppPackager)
def test_validation_error_if_no_role_provided_when_manage_false(sample_app):
    # We're indicating that we should not be managing the
    # IAM role, but we're not giving a role ARN to use.
    # This is a validation error.
    config = Config.create(chalice_app=sample_app, manage_iam_role=False)
    with pytest.raises(ValueError):
        validate_configuration(config)
Beispiel #5
0
 def test_tags_specified_does_not_override_chalice_tag(self):
     c = Config.create(
         chalice_stage='dev', app_name='myapp',
         tags={'aws-chalice': 'attempted-override'})
     assert c.tags == {
         'aws-chalice': 'version=%s:stage=dev:app=myapp' % chalice_version,
     }
Beispiel #6
0
def test_can_create_scope_obj_with_new_function():
    disk_config = {
        'lambda_timeout': 10,
        'stages': {
            'dev': {
                'manage_iam_role': True,
                'iam_role_arn': 'role-arn',
                'autogen_policy': True,
                'iam_policy_file': 'policy.json',
                'environment_variables': {'env': 'stage'},
                'lambda_timeout': 1,
                'lambda_memory_size': 1,
                'tags': {'tag': 'stage'},
                'lambda_functions': {
                    'api_handler': {
                        'lambda_timeout': 30,
                    },
                    'myauth': {
                        # We're purposefully using different
                        # values for everything in the stage
                        # level config to ensure we can pull
                        # from function scoped config properly.
                        'manage_iam_role': True,
                        'iam_role_arn': 'auth-role-arn',
                        'autogen_policy': True,
                        'iam_policy_file': 'function.json',
                        'environment_variables': {'env': 'function'},
                        'lambda_timeout': 2,
                        'lambda_memory_size': 2,
                        'tags': {'tag': 'function'},
                    }
                }
            }
        }
    }
    c = Config(chalice_stage='dev', config_from_disk=disk_config)
    new_config = c.scope(chalice_stage='dev',
                         function_name='myauth')
    assert new_config.manage_iam_role
    assert new_config.iam_role_arn == 'auth-role-arn'
    assert new_config.autogen_policy
    assert new_config.iam_policy_file == 'function.json'
    assert new_config.environment_variables == {'env': 'function'}
    assert new_config.lambda_timeout == 2
    assert new_config.lambda_memory_size == 2
    assert new_config.tags['tag'] == 'function'
Beispiel #7
0
def new_project(project_name, profile):
    # type: (str, str) -> None
    if project_name is None:
        project_name = getting_started_prompt(click)
    if os.path.isdir(project_name):
        click.echo("Directory already exists: %s" % project_name, err=True)
        raise click.Abort()
    create_new_project_skeleton(project_name, profile)
    validate_python_version(Config.create())
Beispiel #8
0
def test_can_create_scope_new_stage_and_function(stage_name, function_name,
                                                 expected):
    disk_config = {
        'environment_variables': {'from': 'global'},
        'stages': {
            'dev': {
                'environment_variables': {'from': 'dev-stage'},
                'lambda_functions': {
                    'api_handler': {
                        'environment_variables': {
                            'from': 'dev-api-handler',
                        }
                    },
                    'myauth': {
                        'environment_variables': {
                            'from': 'dev-myauth',
                        }
                    }
                }
            },
            'beta': {
                'environment_variables': {'from': 'beta-stage'},
                'lambda_functions': {
                    'api_handler': {
                        'environment_variables': {
                            'from': 'beta-api-handler',
                        }
                    },
                    'myauth': {
                        'environment_variables': {
                            'from': 'beta-myauth',
                        }
                    }
                }
            },
            'prod': {
                'environment_variables': {'from': 'prod-stage'},
            }
        }
    }
    c = Config(chalice_stage='dev', config_from_disk=disk_config)
    new_config = c.scope(chalice_stage=stage_name,
                         function_name=function_name)
    assert new_config.environment_variables == {'from': expected}
Beispiel #9
0
 def test_can_generate_rest_api(self, sample_app_with_auth):
     config = Config.create(chalice_app=sample_app_with_auth,
                            project_dir='.',
                            api_gateway_stage='api')
     template = self.generate_template(config, 'dev')
     resources = template['Resources']
     # Lambda function should be created.
     assert resources['APIHandler']['Type'] == 'AWS::Serverless::Function'
     # Along with permission to invoke from API Gateway.
     assert resources['APIHandlerInvokePermission'] == {
         'Type': 'AWS::Lambda::Permission',
         'Properties': {
             'Action': 'lambda:InvokeFunction',
             'FunctionName': {'Ref': 'APIHandler'},
             'Principal': 'apigateway.amazonaws.com',
             'SourceArn': {
                 'Fn::Sub': [
                     ('arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}'
                      ':${RestAPIId}/*'),
                     {'RestAPIId': {'Ref': 'RestAPI'}}]}},
     }
     assert resources['RestAPI']['Type'] == 'AWS::Serverless::Api'
     # We should also create the auth lambda function.
     assert resources['Myauth']['Type'] == 'AWS::Serverless::Function'
     # Along with permission to invoke from API Gateway.
     assert resources['MyauthInvokePermission'] == {
         'Type': 'AWS::Lambda::Permission',
         'Properties': {
             'Action': 'lambda:InvokeFunction',
             'FunctionName': {'Fn::GetAtt': ['Myauth', 'Arn']},
             'Principal': 'apigateway.amazonaws.com',
             'SourceArn': {
                 'Fn::Sub': [
                     ('arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}'
                      ':${RestAPIId}/*'),
                     {'RestAPIId': {'Ref': 'RestAPI'}}]}},
     }
     # Also verify we add the expected outputs when using
     # a Rest API.
     assert template['Outputs'] == {
         'APIHandlerArn': {
             'Value': {
                 'Fn::GetAtt': ['APIHandler', 'Arn']
             }
         },
         'APIHandlerName': {'Value': {'Ref': 'APIHandler'}},
         'EndpointURL': {
             'Value': {
                 'Fn::Sub': (
                     'https://${RestAPI}.execute-api.'
                     '${AWS::Region}.amazonaws.com/api/'
                 )
             }
         },
         'RestAPIId': {'Value': {'Ref': 'RestAPI'}}
     }
Beispiel #10
0
def test_preconfigured_policy_proxies():
    policy_gen = mock.Mock(spec=ApplicationPolicyHandler)
    config = Config.create(project_dir='project_dir', autogen_policy=False)
    generator = package.PreconfiguredPolicyGenerator(
        config, policy_gen=policy_gen)
    policy_gen.generate_policy_from_app_source.return_value = {
        'policy': True}
    policy = generator.generate_policy_from_app_source()
    policy_gen.generate_policy_from_app_source.assert_called_with(config)
    assert policy == {'policy': True}
Beispiel #11
0
def test_will_create_outdir_if_needed(tmpdir):
    appdir = _create_app_structure(tmpdir)
    outdir = str(appdir.join('outdir'))
    config = Config.create(project_dir=str(appdir),
                           chalice_app=sample_app())
    p = package.create_app_packager(config)
    p.package_app(config, str(outdir))
    contents = os.listdir(str(outdir))
    assert 'deployment.zip' in contents
    assert 'sam.json' in contents
Beispiel #12
0
def test_will_create_outdir_if_needed(tmpdir):
    appdir = _create_app_structure(tmpdir)
    outdir = str(appdir.join('outdir'))
    default_params = {'autogen_policy': True}
    config = Config.create(project_dir=str(appdir),
                           chalice_app=sample_app(),
                           **default_params)
    p = package.create_app_packager(config)
    p.package_app(config, str(outdir), 'dev')
    contents = os.listdir(str(outdir))
    assert 'deployment.zip' in contents
    assert 'sam.json' in contents
Beispiel #13
0
def test_validate_names_across_function_types(sample_app):
    @sample_app.lambda_function()
    def foo(event, context):
        pass

    @sample_app.schedule('rate(1 hour)', name='foo')
    def bar(event):
        pass

    config = Config.create(chalice_app=sample_app, manage_iam_role=False)
    with pytest.raises(ValueError):
        validate_unique_function_names(config)
Beispiel #14
0
def test_validate_names_using_name_kwarg(sample_app):
    @sample_app.authorizer(name='duplicate')
    def foo(auth_request):
        pass

    @sample_app.lambda_function(name='duplicate')
    def bar(event):
        pass

    config = Config.create(chalice_app=sample_app, manage_iam_role=False)
    with pytest.raises(ValueError):
        validate_unique_function_names(config)
Beispiel #15
0
def test_default_function_memory_size(sample_app,
                                      mock_swagger_generator,
                                      mock_policy_generator):
    p = package.SAMTemplateGenerator(
        mock_swagger_generator, mock_policy_generator)
    mock_swagger_generator.generate_swagger.return_value = {
        'swagger': 'document'
    }
    config = Config.create(chalice_app=sample_app, api_gateway_stage='dev')
    template = p.generate_sam_template(config)
    properties = template['Resources']['APIHandler']['Properties']
    assert properties['MemorySize'] == 128
Beispiel #16
0
def test_timeout_added_to_function(sample_app,
                                   mock_swagger_generator,
                                   mock_policy_generator):
    p = package.SAMTemplateGenerator(
        mock_swagger_generator, mock_policy_generator)
    mock_swagger_generator.generate_swagger.return_value = {
        'swagger': 'document'
    }
    config = Config.create(chalice_app=sample_app, api_gateway_stage='dev',
                           app_name='myapp', lambda_timeout=240)
    template = p.generate_sam_template(config)
    properties = template['Resources']['APIHandler']['Properties']
    assert properties['Timeout'] == 240
Beispiel #17
0
def test_sam_injects_swagger_doc(sample_app,
                                 mock_swagger_generator,
                                 mock_policy_generator):
    p = package.SAMTemplateGenerator(mock_swagger_generator,
                                      mock_policy_generator)
    mock_swagger_generator.generate_swagger.return_value = {
        'swagger': 'document'
    }
    config = Config.create(chalice_app=sample_app,
                           api_gateway_stage='dev')
    template = p.generate_sam_template(config)
    properties = template['Resources']['RestAPI']['Properties']
    assert properties['DefinitionBody'] == {'swagger': 'document'}
Beispiel #18
0
def test_can_create_app_packager_with_no_autogen(tmpdir):
    appdir = _create_app_structure(tmpdir)

    outdir = tmpdir.mkdir('outdir')
    config = Config.create(project_dir=str(appdir),
                           chalice_app=sample_app())
    p = package.create_app_packager(config)
    p.package_app(config, str(outdir))
    # We're not concerned with the contents of the files
    # (those are tested in the unit tests), we just want to make
    # sure they're written to disk and look (mostly) right.
    contents = os.listdir(str(outdir))
    assert 'deployment.zip' in contents
    assert 'sam.json' in contents
Beispiel #19
0
    def test_helpful_error_message_on_s3_event(self, sample_app):
        @sample_app.on_s3_event(bucket='foo')
        def handler(event):
            pass

        config = Config.create(chalice_app=sample_app,
                               project_dir='.',
                               api_gateway_stage='api')
        with pytest.raises(NotImplementedError) as excinfo:
            self.generate_template(config, 'dev')
        # Should mention the decorator name.
        assert '@app.on_s3_event' in str(excinfo.value)
        # Should mention you can use `chalice deploy`.
        assert 'chalice deploy' in str(excinfo.value)
Beispiel #20
0
def test_chalice_tag_added_to_function(sample_app,
                                       mock_swagger_generator,
                                       mock_policy_generator):
    p = package.SAMTemplateGenerator(
        mock_swagger_generator, mock_policy_generator)
    mock_swagger_generator.generate_swagger.return_value = {
        'swagger': 'document'
    }
    config = Config.create(chalice_app=sample_app, api_gateway_stage='dev',
                           app_name='myapp')
    template = p.generate_sam_template(config)
    properties = template['Resources']['APIHandler']['Properties']
    assert properties['Tags'] == {
        'aws-chalice': 'version=%s:stage=dev:app=myapp' % chalice_version}
Beispiel #21
0
def test_sam_generates_sam_template_basic(sample_app,
                                          mock_swagger_generator,
                                          mock_policy_generator):
    p = package.SAMTemplateGenerator(mock_swagger_generator,
                                     mock_policy_generator)
    config = Config.create(chalice_app=sample_app,
                           api_gateway_stage='dev')
    template = p.generate_sam_template(config, 'code-uri')
    # Verify the basic structure is in place.  The specific parts
    # are validated in other tests.
    assert template['AWSTemplateFormatVersion'] == '2010-09-09'
    assert template['Transform'] == 'AWS::Serverless-2016-10-31'
    assert 'Outputs' in template
    assert 'Resources' in template
Beispiel #22
0
def test_validate_unique_lambda_function_names(sample_app):
    @sample_app.lambda_function()
    def foo(event, context):
        pass

    # This will cause a validation error because
    # 'foo' is already registered as a lambda function.
    @sample_app.lambda_function(name='foo')
    def bar(event, context):
        pass

    config = Config.create(chalice_app=sample_app, manage_iam_role=False)
    with pytest.raises(ValueError):
        validate_unique_function_names(config)
Beispiel #23
0
def test_env_vars_set_in_local(runner, mock_cli_factory,
                               monkeypatch):
    local_server = mock.Mock(spec=local.LocalDevServer)
    mock_cli_factory.create_local_server.return_value = local_server
    mock_cli_factory.create_config_obj.return_value = Config.create(
        project_dir='.', environment_variables={'foo': 'bar'})
    actual_env = {}
    monkeypatch.setattr(os, 'environ', actual_env)
    with runner.isolated_filesystem():
        cli.create_new_project_skeleton('testproject')
        os.chdir('testproject')
        _run_cli_command(runner, cli.local, [],
                         cli_factory=mock_cli_factory)
        assert actual_env['foo'] == 'bar'
Beispiel #24
0
def test_can_lazy_load_chalice_app():

    app = Chalice(app_name='foo')
    calls = []

    def call_recorder(*args, **kwargs):
        calls.append((args, kwargs))
        return app

    c = Config.create(chalice_app=call_recorder)
    # Accessing the property multiple times will only
    # invoke the call once.
    assert isinstance(c.chalice_app, Chalice)
    assert isinstance(c.chalice_app, Chalice)
    assert len(calls) == 1
Beispiel #25
0
def test_role_arn_added_to_function(sample_app,
                                    mock_swagger_generator,
                                    mock_policy_generator):
    p = package.SAMTemplateGenerator(
        mock_swagger_generator, mock_policy_generator)
    mock_swagger_generator.generate_swagger.return_value = {
        'swagger': 'document'
    }
    config = Config.create(
        chalice_app=sample_app, api_gateway_stage='dev', app_name='myapp',
        manage_iam_role=False, iam_role_arn='role-arn')
    template = p.generate_sam_template(config)
    properties = template['Resources']['APIHandler']['Properties']
    assert properties['Role'] == 'role-arn'
    assert 'Policies' not in properties
Beispiel #26
0
def test_sam_injects_policy(sample_app,
                            mock_swagger_generator,
                            mock_policy_generator):
    p = package.SAMTemplateGenerator(mock_swagger_generator,
                                     mock_policy_generator)

    mock_policy_generator.generate_policy_from_app_source.return_value = {
        'iam': 'policy',
    }
    config = Config.create(chalice_app=sample_app,
                           api_gateway_stage='dev')
    template = p.generate_sam_template(config)
    assert template['Resources']['APIHandler']['Properties']['Policies'] == [{
        'iam': 'policy',
    }]
    assert 'Role' not in template['Resources']['APIHandler']['Properties']
Beispiel #27
0
def test_maps_python_version(sample_app,
                             mock_swagger_generator,
                             mock_policy_generator):
    p = package.SAMTemplateGenerator(
        mock_swagger_generator, mock_policy_generator)
    mock_swagger_generator.generate_swagger.return_value = {
        'swagger': 'document'
    }
    config = Config.create(
        chalice_app=sample_app,
        api_gateway_stage='dev',
    )
    template = p.generate_sam_template(config)
    expected = config.lambda_python_version
    actual = template['Resources']['APIHandler']['Properties']['Runtime']
    assert actual == expected
Beispiel #28
0
    def test_vpc_config_added_to_function(self, sample_app_lambda_only):
        config = Config.create(chalice_app=sample_app_lambda_only,
                               project_dir='.',
                               autogen_policy=True,
                               api_gateway_stage='api',
                               security_group_ids=['sg1', 'sg2'],
                               subnet_ids=['sn1', 'sn2'])
        template = self.generate_template(config, 'dev')
        resources = template['Resources'].values()
        lambda_fns = [resource for resource in resources
                      if resource['Type'] == 'AWS::Serverless::Function']
        assert len(lambda_fns) == 1

        vpc_config = lambda_fns[0]['Properties']['VpcConfig']
        assert vpc_config['SubnetIds'] == ['sn1', 'sn2']
        assert vpc_config['SecurityGroupIds'] == ['sg1', 'sg2']
Beispiel #29
0
def test_endpoint_url_reflects_apig_stage(sample_app,
                                          mock_swagger_generator,
                                          mock_policy_generator):
    p = package.SAMTemplateGenerator(
        mock_swagger_generator, mock_policy_generator)
    mock_swagger_generator.generate_swagger.return_value = {
        'swagger': 'document'
    }
    config = Config.create(
        chalice_app=sample_app,
        api_gateway_stage='prod',
    )
    template = p.generate_sam_template(config)
    endpoint_url = template['Outputs']['EndpointURL']['Value']['Fn::Sub']
    assert endpoint_url == (
        'https://${RestAPI}.execute-api.${AWS::Region}.amazonaws.com/prod/')
Beispiel #30
0
 def test_sam_generates_sam_template_basic(self, sample_app):
     config = Config.create(chalice_app=sample_app,
                            project_dir='.',
                            api_gateway_stage='api')
     template = self.generate_template(config, 'dev')
     # Verify the basic structure is in place.  The specific parts
     # are validated in other tests.
     assert template['AWSTemplateFormatVersion'] == '2010-09-09'
     assert template['Transform'] == 'AWS::Serverless-2016-10-31'
     assert 'Outputs' in template
     assert 'Resources' in template
     assert list(sorted(template['Resources'])) == [
         'APIHandler', 'APIHandlerInvokePermission',
         # This casing on the ApiHandlerRole name is unfortunate, but the 3
         # other resources in this list are hardcoded from the old deployer.
         'ApiHandlerRole',
         'RestAPI',
     ]
Beispiel #31
0
def test_env_vars_chain_merge():
    config_from_disk = {
        'environment_variables': {
            'top_level': 'foo',
            'shared_key': 'from-top',
        },
        'stages': {
            'prod': {
                'environment_variables': {
                    'stage_var': 'bar',
                    'shared_key': 'from-stage',
                }
            }
        }
    }
    c = Config('prod', config_from_disk=config_from_disk)
    resolved = c.environment_variables
    assert resolved == {
        'top_level': 'foo',
        'stage_var': 'bar',
        'shared_key': 'from-stage',
    }
Beispiel #32
0
 def create_config_obj(self, chalice_stage_name=DEFAULT_STAGE_NAME,
                       autogen_policy=True, api_gateway_stage=None):
     # type: (str, bool, Optional[str]) -> Config
     user_provided_params = {}  # type: Dict[str, Any]
     default_params = {'project_dir': self.project_dir}
     try:
         config_from_disk = self.load_project_config()
     except (OSError, IOError):
         raise RuntimeError("Unable to load the project config file. "
                            "Are you sure this is a chalice project?")
     self._validate_config_from_disk(config_from_disk)
     app_obj = self.load_chalice_app()
     user_provided_params['chalice_app'] = app_obj
     if autogen_policy is not None:
         user_provided_params['autogen_policy'] = autogen_policy
     if self.profile is not None:
         user_provided_params['profile'] = self.profile
     if api_gateway_stage is not None:
         user_provided_params['api_gateway_stage'] = api_gateway_stage
     config = Config(chalice_stage_name, user_provided_params,
                     config_from_disk, default_params)
     return config
Beispiel #33
0
    def test_can_package_sqs_handler(self, sample_app):
        @sample_app.on_sqs_message(queue='foo', batch_size=5)
        def handler(event):
            pass

        config = Config.create(chalice_app=sample_app,
                               project_dir='.',
                               api_gateway_stage='api')
        template = self.generate_template(config, 'dev')
        sns_handler = template['Resources']['Handler']
        assert sns_handler['Properties']['Events'] == {
            'HandlerSqsEventSource': {
                'Type': 'SQS',
                'Properties': {
                    'Queue': {
                        'Fn::Sub':
                        ('arn:aws:sqs:${AWS::Region}:${AWS::AccountId}:foo')
                    },
                    'BatchSize': 5,
                },
            }
        }
Beispiel #34
0
    def test_single_role_generated_for_default_config(self,
                                                      sample_app_lambda_only):
        # The sample_app has one lambda function.
        # We'll add a few more and verify they all share the same role.
        @sample_app_lambda_only.lambda_function()
        def second(event, context):
            pass

        @sample_app_lambda_only.lambda_function()
        def third(event, context):
            pass

        config = Config.create(chalice_app=sample_app_lambda_only,
                               project_dir='.',
                               autogen_policy=True,
                               api_gateway_stage='api')
        template = self.generate_template(config, 'dev')
        roles = [
            resource for resource in template['Resources'].values()
            if resource['Type'] == 'AWS::IAM::Role'
        ]
        assert len(roles) == 1
        # The lambda functions should all reference this role.
        functions = [
            resource for resource in template['Resources'].values()
            if resource['Type'] == 'AWS::Serverless::Function'
        ]
        role_names = [function['Properties']['Role'] for function in functions]
        assert role_names == [
            {
                'Fn::GetAtt': ['DefaultRole', 'Arn']
            },
            {
                'Fn::GetAtt': ['DefaultRole', 'Arn']
            },
            {
                'Fn::GetAtt': ['DefaultRole', 'Arn']
            },
        ]
Beispiel #35
0
    def test_can_package_sns_handler(self, sample_app):
        @sample_app.on_sns_message(topic='foo')
        def handler(event):
            pass

        config = Config.create(chalice_app=sample_app,
                               project_dir='.',
                               api_gateway_stage='api')
        template = self.generate_template(config, 'dev')
        sns_handler = template['Resources']['Handler']
        assert sns_handler['Properties']['Events'] == {
            'HandlerSnsSubscription': {
                'Type': 'SNS',
                'Properties': {
                    'Topic': {
                        'Fn::Sub': (
                            'arn:aws:sns:${AWS::Region}:${AWS::AccountId}:foo'
                        )
                    }
                },
            }
        }
Beispiel #36
0
def test_can_chain_lookup():
    user_provided_params = {
        'api_gateway_stage': 'user_provided_params',
    }

    config_from_disk = {
        'api_gateway_stage': 'config_from_disk',
        'app_name': 'config_from_disk',
    }

    default_params = {
        'api_gateway_stage': 'default_params',
        'app_name': 'default_params',
        'project_dir': 'default_params',
    }

    c = Config('dev', user_provided_params, config_from_disk, default_params)
    assert c.api_gateway_stage == 'user_provided_params'
    assert c.app_name == 'config_from_disk'
    assert c.project_dir == 'default_params'

    assert c.config_from_disk == config_from_disk
Beispiel #37
0
    def test_lambda_deployer_with_memory_size_configured(self, sample_app):
        cfg = Config.create(chalice_stage='dev',
                            app_name='myapp',
                            chalice_app=sample_app,
                            manage_iam_role=False,
                            iam_role_arn='role-arn',
                            project_dir='.',
                            lambda_memory_size=256)
        deployer = LambdaDeployer(self.aws_client, self.packager,
                                  self.prompter, self.osutils, self.app_policy)

        deployer.deploy(cfg, self.deployed_resources, 'dev')
        self.aws_client.update_function.assert_called_with(
            function_name=self.lambda_function_name,
            zip_contents=self.package_contents,
            runtime=cfg.lambda_python_version,
            tags={
                'aws-chalice':
                'version=%s:stage=dev:app=myapp' % (chalice_version),
            },
            environment_variables={},
            timeout=60,
            memory_size=256)
Beispiel #38
0
    def test_lambda_deployer_defaults(self, sample_app):
        cfg = Config.create(chalice_stage='dev',
                            app_name='myapp',
                            chalice_app=sample_app,
                            manage_iam_role=False,
                            iam_role_arn='role-arn',
                            project_dir='.')
        deployer = LambdaDeployer(self.aws_client, self.packager, None,
                                  self.osutils, self.app_policy)

        deployer.deploy(cfg, None, 'dev')
        self.aws_client.create_function.assert_called_with(
            function_name='myapp-dev',
            role_arn='role-arn',
            zip_contents=b'package contents',
            runtime=cfg.lambda_python_version,
            tags={
                'aws-chalice':
                'version=%s:stage=dev:app=myapp' % (chalice_version)
            },
            environment_variables={},
            timeout=60,
            memory_size=128)
Beispiel #39
0
    def test_managed_layer_removed_if_no_deps(self):
        function = create_function_resource('myfunction')
        function.managed_layer = models.LambdaLayer(
            resource_name='managed-layer',
            layer_name='appname-dev-managed-layer',
            runtime='python2.7',
            deployment_package=models.DeploymentPackage(
                models.Placeholder.BUILD_STAGE))
        lambda_packager = mock.Mock(spec=packager.BaseLambdaDeploymentPackager)
        layer_packager = mock.Mock(spec=packager.BaseLambdaDeploymentPackager)
        lambda_packager.create_deployment_package.return_value = 'package.zip'
        layer_packager.create_deployment_package.side_effect = \
            packager.EmptyPackageError()

        config = Config.create(project_dir='.')

        p = ManagedLayerDeploymentPackager(lambda_packager, layer_packager)
        p.handle(config, function.managed_layer)
        p.handle(config, function)
        # If the deployment package for layers would result in an empty
        # deployment package, we expect that resource to be removed, it can't
        # be created on the service.
        assert function.managed_layer is None
Beispiel #40
0
 def test_tags_merge(self):
     config_from_disk = {
         'app_name': 'myapp',
         'tags': {
             'onlyglobalkey': 'globalvalue',
             'sharedkey': 'globalvalue'
         },
         'stages': {
             'dev': {
                 'tags': {
                     'sharedkey': 'stagevalue',
                     'onlystagekey': 'stagevalue'
                 }
             }
         }
     }
     c = Config('dev', config_from_disk=config_from_disk)
     assert c.tags == {
         'onlyglobalkey': 'globalvalue',
         'sharedkey': 'stagevalue',
         'onlystagekey': 'stagevalue',
         'aws-chalice': 'version=%s:stage=dev:app=myapp' % chalice_version
     }
    def create_config_obj(self,
                          chalice_stage_name=DEFAULT_STAGE_NAME,
                          autogen_policy=None,
                          api_gateway_stage=None,
                          user_provided_params=None):
        # type: (str, Optional[bool], str, Optional[Dict[str, Any]]) -> Config
        if user_provided_params is None:
            user_provided_params = {}
        default_params = {
            'project_dir': self.project_dir,
            'api_gateway_stage': DEFAULT_APIGATEWAY_STAGE_NAME,
            'api_gateway_endpoint_type': DEFAULT_ENDPOINT_TYPE,
            'autogen_policy': True
        }
        try:
            config_from_disk = self.load_project_config()
        except (OSError, IOError):
            raise RuntimeError("Unable to load the project config file. "
                               "Are you sure this is a chalice project?")
        except ValueError as err:
            raise RuntimeError("Unable to load the project config file: %s" %
                               err)

        self._validate_config_from_disk(config_from_disk)
        if autogen_policy is not None:
            user_provided_params['autogen_policy'] = autogen_policy
        if self.profile is not None:
            user_provided_params['profile'] = self.profile
        if api_gateway_stage is not None:
            user_provided_params['api_gateway_stage'] = api_gateway_stage
        config = Config(chalice_stage=chalice_stage_name,
                        user_provided_params=user_provided_params,
                        config_from_disk=config_from_disk,
                        default_params=default_params)
        user_provided_params['chalice_app'] = functools.partial(
            self.load_chalice_app, config.environment_variables)
        return config
Beispiel #42
0
def test_lambda_deployer_repeated_deploy():
    osutils = InMemoryOSUtils({'packages.zip': b'package contents'})
    aws_client = mock.Mock(spec=TypedAWSClient)
    packager = mock.Mock(spec=LambdaDeploymentPackager)

    packager.deployment_package_filename.return_value = 'packages.zip'
    # Given the lambda function already exists:
    aws_client.lambda_function_exists.return_value = True
    # And given we don't want chalice to manage our iam role for the lambda
    # function:
    cfg = Config({'chalice_app': sample_app, 'manage_iam_role': False,
                  'app_name': 'appname', 'iam_role_arn': True,
                  'project_dir': './myproject'})

    d = LambdaDeployer(aws_client, packager, None, osutils)
    # Doing a lambda deploy:
    d.deploy(cfg)

    # Should result in injecting the latest app code.
    packager.inject_latest_app.assert_called_with('packages.zip', './myproject')

    # And should result in the lambda function being updated with the API.
    aws_client.update_function_code.assert_called_with(
        'appname', 'package contents')
Beispiel #43
0
def test_lambda_deployer_repeated_deploy(app_policy, sample_app):
    osutils = InMemoryOSUtils({'packages.zip': b'package contents'})
    aws_client = mock.Mock(spec=TypedAWSClient)
    packager = mock.Mock(spec=LambdaDeploymentPackager)

    packager.deployment_package_filename.return_value = 'packages.zip'
    # Given the lambda function already exists:
    aws_client.lambda_function_exists.return_value = True
    aws_client.update_function.return_value = {"FunctionArn": "myarn"}
    # And given we don't want chalice to manage our iam role for the lambda
    # function:
    cfg = Config.create(
        chalice_stage='dev',
        chalice_app=sample_app,
        manage_iam_role=False,
        app_name='appname',
        iam_role_arn=True,
        project_dir='./myproject',
        environment_variables={"FOO": "BAR"},
    )

    d = LambdaDeployer(aws_client, packager, None, osutils, app_policy)
    # Doing a lambda deploy:
    lambda_function_name = 'lambda_function_name'
    deployed = DeployedResources('api', 'api_handler_arn',
                                 lambda_function_name, None, 'dev', None, None)
    d.deploy(cfg, deployed, 'dev')

    # Should result in injecting the latest app code.
    packager.inject_latest_app.assert_called_with('packages.zip',
                                                  './myproject')

    # And should result in the lambda function being updated with the API.
    aws_client.update_function.assert_called_with(lambda_function_name,
                                                  'package contents',
                                                  {"FOO": "BAR"})
 def test_default_tags(self):
     c = Config('dev', config_from_disk={'app_name': 'myapp'})
     assert c.tags == {
         'aws-chalice': 'version=%s:stage=dev:app=myapp' % chalice_version
     }
 def test_set_lambda_memory_size_stage(self):
     config_from_disk = {'stages': {'dev': {'lambda_timeout': 120}}}
     c = Config('dev', config_from_disk=config_from_disk)
     assert c.lambda_timeout == 120
 def test_set_lambda_timeout_global(self):
     config_from_disk = {'lambda_timeout': 120}
     c = Config('dev', config_from_disk=config_from_disk)
     assert c.lambda_timeout == 120
 def test_not_set(self):
     c = Config('dev', config_from_disk={})
     assert c.lambda_timeout is None
def test_default_value_of_manage_iam_role():
    c = Config.create()
    assert c.manage_iam_role
Beispiel #49
0
def mock_cli_factory(mock_deployer):
    cli_factory = mock.Mock(spec=factory.CLIFactory)
    cli_factory.create_config_obj.return_value = Config.create(project_dir='.')
    cli_factory.create_botocore_session.return_value = mock.sentinel.Session
    cli_factory.create_default_deployer.return_value = mock_deployer
    return cli_factory
 def test_not_set(self):
     c = Config('dev', config_from_disk={})
     assert c.lambda_memory_size is None
def test_version_defaults_to_1_when_missing():
    c = Config()
    assert c.config_file_version == '1.0'
 def test_set_minimum_compression_size_global(self):
     config_from_disk = {'minimum_compression_size': 5000}
     c = Config('dev', config_from_disk=config_from_disk)
     assert c.minimum_compression_size == 5000
 def test_not_set(self):
     c = Config('dev', config_from_disk={})
     assert c.minimum_compression_size is None
def test_default_chalice_stage():
    c = Config()
    assert c.chalice_stage == 'dev'
def test_environment_from_top_level():
    config_from_disk = {'environment_variables': {"foo": "bar"}}
    c = Config('dev', config_from_disk=config_from_disk)
    assert c.environment_variables == config_from_disk['environment_variables']
def test_lazy_load_chalice_app_must_be_callable():
    c = Config.create(chalice_app='not a callable')
    with pytest.raises(TypeError):
        c.chalice_app
def test_manage_iam_role_explicitly_set():
    c = Config.create(manage_iam_role=False)
    assert not c.manage_iam_role
    c = Config.create(manage_iam_role=True)
    assert c.manage_iam_role
 def test_set_lambda_memory_size_global(self):
     config_from_disk = {'lambda_memory_size': 256}
     c = Config('dev', config_from_disk=config_from_disk)
     assert c.lambda_memory_size == 256
Beispiel #59
0
def config():
    return Config()
 def test_set_lambda_memory_size_stage(self):
     config_from_disk = {'stages': {'dev': {'lambda_memory_size': 256}}}
     c = Config('dev', config_from_disk=config_from_disk)
     assert c.lambda_memory_size == 256