Libro: ¿Cuando? La ciencia de encontrar el momento preciso

Soy de esas personas que, además de tener libros en casa que no han empezado, tengo muchos que empiezo y dejo por la mitad. En este mes de marzo he intentado ponerme al día en los libros que tengo empezados, algunos de ellos he tenido que volver a empezar desde el principio pero otros los he retomado por donde estaba.

Uno de los libros que he retomado es ¿Cuando?, de Daniel H. Pink (When: The Scientific Secrets of Perfect Timing en su versión en inglés).

Es un libro que habla de muchas cosas, pero sobre todo es un libro que habla del tiempo, desde la manera en la que somos productivos a lo largo del día, la diferencia entre búhos y alondras, pasando por los principios, los intermedios y los finales, hasta temas como el concepto del tiempo y del futuro, que no está presente de manera tan fuerte en todos los lenguajes y modifica no solamente la manera de interactuar, sino la manera de ver el mundo.

El libro se divide en tres bloques. Cada bloque, además, consta de una parte que podríamos denominar teórica o divulgativa, y una parte más práctica que Daniel denomina “Manual del Hacker del Tiempo” con consejos prácticos para poner en uso lo enseñado en el apartado anterior.

  • El día: En ella habla de cómo definimos nuestro día, cómo y cuando dormimos, cómo algunos somos de levantarnos pronto y otros de quedarnos hasta tarde, cómo afecta eso a nuestras decisiones, y cuando tomar decisiones importantes.
  • Comienzos, finales y mitades: En este bloque habla de diferentes tipos de comienzo, la importante de volver a empezar en algunos momentos de nuestra vida, la importancia de los finales, de por qué hacemos locuras o cosas intensas en el último año de cada década o cómo varían las relaciones entre la edad adulta y la vejez.
  • Sincronizar y pensar: Finalmente, usando como ejemplos a los dabbawalas, los miembros de un coro, y de un equipo de remo, habla de la importancia y la necesidad de mantener sincronía con aquello que marca el tiempo (que puede ser una persona, un reloj, una situación), sincronía con el grupo y finalmente, lo que denomina sincronía del corazón, es decir, la razón última de por qué hacemos las cosas, en el coro puede ser por motivos religiosos, en el remo por el esfuerzo conjunto, y en el caso de los dabbawalas, por la importancia de lo que están transportando, comida hecha en casa.

Un libro interesante, que te puede hacer pensar y reflexionar, siendo mi parte favorita la de los comienzos, finales y mitades. Todo lo que hacemos, inexorablemente tiene un principio, una mitad, y un final, como también lo tiene este artículo que comparto contigo, querido lector.

Si sientes curiosidad, tienes el libro disponible aquí: ¿Cuándo?: La ciencia de encontrar el momento preciso o si lo prefieres en versión original: When: The Scientific Secrets of Perfect Timing (English Edition)

Libro: The End of Procrastination

Procrastinar
Del lat.procrastināre.
1. tr. Diferir, aplazar.

RAE

Una de las cosas que intento hacer siempre que estoy en un aeropuerto es pasar por la sección de libros de las tiendas de Duty Free, si veo algo interesante en un idioma que entiendo y me puedo beneficiar de algún cambio de moneda, no lo dudo y compro un ejemplar, aunque tenga una pila infinita de libros por leer, con la errónea suposición de que leeré el libro mientras vuelo.

Así, casi dos meses después de su compra, te traigo “The End of Procrastination”, un libro corto (apenas 240 páginas de contenido) y pequeño que nos trae algunos trucos sobre cómo combatir la tendencia que tenemos algunos de postergar cosas, especialmente si son importantes o aburridas.

En un formato diferente a otros libros (cuadrado para ser exactos) y lleno de ayudas visuales, el libro nos provee con varias herramientas para intentar superarnos poco a poco.

