Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions TODO-Feature.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@


-->> Criar issue no github para iniciar discussao.
-> Melhora para tornar mais flexivel o built in custom authorizer.
* type
The authorizer type. Valid values are TOKEN for a Lambda function using a single authorization token submitted in a custom header, REQUEST for a Lambda function using incoming request parameters, and COGNITO_USER_POOLS for using an Amazon Cognito user pool.
Issue = Extend Custom Authorizer Support API Gateway Request Parameter #948
-> Feature para permitir deploys de rest api com multiplos lambdas.
* motivacao eh poder segregar rotas do api gateway para multiplos lambdas
- Porque?
- Melhorar o monitoramento e controle (permissoes e throtling especificos por handler)
- Permitir otimizar o pacote .zip
- Se algum handler estiver com problema ele nao impacta os demais



-->> Possibilidade de virar uma extensao.

* definir boiler plate (organização dos diretorios) desse novo tipo de projeto

<project-dir>
├── helloworld
│ ├── functionlib
│ │ ├── __init__.py
│ │ └── utils.py
│ ├── __init__.py
│ └── helloworld.py
├── chalicelib
│ ├── __init__.py
│ └── generics.py
├── app.py
├── requirements.txt
└── etc ...

* definir novas regras do framework e seus impactos
user_blueprint.registrate_route(
name='user_delete',
path='/v1/user/delete',
function=UserDeleteHandler,
)

* dificuldades de design de codigo:
* model DeploymentPackage é esperado por ser unico, hoje em dia. Uma instancia compartilhada.
- Possibilidades para resolver o problema:
- verificar a nessecidade de criar um DeploymentPackage dentro de
cada um dos metodos que cria os recursos.
- utilizar ou não a instancia global dentro dos metodos que criam os modelos. (utilizada) -> (done)
- iniciar pelo Rest Api



---->>> Dificuldade de design de meio de campo resolvida <<<----

* Criar projeto baseado na estrutura de pasta definida, para testar casos de uso.

* Abordagem Top-Down:
- Criar regras e logica no app:
- Metodo de interface entre a view do Chalice e um handler padrão de lambda:
- Estudar inputs do handler do chalice vs o handler padrao da aws
- chalice input:
reimplementar o metodo __call__ da classe Chalice
class Request
- local runner:
- garantir que o handler seja direcionado localmente
mas que não seja apontado nos templates do api gateway
(ver uma maneira de bloquear)
- LambdaHandler:
Parecido com o atual BaseHandler da autenticação porem de uso mais genérico.
- Classe para traduzir os inputs, similar ao BifrostChalice

- Traduzir o import do Handler para o function_path (conseguir achar a pasta a ser buildada a partir do import)
- Traduzir os methods a partir dos metodos da classe.

- segregar o metodo _create_rest_api_model em dois outros metodos dependendo do tipo de rest api (?)
- Nao sei se ainda é necessário depois de ter resolvido a questão do deployment object.
- Pode se criar metodos apenas para organizar caso seja preciso.

- segregar o metodo create_deployment_package em dois outros metodos dependendo do tipo de package
- Para separar:
- diretorio do projeto a ser deployado.
- logica para pegar arquivos.
- logica de build do requirements

- Outras funcionalidades adicionais


* template do cloudformation:
- ?

* template do terraform:
- adicionar lambda functions no template (done)
- referenciar o filename correto no template do terraform (done)
- Referenciar os lambdas corretos nas determinadas rotas (done)

- corrigir o bug da duplicacao no nome api_handler_handler

* adicionar arquivos nos pacotes dos lambdas

* variaveis de ambiente (?)

* Ver diferenca entre nosso api gateway e gerado
- como implementar vpc link
- mock de resposta para o options

* instalar dependencias que nao foram possiveis pelo pip do chalice

* ver como ele faz o deploy de fato do terraform

* como deployar apenas parte do detalhe do terraform

** Mesclar funcionalidades anteriores com alteracao **

** testes unitarios **

** padroes de codigo **
15 changes: 11 additions & 4 deletions chalice/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ class RouteEntry(object):

