Skip to content

Commit

Permalink
Update README.md
Browse files Browse the repository at this point in the history
  • Loading branch information
Ruben Galeano committed Dec 29, 2020
1 parent 1cffd4f commit 6c960c1
Show file tree
Hide file tree
Showing 17 changed files with 856 additions and 38 deletions.
121 changes: 83 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,44 +1,81 @@
<!--
title: 'AWS Serverless REST API with DynamoDB store example in Python'
description: 'This example demonstrates how to setup a RESTful Web Service allowing you to create, list, get, update and delete Todos. DynamoDB is used to store the data.'
layout: Doc
framework: v1
platform: AWS
language: Python
authorLink: 'https://github.com/godfreyhobbs'
authorName: 'Rubén Galeano'
authorAvatar: 'https://avatars1.githubusercontent.com/u/8434141?v=4&s=140'
-->

# Serverless REST API

This example demonstrates how to setup a [RESTful Web Services](https://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_web_services) allowing you to create, list, get, update and delete Todos. DynamoDB is used to store the data. This is just an example and of course you could use any data storage as a backend.
Este ejemplo demuestra cómo configurar un [Servicios Web RESTful](https://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_web_services) que le permite crear, listar, obtener, actualizar y borrar listas de Tareas pendientes(ToDo). DynamoDB se utiliza para persistir los datos.

Este ejemplo está obtenido del [repositorio de ejemplos](https://github.com/serverless/examples/tree/master/aws-python-rest-api-with-dynamodb) de Serverless Framework. Debido a que el objetivo de la práctica es implementar una serie de Pipelines de CI/CD de diferente manera, el objetivo principal del alumno no será codificar desde cero un servicio. Por eso se ha elegido este caso que aunque no es excesivamente complejo, si representa un reto en determinados puntos, al ser un ecosistema al que probablemente el alumno no estará acostumbrado.
## Estructura

Este repositorio consta de directorio separado para todas las operaciones de la lista de ToDos en Python. Para cada operación existe exactamente un fichero, por ejemplo "todos/delete.py". En cada uno de estos archivos hay exactamente una función definida.

La idea del directorio `todos` es que en caso de que se quiera crear un servicio que contenga múltiples recursos, por ejemplo, usuarios, notas, comentarios, se podría hacer en el mismo servicio. Aunque esto es ciertamente posible, se podría considerar la creación de un servicio separado para cada recurso. Depende del caso de uso y de la preferencia del desarrollador.

## Structure
La estructura actual del repositorio sería la siguiente:

This service has a separate directory for all the todo operations. For each operation exactly one file exists e.g. `todos/delete.py`. In each of these files there is exactly one function defined.

The idea behind the `todos` directory is that in case you want to create a service containing multiple resources e.g. users, notes, comments you could do so in the same service. While this is certainly possible you might consider creating a separate service for each resource. It depends on the use-case and your preference.
```
├── package.json
├── pipeline
│ ├── ENABLE-UNIR-CREDENTIALS
│ │ └── Jenkinsfile
│ ├── PIPELINE-FULL-CD
│ │ └── Jenkinsfile
│ ├── PIPELINE-FULL-PRODUCTION
│ │ └── Jenkinsfile
│ └── PIPELINE-FULL-STAGING
│ └── Jenkinsfile
├── README.md
├── serverless.yml
├── terraform
│ ├── configure_environment.sh
│ ├── main.tf
│ ├── outputs.tf
│ ├── resources
│ │ └── get-ssh-key.sh
│ ├── variables.tf
│ └── var.tfvars
├── test
│ ├── TestToDo.py
│ ├── ToDoCreateTable.py
│ ├── ToDoDeleteItem.py
│ ├── ToDoGetItem.py
│ ├── ToDoPutItem.py
│ └── ToDoUpdateItem.py
└── todos
├── create.py
├── decimalencoder.py
├── delete.py
├── get.py
├── __init__.py
├── list.py
└── update.py
```

Directorios a tener en cuenta:
- pipeline: en este directorio el alumno deberá de persistir los ficheros Jenkinsfile que desarrolle durante la práctica. Si bien es cierto que es posible que no se puedan usar directamente usando los plugins de Pipeline por las limitaciones de la cuenta de AWS, si es recomendable copiar los scripts en groovy en esta carpeta para su posterior corrección. Se ha dejado el esqueleto de uno de los pipelines a modo de ayuda, concretamente el del pipeline de PIPELINE-FULL-STAGING.
- test: en este directorio se almacenarán las pruebas desarrolladas para el caso práctico. A COMPLETAR POR EL ALUMNO
- terraform: en este directorio se almacenan los scripts necesarios para levantar la infraestructura necesaria para el apartado B de la práctica. Para desplegar el contexto de Jenkins se ha de ejecutar el script de bash desde un terminal de linux (preferiblemente en la instancia de Cloud9). Durante el despliegue de la infraestructura, se solicitará la IP del equipo desde donde se va a conectar al servidor de Jenkins. Puedes consultarla previamente aquí: [cualesmiip.com](https://cualesmiip.com)
- todos: en este directorio se almacena el código fuente de las funciones lambda con las que se va a trabajar

## Use-cases
## Casos de uso

- API for a Web Application
- API for a Mobile Application

## Setup
## Configuración

```bash
npm install -g serverless
```
## Despliegue con Serverless Framework

## Deploy

In order to deploy the endpoint simply run
De cara a simplificar el despliegue, simplemente habría que ejecutar

```bash
serverless deploy
```

The expected result should be similar to:
Los resultados esperados deberían de ser así:

```bash
Serverless: Packaging service…
Expand Down Expand Up @@ -68,54 +105,63 @@ functions:
serverless-rest-api-with-dynamodb-dev-delete: arn:aws:lambda:us-east-1:488110005556:function:serverless-rest-api-with-dynamodb-dev-delete
```

## Usage
## Despliegue infraestructura de Terraform para el Apartado BTerraform

En la instancia de Cloud9, simplemente se ha de ejecutar el script de `configure_enviroment.sh`, dentro del directorio de [terraform](https://registry.terraform.io/).
Cuando se pregunte por la IP, indicar la del equipo desde se desea conectar.
```bash
cd terraform
./configure_environment.sh
```

You can create, retrieve, update, or delete todos with the following commands:
Si se desea desplegar desde un terminal local, recordar que este script está pensado para ejecutar en un entorno de Linux y que desde local, habrá que configurar las credenciales temporales de la cuenta de Aws Credentials dentro del fichero `~/.aws./credentials` del home del usuario.
## Uso

### Create a Todo
Se puede crear, lista, coger, actualizar y borrar una tarea, ejecutando los siguientes comandos `curl` desde la línea de comandos del terminal:
### Crear una tarea

```bash
curl -X POST https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos --data '{ "text": "Learn Serverless" }'
```

No output
No hay salida

### List all Todos
### Listar todas las tareas

```bash
curl https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos
```

Example output:
Ejemplo de salida:
```bash
[{"text":"Deploy my first service","id":"ac90feaa11e6-9ede-afdfa051af86","checked":true,"updatedAt":1479139961304},{"text":"Learn Serverless","id":"206793aa11e6-9ede-afdfa051af86","createdAt":1479139943241,"checked":false,"updatedAt":1479139943241}]%
```

### Get one Todo
### Coger una tarea

```bash
# Replace the <id> part with a real id from your todos table
curl https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos/<id>
```

Example Result:
Ejemplo de salida:
```bash
{"text":"Learn Serverless","id":"ee6490d0-aa11e6-9ede-afdfa051af86","createdAt":1479138570824,"checked":false,"updatedAt":1479138570824}%
```

### Update a Todo
### Actualizar una tarea

```bash
# Replace the <id> part with a real id from your todos table
curl -X PUT https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos/<id> --data '{ "text": "Learn Serverless", "checked": true }'
```

Example Result:
Ejemplo de salida:
```bash
{"text":"Learn Serverless","id":"ee6490d0-aa11e6-9ede-afdfa051af86","createdAt":1479138570824,"checked":true,"updatedAt":1479138570824}%
```

### Delete a Todo
### Borrar una tarea

```bash
# Replace the <id> part with a real id from your todos table
Expand All @@ -124,22 +170,21 @@ curl -X DELETE https://XXXXXXX.execute-api.us-east-1.amazonaws.com/dev/todos/<id

No output

## Scaling
## Escalado

### AWS Lambda

By default, AWS Lambda limits the total concurrent executions across all functions within a given region to 100. The default limit is a safety limit that protects you from costs due to potential runaway or recursive functions during initial development and testing. To increase this limit above the default, follow the steps in [To request a limit increase for concurrent executions](http://docs.aws.amazon.com/lambda/latest/dg/concurrent-executions.html#increase-concurrent-executions-limit).
Por defecto, AWS Lambda limita el total de ejecuciones simultáneas en todas las funciones dentro de una región dada a 100. El límite por defecto es un límite de seguridad que le protege de los costes debidos a posibles funciones desbocadas o recursivas durante el desarrollo y las pruebas iniciales. Para aumentar este límite por encima del predeterminado, siga los pasos en [Solicitar un aumento del límite para las ejecuciones simultáneas] (http://docs.aws.amazon.com/lambda/latest/dg/concurrent-executions.html#increase-concurrent-executions-limit).

### DynamoDB

When you create a table, you specify how much provisioned throughput capacity you want to reserve for reads and writes. DynamoDB will reserve the necessary resources to meet your throughput needs while ensuring consistent, low-latency performance. You can change the provisioned throughput and increasing or decreasing capacity as needed.

This is can be done via settings in the `serverless.yml`.
Cuando se crea una tabla, se especifica cuánta capacidad de rendimiento provisto se quiere reservar para lecturas y escritos. DynamoDB reservará los recursos necesarios para satisfacer sus necesidades de rendimiento mientras asegura un rendimiento consistente y de baja latencia. Usted puede cambiar el rendimiento provisto y aumentar o disminuir la capacidad según sea necesario.

Esto se puede hacer a través de los ajustes en el `serverless.yml`.
```yaml
ProvisionedThroughput:
ReadCapacityUnits: 1
WriteCapacityUnits: 1
```
In case you expect a lot of traffic fluctuation we recommend to checkout this guide on how to auto scale DynamoDB [https://aws.amazon.com/blogs/aws/auto-scale-dynamodb-with-dynamic-dynamodb/](https://aws.amazon.com/blogs/aws/auto-scale-dynamodb-with-dynamic-dynamodb/)
En caso de que esperes mucha fluctuación de tráfico, te recomendamos que consultes esta guía sobre cómo escalar automáticamente el DynamoDB [https://aws.amazon.com/blogs/aws/auto-scale-dynamodb-with-dynamic-dynamodb/](https://aws.amazon.com/blogs/aws/auto-scale-dynamodb-with-dynamic-dynamodb/)
36 changes: 36 additions & 0 deletions pipeline/ENABLE-UNIR-CREDENTIALS/Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
pipeline {
agent any
stages {
// Limpieza del entorno ante ejecuciones previas
stage('Clean'){
steps {
deleteDir()
sh 'printenv'
}
}
// Configuración de las credenciales temporales de la cuenta educate
stage('Setup Credentials'){
steps {
deleteDir()
sh "echo ${env.CREDENTIALS} > /var/lib/jenkins/.aws/credentials"
writeFile (file: '/var/lib/jenkins/.aws/credentials', text: "${env.CREDENTIALS}")

}
}
// Validación de las credenciales temporales haciendo una petición a la API de aws a través del aws cli
stage('Validate Credentials'){
steps {
deleteDir()
sh "aws s3 ls"
}
}
// Validación del software instalado en el servicio
stage('Validate software'){
steps {
sh 'sam --version'
sh 'aws --version'
sh 'python3.8 --version'
}
}
}
}
1 change: 1 addition & 0 deletions pipeline/PIPELINE-FULL-CD/Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
//A rellenar por el alumno
1 change: 1 addition & 0 deletions pipeline/PIPELINE-FULL-PRODUCTION/Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
// A rellenar por el alumno
86 changes: 86 additions & 0 deletions pipeline/PIPELINE-FULL-STAGING/Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
pipeline {
agent any
stages {
stage('Clean'){
steps {
deleteDir()
sh 'printenv'
}
}

stage('Checkout') {
steps {
// Get some code from a CodeCommit repository
sh "git clone https://${env.CODECOMMIT_USER}:${env.CODECOMMIT_PASSWORD}@git-codecommit.us-east-1.amazonaws.com/v1/repos/todo-list-serverless"
}
}
stage('SetUp'){
steps{
// Setup Virtualenv for testing
}
}
stage('Test'){
steps{
dir("todo-list-serverless/test") {
// Static program analysis -> radon
echo 'Make some cool static program analysis wich radon. IIs the code enought simple to understand?'
}
}
steps{
dir("todo-list-serverless/test") {
// Quality program analysis -> flake8
echo 'echo My code has enought quality?'
}
}
steps{
dir("todo-list-serverless/test") {
// Security programa analysis -> bandit
echo 'Make some security analysis of the code. Is the code secure?'
}
}
steps{
dir("todo-list-serverless/test") {
// Unitary testing -> unittest or pytest
// Coverage report -> coverage
echo 'Execute something like coverage run -m & coverage report -m'
}
}
}
stage('Build') {
steps {
dir("todo-list-serverless") {
// Build release
echo 'Maybe something like sam build?'
// Package release and persist in s3 bucket
sh "sam package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket ${env.COUNTRY}-${env.TEAM}-${env.ENVIRONMENT}-${env.SERVICE}-${env.RAND_ID}-artifacts"
}
}
}
stage('Build') {
steps{
dir("todo-list-serverless/test") {
// Unittest or pytest
// Integration test over local -> unittest or pytest against the lambda functions.
echo 'test all methods works fine. Maybe with sam-local and aws dynamodb official docker image'
}
}
}
stage('Deploy'){
steps{
dir("todo-list-serverless") {
// Deploy architecture
sh "yes | sam deploy --template-file packaged.yaml --stack-name ${env.STACK_NAME} --parameter-overrides Environment=${env.ENVIRONMENT}"
}
}
}
stage('Integration Test after deploy'){
steps{
dir("todo-list-serverless") {
// Unittest or pytest
// Unitary testing -> unittest or pytest against the lambda functions.
echo 'test all methods works fine'
}
}
}
}
}
22 changes: 22 additions & 0 deletions terraform/configure_environment.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash


# Download terraform
wget https://releases.hashicorp.com/terraform/0.14.3/terraform_0.14.3_linux_amd64.zip
# Unzip terraform
unzip terraform
# remove terraform zip
rm -f terraform_0.14.3_linux_amd64.zip


# terraform init
./terraform init
# terraform validate
./terraform validate
# terraform plan -out plan
./terraform plan -out=plan
# terraform apply plan
yes | ./terraform apply plan

# clean wokspace
rm -rf .terraform
Loading

0 comments on commit 6c960c1

Please sign in to comment.