Partiendo de un análisis personal, utilizando métodos como SWOT o DAFO para ver cuales son nuestras fortalezas y debilidades, una lista de lo que creemos que puedan ser nuestros mayores logros, así como una visión personal, podemos tener una idea más realista de donde estamos y a donde queremos llegar, siendo el principal objetivo limitar el espectro de opciones a nuestro alcance a aquellas que nos ayuden a lograr esa visión, ya que está demostrado que tener demasiadas opciones bloquea nuestra capacidad de elegir, y ante la frustración de no poder elegir, elegimos no hacer nada.

A partir de ahí, el libro pasa a temas más de nuestro día a día, como mantener actualizada una lista de hábitos, planificar las tareas diarias de manera visual, encadenando unas con otras y agregando marcadores de importancia, maneras de organizar aquellas tareas que no requieren acción inmediata, cómo tener listas de ideas en las cuales actuar a futuro, y cómo salir de nuestra zona de confort para poder hacer más.

Finalmente, el libro pasa a temas más complejos, como qué pasa cuando nos vemos en una situación de bloqueo, en el cual nos vemos atados a un presente o a una situación pasada negativa y no podemos salir de ahí, mencionando cómo tenemos el control sobre la manera en la que respondemos a estímulos, por mucho que puedan ser negativos, o cómo mantener una lista de cosas positivas que han pasado durante el día (otros autores lo mencionan como las tres gratitudes)

Personalmente me ha gustado el formato, aunque, tras haberlo intentado, no esté del todo convencido del formato de organización de tareas diarias, para ello me quedo con el método de Cal Newport que recomienda tanto en su blog Deep Habits: The Importance of Planning Every Minute of Your Work Day como en su libro Deep work, que ya comenté en este blog en 2016.

Como estas, muchas más herramientas y muchos más dibujos en The End of Procrastination: How to stop postponing and live a fulfilled life

Espero que te resulte interesante (y a diferencia de mi, tardes menos de dos meses en terminarlo).

De vuelta de WeCodeFest 2019

Este año he vuelto a Valladolid a aprender y compartir con compañeros de batallas en un evento con charlas, talleres y debates durante dos días siguiendo un formato mixto de agenda cerrada + open space.

Durante el evento tuve tanto la oportunidad de escuchar y comentar en varios foros que iban entre el uso de frameworks, el trato con clientes complicados, los procesos de onboarding… , así como facilitar dos sesiones, una relacionada con productividad y distracciones, y la otra relacionada con libros, eventos y charlas que nos han marcado o han cambiado nuestra manera de ver problemas.

Esta fue fue una ocasión más para volver a ver a los compañeros de Códice Software, creadores de PlasticSCM, y la casa que me acogió cuando salí de la carrera y donde realmente aprendí a construir software, a hacer tests y a descubrir la diferencia entre programa y producto. Después de más de 10 años siguen luchando contra viento y marea por hacer el mejor sistema de control de versiones del mundo.

A continuación resumo algunas ideas que me han parecido interesantes de las sesiones a las que he asistido:

Microservicios

Me llevo deberes, concretamente este artículo: the Twelve-Factor App que da una definición de qué constituye un microservicio. Durante la conversación se debatió además el hecho de utilizar microservicios como una manera de organizar equipos, y aislar funcionalidad para intentar mejorar problemas de comunicación entre equipos.

Motivación

Me llevo varios conceptos relacionados con motivación intrínseca, qué es lo que nos lleva a hacer lo que hacemos y a mantenerlo, que va en línea con lo que he estado leyendo últimamente y de lo que espero escribir pronto, y echar un vistazo a este libro Drive: de Daniel H. Pink.

Productividad y distracciones