def __init__(self, view_function, view_name, path, method,
api_key_required=None, content_types=None,
cors=False, authorizer=None):
cors=False, authorizer=None, function=None):
self.view_function = view_function
self.view_name = view_name
self.uri_pattern = path
Expand All @@ -495,6 +495,7 @@ def __init__(self, view_function, view_name, path, method,
cors = None
self.cors = cors
self.authorizer = authorizer
self.function = function

def _parse_view_args(self):
if '{' not in self.uri_pattern:
Expand Down Expand Up @@ -590,12 +591,14 @@ def info(self, connection_id):


class DecoratorAPI(object):
def authorizer(self, ttl_seconds=None, execution_role=None, name=None):
def authorizer(self, ttl_seconds=None, execution_role=None, name=None, function=None):
return self._create_registration_function(
handler_type='authorizer',
name=name,
registration_kwargs={
'ttl_seconds': ttl_seconds, 'execution_role': execution_role,
'ttl_seconds': ttl_seconds,
'execution_role': execution_role,
'function': function
}
)

Expand Down Expand Up @@ -864,6 +867,7 @@ def _register_authorizer(self, name, handler_string, wrapped_handler,
actual_kwargs = kwargs.copy()
ttl_seconds = actual_kwargs.pop('ttl_seconds', None)
execution_role = actual_kwargs.pop('execution_role', None)
function = actual_kwargs.pop('function', None)
if actual_kwargs:
raise TypeError(
'TypeError: authorizer() got unexpected keyword '
Expand All @@ -873,6 +877,7 @@ def _register_authorizer(self, name, handler_string, wrapped_handler,
handler_string=handler_string,
ttl_seconds=ttl_seconds,
execution_role=execution_role,
function=function,
)
wrapped_handler.config = auth_config
self.builtin_auth_handlers.append(auth_config)
Expand All @@ -891,6 +896,7 @@ def _register_route(self, name, user_handler, kwargs, **unused):
'content_types': actual_kwargs.pop('content_types',
['application/json']),
'cors': actual_kwargs.pop('cors', self.api.cors),
'function': actual_kwargs.pop('function', 'api_handler'),
}
if route_kwargs['cors'] is None:
route_kwargs['cors'] = self.api.cors
Expand Down Expand Up @@ -1151,12 +1157,13 @@ def _add_cors_headers(self, response, cors_headers):

class BuiltinAuthConfig(object):
def __init__(self, name, handler_string, ttl_seconds=None,
execution_role=None):
execution_role=None, function=None):
# We'd also support all the misc config options you can set.
self.name = name
self.handler_string = handler_string
self.ttl_seconds = ttl_seconds
self.execution_role = execution_role
self.function = function


# ChaliceAuthorizer is unique in that the runtime component (the thing
Expand Down
50 changes: 44 additions & 6 deletions chalice/deploy/deployer.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
from botocore.session import Session # noqa
from typing import Optional, Dict, List, Any, Set, Tuple, cast # noqa

import chalice
from chalice import app
from chalice.config import Config # noqa
from chalice.config import DeployedResources # noqa
Expand Down Expand Up @@ -380,6 +381,7 @@ def __init__(self):

def build(self, config, stage_name):
# type: (Config, str) -> models.Application
print('build')
resources = [] # type: List[models.Model]
deployment = models.DeploymentPackage(models.Placeholder.BUILD_STAGE)
for function in config.chalice_app.pure_lambda_functions:
Expand Down Expand Up @@ -444,10 +446,36 @@ def _create_rest_api_model(self,
):
# type: (...) -> models.RestAPI
# Need to mess with the function name for back-compat.
lambda_function = self._create_lambda_model(
config=config, deployment=deployment, name='api_handler',
handler_name='app.app', stage_name=stage_name
)
print("_create_rest_api_model")

lambdas_to_build = set()
for route_key, route_value in config.chalice_app.routes.items():
for method_key, method_value in route_value.items():
lambdas_to_build.add(method_value.function)

# Check here if the deployment instance must be used and appended to
# lambdas_functions list
lambdas_functions = []
if 'api_handler' in lambdas_to_build:
lambdas_to_build.remove('api_handler')
lambda_function = self._create_lambda_model(
config=config, deployment=deployment, name='api_handler',
handler_name='app.app', stage_name=stage_name
)
lambdas_functions.append(lambda_function)

for lambda_path in lambdas_to_build:
name = '%s_handler' % ('_'.join(lambda_path.split('/')))

deployment = models.DeploymentPackage(
models.Placeholder.BUILD_STAGE,
lambda_path
)
lambda_function = self._create_lambda_model(
config=config, deployment=deployment, name=name,
handler_name='app.app', stage_name=stage_name
)
lambdas_functions.append(lambda_function)
# For backwards compatibility with the old deployer, the
# lambda function for the API handler doesn't have the
# resource_name appended to its complete function_name,
Expand Down Expand Up @@ -485,6 +513,7 @@ def _create_rest_api_model(self,
api_gateway_stage=config.api_gateway_stage,
lambda_function=lambda_function,
authorizers=authorizers,
lambdas_functions=lambdas_functions,
policy=policy
)

Expand Down Expand Up @@ -614,6 +643,7 @@ def _create_lambda_model(self,
handler_name, # type: str
stage_name, # type: str
):
print("_create_lambda_model")
# type: (...) -> models.LambdaFunction
new_config = config.scope(
chalice_stage=config.chalice_stage,
Expand Down Expand Up @@ -736,7 +766,8 @@ def _build_lambda_function(self,
security_group_ids=security_group_ids,
subnet_ids=subnet_ids,
reserved_concurrency=config.reserved_concurrency,
layers=lambda_layers
layers=lambda_layers,
function_path=deployment.function_path
)
self._inject_role_traits(function, role)
return function
Expand Down Expand Up @@ -875,9 +906,16 @@ def handle_deploymentpackage(self, config, resource):
# type: (Config, models.DeploymentPackage) -> None
if isinstance(resource.filename, models.Placeholder):
zip_filename = self._packager.create_deployment_package(
config.project_dir, config.lambda_python_version)
config.project_dir, config.lambda_python_version, function_path=resource.function_path)
resource.filename = zip_filename

# def handle_functionpackage(self, config, resource):
# # type: (Config, models.DeploymentPackage) -> None
# if isinstance(resource.filename, models.Placeholder):
# zip_filename = self._packager.create_deployment_package(
# config.project_dir, config.lambda_python_version, function_path=resource.function_path)
# resource.filename = zip_filename


class SwaggerBuilder(BaseDeployStep):
def __init__(self, swagger_generator):
Expand Down
11 changes: 10 additions & 1 deletion chalice/deploy/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@ def dependencies(self):
@attrs
class DeploymentPackage(Model):
filename = attrib() # type: DV[str]
function_path = attrib(default='') # type: str


@attrs
class FunctionPackage(DeploymentPackage):
filename = attrib() # type: DV[str]
function_path = attrib() # type: str


@attrs
Expand Down Expand Up @@ -166,6 +173,7 @@ class LambdaFunction(ManagedModel):
subnet_ids = attrib() # type: List[str]
reserved_concurrency = attrib() # type: int
layers = attrib() # type: List[str]
function_path = attrib(default='') # type: str

def dependencies(self):
# type: () -> List[Model]
Expand Down Expand Up @@ -209,10 +217,11 @@ class RestAPI(ManagedModel):
lambda_function = attrib() # type: LambdaFunction
policy = attrib(default=None) # type: Optional[IAMPolicy]
authorizers = attrib(default=Factory(list)) # type: List[LambdaFunction]
lambdas_functions = attrib(default=Factory(list)) # type: List[LambdaFunction]

def dependencies(self):
# type: () -> List[Model]
return cast(List[Model], [self.lambda_function] + self.authorizers)
return cast(List[Model], self.lambdas_functions + self.authorizers)


@attrs
Expand Down
Loading