Entre los puntos que discutimos en esta sesión me gustaría destacar.

  • La necesidad de proteger nuestra concentración (auriculares con cancelación de ruido, sonido de ambiente, ambientes silenciosos si es posible) y la de nuestros compañeros, (manda una pregunta por chat, y cuando él pueda contestará, y así el compañero controla cuanto quiere ser interrumpido).
  • El uso de técnicas como revisar el correo en momentos puntuales del día, desconectar notificaciones, cerrar Slack o usar técnicas como pomodoro para tener momentos de no molestar, que podemos combinar con herramientas como Cuckoo para que el equipo sea consciente de si otros compañeros están ocupados en ese momento.
  • Ls emociones que genera la música y cómo afecta a nuestra capacidad de concentración, y cómo herramientas como Noisli pueden generar ruidos “de ambiente” o directamente ruido blanco pueden ser más útiles que canciones, especialmente canciones con letra. Dichas emociones, por otro lado nos pueden ayudar a desconectar, relajarnos o directamente “sacarnos de la caja”.
  • El hecho de cuán interesante o aburrida sea la tarea constituye un factor importante a la hora de que nuestra mente esté buscando activamente distraerse, y que el aburrimiento provoque no solo que nos distraigamos sino que distraigamos a otros.

Libros que nos han marcado

En esta sesión hablamos de diversos tipos de fuentes de inspiración:

  • Libros de teoría y arquitectura de software o de gestión de equipos de desarrollo, entre los que están Extreme Programming, Scrum from the trences, Refactoring, Clean Code, Clean Architecture, Design Patterns, POSA, Documenting Software Architecture, The Pragmatic Programmer…
  • Libros y ejercicios prácticos como Learn You a Haskell for Great Good!, Go by Example o las Ruby Koans que son ejercicios prácticos que te obligan a terminar un código para aprender a usar el lenguaje.
  • Podcasts como Software Engineering Daily o Agile in 3 Minutes

Y ahora qué?

Seguir leyendo, seguir escribiendo y tener siempre presente una frase compartida en la sesión sobre motivación de equipo que decía: todo lo que has aprendido es inútil si no lo usas, y estéril si no lo compartes.

De momento, comparto, con la intención de usar los conocimientos aprendidos.

¡Gracias a la organización por hacer este evento posible!

18. Echando la vista atrás

Hace más de 7 meses desde mi última entrada en este blog, y no ha pasado mes en el que me diga “debería escribir más”, y siempre he encontrado excusas interesantes para no escribir, pero sobre todo, y la más importante, es que he tenido relativamente poco que compartir. Pero no podía dejar de hacer balance un año más de cosas que han pasado y poner un la vista en lo que queda por venir, así que aquí va mi retrospectiva.

En el ámbito profesional ha sido verdaderamente intenso, análisis de requisitos, diseño de arquitecturas, alineamientos con equipos de todas partes del mundo (a horas intempestivas tanto para los que trabajamos en GMT+1 como para los de otras zonas horarias), muchísimo código en Java 8, JavaScript y Kotlin, incontables líneas de test unitarios, de integración, de carga, varias horas de presentaciones ante compañeros, unas sesenta horas entre aviones y aeropuertos entre España, USA y el Reino Unido, muchos litros de café y de tinta tomando notas.

Siguiendo con el gremio pero fuera de “horas de oficina”, este año me perdí la BilboStack, con entrada, vuelo y hotel comprados :(, (este año lo intentaremos otra vez) aunque sí que me pude dejar caer por la MindCamp, a la Pamplona SW Craftmanship, a WeCode y LechazoConf en Valladolid, y a DotNet 2018, donde tuve la oportunidad de volver a ver a algunos amigos y compañeros de batallas. Entre otros eventos memorables, pude ver en directo a Martin Fowler hablando, entre otras cosas, de la importancia de la entrega continua, el valor de los tests, y cómo se podía implementar entrega continua en productos existentes (este habría sido un buen candidato para escribir del tema).

Algunos de los que me leéis sabréis que tengo la suerte de compartir profesión y pasión por la tecnología con mi madre, y que en algunos eventos yo me presento como “el hijo de Ana” y en otros ella se presenta como “la madre de Rober”. Este año he visto con el orgullo que solo un hijo puede ver como Microsoft le reconocían sus méritos a la comunidad al nombrarla Most Valuable Professional (MVP).

Para aquellos que no os suene, es un reconocimiento que entrega Microsoft a profesionales que hagan aportaciones significativas a la comunidad, como eventos, ayuda en los foros, artículos en blogs o revistas, contribuciones de código a proyectos Open Source… Ana lleva desde hace más de quince años formando parte de diversas comunidades relacionadas con tecnologías Microsoft, desde FoxPro, SQL y ahora Power BI. Como testigo de esa evolución, y de su capacidad de reinventarse, es todo un reconocimiento a tantos años de trabajo y dedicación a la comunidad.

En el ámbito deportivo, este año ha habido obligaciones profesionales y familiares que me han brindado una excelente excusa para no hacer más deporte, aunque he hecho un esfuerzo por acabar el año haciendo más kilómetros. De acuerdo con Endomondo en 2017 corrí entre calle y cinta unos 249 km, este año 267, un poco más que el año anterior, pero menos de lo que habría querido. Este año sin embargo me ha traído un éxito en parte inesperado, que ha sido un récord personal de 58:32 en la San Silvestre Vallecana el 31 de diciembre, superando la barrera de una hora que llevaba un par de años intentando conseguir.

Volviendo al blog, he escrito cuatro artículos, dos relacionados con AWS en mi intención de aprender para examinarme de Solutions Architect, un tercero como revisión del libro “The Phonenix Project” y el resumen de 2017. Es el segundo año consecutivo que escribo menos de un artículo al mes, lejos de aquel año 2014 en el que este blog cosechó 60 entradas, más de una semanal.

Finalmente, respecto a los objetivos fijados el pasado año, este año no he sido capaz de cumplir ninguno de ellos, así que listarlos parece un poco repetitivo.

Dicho lo cual, este año voy a listar no tanto objetivos específicos sino ciertos hábitos que estoy intentando incorporar en mi vida diaria.

  1. Conseguir concentrarme en bloques de, al menos, 15 minutos: Tras leer técnicas como Pomodoro, que hablan de fijar bloques para tareas de unos 25 minutos, o libros como Deep Work donde recomiendan bloques más largos de varias horas, creo que 2019 será un año para poner estos métodos en práctica, Leí recientemente este artículo How to Multitask Without Breaking Your Brain – Member Feature Stories – Medium y me llamó mucho la atención la idea de mantener la concentración durante al menos 15 minutos antes de cambiar de actividad, llevo unos días usándolo y es sorprendentemente poderoso.

  2. Correr cada semana: Había pensado originalmente en fijar algo así como “correr 500 km, pero el truco está en buscar el hábito de correr semanalmente, y que no sea algo puntual antes de cada carrera. Idealmente quiero estirar la cantidad de kilómetros que hago en cada sesión y reducir el ritmo cardiaco, para poder preparar mayores distancias sin que el cuerpo sufra demasiado.

  3. Mejorar mi organización: Me encantan las listas de tareas y los diferentes sistemas de organización, mi favorito sigue siendo GTD ya que me permite tenerlo todo en un único lugar, aunque en 2018 he vuelto a utilizar Bullet Journal para tomar notas en papel de reuniones, ideas, tareas que van surgiendo y otras. En este año quiero agregar el hábito de la revisión semanal que propone GTD para mantener tareas y proyectos al día.

  4. Desconectar activamente: Buscar o potenciar hobbies para mantener ocupado el cerebro cuando no estoy trabajando. Montar legos, tocar el piano, pintar, escribir, correr, o todas las anteriores.

  5. Agregar a mi rutina diaria más tiempo para leer: La combinación de Audible + Correr es increíblemente motivadora para ponerme al día con libros de acción como la saga de “The Gray Man” de Mark Greaney, aunque la literatura técnica, ya sea relacionada con el software, el trabajo corporativo o el mundo de los negocios, es más conveniente leerlas más que escucharlas. En un mundo donde hay cientos de artículos en medium de cualquier tema, sigo prefiriendo la estructura y el orden de un buen libro (en papel o en Kindle), por ello, me gustaría dedicar unos 15 minutos al día para leer. Habrá días que pueda dedicar más, habrá días que pueda dedicar menos. Además como motivación adicional, quiero escribir en el blog acerca de los libros “de trabajo” que lea.

  6. Buscar activamente nuevas oportunidades para aprender y mantener conocimiento: Inscribirme en un examen de certificación para buscar una excusa para estudiar, asistir a un evento de una tecnología que no conozca, hacer un pet-project que involucre algún concepto relacionado con IA, construir mejores interfaces aprendiendo de mis compañeros de UX, aprender a escribir documentos técnicos pidiendo ayuda a compañeros más experimentados…, hay muchas maneras de seguir aprendiendo, mantener nuestros conocimientos y mejorar en lo que hacemos.

  7. Respirar: Vivimos en un mundo frenético, con múltiples estímulos que vienen en forma de e-mail, mensajería instantánea, nuestro jefe, nuestros compañeros, la familia, amigos, y obligaciones que muchas veces requieren una respuesta inmediata. En mi caso he vivido más de una vez cómo no tomar una bocanada de aire y soltarlo antes de responder ha dado como resultado una respuesta tosca, agresiva, defensiva o simplemente equivocada por no pararme a pensar en la pregunta. Para ello este 2019 pienso respirar más, sobre todo antes de hablar.

2019 se presenta como un año cargado de retos personales, profesionales y deportivos. Espero poder compartir parte de lo aprendido en este blog que lleva siendo mi casa en las nubes desde hace ya 10 años.

Feliz año nuevo.

Aprendiendo AWS: Lambda usando VSCode y Python

Continuando con la serie sobre AWS, en este caso he decidido jugar un poco con una de las plataformas del momento, Lambda. Para ello he construido una API con Python para leer y escribir datos de una base de datos, en local y con diferentes capas de test.

¿Qué es Lambda?

Lambda es un producto de AWS que permite ejecutar trozos de código (funciones) de manera aislada de otras aplicaciones. Esto aporta una capa extra de abstracción con todo lo bueno y malo que ello implica, y además únicamente se factura por el tiempo en el que la función se está ejecutando.

Se puede interactuar con Lambda utilizando el editor en la nube que ofrecen, subir el código a S3 usando un formulario, o utilizar sistemas como SAM local para automatizar todo el proceso, y este último es el que se ha usado en este artículo.

El objetivo

Para este pequeño proyecto, el plan consistía en crear al menos un par de funciones que expusieran una API REST, escribir en una base de datos, definir todo lo posible mediante código y configuración y que el despliegue se realizara utilizando la consola.

El ejemplo es un banco con cinco funciones, crear, depositar, retirar, ver saldo, y hacer una transferencia.

Escribiendo la primera función

El lenguaje utilizado en este caso ha sido Python, así que parte del reto ha sido aprender a escribir utilizando la sintaxis del lenguaje de la serpiente:

def setup(event, context):
    payload = json.loads(event['body’])
    account = payload['id']
    bank = Bank()
    bank.save_account({"id": account, "balance": 0})
    return {
        "statusCode": 201
    }

En Lambda, y para el caso particular de Python, se define una función como un método que acepta dos parámetros, event que contiene los datos que se le pasan a la función, y context que contiene información relativa a la ejecución de la misma.

En este ejemplo se puede ver los valores que se pasan a esta función dentro de event

{'httpMethod': 'PUT', 'body': '{"id": "test_alice"}', 'resource': '/account', 'requestContext': {'resourcePath': '/account', 'httpMethod': 'PUT', 'stage': 'prod', 'identity': {'sourceIp': '127.0.0.1:61479'}}, 'queryStringParameters': {}, 'headers': {'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'keep-alive', 'Content-Length': '20', 'Host': 'localhost', 'User-Agent': 'python-requests/2.18.4', 'X-Forwarded-Port': '', 'X-Forwarded-Proto': ''}, 'pathParameters': None, 'stageVariables': None, 'path': '/account', 'isBase64Encoded': False}

Para poder continuar, es necesario interpretar los parámetros. En este caso, el valor body es un JSON con la información de la cuenta, y para ello se crea un objeto a partir de la cadena de texto utilizando json.loads(event['body’])

Esto permite interactuar con los datos que se pasan a la función, que en este caso lo que hace es guardar la nueva cuenta en la clase Bank creada para abstraer toda la información relativa a la base de datos.

Finalmente, la función ha de devolver un objeto que contenga, al menos un campo con el estado HTTP en statusCode, que en este caso es 201 (Created).

Utilizando la misma lógica se puede hacer las operaciones de depósito, retirada, saldo y transferencia, aunque para ello puede resultar interesante abstraer la función que recibe el evento de la lógica de la función, usando una función que se llamará dispatch:

def dispatch(event, context):
    requestContext = event["requestContext"]
    resourcePath = requestContext["resourcePath"]
    method = requestContext["httpMethod"]

    if(method == "GET"):
        payload = event['queryStringParameters']
    else:
        payload = json.loads(event['body'])
    try:

        if(resourcePath == "/account"):
            if(method == "PUT"):
                setup(payload)
                return {
                    "statusCode": 201
                }

            elif(method == "GET"):
                return {
                    "statusCode": 200,
                    "body": get_balance(payload)
                }
        ...

    except Exception:
        return {
            "statusCode": 500
        }

Esta función permite leer los parámetros, interpretar la ruta y llamar a la función específica de la misma, así como hacer un pequeño tratamiento de errores.

Integrando con DynamoDB

Una vez que están todas las funciones definidas, el siguiente paso es escribir la clase Bank que será la que escriba información en la base de datos.
Mantener estas responsabilidades separadas permite, en primer lugar, una mejor capacidad de pruebas, y en segundo lugar, hace al código de la función independiente del proveedor de bases de datos.

import boto3
import os
import uuid

class Bank:

    def __init__(self):
        endpoint = os.environ.get("ENDPOINT")
        if(endpoint is None):
            self.dynamodb = boto3.resource('dynamodb')
        else:
            self.dynamodb = boto3.resource('dynamodb', endpoint_url=endpoint)

        self.accounts = self.dynamodb.Table("Accounts")
        self.transactions = self.dynamodb.Table("Transactions")

    def get_account(self, account_name):
        try:
            result = self.accounts.get_item(Key={'id': account_name})
            return result['Item']
        except:
            return None

    def log_transaction(self, transaction):
        transaction["id"] = str(uuid.uuid1())
        self.transactions.put_item(Item=transaction)

    def save_account(self, account):
        self.accounts.put_item(Item=account)

El único detalle destacable de esta clase, es que comprueba si existe un endpoint para DynamoDB definido, esto permitirá utilizar la misma clase para los tests.

Probando la función

Una vez escrito el código de las funciones y la conexión con la base de datos, el siguiente paso es probar que todo funciona como se espera.

Configurando la base de datos

Para probar la interacción con la base de datos se puede, o bien configurarla utilizando el sdk de aws y el comando aws configure o bien utilizando una base de datos local, que podemos arrancar utilizando el siguiente comando:

java -Djava.library.path=./DynamoDBLocal_lib -jar DynamoDBLocal.jar --inMemory

Esto proporciona una base de datos de DynamoDB en local lista para utilizar. La creación de tablas, en este ejemplo, se realiza como parte de los test unitarios:

table = dynamodb.create_table(
    TableName="Accounts",
    KeySchema=[
        {
            'AttributeName': 'id',
            'KeyType': 'HASH'
        }],
    AttributeDefinitions=[
        {
                'AttributeName': 'id',
                'AttributeType': 'S'
        }],
    ProvisionedThroughput={
        'ReadCapacityUnits': 5,
        'WriteCapacityUnits': 5
})
            table.meta.client.get_waiter('table_exists').wait(TableName='Accounts')

Probando las funciones

Con la base de datos funcionando y las tablas creadas, llega el momento de escribir las diferentes pruebas, como esta, que comprueba que un ingreso ha sido efectivo:

...

def test_deposit(self):
    function.setup({'id': "Bob"})
    function.deposit({'id': "Bob", "amount": 10.0})
    self.assertEqual(function.get_balance({'id': "Bob"}), 10)

Para ejecutar los tests es tan sencillo como escribir python function-tests.pydesde la consola de comandos.

Configurando Lambda

Para convertir el código de las funciones en una API que se pueda consultar vía HTTP se ha recurrido a SAM (Serverless Application Model) local, un conjunto de herramientas para definir, probar y desplegar funciones Lambda.

La plantilla

Una plantilla de SAM no es más que un subconjunto de una plantilla de CloudFormation, que en un artículo anterior comentaba que es una manera de automatizar la creación y actualización de recursos dentro de AWS.

Para este ejemplo la plantilla tiene el siguiente aspecto:

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: 'A simple banking app built on lambdas'

Resources:
  Bank:
    Type: AWS::Serverless::Function
    Properties:
      Handler: function.dispatch
      CodeUri: .
      Runtime: python3.6
      Events:
        CreateAccount:
          Type: Api
          Properties:
            Path: '/account/new'
            Method: put
        GetBalance:
          Type: Api
          Properties:
            Path: '/account'
            Method: get
        Deposit:
          Type: Api
          Properties:
            Path: '/account/deposit'
            Method: post
        Transfer:
          Type: Api
          Properties:
            Path: '/account/transfer'
            Method: post
        Withdraw:
          Type: Api
          Properties:
            Path: '/account/withdraw'
            Method: post
      Policies:
        - Version: '2012-10-17'
          Statement:
            - Effect: Allow
              Action:
                - 'dynamodb:PutItem'
                - 'dynamodb:GetItem'
              Resource: 'arn:aws:dynamodb:*:*:*'

En esta plantilla se define:
– El handler, o función que responderá a la llamada
– Los eventos que dispararán la llamada (varios eventos pueden disparar el mismo handler)
– Las políticas que se aplican (en esta caso necesitamos permisos de lectura y escritura para la base de datos).

Validando y probando la plantilla con SAM

Una vez definidos todos los valores para la plantilla, se puede ejecutar SAM para comprobar que la plantilla es válida:

sam validate

El cliente SAM permite, además, probar la definición de la plantilla de manera local:
sam local start-api

Este comando inicializa un servidor en el puerto 3000 con el que se pueden probar las funciones desde un cliente HTTP (en este ejemplo he utilizado Postman) y ver como la API responde a las diferentes llamadas.

Pruebas de integración

Para comprobar que todo funciona bien antes de subir la plantilla a AWS, he creado un conjunto de tests un tanto diferentes, esta vez para comprobar que los datos se transforman correctamente, llamando al cliente de localhost.

def test_deposit(self):
    r = requests.get('http://localhost:3000/account?id=test_bob')
    initial_bob_balance = float(r.text)

    r = requests.post('http://localhost:3000/account/deposit', data =  json.dumps({'id':'test_bob', 'amount': 100}))
    self.assertEqual(200, r.status_code)

    r = requests.get('http://localhost:3000/account?id=test_bob')
    new_balance = float(r.text)

    self.assertEqual(new_balance, initial_bob_balance + 100)

Para ejecutar los tests es tan sencillo como escribir python integration-tests.pydesde la consola de comandos.

Desplegando la plantilla

Finalmente queda empaquetar la función y desplegarla en la consola de AWS. En primer lugar se empaqueta la función en un fichero zip, se guarda en una carpeta (bucket) de S3 y se actualizan las referencias en el fichero que se ha denominado package.yaml:

sam package --template-file template.yaml --s3-bucket my-bucket --output-template-file packaged.yaml

En segundo lugar se invoca a CloudFormation para crear todos los recursos definidos en el paquete, incluyendo el código fuente y el conjunto de permisos:

sam deploy --template-file packaged.yaml --stack-name my-stack-name --capabilities CAPABILITY_IAM

Una vez se haya desplegado el paquete, se puede ir a la consola de AWS y ver cómo se ha desplegado la función:

Captura de pantalla 2018-05-12 a las 21.00.03

Al hacer click, se puede ver además los diferentes endpoints que API Gateway ha creado. así como las diferentes opciones:

Captura de pantalla 2018-05-13 a las 9.54.07

Con esto la función creada está lista para ser ejecutada.

En resumen

Eh este artículo se ha definido una función Lambda de manera local, utilizando tantas capas de abstracción como hayan sido necesarias. Se han creado diferentes tipos de test para probar los diferentes puntos de integración, y finalmente se ha empaquetado y desplegado la función desde la línea de comandos.

El código está disponible en GitHub.

Sin embargo, se han quedado algunas cosas fuera del alcance del artículo, y quedan como sugerencia al lector para continuar experimentando:

  • Inyección de dependencias y Mocking para hacer tests unitarios
  • Integración con un sistema como Jenkins para ejecutar tests
  • Crear la base de datos utilizando la plantilla de SAM
  • Uso de frameworks como Serverless que agregan una capa de abstracción incluso mayor, aislando de las implementaciones de AWS, Azure, Google Cloud o IBM.

¿Y tú, has hecho alguna prueba con Lambdas u otra plataforma Serverless?

Herramientas utilizadas

  • SAM local para probar la función en local, así como para desplegarla en AWS.
  • Visual Studio Code para editar el código y para interactuar con la API de SAM local usando su consola integrada.
  • DynamoDB Local para emular una base de datos de DynamoDB.
  • Boto 3 el SDK oficial de AWS para Python.
  • Postman para probar las diferentes APIs tanto locales como remotas.

Más documentación y ejemplos

Aprendiendo AWS: Nube privada Virtual o VPC

Desde hace ya unos días estoy empezando a preparar el examen de certificación de AWS Solutions Architect, y eso me permite aprender sobre los diferentes componentes que forman la plataforma cloud de Amazon. En este artículo veremos uno de los pilares de estos componentes, la nube privada virtual o VPC.

Hasta hace relativamente poco, mi idea era que en cualquier proveedor de nube, tenías máquinas virtuales y servicios, y podías realizar ciertos ajustes para detectar desde donde se puede acceder a tu instancia, y poco más. Uno de los componentes al que había prestado poco o nulo interés era el concepto de VPC (llamado también Virtual Network en Azure).

Básicamente una VPC nos permite crear nuestra propia topología de red en la nube como si tuviéramos nuestro propio CPD. Con topología nos referimos de la posibilidad de crear una red, diferentes subredes, decidir cómo se conectan entre ellas, cómo se conectan a internet, y a qué recursos tienen acceso.

Esto también nos permite tener diferentes recursos en diferentes subredes, y poder aplicar directivas de seguridad y control de acceso a nivel de subred, en vez de tener que aplicarlas a recursos individuales.

Cuando gestionamos redes privadas en AWS podemos hacer uso de diferentes componentes, entre los que destacan:

  • Subnets: Permiten aislar varios recursos dentro de la misma VPC (i.e. Servidor Web, Base de datos)
  • Internet Gateway: Necesaria para que una VPC pueda acceder a internet.
  • Elastic IP Address: Necesaria para poder servir tráfico a internet desde nuestra VPC. Podemos tener direcciones IP elásticas asociadas a una VPC o a un recurso específico (una instancia de EC2, por ejemplo).
  • Route Tables: Permiten definir una tabla de origen y destino, y direccionar el tráfico que proviene de una subred tanto a la red interna o al Internet Gateway, para dar acceso a internet.
  • Security Groups: Asociado a una instancia, permite establecer que rango de IPs puede acceder a puertos específicos. Por ejemplo, un servidor web puede permitir tráfico entrante para todo internet en el puerto 80, pero sin embargo limitar el tráfico de conexiones SSH (puerto 22) a máquinas específicas.
  • NAT Gateway / NAT Instance: Permiten que una subred tenga acceso a internet y limitar el acceso a la misma desde internet. Se puede configurar como servicio o manualmente utilizando una máquina virtual dedicada.

Recursos