<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: camilo cabrales</title>
    <description>The latest articles on DEV Community by camilo cabrales (@cecamilo).</description>
    <link>https://dev.to/cecamilo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F714407%2F1d4b4bcb-02f0-4e52-be5e-6d2f2ab99ded.jpeg</url>
      <title>DEV Community: camilo cabrales</title>
      <link>https://dev.to/cecamilo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cecamilo"/>
    <language>en</language>
    <item>
      <title>IA Generativa en el desarrollo de Software</title>
      <dc:creator>camilo cabrales</dc:creator>
      <pubDate>Tue, 05 Nov 2024 22:27:18 +0000</pubDate>
      <link>https://dev.to/cecamilo/ia-generativa-en-el-desarrollo-de-software-350c</link>
      <guid>https://dev.to/cecamilo/ia-generativa-en-el-desarrollo-de-software-350c</guid>
      <description>&lt;p&gt;La IA Generativa nos da muchas oportunidades para mejorar, crear y aprender cuando vamos a crear o actualizar software.&lt;/p&gt;

&lt;p&gt;Cuando empece en el desarrollo de software los IDE eran muy incipientes y no tenían muchas funcionalidades ni siquiera auto completar, después fueron mejorando con otras funcionalidades hasta llegar hasta el tiempo de la IA donde con unas simples instrucciones podemos obtener bastante código funcional y en poco tiempo. Ahora con esta aceleración a llegado un cambio exponencial para las personas que desarrollamos ya que nos debemos y tenemos que acostumbrarnos y aprender a usar estas herramientas para sacar el mejor provecho de ellas.&lt;/p&gt;

&lt;p&gt;Hay muchas herramientas en el mercado especializadas en desarrollo de software las cuales podemos usar como:&lt;/p&gt;

&lt;p&gt;Amazon Q&lt;br&gt;
GitHub Copilot&lt;br&gt;
Gemini&lt;br&gt;
Cursor (IDE especializado para IA)&lt;/p&gt;

&lt;p&gt;y todos los LLM que podemos encontrar: ChatGPT, Gemini, Claude, LLama, etc.&lt;/p&gt;

&lt;p&gt;Tenemos demasiadas herramientas en este momento sin embargo lo que creo mas importante es que las adoptemos y nos acostumbremos a usarlas en nuestro día a día, para encontrarles la mejor aplicación en nuestras actividades de desarrollo ya que no hay otra forma de encontrarles su utilidad si no las usamos. &lt;br&gt;
En estos momentos en muchos casos no es necesario tener todo un equipo: front, back, qa o arquitectura para crear un proyecto pequeño o mediano ya que estas herramientas nos ayudan a suplir estos roles de cierta forma.&lt;/p&gt;

&lt;p&gt;Con el uso de Amazon Q me apoye para crear el siguiente juego para familiarizarse con los servicios de AWS:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://d3ohjbsa11flwi.cloudfront.net/" rel="noopener noreferrer"&gt;https://d3ohjbsa11flwi.cloudfront.net/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Utilice estas herramientas de IA sobre todo para la creación de la interfaz de usuario ya que no soy experto, reduciendo el tiempo bastante, creo que si lo hubiera hecho solo tal vez me habría tardado mas de dos semanas y con este acelerador me demore solamente un par de días.&lt;/p&gt;

&lt;p&gt;Desde mi punto de vista creo que estas herramientas las van a seguir perfeccionando por lo que es necesario que desde sus "inicios" las aprendamos a usar  ya que en realidad son de bastante ayuda y como en este caso de una persona no experta en front logro un buen resultado en poco tiempo, cuanto mejor seria el resultado en manos de una persona experta en front. Mucho mejor.&lt;/p&gt;

&lt;p&gt;Mi invitación es a que utilicemos estas herramientas para mejorar nuestros desarrollos y crear mejores productos, esto es el presente y futuro del desarrollo. Aprovechémoslo. &lt;/p&gt;

&lt;p&gt;English&lt;/p&gt;

&lt;p&gt;Generative AI gives us many opportunities to improve, create, and learn when we set out to develop or update software.&lt;/p&gt;

&lt;p&gt;When I started in software development, IDEs were very basic and lacked many functionalities, not even offering autocomplete. Over time, they gradually improved with additional features, leading up to today’s AI-driven era, where with just a few instructions, we can generate functional code in very little time. This acceleration has brought an exponential shift for developers like us, as we now need to adapt and learn to use these tools to maximize their potential.&lt;/p&gt;

&lt;p&gt;There are many specialized software development tools available on the market that we can use, such as:&lt;/p&gt;

&lt;p&gt;Amazon Q&lt;br&gt;
GitHub Copilot&lt;br&gt;
Gemini&lt;br&gt;
Cursor (an AI-specialized IDE)&lt;br&gt;
...and all the LLMs we can find: ChatGPT, Gemini, Claude, LLaMA, and so on.&lt;/p&gt;

&lt;p&gt;We have a vast array of tools available at the moment; however, what I believe is most important is that we adopt them and get used to using them daily to find the best application for our development activities. We can’t truly understand their utility unless we actually use them.&lt;/p&gt;

&lt;p&gt;Currently, in many cases, it’s no longer necessary to have an entire team—front-end, back-end, QA, or architecture—to create a small or medium project, as these tools can help us cover these roles to some extent.&lt;/p&gt;

&lt;p&gt;For instance, I used Amazon Q to support the creation of the following game to help people become familiar with AWS services:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://d3ohjbsa11flwi.cloudfront.net/" rel="noopener noreferrer"&gt;https://d3ohjbsa11flwi.cloudfront.net/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I relied heavily on these AI tools, especially for creating the user interface, as I'm not an expert in UI design. This greatly reduced the time; if I had done it alone, it might have taken me over two weeks, but with this accelerator, I completed it in just a couple of days.&lt;/p&gt;

&lt;p&gt;In my opinion, I think these tools will continue to improve, so it’s essential that we learn to use them from these “early stages,” as they are incredibly helpful. In this case, a non-expert in front-end achieved a good result in little time; imagine how much better the outcome would be in the hands of a front-end expert. Much better.&lt;/p&gt;

&lt;p&gt;My invitation is for us to use these tools to improve our development processes and create better products—this is the present and future of development. Let’s make the most of it.&lt;/p&gt;

</description>
      <category>aws</category>
    </item>
    <item>
      <title>Limpiar y preparar grandes cantidades de datos de manera fácil con Glue DataBrew</title>
      <dc:creator>camilo cabrales</dc:creator>
      <pubDate>Mon, 27 Mar 2023 16:48:49 +0000</pubDate>
      <link>https://dev.to/cecamilo/limpiar-y-preparar-grandes-cantidades-de-datos-de-manera-facil-con-glue-databrew-37fc</link>
      <guid>https://dev.to/cecamilo/limpiar-y-preparar-grandes-cantidades-de-datos-de-manera-facil-con-glue-databrew-37fc</guid>
      <description>&lt;p&gt;Usualmente cuando queremos realizar un proceso de ETL (Extraer, Transformar, Cargar) utilizamos algunas herramientas o lenguajes de programación nos ayudan en este proceso. El desarrollo de ETL requiere de ciertos conocimientos técnicos, que nos tomaran un tiempo en adquirir. Para simplificar este proceso AWS tiene un servicio llamado &lt;a href="https://aws.amazon.com/es/glue/features/databrew/" rel="noopener noreferrer"&gt;Glue DataBrew&lt;/a&gt; que nos va a simplificar y agilizar la tarea de realizar las ETL.&lt;/p&gt;

&lt;p&gt;En este post vamos a crear la siguiente arquitectura:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpdu1350xhozdii9f4viu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpdu1350xhozdii9f4viu.png" alt="Arquitectura" width="800" height="2214"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;EL objetivo de esta arquitectura es: Cuando se cargue un archivo al Bucket este llame a una función Lambda que a su vez va a ejecutar una Step Fucntion que va realizar el procesamiento que hallamos definido para nuestro data set y enviara un mensaje de texto si se ejecuto correctamente o si hubo un error durante el procesamiento de la información.  &lt;/p&gt;

&lt;p&gt;Iniciemos creando el Bucket que va almacenar nuestro conjunto de datos y el resultado del proceso de ETL. Para esto buscamos el servicio de S3 y damos click en el botón &lt;em&gt;Create Bucket&lt;/em&gt;, una vez en la pagina de creación del Bucket le damos un nombre (el nombre debe ser úrico en todo AWS), dejamos las opciones por defecto y damos click en el botón en &lt;em&gt;Create Bucket&lt;/em&gt; que se encuentra en la parte inferior de la pantalla.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3199n5afwddht3r95gu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa3199n5afwddht3r95gu.png" alt="Crear Bucket" width="687" height="752"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos a crear dos carpetas en nuestro Bucket una para los archivos que vamos a procesar y otra de resultados. Damos click en el botón &lt;em&gt;Create Folder&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4r4us1zerl9cbu9ku9d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq4r4us1zerl9cbu9ku9d.png" alt="Create Folder" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La carpeta que contiene el archivo a procesar le damos el nombre de &lt;em&gt;procesardata&lt;/em&gt; y la que almacena los &lt;em&gt;resultados&lt;/em&gt; le damos el nombre de resultados. &lt;br&gt;
Creamos la carpeta &lt;em&gt;procesardata&lt;/em&gt; y realizamos el mismo procedimiento para la carpeta de &lt;em&gt;resultados&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjcdq1l5dligs42u509e0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjcdq1l5dligs42u509e0.png" alt="Create Procesardata" width="800" height="755"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creadas las carpetas deberíamos verlas en nuestro Bucket.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvzz8n50qycnyysyg8ks.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuvzz8n50qycnyysyg8ks.png" alt="Folders" width="800" height="216"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora necesitamos subir a la carpeta de &lt;em&gt;procesardata&lt;/em&gt; el archivo con el cual vamos a trabajar damos click en la carpeta y damos click en el botón &lt;em&gt;Upload&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff05uemlybjb2ytke8rsp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff05uemlybjb2ytke8rsp.png" alt="Folders" width="800" height="212"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seleccionamos el &lt;a href="https://github.com/cecamilo00/posts/blob/circleci-project-setup/gluedatabrew/precios.csv" rel="noopener noreferrer"&gt;archivo&lt;/a&gt; y damos click en el botón &lt;em&gt;Upload&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Ya que tenemos el archivo con el cual vamos a trabajar, buscamos el servicio &lt;strong&gt;Glue DataBrew&lt;/strong&gt; una vez en la pagina principal damos click en &lt;em&gt;DataSets&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2khfhs9uxq85dob3zcs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe2khfhs9uxq85dob3zcs.png" alt="Page DataSet" width="800" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la siguiente pantalla seleccionamos el Bucket, el folder &lt;em&gt;procesardata&lt;/em&gt; y el archivo &lt;em&gt;precios.csv&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F882ba98633mdei5s6819.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F882ba98633mdei5s6819.png" alt="DataSet" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para terminar con la creación del DataSet seleccionamos el tipo de archivo el cual estamos utilizando (.CSV separado por comas) e indicamos que la primera fila del archivo es la cabecera y damos click en el botón &lt;em&gt;Create dataset&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ns6ut1x696xfp4vdscq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1ns6ut1x696xfp4vdscq.png" alt="Type File" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creado nuestro DataSet el siguiente paso es crear un proyecto  en el cual vamos a realizar las modificaciones de nuestros datos. para esto damos click en &lt;em&gt;Projects&lt;/em&gt; y luego en el botón &lt;em&gt;Create project&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8p62fxu0sxak91bxphe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl8p62fxu0sxak91bxphe.png" alt="Page Project" width="800" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para crear el proyecto necesitamos la siguiente información:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Nombre del proyecto&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Receta o nombre de la receta si vamos a crear una nueva. La receta son las modificaciones que vamos a realizar al conjunto de datos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Debemos seleccionar el Dataset con el cual vamos a trabajar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Debemos utilizar un rol existente o crear uno nuevo definiendo un prefijo para este.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mvikg3131e6ehj66a3n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mvikg3131e6ehj66a3n.png" alt="Create Project" width="800" height="735"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creado nuestro proyectos veremos una pagina como la siguiente. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;En la parte superior vamos a ver las opciones de uso frecuente de la receta que podemos aplicar a nuestros datos. &lt;/li&gt;
&lt;li&gt;Abajo de la cabecera de nuestros datos vamos a poder observar las estadísticas de cada columna, lo que nos ayuda a tener una idea del comportamiento de los datos que están almacenados dentro de cada una de ellas.&lt;/li&gt;
&lt;li&gt;En la parte derecha de la pantalla tenemos la sección de la receta, donde vamos a poder agregar diferentes tipos de modificaciones a nuestro conjunto de datos. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdiv07coe6v0vrlyehctm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdiv07coe6v0vrlyehctm.png" alt="Page Project" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ya que esta listo nuestro proyecto para trabajar vamos a crear nuestra receta, para esto damos click en el botón &lt;em&gt;Add step&lt;/em&gt; que se encuentra en la sección de la receta.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp7txulpvo19nzi0zm2qb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp7txulpvo19nzi0zm2qb.png" alt="Add step" width="800" height="284"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez damos click en el botón &lt;em&gt;Add step&lt;/em&gt; se despliegan las diferentes opciones que podemos utilizar para modificar los datos. Vamos a seleccionar la opción &lt;em&gt;Change to capital case&lt;/em&gt; de la sección de FORMAT.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97kvlq3m7d4m30aaaekc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97kvlq3m7d4m30aaaekc.png" alt="Capital Case 1" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como la columna PRODUCTO tiene los nombres en mayusculas los vamos a cambiar para que cada palabra empieza por una letra en mayúscula.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3la930iynawa4mqrb55n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3la930iynawa4mqrb55n.png" alt="Capital Case 2" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al dar click en el botón Apply veremos los resultados.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2ztx7vucg7q2oi1rz9i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa2ztx7vucg7q2oi1rz9i.png" alt="Capital Case 3" width="800" height="330"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vemos que las columnas de los días tienen los precios de cada producto, sin embargo si quisiéramos hacer alguna operación matemática sobre ellos no será posible debido a que tienen el signo $. Veamos como podemos eliminar el signo $ de las columnas. &lt;/p&gt;

&lt;p&gt;Vamos al menú superior seleccionamos &lt;em&gt;Clean&lt;/em&gt; y en la sección &lt;em&gt;Remove&lt;/em&gt; seleccionamos &lt;em&gt;Special characters&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbsgbtwglqpg0vwulxyl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftbsgbtwglqpg0vwulxyl.png" alt="Remove Special Characters" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al realizar la selección en sección de &lt;em&gt;Recipies&lt;/em&gt; se nos despliegan las opciones para realizar la limpieza de la columna. Seleccionamos la columna &lt;em&gt;LUNES&lt;/em&gt;,&lt;em&gt;Special characters&lt;/em&gt; y &lt;em&gt;Custom value&lt;/em&gt; para remover el signo - que aparece delante de los ceros. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx75j7ukr94m0ffy14kwe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx75j7ukr94m0ffy14kwe.png" alt="Remove Special Characters 2" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al dar click en el botón &lt;em&gt;Apply&lt;/em&gt; veremos que de la columna LUNES se quitaron los caracteres: - $ y se agrego un nuevo paso a nuestra receta. Este proceso lo puedes realizar para el resto de columnas de los días de la semana.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk0341hnfijrcnpqn6px1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk0341hnfijrcnpqn6px1.png" alt="Remove Special Characters 3" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al finalizar de remover los caracteres especiales de las columnas de los días de la semana, nuestra receta se vera de la siguiente forma.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsdo3zqrlvi1wjurbz0z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbsdo3zqrlvi1wjurbz0z.png" alt="Remove Special Characters 4" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora que nuestras columnas no tienen caracteres especiales vamos a cambiar el tipo de dato para poder realizar algunas operaciones. En la parte superior de cada columna podemos ver el tipo de datos de cada columna, en las columnas de los días de la semana identificamos que son de tipo string y necesitamos cambiarlas a un valor numérico en este caso double.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5igesh1a9qrd9kqa96d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp5igesh1a9qrd9kqa96d.png" alt="Change Type 1" width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al dar click en &lt;em&gt;Change type&lt;/em&gt; se nos presentan las opciones donde debemos seleccionar la columna y el tipo de dato al cual queremos cambiar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnsa9qpgxknwyq8qf6en.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frnsa9qpgxknwyq8qf6en.png" alt="Change Type 2" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Damos click en el botón &lt;em&gt;Apply&lt;/em&gt; dando como resultado el cambio de tipo de columna y un nuevo paso se agrego a nuestra receta. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbj5t30dcgwp1bgwda2d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgbj5t30dcgwp1bgwda2d.png" alt="Change Type 3" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Debemos hacer este mismo procedimiento a las otras columnas, para que nuestra receta quede de la siguiente forma.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c5ol4eft1k1hy4uh6o4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2c5ol4eft1k1hy4uh6o4.png" alt="Change Type 4" width="800" height="334"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para terminar con nuestra receta vamos a crear un nueva columna llamada Total que va almacenar la suma de los días &lt;em&gt;LUNES&lt;/em&gt; Y &lt;em&gt;VIERNES&lt;/em&gt;.&lt;br&gt;
Hacemos click en botón &lt;em&gt;FUNCTIONS&lt;/em&gt; - Math functions - &lt;em&gt;ADD&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4epe8pkwusrwd6ahci8j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4epe8pkwusrwd6ahci8j.png" alt="Sum1" width="800" height="335"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la sección de la receta veremos las opciones donde seleccionamos el tipo de función (ADD), las columnas que vamos a sumar (LUNES Y VIERNES) y por ultimo damos el nombre de la columna que va almacenar el resultado (Total).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ihkthwlad1ng08d2hck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ihkthwlad1ng08d2hck.png" alt="Sum2" width="800" height="351"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al dar click en el botón &lt;em&gt;Apply&lt;/em&gt; vemos que se creo la columna total y contiene la suma de las columnas &lt;em&gt;LUNES&lt;/em&gt; Y &lt;em&gt;VIERNES&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjr0v6s2nxy4ib80c9qra.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjr0v6s2nxy4ib80c9qra.png" alt="Sum3" width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con esto finalizamos la modificación de nuestro DataSet, ahora necesitamos definir como se van a ejecutar estas modificaciones por lo tanto necesitamos crear un Job.&lt;br&gt;
Damos click en el botón &lt;em&gt;Create job&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23g9z9dxdj3r43t6ygv2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F23g9z9dxdj3r43t6ygv2.png" alt="Select Job" width="800" height="329"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la pantalla de creación del Job le asignamos un nombre al Job, seleccionamos el Bucket y la carpeta en la cual queremos que se almacenen los resultados (Bucket y carpeta que creamos al inicio) y le asignamos un rol que puede ser el que creamos  al momento de configurar el proyecto o uno nuevo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdh32rugnjf38fh7vcjcw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdh32rugnjf38fh7vcjcw.png" alt="Create Job" width="800" height="820"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al crearse el Job vamos a ver el listado con los Jobs que hayamos creado, seleccionamos el Job que acabamos de crear y damos click en el botón &lt;em&gt;Run Job&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffn7p2bc7hud9emgx3xk2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffn7p2bc7hud9emgx3xk2.png" alt="Run Job" width="800" height="174"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para ver los resultados podemos ir a la carpeta &lt;em&gt;resultados&lt;/em&gt; del Bucket que creamos y ver el archivo que genero el Job.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk3jgbprukl4lmyn05l55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk3jgbprukl4lmyn05l55.png" alt="Results Job" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hemos visto como crear, modificar un DataSet y obtener los resultados por medio de las recetas y los Jobs. &lt;br&gt;
Ahora necesitamos implementar los siguientes servicios para completar nuestra arquitectura:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Un Topic y una Suscripción de SNS para enviar los mensajes de notificación.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Una Step Function que va a realizar todo el flujo para procesar el Dataset, modificando el Dataset para que tome el archivo que se suba a S3, ejecutar el Job y enviar una mensaje de texto para notificar que el proceso se realizo correctamente.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Una función Lambda que se va encargar de llamar a la Step Function cuando se suba un archivo al Bucket de S3.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Esta implementación la vamos a realizar con la siguiente &lt;a href="https://github.com/cecamilo00/posts/blob/circleci-project-setup/gluedatabrew/gluedatabrew.tf" rel="noopener noreferrer"&gt;plantilla&lt;/a&gt; de Terraform.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
  region = "us-east-1"
}


resource "random_id" "random" {
  byte_length = 2
}

variable "job_name"{
    type= string
    default= "PreciosJob"
}

variable "bucket_name" {
    type = string
    default = "datosgluedatabrew"
}

variable "telefono"{
    type = string
    default = "+573005465765"
}

resource "aws_lambda_function" "lambda_function_call_step_function" {
  filename      = "lambda_function.py.zip"
  function_name = "LambdaStepFunction-${random_id.random.hex}"
  role          = aws_iam_role.lambda_execution_role.arn
  handler       = "lambda_function.lambda_handler"
  runtime       = "python3.8"
  memory_size   = 128
  timeout       = 5
  environment {
    variables = {
      STEPFUNCTIONARN = aws_sfn_state_machine.function.arn
    }
  }
}

resource "aws_iam_role" "lambda_execution_role" {
  name = "lambda_execution_role-${random_id.random.hex}"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "lambda.amazonaws.com"
        }
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "lambda_execution_role_policy_attach" {
  policy_arn = "arn:aws:iam::aws:policy/AWSStepFunctionsFullAccess"
  role       = aws_iam_role.lambda_execution_role.name
}

resource "aws_iam_role_policy_attachment" "lambda_execution_role_cloudwatch_attach" {
  policy_arn = "arn:aws:iam::aws:policy/CloudWatchLogsFullAccess"
  role       = aws_iam_role.lambda_execution_role.name
}


resource "aws_lambda_permission" "s3_permission_to_trigger_lambda" {
  statement_id  = "AllowExecutionFromS3Bucket"
  action        = "lambda:InvokeFunction"
  function_name = aws_lambda_function.lambda_function_call_step_function.arn
  principal     = "s3.amazonaws.com"
  source_arn    = "arn:aws:s3:::${var.bucket_name}"
}

resource "aws_s3_bucket_notification" "bucket_notification_put" {
  bucket = "${var.bucket_name}"

  lambda_function {
    lambda_function_arn = aws_lambda_function.lambda_function_call_step_function.arn
    events              = ["s3:ObjectCreated:Put"]
    filter_prefix = "procesardata/"
    filter_suffix = ".csv"
  }
  depends_on = [aws_lambda_permission.s3_permission_to_trigger_lambda]
}


resource "aws_sfn_state_machine" "function" {
  name     = "StateMachineGlueDataBrew-${random_id.random.hex}"
  role_arn = aws_iam_role.function_role.arn

  definition = &amp;lt;&amp;lt;DEFINITION
    {
  "Comment": "A description of my state machine",
  "StartAt": "Actualizar DataSet",
  "States": {
    "Actualizar DataSet": {
      "Type": "Task",
      "Parameters": {
        "Format": "CSV",
        "Input": {
          "S3InputDefinition": {
            "Bucket.$": "$.bucket",
            "BucketOwner.$": "$.cuenta",
            "Key.$": "$.carpeta"
          }
        },
        "Name": "Precios"
      },
      "Resource": "arn:aws:states:::aws-sdk:databrew:updateDataset",
      "Next": "Ejecutar Job"
    },
    "Ejecutar Job": {
      "Type": "Task",
      "Resource": "arn:aws:states:::databrew:startJobRun",
      "Parameters": {
        "Name": "${var.job_name}"
      },
      "Catch": [
        {
          "ErrorEquals": [
            "DataBrew.ConflictException"
          ],
          "Next": "SNS Error"
        }
      ],
      "Next": "SNS Job Ejecutado"
    },
    "SNS Error": {
      "Type": "Task",
      "Resource": "arn:aws:states:::sns:publish",
      "Parameters": {
        "Message": {
          "Mensaje": "Se produjo un error"
        },
        "TopicArn": "${aws_sns_topic.topic_glue_databrew.arn}"
      },
      "End": true
    },
    "SNS Job Ejecutado": {
      "Type": "Task",
      "Resource": "arn:aws:states:::sns:publish",
      "Parameters": {
        "TopicArn": "${aws_sns_topic.topic_glue_databrew.arn}",
        "Message": {
          "Mensaje": "Se ejecuto el job correctamente"
        }
      },
      "End": true
    }
  }
}
  DEFINITION
}

resource "aws_iam_role" "function_role" {
  name = "my-state-machine-role-${random_id.random.hex}"

  assume_role_policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = "sts:AssumeRole"
        Effect = "Allow"
        Principal = {
          Service = "states.amazonaws.com"
        }
      }
    ]
  })
}

resource "aws_iam_role_policy_attachment" "function_policy_role_sns" {
  policy_arn = "arn:aws:iam::aws:policy/AmazonSNSFullAccess"
  role       = aws_iam_role.function_role.name
}

resource "aws_iam_role_policy_attachment" "lambda_policy_glue_data_brew" {
  policy_arn = "arn:aws:iam::aws:policy/AwsGlueDataBrewFullAccessPolicy"
  role       = aws_iam_role.function_role.name
}

resource "aws_sns_topic" "topic_glue_databrew" {
  name = "topic_glue_databrew-${random_id.random.hex}"
}

resource "aws_sns_topic_subscription" "subscription_glue_databrew" {
  topic_arn = aws_sns_topic.topic_glue_databrew.arn
  protocol  = "sms"
  endpoint  = "${var.telefono}"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De la plantilla anterior debemos modificar las variables y la región en la cual se van desplegar los servicios. &lt;/p&gt;

&lt;p&gt;La región.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
   region = "us-east-1"
 }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El nombre que le dimos la Job.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "job_name"{
    type= string
    default= "PreciosJob"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El nombre que le dimos al Bucket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "bucket_name" {
    type = string
    default = "datosgluedatabrew"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El numero de teléfono al cual queremos que lleguen los mensajes cuando se ejecuta el Job.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "telefono"{
    type = string
    default = "+573005465765"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez que hemos modificado las variables de acuerdo a nuestras configuraciones podemos validar y ejecutar la plantilla.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Valida la plantilla
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform validate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Crea los servicios. Recuerda que la &lt;a href="https://github.com/cecamilo00/posts/blob/circleci-project-setup/gluedatabrew/gluedatabrew.tf" rel="noopener noreferrer"&gt;plantilla&lt;/a&gt; y el &lt;a href="https://github.com/cecamilo00/posts/blob/circleci-project-setup/gluedatabrew/lambda_function.py.zip" rel="noopener noreferrer"&gt;código&lt;/a&gt; de la función &lt;em&gt;Lambda&lt;/em&gt; se encuentren en la misma carpeta.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez terminada la ejecución del comando, vamos a revisar que los servicios se hayan desplegado correctamente.&lt;/p&gt;

&lt;p&gt;Buscamos &lt;em&gt;SNS&lt;/em&gt; y damos click en &lt;em&gt;Topics&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwbnkytrs8r66ntjgp75.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwbnkytrs8r66ntjgp75.png" alt="SNS" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Buscamos la función &lt;em&gt;Lambda&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fne0q9lqe04egj80yxqab.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fne0q9lqe04egj80yxqab.png" alt="Lambda" width="800" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Buscamos la &lt;em&gt;Step Function&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ev7fvlaijipkyijxqap.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ev7fvlaijipkyijxqap.png" alt="Step Function" width="800" height="107"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como todos los servicios fueron desplegados con éxito vamos a subir un nuevo archivo al &lt;em&gt;Bucket&lt;/em&gt; para que se procese el archivo con la llamada a la  función &lt;em&gt;Lambda&lt;/em&gt; y la &lt;em&gt;Step Function&lt;/em&gt;, cuando esta termina su proceso damos click en el nombre de la &lt;em&gt;Step Function&lt;/em&gt;  y damos click en la ultima ejecución para ver el gráfico del proceso.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F644a3i1fhp07fd3f56tg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F644a3i1fhp07fd3f56tg.png" alt=" Exec Step Function" width="800" height="352"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con esto finalizamos la implementación y pruebas de la arquitectura planteada al inicio.Pueden realizar mas pruebas modificando la receta o agregando mas pasos a la &lt;em&gt;Step Funcion&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Para no incurrir en ningún costo pueden borrar el proyecto de &lt;em&gt;Glue DataBrew&lt;/em&gt;, el Bucket y para eliminar los servicios creados con &lt;em&gt;Terraform&lt;/em&gt; pueden utilizar el siguiente comando.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Me pueden encontrar en&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/camilo-cabrales-31a0bb53/" rel="noopener noreferrer"&gt;Camilo Cabrales&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Referencias
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/databrew/latest/dg/api-reference.html" rel="noopener noreferrer"&gt;API&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
    </item>
    <item>
      <title>Tunea tus funciones Lambda</title>
      <dc:creator>camilo cabrales</dc:creator>
      <pubDate>Thu, 09 Mar 2023 23:30:50 +0000</pubDate>
      <link>https://dev.to/cecamilo/tunea-tus-funciones-lambda-31a4</link>
      <guid>https://dev.to/cecamilo/tunea-tus-funciones-lambda-31a4</guid>
      <description>&lt;p&gt;Las funciones Lambda tienen un tiempo limitado a 15 minutos para procesar cada solicitud. Por este motivo debemos seleccionar de manera optima la cantidad de memoria que asignamos a nuestra función.&lt;/p&gt;

&lt;p&gt;Con el objetivo de encontrar el rendimiento optimo para nuestra función se creo un proyecto en &lt;a href="https://github.com/alexcasalboni/aws-lambda-power-tuning" rel="noopener noreferrer"&gt;Git - aws-lambda-power-tuning&lt;br&gt;
Public&lt;/a&gt; que nos va ayudar a encontrar la cantidad de memoria que requiere nuestra función para su optimo funcionamiento.&lt;/p&gt;

&lt;p&gt;Este proyecto crea un Step Function que de acuerdo a los parámetros de memoria que le enviamos va a ejecutar la función Lambda que definamos, retornándonos los tiempos de respuesta y un consto aproximado por ejecución de cada una de los parámetros que le definimos.&lt;/p&gt;

&lt;p&gt;En la pagina del proyecto podemos encontrar diferentes formas de realizar el despliegue de los servicios requeridos para ejecutarlo. En este caso vamos a utilizar el despliegue usando SAM como lo mencionan en la &lt;a href="https://github.com/alexcasalboni/aws-lambda-power-tuning/blob/master/README-DEPLOY.md" rel="noopener noreferrer"&gt;pagina - opción 2&lt;/a&gt;.&lt;br&gt;
Nota: hay que tener &lt;a href="https://www.docker.com/" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; instalado y corriendo para poder ejecutar la plantilla de SAM.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install the AWS SAM CLI in your local environment.

Configure your AWS credentials (requires AWS CLI installed):

$ aws configure
Clone this git repository:

$ git clone https://github.com/alexcasalboni/aws-lambda-power-tuning.git
Build the Lambda layer and any other dependencies (Docker is required):

$ cd ./aws-lambda-power-tuning
$ sam build -u
sam build -u will run SAM build using a Docker container image that provides an environment similar to that which your function would run in. SAM build in-turn looks at your AWS SAM template file for information about Lambda functions and layers in this project.

Once the build has completed you should see output that states Build Succeeded. If not there will be error messages providing guidance on what went wrong.

Deploy the application using the SAM deploy "guided" mode:

$ sam deploy -g

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En el transcurso del despliegue nos va ir solicitando algunos datos que utiliza la plantilla para su despliegue, los cuales podemos dejar los que vienen por defecto dando ENTER cuando nos los solicite.&lt;/p&gt;

&lt;p&gt;Una vez desplegada la infraestructura, vamos a crear una función Lambda a la cual queremos hacer un tuning en la asignación de la memoria. Esta función nos ayuda a calcular el factorial de un numero grande. Se eligió este tipo de calculo ya que puede tardar varios segundos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0bdkyre8yqsqp5d0iuy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0bdkyre8yqsqp5d0iuy.png" alt="Crear funcion" width="800" height="345"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pegamos el código fuente y damos click en &lt;strong&gt;Deploy&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json
import sys
sys.set_int_max_str_digits(1000000000)

def CalcularFactorial(numero):
    resultado = 1
    for i in range(1, numero+1):
        resultado *= i
    return resultado


def lambda_handler(event, context):
    numero = 30000
    print(CalcularFactorial(numero))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fasignar%2520codigo%25202.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fasignar%2520codigo%25202.png%3Fraw%3Dtrue" alt="Asignar codigo" width="800" height="415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora que hemos creado la función Lambda, vamos a realizar las pruebas de tuning, para esto vamos a buscar el servicio Step Functions y la función que comienza con el nombre &lt;em&gt;powerTuningStateMachine&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fstep%2520function.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fstep%2520function.png%3Fraw%3Dtrue" alt="Step Function" width="800" height="22"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Damos click en el nombre y despues en &lt;em&gt;Star Execution&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fstart%2520execution1.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fstart%2520execution1.png%3Fraw%3Dtrue" alt="Star Function" width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Después ingresamos los parámetros que requiere la función:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "lambdaARN": "arn:aws:lambda:us-east-1:385033107168:function:Factorial",
    "powerValues": [256, 512, 1024],
    "num": 50,
    "payload": {},
    "strategy": "balanced"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En este caso le pasamos el arn de la función Lambda que acabamos de crear, la cantidad de memoria con la cual queremos que se ejecute, el numero de ejecuciones y la estrategia que es este caso es &lt;em&gt;balanced&lt;/em&gt;, que sirve para encontrar la mejor relación velocidad precio por ejecución. Podemos encontrar la documentación de los parametros en este &lt;a href="https://github.com/alexcasalboni/aws-lambda-power-tuning/blob/master/README-INPUT-OUTPUT.md#user-content-state-machine-input" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fstart%2520execution%25203.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fstart%2520execution%25203.png%3Fraw%3Dtrue" alt="Star Function 2" width="800" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora veamos el resultado de la ejecución:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fresult%2520execution%25201.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fresult%2520execution%25201.png%3Fraw%3Dtrue" alt="Result 1" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En esta ejecución podemos identificar que el tiempo (3 segundos) que tiene configurado por defecto la función Lambda no es suficiente para completar la tarea que debe realizar. Lo que debemos hacer es incrementar el tiempo que tiene la función Lambda para completar la tarea.&lt;br&gt;
Vamos a la función Lambda y modificamos el tiempo de ejecución.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fgeneral%2520configuration.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fgeneral%2520configuration.png%3Fraw%3Dtrue" alt="General Configuration" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Definimos el tiempo a 3 minutos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fbasic%2520settings1.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fbasic%2520settings1.png%3Fraw%3Dtrue" alt="Set Time" width="753" height="874"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Modificado el tiempo de ejecución vamos nuevamente a la &lt;em&gt;Step Fuction&lt;/em&gt; y damos click en &lt;em&gt;Start Execution&lt;/em&gt; y copiamos los parámetros anteriores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Ffinal%2520result%25201.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Ffinal%2520result%25201.png%3Fraw%3Dtrue" alt="Final Execution" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al terminar la ejecución podemos ver los resultados del análisis el cual nos indica que la cantidad de memoria que que tiene mejor relación tiempo - precio es 1024.En caso que deseemos ver los resultados de una manera mas gráfica podemos copiar el link que aparece en el output y pegarlo en un navegador y veremos una pagina como la siguiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fgraphic%2520result.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fgraphic%2520result.png%3Fraw%3Dtrue" alt="Graphics Results" width="800" height="343"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;EL gráfico nos facilita realizar el análisis del comportamiento de la función de acuerdo a la cantidad de memoria asignada a la función Lambda.&lt;/p&gt;

&lt;p&gt;Por ultimo si no queremos tener los servicios que se desplegaron con SAM debemos ir a CloudFormation y eliminar la plantilla para que se borren todos los servicios.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fdelete%2520template.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FLambdaTuning%2Fdelete%2520template.png%3Fraw%3Dtrue" alt="Delete Template" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Me pueden encontrar en&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/camilo-cabrales-31a0bb53/" rel="noopener noreferrer"&gt;Camilo Cabrales&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Referencias
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/alexcasalboni/aws-lambda-power-tuning/blob/master/README-DEPLOY.md" rel="noopener noreferrer"&gt;Despliegue Lambda Power Tools&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/es_es/lambda/latest/dg/gettingstarted-limits.html" rel="noopener noreferrer"&gt;Cuotas Lambda&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>lambda</category>
    </item>
    <item>
      <title>Definición de arquitectura con Application Composer para análisis de documentos con Textract</title>
      <dc:creator>camilo cabrales</dc:creator>
      <pubDate>Fri, 09 Dec 2022 19:57:23 +0000</pubDate>
      <link>https://dev.to/cecamilo/definicion-de-arquitectura-con-application-composer-para-analisis-de-documentos-con-textract-2b5</link>
      <guid>https://dev.to/cecamilo/definicion-de-arquitectura-con-application-composer-para-analisis-de-documentos-con-textract-2b5</guid>
      <description>&lt;p&gt;Este mes (Diciembre de 2022) AWS lanzo un nuevo servicio llamado &lt;strong&gt;Application Composer&lt;/strong&gt;, que nos sirve para la definición de arquitecturas Serverless de manera gráfica e intuitiva, donde podemos arrastrar los diferentes servicios en el espacio de trabajo con el objetivo de definir nuestra arquitectura.&lt;/p&gt;

&lt;p&gt;En este post vamos a definir una arquitectura que nos va a permitir extraer el texto de varias facturas para llevar el control de nuestros gastos.&lt;/p&gt;

&lt;p&gt;Iniciemos buscando el Servicio &lt;strong&gt;Application Composer&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnxant0o8ygx8fvst0zz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnxant0o8ygx8fvst0zz.png" alt="Init Page" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Y en la pagina principal le damos click en Canvas, que nos va a mostrar las opciones de creación de nuestra arquitectura. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fornr1ehfrxvyklcj706z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fornr1ehfrxvyklcj706z.png" alt="Create Project" width="800" height="374"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vemos dos opciones para la creación de nuestra arquitectura conectada y no conectada. La opción conectada va a sincronizar los cambios que realicemos en una carpeta de nuestro equipo y no conectada nosotros somos los encargados de guardar nuestra arquitectura. &lt;br&gt;
Seleccionamos la opción no conectada y damos click en crear.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faafcgliuh6ak2dv3v2ck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faafcgliuh6ak2dv3v2ck.png" alt="Canvas" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como podemos ver la pantalla es muy intuitiva y podemos encontrar los servicios que podemos incluir, la vista de diseño, la vista de la plantilla de SAM que se va generando de acuerdo vamos incluyendo servicios en nuestra arquitectura y el ménu.&lt;/p&gt;

&lt;p&gt;Vamos a crear la siguiente arquitectura arrastrando los servicios al Canvas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbz2au2viqqinh36nin0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbz2au2viqqinh36nin0e.png" alt="Canvas" width="800" height="364"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora vamos a configurar algunas de las propiedades que están disponibles desde el diseñador.&lt;/p&gt;

&lt;p&gt;Para el Bucket configuramos el nombre:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsbcrccutto4gi5ys8xp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsbcrccutto4gi5ys8xp.png" alt="Bucket" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para la función Lambda configuramos el nombre, el runtime, la memoria y el tiempo de ejecución:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwcx7cjimij9frx4z3d2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjwcx7cjimij9frx4z3d2.png" alt="Lambda" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para la tabla de DynamoDB le definimos un nombre  y el nombre de la primarykey:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfyv9zzuttsyr4i7hkzb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfyv9zzuttsyr4i7hkzb.png" alt="DynamoDB" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora podemos visualizar la plantilla generada y guardamos el archivo desde el menú.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvz77224qsez6y7h858kv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvz77224qsez6y7h858kv.png" alt="Template" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Antes de validar y modificar nuestra plantilla, vamos a ver el servicio &lt;a href="https://aws.amazon.com/es/textract/" rel="noopener noreferrer"&gt;Textract&lt;/a&gt; que nos sirve para extraer texto de diferentes tipos de documentos.&lt;/p&gt;

&lt;p&gt;Para esto buscamos el servicio Textract, en la pantalla principal del servicio damos click en &lt;em&gt;Analyze Document&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9hgepckcsysk6d0cmx5e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9hgepckcsysk6d0cmx5e.png" alt="Textract" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la pagina podemos ver los resultados de la extracción de texto de un documento de ejemplo que nos brinda AWS y las formas con las cuales podemos obtener la información, que son: texto plano, formularios, tablas, consultas o firmas. Para nuestro caso vamos utilizar consultas (queries). &lt;/p&gt;

&lt;p&gt;Ahora utilicemos una de las imágenes de nuestro ejemplo.&lt;/p&gt;

&lt;p&gt;Primero seleccionamos la &lt;a href="https://github.com/cecamilo00/posts/tree/circleci-project-setup/applicationcomposer/facturas" rel="noopener noreferrer"&gt;imagen&lt;/a&gt; de la cual queremos extraer el texto: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnxpmv7jlsx31i54ca1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnxpmv7jlsx31i54ca1z.png" alt="Select File" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora seleccionamos como queremos ver los resultados (Forms,Tables,Queries) y agregamos las consultas que vamos hacer sobre el documento. Es importante que todas las consultas empiecen por &lt;strong&gt;&lt;em&gt;what&lt;/em&gt;&lt;/strong&gt; o &lt;strong&gt;&lt;em&gt;where&lt;/em&gt;&lt;/strong&gt;, en este caso utilice una mezcla de ingles y español para que Textract encontrara los resultados de manera mas acertada, ya que si hacia los queries solo en ingles no encontraba de manera correcta los valores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2zt3ytp8j910sv5hfxi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi2zt3ytp8j910sv5hfxi.png" alt="Select Queries" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al final Textract nos muestra los resultados en los formatos que hallamos seleccionado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp9ocdujm3ke5p846z2he.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp9ocdujm3ke5p846z2he.png" alt="Result Queries" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ya que hemos visto el funcionamiento de Textract vamos a ver como podemos realizar esto de manera asíncrona con la arquitectura que definimos al inicio del post.&lt;/p&gt;

&lt;p&gt;Vamos hacer algunas modificaciones a la plantilla que descargamos de &lt;strong&gt;Application Composer&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Empecemos modificando la sección de la funcion Lambda agregando las políticas &lt;strong&gt;&lt;em&gt;TextractDetectAnalyzePolicy&lt;/em&gt;,CloudWatchPutMetricPolicy,S3FullAccessPolicy&lt;/strong&gt;  &lt;strong&gt;Lambda&lt;/strong&gt; y después agregamos el código fuente de la función.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3
import urllib

textract = boto3.client('textract')
dynamodb = boto3.client('dynamodb')

class Factura:

    def __init__(self, idFactura="", fechaFactura="", valorAPagar="",nombreArchivo=""):
        self.idFactura = idFactura
        self.fechaFactura = fechaFactura
        self.valorAPagar = valorAPagar
        self.nombreArchivo = nombreArchivo

    def getNombreArchivo(self):
        return self.nombreArchivo

    def getIdFactura(self):
        return self.idFactura

    def getFechaFactura(self):
        return self.fechaFactura

    def getValorAPagar(self):
        return self.valorAPagar

    def setIdFactura(self, idFactura):
        self.idFactura = idFactura

    def setFechaFactura(self, fechaFactura):
        self.fechaFactura = fechaFactura

    def setValorAPagar(self, valorAPagar):
        self.valorAPagar = valorAPagar

    def setNombreArchivo(self, nombreArchivo):
        self.nombreArchivo = nombreArchivo

def lambda_handler(event, context):
    # TODO implement
    bucket = event['Records'][0]['s3']['bucket']['name']
    nombreObjeto = urllib.parse.unquote_plus(event['Records'][0]['s3']['object']['key'], encoding='utf-8')

    response = textract.analyze_document(
        Document={
            'S3Object': {
                'Bucket': bucket,
                'Name': nombreObjeto
            }
        },
        FeatureTypes=["QUERIES"],
        QueriesConfig={
            "Queries": [{
                "Text": "What is the Fecha vencimiento y pago",
                "Alias": "Fecha de pago"
            },
                {
                "Text": "What is the Total a pagar",
                "Alias": "Valor a pagar"
            },
                {
                "Text": "What is the BEC",
                "Alias": "Numero de Factura"
            }]
        })
    blocks = response['Blocks']
    i = 0
    factura = Factura()
    factura.setNombreArchivo(nombreObjeto)
    for block in blocks:
        if block['BlockType'] == "QUERY_RESULT":
            if float(block['Confidence']) &amp;gt;= 60:
                if i == 0:
                    factura.setFechaFactura(block["Text"])
                elif i == 1:
                    factura.setValorAPagar(block["Text"])
                elif i == 2:
                    factura.setIdFactura(block["Text"])
            i += 1
            print(block)
    result = dynamodb.put_item(
        TableName='datosfacturas',
        Item={
            'PK': {'S': factura.getIdFactura()},
            'FechaPago': {'S': factura.getFechaFactura()},
            'ValorPago': {'S': factura.getValorAPagar()},
            'NombreArchivo': {'S': factura.getNombreArchivo()}
        },
        ConditionExpression="attribute_not_exists(PK)"
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cuando ejecutamos el código vamos a obtener un error. &lt;br&gt;
De acuerdo a la que encontré me di cuenta que al parecer se debe a la versión de boto3 que tiene Lambda configurada, para solucionar este error debemos crear una Layer con una versión mas actualizada de Boto3.&lt;/p&gt;

&lt;p&gt;Para saber la versión de Boto3 que maneja Lambda se puede ejecutar dentro de la función:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;print(boto3.__version__)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Que en mi caso el resultado es: &lt;em&gt;1.26.23&lt;/em&gt; y la version actual en este momento de Boto3 es: &lt;em&gt;1.26.26&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Para dar solución vamos a crear el &lt;a href="https://aws.amazon.com/es/premiumsupport/knowledge-center/lambda-python-runtime-errors/#:~:text=All%20AWS%20services%20and%20arguments,of%20Boto%203%20and%20Botocore." rel="noopener noreferrer"&gt;Layer&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LIB_DIR=boto3-mylayer/python
mkdir -p $LIB_DIR

pip3 install boto3 -t $LIB_DIR

cd boto3-mylayer
zip -r /tmp/boto3-mylayer.zip .

aws lambda publish-layer-version --layer-name boto3updated --zip-file fileb:///tmp/boto3-mylayer.zip --compatible-runtimes "python3.7" "python3.8"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez creado el Layer debemos copiar el ARN y agregarlo al template.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwbpdioy6s7raifajfqn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffwbpdioy6s7raifajfqn.png" alt="Layer" width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez creada la Layer y realizados los cambios en la plantilla vamos a validar y desplegar los servicios.&lt;/p&gt;

&lt;p&gt;Para validar la &lt;a href="https://github.com/cecamilo00/posts/blob/circleci-project-setup/applicationcomposer/textract.yml" rel="noopener noreferrer"&gt;plantilla&lt;/a&gt; debemos ejecutar el siguiente comando desde la terminal (textract.yml es el nombre que le dimos a nuestra plantilla).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sam validate --template textract.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Al ejecutar este comando debemos ver en la terminal algo como  esto:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0rn1hpz721cf0nxwlhr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs0rn1hpz721cf0nxwlhr.png" alt="SAM Validate" width="710" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora que la validación de nuestra plantilla es correcta debemos eejecutar el siguiente comando para desplegar los servicios de nuestra arquitectura.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sam deploy --template textract.yml --stack-name textractinvoices --capabilities CAPABILITY_IAM
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El resultado del comando es el siguiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9d0kjzgnnzxsxeou1xus.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9d0kjzgnnzxsxeou1xus.png" alt="Deploy" width="800" height="602"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hemos finalizado con el despliegue satisfactoriamente, ahora podemos ingresar a S3 y subir los &lt;a href="https://github.com/cecamilo00/posts/tree/circleci-project-setup/applicationcomposer/facturas" rel="noopener noreferrer"&gt;archivos de prueba&lt;/a&gt; al bucket y validar en DynamoDB que los datos se hayan ingresado correctamente. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Application Composer&lt;/strong&gt; es un nuevo servicio que como tal hacen algunas cosas por afinar como: agregar mas opciones de edición a cada servicio, mejorar como se generan las plantillas, sin embargo es una muy opción para definir arquitecturas Serverless y tener una plantilla SAM base que nos ayude a mejorar nuestros tiempos de desarrollo.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Archivos del post:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/cecamilo00/posts/blob/circleci-project-setup/applicationcomposer/textract.yml" rel="noopener noreferrer"&gt;plantilla&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/cecamilo00/posts/tree/circleci-project-setup/applicationcomposer/facturas" rel="noopener noreferrer"&gt;archivos de prueba&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Me pueden encontrar en&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/camilo-cabrales-31a0bb53/" rel="noopener noreferrer"&gt;Camilo Cabrales&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Referencias
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/textract.html" rel="noopener noreferrer"&gt;Textract Boto3&lt;/a&gt;&lt;br&gt;
&lt;a href="https://aws.amazon.com/es/premiumsupport/knowledge-center/lambda-python-runtime-errors/#:~:text=All%20AWS%20services%20and%20arguments,of%20Boto%203%20and%20Botocore." rel="noopener noreferrer"&gt;Crear Layer Boto3&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dsa</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>Tips para aprobar las certificaciones Associate de AWS</title>
      <dc:creator>camilo cabrales</dc:creator>
      <pubDate>Wed, 16 Nov 2022 21:45:55 +0000</pubDate>
      <link>https://dev.to/cecamilo/tips-para-aprobar-las-certificaciones-associate-de-aws-399g</link>
      <guid>https://dev.to/cecamilo/tips-para-aprobar-las-certificaciones-associate-de-aws-399g</guid>
      <description>&lt;p&gt;En este post vamos a ver algunas de las actividades que realice para aprobar las certificaciones de nivel asociado que ofrece AWS.&lt;/p&gt;

&lt;p&gt;Veamos el porque:&lt;/p&gt;

&lt;p&gt;Para mi el objetivo principal de realizar las certificaciones  es aprender mas sobre los servicios AWS. Vi que realizar una certificación era una de las mejores manera de adquirir y afianzar los conocimientos. Ademas las certificaciones en algunos empleos son requeridas lo cual es un plus tenerlas. &lt;/p&gt;

&lt;p&gt;Por donde empezar. Creo que si no se tiene experiencia en AWS la mejor manera de empezar es por lo básico por tener una noción de general de los servicios (Cloud Practitioner), si ya se tiene experiencia lo ideal seria empezar por la certificación mas cercana al rol que se este desempeñando actualmente.&lt;/p&gt;

&lt;p&gt;Después de aprobar la primera certificación, pienso que lo ideal es continuar realizando certificaciones hasta el punto que se sienta cómodo y motivado en seguir aprendiendo haciéndolas. Prepararse para aprobar diferentes certificaciones ayuda a adquirir conocimientos de una mayor cantidad de servicios de AWS ya que cada una se enfoca mas en diferentes tipos de servicios.&lt;/p&gt;

&lt;p&gt;Ahora veamos el como:&lt;/p&gt;

&lt;p&gt;Seguí los siguientes pasos en la preparación de cada examen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Hacer mas de un curso.&lt;/li&gt;
&lt;li&gt;Practicar en la consola de AWS.&lt;/li&gt;
&lt;li&gt;Presentar los test de practica.&lt;/li&gt;
&lt;li&gt;Repetición o repaso espaciado.&lt;/li&gt;
&lt;li&gt;Definir la fecha de presentación del examen y el lenguaje.&lt;/li&gt;
&lt;li&gt;Repetir los puntos: 2,3,4. &lt;/li&gt;
&lt;li&gt;Presentar el examen. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Hacer mas de un curso:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;En mi caso siempre hice los cursos de &lt;em&gt;Stephane Maarek&lt;/em&gt; en Udemy. Hice estos cursos ya que en mi búsqueda siempre eran recomendados.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.udemy.com/course/aws-certified-cloud-practitioner-new/" rel="noopener noreferrer"&gt;Cloud Practitioner&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.udemy.com/course/aws-certified-solutions-architect-associate-saa-c03/" rel="noopener noreferrer"&gt;Solutions Architect Associate&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.udemy.com/course/aws-certified-developer-associate-dva-c01/" rel="noopener noreferrer"&gt;Developer Associate&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.udemy.com/course/ultimate-aws-certified-sysops-administrator-associate/" rel="noopener noreferrer"&gt;SysOps Administrator Associate&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Adicional a los cursos anteriores, realice cursos en las siguientes plataformas:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://explore.skillbuilder.aws/learn" rel="noopener noreferrer"&gt;Skillbuilder&lt;/a&gt;(Hay muchos cursos gratuitos, hace poco (2022) lanzaron una opción de pago con laboratorios)&lt;br&gt;
&lt;a href="https://cloudacademy.com/" rel="noopener noreferrer"&gt;Cloudacademy&lt;/a&gt;(Es de pago)&lt;br&gt;
&lt;a href="https://www.clouding.la/" rel="noopener noreferrer"&gt;Clouding La&lt;/a&gt;(Es de pago,Ofrece cursos personalizados)&lt;br&gt;
&lt;a href="https://platzi.com/aws/" rel="noopener noreferrer"&gt;Platzi&lt;/a&gt; (Es de pago)&lt;br&gt;
&lt;a href="https://www.pluralsight.com/" rel="noopener noreferrer"&gt;Pluralsight&lt;/a&gt; (Es de pago)&lt;br&gt;
&lt;a href="https://www.whizlabs.com/" rel="noopener noreferrer"&gt;Whizlabs&lt;/a&gt; (Es de pago algunos, los cursos se pueden comprar por separado o subscripción anual)&lt;/p&gt;

&lt;p&gt;Estas plataformas también ofrecen cursos de nube, aunque los utilice en menor medida:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.exampro.co/" rel="noopener noreferrer"&gt;Exampro&lt;/a&gt; (Algunas partes son gratis)&lt;br&gt;
&lt;a href="https://acloudguru.com/" rel="noopener noreferrer"&gt;Cloudguru&lt;/a&gt;(ofrecen cursos gratuitos mensualmente y subscripciones)&lt;br&gt;
&lt;a href="https://digitalcloud.training/" rel="noopener noreferrer"&gt;Digitalcloud&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Practicar en la consola de AWS&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;La mejor forma de aprender es practicando (dicen: nadie aprende a nadar únicamente leyendo libros :)). Es mejor crear tu propia cuenta y practicar ya que AWS ofrece el &lt;a href="https://aws.amazon.com/es/free/?all-free-tier.sort-by=item.additionalFields.SortRank&amp;amp;all-free-tier.sort-order=asc&amp;amp;awsf.Free%20Tier%20Types=*all&amp;amp;awsf.Free%20Tier%20Categories=*all" rel="noopener noreferrer"&gt;nivel gratuito&lt;/a&gt; en el cual se pueden probar muchos de los servicios que aparecen en los exámenes. Es posible que en algunos casos sea necesario realizar un pago dependiendo el tipo de pruebas que estemos realizando. Para evitar sorpresas con los valores a pagar, con el usuario root vamos a &lt;em&gt;Billing&lt;/em&gt; y creemos un &lt;em&gt;Budget&lt;/em&gt; con el objetivo de definir cual es el presupuesto que estamos dispuestos a invertir y así poder tomar las medidas correspondientes a tiempo.  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyt6x63gf4qeomhigcj5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjyt6x63gf4qeomhigcj5.png" alt="Budget" width="800" height="310"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Algunas de las plataformas que utilice para practicar  laboratorios :&lt;/p&gt;

&lt;p&gt;&lt;a href="https://explore.skillbuilder.aws/learn" rel="noopener noreferrer"&gt;Skillbuilder&lt;/a&gt; Con la version de pago ofrecen bastantes laboratorios adicionalmente ofrecen &lt;a href="https://aws.amazon.com/es/training/digital/aws-cloud-quest/" rel="noopener noreferrer"&gt;Cloud Quest&lt;/a&gt; que es un juego de rol interactivo en el cual podemos aprender con base en laboratorios (me gusto bastante la metodología)&lt;br&gt;
&lt;a href="https://cloudacademy.com/" rel="noopener noreferrer"&gt;Cloudacademy&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.whizlabs.com/" rel="noopener noreferrer"&gt;Whizlabs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Presentar los test de practica&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Otra buena forma de aprender es poner a prueba nuestros conocimientos y que mejor manera hacer test que simulan las preguntas de los exámenes. Estos test nos ayudan a hacernos una idea del tipo de preguntas que vamos a encontrar en los exámenes, no son las mismas preguntas sin embargo son muy parecidas y son una buena forma de repaso ya que las plataformas que ofrecen este tipo de test dan una explicación de la respuesta. Los test también nos ayudan a acostumbrarnos a contestar preguntas y que al momento del examen sea mas natural y no sea tan estresante la presentación del examen.&lt;/p&gt;

&lt;p&gt;Aunque la mayoría de cursos tiene una sección de test para evaluar los conceptos, yo utilice las siguientes plataformas  ya que tienen bastantes preguntas para practicar:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.whizlabs.com/" rel="noopener noreferrer"&gt;Whizlabs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://portal.tutorialsdojo.com/video-course-practice-exam-ebook-bundle/" rel="noopener noreferrer"&gt;Tutorialsdojo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;AWS ofrece algunos cursos &lt;a href="https://www.aws.training/LearningLibrary?query=&amp;amp;filters=TrainingFormat%3A113%20DeliveryFormat%3A0&amp;amp;from=0&amp;amp;size=15&amp;amp;sort=_score" rel="noopener noreferrer"&gt;cursos&lt;/a&gt; enfocados en las diferentes certificaciones donde un especialista de AWS explica de manera superficial los servicios que se evalúan en el examen y la mejor forma de abordar las preguntas, creo que puede ser un buen inicio para entender el examen que se va a presentar sin embargo no creo que sea de mucho valor hacer mas de un curso en este formato sobre el mismo examen.&lt;/p&gt;

&lt;p&gt;Pueden encontrar los temas y el porcentaje por dominio en las guías de los exámenes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://d1.awsstatic.com/es_ES/training-and-certification/docs-dev-associate/AWS-Certified-Developer-Associate_Exam-Guide.pdf" rel="noopener noreferrer"&gt;Developer&lt;/a&gt;&lt;br&gt;
&lt;a href="https://d1.awsstatic.com/training-and-certification/docs-sysops-associate/AWS-Certified-SysOps-Administrator-Associate_Exam-Guide.pdf" rel="noopener noreferrer"&gt;SysOps&lt;/a&gt;&lt;br&gt;
&lt;a href="https://d1.awsstatic.com/es_ES/training-and-certification/docs-sa-assoc/AWS-Certified-Solutions-Architect-Associate_Exam-Guide.pdf" rel="noopener noreferrer"&gt;Architect&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repetición o repaso espaciado&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Para prepararme para presentar mis primeros exámenes (Cloud Practitioner, Solutions Architect) lo que hice fue crear mapas mentales de los servicios en hojas bond y pegarlos en la pared para repasar constantemente (utilice casi dos paredes :)).&lt;/p&gt;

&lt;p&gt;Un ejemplo:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fcertificaciones-associate%2Fec2.jpg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fcertificaciones-associate%2Fec2.jpg%3Fraw%3Dtrue" alt="EC2" width="800" height="551"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En una version mejorada de estudio, decidí utilizar la aplicación &lt;a href="https://apps.ankiweb.net/" rel="noopener noreferrer"&gt;Anki&lt;/a&gt; (tiene version para &lt;a href="https://play.google.com/store/apps/details?id=com.ichi2.anki&amp;amp;hl=es_CO&amp;amp;gl=US" rel="noopener noreferrer"&gt;Android&lt;/a&gt;)  que utiliza la técnica de &lt;a href="https://es.wikipedia.org/wiki/Repaso_espaciado#:~:text=El%20repaso%20espaciado%20es%20un,reaccione%20a%20preguntas%20o%20a%20est%C3%ADmulos." rel="noopener noreferrer"&gt;repaso espaciado&lt;/a&gt;, que me ha ayudado a retener la información  a largo plazo y no solamente para aprobar un examen, ya que el objetivo principal es aprender sobre los servicios de AWS.&lt;br&gt;
Les comparto los links donde pueden descargar mis apuntes realizados en la aplicación Anki:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://drive.google.com/file/d/1nwbXGo79jPUynE1VP9sGiM5Dronlp6Jr/view?usp=sharing" rel="noopener noreferrer"&gt;Apuntes Developer&lt;/a&gt;.&lt;br&gt;
&lt;a href="https://github.com/cecamilo00/posts/blob/circleci-project-setup/certificaciones-associate/SysOps.apkg" rel="noopener noreferrer"&gt;Apuntes SysOps&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Definir la fecha de presentación del examen y el idioma&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Es importante establecer con anticipación la fecha del examen para así poder definir la intensidad de estudio para llegar bien preparado a la fecha del examen. En caso que no sea posible presentar el examen en la fecha que se definió al inicio puede aplazar el examen hasta en dos ocasiones. Otro factor a tener en cuenta es el lugar de presentación, tenemos dos opciones: remoto o en un centro de certificación.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Remoto&lt;/em&gt;&lt;/strong&gt;: debemos adecuar lugar de presentación para cumplir todas los requisitos que nos solicitan, en nuestro equipo debemos instalar el programa para presentar el examen, debemos realizar un registro donde nos piden fotos de nosotros y de nuestra identificación,  hay una persona que esta vigilándonos por la cámara de nuestro equipo y únicamente habla ingles. &lt;br&gt;
En mi experiencia en el examen de Solutions Architect se demoraron en habilitarme el inicio del examen lo cual me genero un poco de estrés, por lo que les aconsejo estar tranquilos ya que si les sucede se pueden llegar a tardar entre 15 a 20 minutos. En el caso del examen de SysOps lo presente en esta modalidad pero en los laboratorios se bloqueo el examen por lo que tuve que presentarlo nuevamente pero esta vez en un centro de certificación (larga historia).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Nota&lt;/em&gt;: Para la sección de laboratorios del examen de SysOps siempre me aparecieron laboratorios que tenían que ver con: EventBridge,SNS,Route 53 y CloudFormation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Centro de certificación&lt;/em&gt;&lt;/strong&gt;: en este momento creo que es la mejor opción ya que no debemos adecuar nuestra casa o trabajo para la presentación del examen y nos libera de preocupaciones que algo salga mal (alguien entre al cuarto, se caiga el internet, que mire para otro lado ...). En el centro de certificación nos presentamos a la hora definida, verifican nuestros datos, nos piden guardar nuestros objetos personales en un casillero, nos dan las indicaciones en caso de necesitar algo y nos asignan un pc.&lt;/p&gt;

&lt;p&gt;En cuanto al idioma, las 4 certificaciones que aprobé las tome en ingles ya que la mayoría de cursos y sets de preguntas están en ingles. Desde el año pasado (2021) están disponibles en español las certificaciones de Cloud Practitioner, Solutions Architect y Developer, la certificación de SysOps en este momento (2022) solo se encuentra en ingles. Para las personas de habla hispana nos dan 30 minutos adicionales para terminar el examen. Creo que es tiempo mas que suficiente para presentar el examen.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Repetir&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Es necesario estar en continuo aprendizaje, repasando, haciendo test, laboratorios y mucho mejor si trabajan con los servicios AWS diariamente ya que definitivamente la practica les va hacer mucho mas fácil contestar las preguntas ya que van a poder visualizar la solución del escenario planteado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Presentar el examen&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;En este punto lo mas importante es haberse preparado correctamente, llegar a tiempo, dormir bien y ser positivo. &lt;br&gt;
Y en caso que no se llegue a pasar la primera vez un examen, (me paso) &lt;strong&gt;debemos seguir adelante en nuestro aprendizaje&lt;/strong&gt;, revisar el detalle de los resultados, fortalecer los puntos fuertes y reforzar los que nos indiquen en el resumen del resultado y sobre todo &lt;strong&gt;&lt;em&gt;NUNCA PARAR DE APRENDER&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Me pueden encontrar en&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/camilo-cabrales-31a0bb53/" rel="noopener noreferrer"&gt;Camilo Cabrales&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.credly.com/users/camilo-cabrales/badges" rel="noopener noreferrer"&gt;Credly&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
    </item>
    <item>
      <title>Crea tablas para reportes con DynamoDB &amp; DynamoDB Streams</title>
      <dc:creator>camilo cabrales</dc:creator>
      <pubDate>Tue, 18 Oct 2022 16:03:37 +0000</pubDate>
      <link>https://dev.to/cecamilo/crea-tablas-para-reportes-con-dynamodb-dynamodb-streams-3kn6</link>
      <guid>https://dev.to/cecamilo/crea-tablas-para-reportes-con-dynamodb-dynamodb-streams-3kn6</guid>
      <description>&lt;p&gt;Generalmente usamos &lt;strong&gt;DynamoDB&lt;/strong&gt; para soluciones que necesitan un tiempo de respuesta muy bajo y no para BI o analítica de datos debido a su naturaleza. &lt;br&gt;
En este post vamos a utilizar &lt;strong&gt;DynamoDB Streams&lt;/strong&gt; con el objetivo de filtrar los datos y crear una tabla con información especifica para que sea consultada por una herramienta de visualización de datos cómo puede ser &lt;strong&gt;QuickSight&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Vamos a hacer uso de los siguientes servicios en la implementación de la solución.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DynamoDB&lt;/li&gt;
&lt;li&gt;Lambda&lt;/li&gt;
&lt;li&gt;Cloud9&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Suponiendo que tuviéramos almacenada la información de los partidos de futbol de todas las ligas de futbol del mundo desde 1970, vamos a manejar dos tablas una para los  resultados de los partidos de futbol (tabla principal) y en otra tabla (consulta) vamos a almacenar y actualizar las tablas de posiciones para posteriormente hacer nuestras visualizaciones.&lt;/p&gt;

&lt;p&gt;Iniciemos por crear el ambiente en &lt;strong&gt;Cloud9&lt;/strong&gt; en donde vamos ejecutar nuestros scripts para poblar las tablas de &lt;strong&gt;DynamoDB&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Buscamos el servicio &lt;strong&gt;Cloud9&lt;/strong&gt; y damos click en crear entorno.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6qy9z3qnjui92tnzd2s8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6qy9z3qnjui92tnzd2s8.png" alt="Create Channel" width="800" height="347"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos a ver las opciones de configuración de la maquina &lt;strong&gt;EC2&lt;/strong&gt; qué queremos utilizar para nuestro entorno. Que en este caso vamos a dejar las opciones por defecto. Damos click en el botón siguiente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47ri19nkhqd321tkgame.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F47ri19nkhqd321tkgame.png" alt="Configurar entorno" width="720" height="864"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vemos la configuración que definimos para nuestro entorno y damos click en crear.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F88pem3jigx85ko9xk8yl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F88pem3jigx85ko9xk8yl.png" alt="Crear entorno" width="760" height="836"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Veremos una pantalla de espera cómo la siguiente mientras se crea nuestro entorno de trabajo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsjc8sztb17m2j7fkvdwa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsjc8sztb17m2j7fkvdwa.png" alt="Espera entorno" width="800" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez nuestro entorno esta listo, debemos crear el archivo .py (python) que contiene el código fuente de  nuestra tabla de &lt;strong&gt;DynamoDB&lt;/strong&gt;. Damos click en crear archivo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcc1isxxkrn0d76p20bnu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcc1isxxkrn0d76p20bnu.png" alt="Crear archivo" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Debemos copiar el siguiente código en el nuevo archivo y guardarlo con extension .py, en este caso le vamos a dar el nombre de &lt;em&gt;creartabla.py&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3
from boto3.dynamodb.conditions import Key


dynamodb = boto3.resource("dynamodb")

dynamodb.create_table(
        TableName='ResultadosPartidos',
        KeySchema=[
            {
                'AttributeName': 'PK',
                'KeyType': 'HASH'  # Partition key
            },
            {
                'AttributeName': 'SK',
                'KeyType': 'RANGE'  # Sort key
            }
        ],
        #Se deben crear las llaves nuevamente con su tipo de dato
        AttributeDefinitions=[
            {
                'AttributeName': 'PK',
                'AttributeType': 'S'  # Se utiliza S para tipos de datos String y N para numeros
            },
            {
                'AttributeName': 'SK',
                'AttributeType': 'S'
            }

        ],
        ProvisionedThroughput={
            'ReadCapacityUnits': 5,
            'WriteCapacityUnits': 5
        }
    )

dynamodb.create_table(
        TableName='TablaPosiciones',
        KeySchema=[
            {
                'AttributeName': 'Liga',
                'KeyType': 'HASH'  # Partition key
            },
            {
                'AttributeName': 'Equipo',
                'KeyType': 'RANGE'  # Sort key
            }
        ],
        #Se deben crear las llaves nuevamente con su tipo de dato
        AttributeDefinitions=[
            {
                'AttributeName': 'Liga',
                'AttributeType': 'S'  # Se utiliza S para tipos de datos String y N para numeros
            },
            {
                'AttributeName': 'Equipo',
                'AttributeType': 'S'
            }

        ],
        ProvisionedThroughput={
            'ReadCapacityUnits': 5,
            'WriteCapacityUnits': 5
        }
    )
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F623d8r5iniaqlkjt38vs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F623d8r5iniaqlkjt38vs.png" alt="Crear archivo" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez creado el archivo debemos instalar &lt;strong&gt;boto3&lt;/strong&gt; ejecutando en la terminal el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install boto3

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instalado boto3 debemos ejecutar nuestro archivo, ejecutando en la terminal el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python creartabla.py

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feccwalq8c2to6ertv3yl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feccwalq8c2to6ertv3yl.png" alt="Ejecutar archivo" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez ejecutado nuestro script vamos a buscar el servicio de &lt;strong&gt;DynamoDB&lt;/strong&gt; y ver las tablas que acabamos de crear.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswqq7m41axi9ci7v7qel.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fswqq7m41axi9ci7v7qel.png" alt="Tabla DynamoDB" width="800" height="281"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora vamos a crear la función &lt;strong&gt;Lambda&lt;/strong&gt; que va a filtrar los datos de la tabla principal a la tabla que vamos a utilizar para nuestras visualizaciones. Para esto buscamos Lambda en el buscador de servicios y damos click en &lt;em&gt;Create Function&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;Le damos un nombre a la función &lt;strong&gt;Lambda&lt;/strong&gt;, seleccionamos el lenguaje de programación (Runtime = Python3.8)y damos click en &lt;em&gt;Create Function&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafobao5534z6cbr18omg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fafobao5534z6cbr18omg.png" alt="Create Function" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El siguiente paso es darle los permisos necesarios al rol asignado a la función &lt;strong&gt;Lambda&lt;/strong&gt;. Para esto damos click en la pestaña Configuration en el menu Permissions y en el nombre del rol.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74ubkww8czwnx9x57msn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F74ubkww8czwnx9x57msn.png" alt="Select Rol" width="800" height="384"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agregamos las siguientes políticas al rol: &lt;/p&gt;

&lt;p&gt;&lt;em&gt;CloudWatchFullAccess&lt;/em&gt;: Nos sirve para acceder a logs de la función Lambda&lt;/p&gt;

&lt;p&gt;&lt;em&gt;AmazonDynamoDBFullAccess&lt;/em&gt;: Nos sirve para poder guardar información en la tabla y para qué &lt;strong&gt;DynamoDB Streams&lt;/strong&gt; pueda invocar a la función. En otro tipo de entorno recuerden ser mas granulares con sus políticas.&lt;/p&gt;

&lt;p&gt;En caso que únicamente se necesitara hacer invocaciones a la función &lt;strong&gt;Lambda&lt;/strong&gt; desde &lt;strong&gt;DynamoDB Streams&lt;/strong&gt;, se debe usar la política: &lt;em&gt;AWSLambdaInvocation-DynamoDB&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkg3uf3kw001c4i332bno.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkg3uf3kw001c4i332bno.png" alt="Politicas Rol" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creada la función Lambda y asignado los permisos necesarios para su ejecución, vamos a habilitar el Stream en &lt;strong&gt;DynamoDb&lt;/strong&gt; para que llame a la función Lambda cuando se ingrese un nuevo registro a la tabla.Para esto vamos a la pantalla principal de &lt;strong&gt;DynamoDB&lt;/strong&gt; damos click en &lt;em&gt;Tables&lt;/em&gt;, seleccionamos la tabla &lt;em&gt;ResultadosPartidos&lt;/em&gt; y damos click en la pestaña &lt;em&gt;Exports and streams&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0jz1q8zewonyju5sgnz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb0jz1q8zewonyju5sgnz.png" alt="Select Stream" width="800" height="308"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Los siguientes pasos son habilitar el Stream y asignarle la función &lt;strong&gt;Lambda&lt;/strong&gt; que ya creamos.&lt;/p&gt;

&lt;p&gt;Habilitemos el Stream:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1zcpbl31fyyam5ebfxi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx1zcpbl31fyyam5ebfxi.png" alt="Select Stream" width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seleccionamos el tipo de información que va a ser enviada la la función &lt;strong&gt;Lambda&lt;/strong&gt;, en este caso solo seleccionamos la  información del nuevo registro que se ingreso en la tabla.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qbos8z0fsrd4f9u0aep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3qbos8z0fsrd4f9u0aep.png" alt="Select Stream" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Validamos que el stream haya quedado habilitado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ebpf3o91wmms53fpy3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ebpf3o91wmms53fpy3b.png" alt="Validate Stream" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Asignamos la función al trigger la función Lambda. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58afko5zgiwyg2zwxf28.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58afko5zgiwyg2zwxf28.png" alt="Create Trigger 1" width="800" height="423"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seleccionamos la función &lt;strong&gt;Lambda&lt;/strong&gt; que va a procesar el Stream y la cantidad de registros que va a procesar en cada llamado.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8i7rxn5rmopbpks7pwm1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8i7rxn5rmopbpks7pwm1.png" alt="Create Trigger 2" width="800" height="515"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Por ultimo validamos que el trigger este habilitado y que la función &lt;strong&gt;Lambda&lt;/strong&gt; que va a procesar el stream sea la correcta.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhqhyehuk93ifhyg8z8lu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhqhyehuk93ifhyg8z8lu.png" alt="Create Trigger 3" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El diseño de tabla de &lt;strong&gt;DynamoDb&lt;/strong&gt; que vamos a utilizar en este post es de una &lt;em&gt;sola tabla&lt;/em&gt;, necesitamos definir un filtro sobre los mensajes que van a ser enviados a la función Lambda con el objetivo que se procesen solamente los registros que necesitamos para construir la tabla de posiciones.&lt;/p&gt;

&lt;p&gt;Para esto vamos de nuevo a nuestra función &lt;strong&gt;Lambda&lt;/strong&gt; y damos click &lt;em&gt;Configuration - Triggers&lt;/em&gt;. Podemos observar qué se agrego el trigger que creamos desde &lt;strong&gt;DynamoDB&lt;/strong&gt;. Damos click en checkbox del trigger y después en el botón editar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2itatpgx6723w0bnqly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2itatpgx6723w0bnqly.png" alt="Lambda Trigger 1" width="800" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La siguiente pantalla nos muestra la configuración actual del trigger. Damos click &lt;em&gt;Additional settings&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64hr9xmyujktm6ya0e7g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64hr9xmyujktm6ya0e7g.png" alt="Lambda Trigger 2" width="800" height="810"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Buscamos la sección &lt;em&gt;Filter criteria&lt;/em&gt; y copiamos el siguiente filtro en el cuadro de texto.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"eventName":["INSERT"],"dynamodb":{"NewImage":{"Local":{"S":[{ "exists": true }]}}},"dynamodb":{"NewImage":{"Visitante":{"S":[{ "exists": true }]}}}}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Guardamos los cambios.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdxk7ulnd4w8ay9csi1sb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdxk7ulnd4w8ay9csi1sb.png" alt="Lambda Trigger 3" width="800" height="856"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con los pasos anteriores configuramos el filtro del stream para que solo sean procesados por la función Lambda los eventos del tipo &lt;strong&gt;Insert&lt;/strong&gt; y que dentro de la datos enviados se encuentre el campo &lt;strong&gt;Local&lt;/strong&gt; y &lt;strong&gt;Visitante&lt;/strong&gt;, los demás datos que no cumplan con esta condición son ignorados y la función Lambda no es invocada, lo que ayuda a reducir costos debido a que solo se procesa la información necesaria.&lt;/p&gt;

&lt;p&gt;El siguiente paso es ponerle código fuente a nuestra función &lt;strong&gt;Lambda&lt;/strong&gt;, vamos a la pestaña Code, reemplazamos el código existente por el siguiente y damos click en el botón &lt;em&gt;Deploy&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json
import boto3
from boto3.dynamodb.conditions import Key

dynamodb = boto3.resource("dynamodb")
tabla = dynamodb.Table("TablaPosiciones")
local = "local"
visitante = "visitante"

class Partido:

    def __init__(self,local,visitante,marcadorLocal,marcadorVisitante,liga):
        self.local = local
        self.visitante = visitante
        self.marcadorLocal = marcadorLocal
        self.marcadorVisitante = marcadorVisitante
        self.liga = liga


    def getLocal(self):
        return self.local

    def getVisitante(self):
        return self.visitante

    def getMarcadorLocal(self):
        return self.marcadorLocal

    def getMarcadorVisitante(self):
        return self.marcadorVisitante

    def getLiga(self):
        return self.liga

    def setLocal(self,local):
        self.local = local

    def setVisitantel(self,visitante):
        self.visitante = visitante

    def setMarcadorLocal(self,marcadorLocal):
        self.marcadorLocal = marcadorLocal

    def setMarcadorVisitante(self,marcadorVisitante):
        self.marcadorVisitante = marcadorVisitante

    def setLiga(self,liga):
        self.liga = liga

def obtenerPartido(data):
    local = data["Local"]["S"]
    visitante = data["Visitante"]["S"]
    marcadorLocal = data["MarcadorLocal"]["N"]
    marcadorVisitante = data["MarcadorVisitante"]["N"]
    liga = data["PK"]["S"].split("#")[0]
    return Partido(local,visitante,marcadorLocal,marcadorVisitante,liga)

def lambda_handler(event, context):

    data = event["Records"][0]["dynamodb"]["NewImage"]
    partido = obtenerPartido(data)
    datosLocal = tabla.query(KeyConditionExpression=Key('Liga').eq(partido.getLiga()) &amp;amp; Key("Equipo").eq(partido.getLocal()))
    datosVisitante = tabla.query(KeyConditionExpression=Key('Liga').eq(partido.getLiga()) &amp;amp; Key("Equipo").eq(partido.getVisitante()))
    actualizarDatosEquipo(datosLocal["Items"],partido,local)
    actualizarDatosEquipo(datosVisitante["Items"],partido,visitante)
    print("ejecuto")


def actualizarDatosEquipo(datos,partido,localidad):

    puntos = getPuntos(partido,localidad)

    if len(datos) == 0:
        tabla.put_item(Item={
            "Liga": partido.getLiga(),
            "Equipo":partido.getLocal() if localidad == local else partido.getVisitante(),
            "PartidosJugados":1,
            "GolesFavor": partido.getMarcadorLocal() if localidad == local else partido.getMarcadorVisitante(),
            "GolesContra":partido.getMarcadorLocal() if localidad != local else partido.getMarcadorVisitante(),
            "Puntos": puntos
        })
    else:
        tabla.update_item(
                Key={
                    "Liga": partido.getLiga(),
                    "Equipo": partido.getLocal() if localidad == local else partido.getVisitante()
                },
                UpdateExpression="set PartidosJugados=:partidos_jugados,GolesFavor=:goles_favor,GolesContra=:goles_contra,Puntos=:puntos",
                ExpressionAttributeValues={
                    ":partidos_jugados":datos[0]["PartidosJugados"] + 1,
                    ":goles_favor":int(datos[0]["GolesFavor"]) + int(partido.getMarcadorLocal()) if localidad == local else int(datos[0]["GolesFavor"]) +int(partido.getMarcadorVisitante()),
                    ":goles_contra":int(datos[0]["GolesContra"]) + int(partido.getMarcadorVisitante()) if localidad == local else int(datos[0]["GolesContra"])+int(partido.getMarcadorLocal()),
                    ":puntos":int(datos[0]["Puntos"]) + puntos
                },
                ReturnValues="UPDATED_NEW"
            )

def getPuntos(partido,localidad):
    puntos = 1
    if local == localidad:
        if partido.getMarcadorLocal() &amp;gt; partido.getMarcadorVisitante():
            puntos = 3
        elif partido.getMarcadorLocal() &amp;lt; partido.getMarcadorVisitante(): 
            puntos = 0
    else:
        if partido.getMarcadorLocal() &amp;lt; partido.getMarcadorVisitante():
            puntos = 3
        elif partido.getMarcadorLocal() &amp;gt; partido.getMarcadorVisitante(): 
            puntos = 0
    return puntos
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6nwnhdgffi691emhllk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6nwnhdgffi691emhllk.png" alt="Deploy Code" width="800" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Debemos validar  el funcionamiento tanto del filtro como el del código de la función &lt;strong&gt;Lambda&lt;/strong&gt;. Por lo tanto debemos ingresar nuevos items en la tabla &lt;em&gt;ResultadosPartidos&lt;/em&gt;.&lt;br&gt;
Nos dirigimos nuevamente a &lt;strong&gt;Cloud9&lt;/strong&gt; y creamos un nuevo archivo llamado &lt;em&gt;data.py&lt;/em&gt; y lo ejecutamos utilizando en la terminal el comando &lt;em&gt;python data.py&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnh3d6r5yki3wrnaut56.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhnh3d6r5yki3wrnaut56.png" alt="Deploy Code" width="800" height="293"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3
from boto3.dynamodb.conditions import Key

dynamodb = boto3.resource("dynamodb")
table = dynamodb.Table("ResultadosPartidos")
table.put_item(Item={
    "PK": "Premier League#2022/23",
    "SK":"Arsenal#Liverpool#2022/10/09",
    "Local":"Arsenal",
    "Visitante":"Liverpool",
    "MarcadorLocal":3,
    "MarcadorVisitante": 2,
    "Fecha":"2022/10/09"

})


table.put_item(Item={
    "PK": "Premier League#2022/23",
    "SK":"Manchester City#Southampton#2022/10/08",
    "Local":"Manchester City",
    "Visitante":"Southampton",
    "MarcadorLocal":4,
    "MarcadorVisitante": 0,
    "Fecha":"2022/10/08"

})

table.put_item(Item={
    "PK": "Premier League#2022/23",
    "SK":"Everton#Manchester Utd#2022/10/08",
    "Local":"Everton",
    "Visitante":"Manchester Utd",
    "MarcadorLocal":1,
    "MarcadorVisitante": 2,
    "Fecha":"2022/10/09"

})

table.put_item(Item={
    "PK": "Premier League#2022/23",
    "SK":"Manchester City#Manchester Utd#2022/10/08",
    "Local":"Manchester City",
    "Visitante":"Manchester Utd",
    "MarcadorLocal":6,
    "MarcadorVisitante": 3,
    "Fecha":"2022/10/02"

})

table.put_item(Item={
    "PK": "Premier League#2022/23",
    "SK":"Liverpool#Brighton#2022/10/09",
    "Local":"Liverpool",
    "Visitante":"Brighton",
    "MarcadorLocal":3,
    "MarcadorVisitante": 3,
    "Fecha":"2022/10/01"

})


table.put_item(Item={
    "PK": "Manchester City#2022/23",
    "SK":"Jugador#Erling Haaland",
    "Nombre":"Erling Haaland",
    "Goles":15,
    "Partidos Jugados": 9
})

table.put_item(Item={
    "PK": "Liverpool#2022/23",
    "SK":"Jugador#Luis Diaz",
    "Nombre":"Luis Diaz",
    "Goles":3,
    "Partidos Jugados": 8
})

table.put_item(Item={
    "PK": "Tottenham#2022/23",
    "SK":"Jugador#Kane",
    "Nombre":"Kane",
    "Goles":8,
    "Partidos Jugados": 9
})

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por ultimo vamos a validar la información almacenada en las dos tablas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1a5bk7fawbf11pn58ib.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc1a5bk7fawbf11pn58ib.png" alt="Resultado Partidos" width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cómo podemos observar en la tabla ResultadoPartidos se almaceno la información de los resultados de cada partido más la información de los jugadores de los equipos. Esto se realiza de esta forma por el tipo de diseño de tabla que elegimos para el ejercicio que es de única tabla. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4nn48czztu18i3xpqgc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4nn48czztu18i3xpqgc.png" alt="Resultado Partidos" width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la tabla &lt;em&gt;TablaPosiciones&lt;/em&gt; podemos observar que únicamente tenemos almacenado la información de los equipos de futbol y no la de los jugadores porque no cumplen con el filtro creado. Si queremos confirmar que la función &lt;strong&gt;Lambda&lt;/strong&gt; solo se haya llamado las veces correctas (5 que son el numero de partidos que ingresamos), debemos ir a &lt;strong&gt;CloudWatch&lt;/strong&gt; y buscar el log group que termina con el nombre de la función Lambda: &lt;em&gt;lambda/lambda_stream_dynamodb&lt;/em&gt; y observar el numero de veces que la función fue invocada.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fknfyjbkouakgokxsmu9n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fknfyjbkouakgokxsmu9n.png" alt="Resultado Partidos" width="800" height="342"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La Arquitectura de nuestro post es la siguiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgsil8gxhj5l7n4voqlbo.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgsil8gxhj5l7n4voqlbo.jpg" alt="Resultado Partidos" width="452" height="441"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como actividad adicional pueden agregar mas registros al script de inserción, tratar de crear nuevos tipos de filtros o mejorar el código fuente de la función &lt;strong&gt;Lambda&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;En el proximo post vamos a ver cómo crear gráficos de los datos de la tabla TablaPosiciones utilizando el servicio de &lt;strong&gt;QuickSight&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Me pueden encontrar en&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/camilo-cabrales-31a0bb53/" rel="noopener noreferrer"&gt;Camilo Cabrales&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Referencias
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.Python.01.html" rel="noopener noreferrer"&gt;Filtros Eventos Lambda&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GettingStarted.Python.01.html" rel="noopener noreferrer"&gt;Documentación DynamoDB&lt;/a&gt;&lt;br&gt;
&lt;a href="https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/dynamodb.html#DynamoDB.Client.create_table" rel="noopener noreferrer"&gt;Boto3&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
    </item>
    <item>
      <title>Como crear tu página para streaming de vídeo</title>
      <dc:creator>camilo cabrales</dc:creator>
      <pubDate>Thu, 08 Sep 2022 22:34:32 +0000</pubDate>
      <link>https://dev.to/cecamilo/como-crear-tu-propia-pagina-para-streaming-de-video-7na</link>
      <guid>https://dev.to/cecamilo/como-crear-tu-propia-pagina-para-streaming-de-video-7na</guid>
      <description>&lt;p&gt;AWS ofrece diferentes tipos de servicios para muchos tipos de soluciones. En este post vamos a crear una pagina de streaming de video utilizando los siguientes servicios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon Interactive Video Service.&lt;/li&gt;
&lt;li&gt;S3.&lt;/li&gt;
&lt;li&gt;Y utilizaremos la aplicación &lt;a href="https://play.google.com/store/apps/details?id=com.wmspanel.larix_broadcaster&amp;amp;hl=es_CO&amp;amp;gl=US" rel="noopener noreferrer"&gt;Larix Broadcaster&lt;/a&gt; para realizar la transmisión de nuestro streaming.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Comencemos con la creación de nuestro canal buscando el servicio IVS (Amazon Interactive Video Service), en la pagina principal seleccionamos &lt;em&gt;Channels&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwew30garj9z2e7r2wenu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwew30garj9z2e7r2wenu.png" alt="IVS" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Damos click en Create Channel&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhluq300dns2bersrkzbn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhluq300dns2bersrkzbn.png" alt="Create Channel" width="800" height="315"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la siguiente pagina vamos a configurar nuestro canal.Le asignamos un nombre, definimos el tipo de canal, su latencia; no vamos a configurar un token de autorización con el objetivo de ver el streaming desde la consola de AWS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fsetup%2520channel.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fsetup%2520channel.png%3Fraw%3Dtrue" alt="Config Channel" width="680" height="818"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la sección de almacenamiento no vamos a seleccionar que nuestro streaming se almacene en S3. Damos click en guardar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fcreate%2520setup%2520channel.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fcreate%2520setup%2520channel.png%3Fraw%3Dtrue" alt="Save Channel" width="680" height="337"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez creado nuestro canal vamos a ver una pagina con toda la información de configuración y los datos necesarios para empezar a realizar el streaming. En este momento nos vamos a enfocar en los datos de Stream key e Ingest Server.&lt;/p&gt;

&lt;p&gt;Lo primero que debemos hacer es instalar la aplicación &lt;a href="https://play.google.com/store/apps/details?id=com.wmspanel.larix_broadcaster&amp;amp;hl=es_CO&amp;amp;gl=US" rel="noopener noreferrer"&gt;Larix Broadcaster&lt;/a&gt;, después vamos a la siguiente pagina &lt;a href="https://softvelum.com/larix/grove/" rel="noopener noreferrer"&gt;Larix Grove-compliant URL&lt;/a&gt; que nos va a servir para generar el link del cual vamos a hacer el streaming.&lt;/p&gt;

&lt;p&gt;Ya en la pagina de Web vamos a copiar en el campo URL los valores de Ingest Server seguido del Stream Key.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fqr%2520code.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fqr%2520code.png%3Fraw%3Dtrue" alt="QR Code" width="800" height="718"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez pegados el Ingest Server y el Stream Key en el campo URL, debemos escanear el código QR y abrir el link desde la aplicación &lt;strong&gt;Larix&lt;/strong&gt;.Una vez dentro de la aplicación damos click en el botón grabar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Flarix%2520app.jpg%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Flarix%2520app.jpg%3Fraw%3Dtrue" alt="Larix App" width="800" height="360"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dentro de la consola de AWS podemos ir a &lt;em&gt;Live channels&lt;/em&gt; para ver los canales que están transmitiendo en vivo o dentro de nuestro canal en la sección Live Stream.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Flive%2520stream.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Flive%2520stream.png%3Fraw%3Dtrue" alt="Stream" width="800" height="610"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con los pasos anteriores creamos un canal para streaming y logramos transmitir hacia él. El siguiente paso es crear una pagina web en donde podamos ver nuestro streaming.&lt;/p&gt;

&lt;p&gt;Para eso vamos a crear un bucket en S3 (recuerden que el nombre es único en todo AWS).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fname%2520bucket.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fname%2520bucket.png%3Fraw%3Dtrue" alt="Name Bucket" width="800" height="702"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Definimos que el bucket sea publico.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fpublic%2520bucket.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fpublic%2520bucket.png%3Fraw%3Dtrue" alt="Name Bucket" width="800" height="663"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Creamos el bucket&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fsave%2520bucket.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fsave%2520bucket.png%3Fraw%3Dtrue" alt="Name Bucket" width="760" height="788"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora debemos configurar nuestro bucket como un sitio web estático, para esto vamos a la pestaña &lt;em&gt;Properties&lt;/em&gt; y en la sección &lt;em&gt;Static website hosting&lt;/em&gt; damos click en el botón editar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fstatic%2520web%2520hosting.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fstatic%2520web%2520hosting.png%3Fraw%3Dtrue" alt="Static Web Hosting" width="800" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En el campo &lt;em&gt;Index document&lt;/em&gt; colocamos el nombre del archivo principal por el cual se va tener acceso al bucket &lt;em&gt;index.html&lt;/em&gt; y guardamos los cambios.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fconfigure%2520static%2520web%2520hosting.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fconfigure%2520static%2520web%2520hosting.png%3Fraw%3Dtrue" alt="Configure Static Web Hosting" width="566" height="818"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nos hace falta modificar la política del bucket para que podamos ver nuestro sitio publico en internet. &lt;br&gt;
Vamos a la pestaña &lt;em&gt;Permissions&lt;/em&gt; a la sección &lt;em&gt;Bucket policy&lt;/em&gt; y colocamos la siguiente política reemplazando el &lt;strong&gt;arn&lt;/strong&gt; del bucket por el que creamos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Id": "Policy1662669806339",
    "Statement": [
        {
            "Sid": "Stmt1662669804857",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": "arn:aws:s3:::streamingbucketcamilo2022/*"
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fpolicy%2520bucket.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Fpolicy%2520bucket.png%3Fraw%3Dtrue" alt="Bucket Policy" width="800" height="296"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora debemos modificar el archivo &lt;em&gt;index.html&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/cecamilo00/posts/blob/circleci-project-setup/streaming%20aws/index.html" rel="noopener noreferrer"&gt;index.html&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"&amp;gt;
&amp;lt;html xmlns="http://www.w3.org/1999/xhtml"&amp;gt;
&amp;lt;head&amp;gt;
&amp;lt;title&amp;gt;1 Column - fw-1-1-col&amp;lt;/title&amp;gt;
&amp;lt;meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /&amp;gt;
&amp;lt;style&amp;gt;
  * { padding: 0; margin: 0; }

body {
 font-family: Arial, Helvetica, sans-serif;
 font-size: 13px;
}
#wrapper { 
 margin: 0 auto;
 width: 922px;
}
#header {
 width: 900px;
 color: #333;
 padding: 10px;
 border: 1px solid #ccc;
 height: 100px;
 margin: 10px 0px 5px 0px;
 background-color:#FFFFFF;
}
#content { 
 width: 900px;
 color: #333;
 border: 1px solid #ccc;
 background:#FFFFFF;
 margin: 0px 0px 5px 0px;
 padding: 10px;
 height: 350px;
}
#footer { 
 color: #333;
 width: 900px;
 border: 1px solid #ccc;
 background-color:#FFFFFF;
 margin: 0px 0px 10px 0px;
 padding: 10px;
}
&amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body&amp;gt;
&amp;lt;!-- Begin Wrapper --&amp;gt;
&amp;lt;div id="wrapper"&amp;gt;
  &amp;lt;!-- Begin Header --&amp;gt;
  &amp;lt;div id="header"&amp;gt;&amp;lt;h1&amp;gt;&amp;lt;a href="https://aws.amazon.com/es/ivs/"&amp;gt;Amazon IVS&amp;lt;/a&amp;gt;&amp;lt;/h1&amp;gt;&amp;lt;/div&amp;gt;
  &amp;lt;!-- End Header --&amp;gt;
  &amp;lt;!-- Begin Content --&amp;gt;
  &amp;lt;div id="content"&amp;gt; 
    &amp;lt;script src="https://player.live-video.net/1.12.0/amazon-ivs-player.min.js"&amp;gt;&amp;lt;/script&amp;gt;
    &amp;lt;video id="video-player" width="850" height="325"  playsinline&amp;gt;&amp;lt;/video&amp;gt;
    &amp;lt;script&amp;gt;
      if (IVSPlayer.isPlayerSupported) {
        const player = IVSPlayer.create();
        player.attachHTMLVideoElement(document.getElementById('video-player'));
        player.load("Playback URL");
        player.play();
      }
    &amp;lt;/script&amp;gt;
    &amp;lt;/div&amp;gt;
  &amp;lt;!-- End Content --&amp;gt;
  &amp;lt;!-- Begin Footer --&amp;gt;
  &amp;lt;div id="footer"&amp;gt; &amp;lt;a href="https://dev.to/cecamilo"&amp;gt;Camilo Cabrales&amp;lt;/div&amp;gt;
  &amp;lt;!-- End Footer --&amp;gt;
 &amp;lt;/div&amp;gt;
&amp;lt;!-- End Wrapper --&amp;gt;
&amp;lt;/body&amp;gt;
&amp;lt;/html&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Debemos reemplazar el texto &lt;em&gt;Playback URL&lt;/em&gt; de la linea de código &lt;em&gt;player.load("Playback URL");&lt;/em&gt; por el valor que tenemos en nuestro canal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2FPlayback%2520URL.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2FPlayback%2520URL.png%3Fraw%3Dtrue" alt="Playback URL" width="800" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ya hemos configurado el bucket para que funcione como un sitio web estático y modificamos el archivo index.html, el siguiente paso es subir este archivo a nuestro bucket. Para esto vamos a nuestro bucket damos click en el botón &lt;em&gt;Upload&lt;/em&gt; y subimos el archivo. Una vez el archivo este dentro de nuestro bucket le damos click sobre el nombre y copiamos el Object URL para verlo en un navegador web. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Furl%2520object.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Furl%2520object.png%3Fraw%3Dtrue" alt="URL Object" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora debemos iniciar la aplicación de &lt;em&gt;Larix&lt;/em&gt; y comenzar la transmisión la cual veremos en nuestra pagina web después de esperar unos segundos (si no inicia en unos segundos, se debe actualizar la pagina).  &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Ffinal%2520page.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fstreaming%2520aws%2Ffinal%2520page.png%3Fraw%3Dtrue" alt="Steaming Page" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con esto damos por terminado el ejercicio, tal vez puedan complementarlo agregando que el video se guarde en S3 o agregando un método de autenticación a la pagina con &lt;strong&gt;Cognito&lt;/strong&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Me pueden encontrar en:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/camilo-cabrales-31a0bb53/" rel="noopener noreferrer"&gt;Camilo Cabrales&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Referencias
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/ivs/latest/userguide/what-is.html" rel="noopener noreferrer"&gt;Amazon IVS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.free-css.com/free-css-layouts/page1" rel="noopener noreferrer"&gt;Plantillas HTML&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
    </item>
    <item>
      <title>Como configurar multiples profiles desde AWS CLI</title>
      <dc:creator>camilo cabrales</dc:creator>
      <pubDate>Tue, 06 Sep 2022 23:00:24 +0000</pubDate>
      <link>https://dev.to/cecamilo/como-configurar-multiples-profiles-desde-aws-cli-ipm</link>
      <guid>https://dev.to/cecamilo/como-configurar-multiples-profiles-desde-aws-cli-ipm</guid>
      <description>&lt;p&gt;La AWS CLI es la linea de comandos de AWS que es usada para interactuar con los servicios de AWS.&lt;/p&gt;

&lt;p&gt;Cuando usamos la CLI por primera vez debemos configurar nuestra cuenta utilizando el comando &lt;em&gt;aws configure&lt;/em&gt; , que nos pide los siguientes datos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Access Key ID&lt;/li&gt;
&lt;li&gt;AWS Secret Access Key&lt;/li&gt;
&lt;li&gt;Default region name&lt;/li&gt;
&lt;li&gt;Default output format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para obtener el &lt;em&gt;AWS Access Key ID&lt;/em&gt; y el &lt;em&gt;AWS Secret Access Key&lt;/em&gt; vamos a la consola de AWS y buscamos IAM seleccionamos Users -Security Credentials y Create Access Key&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fprofiles-cli%2Fsecurity%2520credentials.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fprofiles-cli%2Fsecurity%2520credentials.png%3Fraw%3Dtrue" alt="Security Credentials" width="800" height="309"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al dar click en el botón &lt;em&gt;Create Access Key&lt;/em&gt; vamos a ver una pantalla donde podemos copiar las Keys para configurar nuestra cuenta en la CLI de la maquina en la cual estamos trabajando.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fprofiles-cli%2FAccess%2520Key.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fprofiles-cli%2FAccess%2520Key.png%3Fraw%3Dtrue" alt="Access Key" width="800" height="530"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Es importante nunca compartir estas Keys, ya que pueden entrar a utilizar la cuenta con los privilegios que tiene asignados el usuario.&lt;/p&gt;

&lt;p&gt;Ahora que sabemos como obtener las keys podemos configurar diferentes cuentas en nuestra maquina. Para esto utilizamos el comando: &lt;strong&gt;&lt;em&gt;aws configure --profile nombredelperfil&lt;/em&gt;&lt;/strong&gt; &lt;br&gt;
lo que nos va a pedir las keys, la region y el formato.&lt;/p&gt;

&lt;p&gt;Para ver las cuentas que tenemos configuradas en nuestra maquina utilizamos el comando: &lt;strong&gt;&lt;em&gt;aws configure list-profiles&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Si queremos ejecutar un comando para un perfil determinado debemos agregar al comando: &lt;strong&gt;&lt;em&gt;--profile nombredelperfil&lt;/em&gt;&lt;/strong&gt; , por ejemplo para traer todos los buckets del perfil &lt;em&gt;cuenta2&lt;/em&gt; debemos ejecutar el siguiente comando: &lt;br&gt;
&lt;strong&gt;&lt;em&gt;aws s3 ls --profile cuenta2&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;En el caso que no queramos agregar el parametro profile a cada comando podemos ejecutar: &lt;/p&gt;

&lt;p&gt;Linux o Mac: &lt;strong&gt;&lt;em&gt;export AWS_PROFILE=_cuenta2&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Windows: &lt;strong&gt;&lt;em&gt;setx AWS_PROFILE _cuenta2&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Si queremos modificar o eliminar los profiles que tenemos configurados en nuestra maquina podemos buscar el archivo &lt;strong&gt;&lt;em&gt;~/.aws/config&lt;/em&gt;&lt;/strong&gt;  que nos va a mostrar algo como lo siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[default]
region = us-east-1
output = json
[profile cuenta2]
region = us-east-2
output = json

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Es posible que necesitemos modificar las key de un profile y las podemos encontrar en el archivo &lt;strong&gt;&lt;em&gt;~/.aws/credentials&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Conociendo los comandos y archivos anteriores podemos tener varias cuentas configuradas en una sola maquina.&lt;/p&gt;

&lt;h4&gt;
  
  
  Me pueden encontrar en:
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/camilo-cabrales-31a0bb53/" rel="noopener noreferrer"&gt;Camilo Cabrales&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Referencias
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html" rel="noopener noreferrer"&gt;Documentación&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Borrar</title>
      <dc:creator>camilo cabrales</dc:creator>
      <pubDate>Tue, 06 Sep 2022 22:48:05 +0000</pubDate>
      <link>https://dev.to/cecamilo/como-configurar-multiples-keys-en-la-misma-maquina-ilf</link>
      <guid>https://dev.to/cecamilo/como-configurar-multiples-keys-en-la-misma-maquina-ilf</guid>
      <description></description>
    </item>
    <item>
      <title>Despliegue y prueba de servicios creados con Terraform en AWS</title>
      <dc:creator>camilo cabrales</dc:creator>
      <pubDate>Tue, 16 Aug 2022 15:00:15 +0000</pubDate>
      <link>https://dev.to/cecamilo/despliegue-y-prueba-de-servicios-creados-con-terraform-en-aws-a6</link>
      <guid>https://dev.to/cecamilo/despliegue-y-prueba-de-servicios-creados-con-terraform-en-aws-a6</guid>
      <description>&lt;p&gt;Terraform es una herramienta de IaC multicloud, basado en el lenguaje de configuración Hansicorp que es un tipo de JSON.&lt;/p&gt;

&lt;p&gt;Las plantillas de Terraform generalmente se distribuyen de la siguiente forma:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Festructura%2520template.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Festructura%2520template.png%3Fraw%3Dtrue" alt="Template Structure" width="371" height="221"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Provider&lt;/strong&gt;: Se define la nube en la cual vamos a trabajar.&lt;br&gt;
&lt;strong&gt;DataSources-Parameters&lt;/strong&gt;: Se definen los parámetros o variables que vamos a utilizar dentro de nuestra plantilla.&lt;br&gt;
&lt;strong&gt;Resources&lt;/strong&gt;: Definimos los recursos a desplegar.&lt;/p&gt;

&lt;p&gt;La siguiente arquitectura muestra los recursos que vamos a desplegar en AWS con Terraform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Farquitectura.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Farquitectura.png%3Fraw%3Dtrue" alt="Arquitectura" width="470" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/cecamilo00/posts/blob/circleci-project-setup/terraformAWS/main.tf" rel="noopener noreferrer"&gt;plantilla&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# PROVIDER

provider "aws" {
    region = "${var.aws_regions[0]}"
    #Se definen los tags comunes a todos los resources
    default_tags {
        tags = {
            despliegue = "Terraform AWS"
        }
    }
}

#DATA - PARAMETERS - VARIABLES


locals {
  tags = {
    despliegue = "Terraform AWS"
  }
}
variable "amiinstance" {
    default = "ami-090fa75af13c156b4"
    type = string  
}

variable "aws_regions" {
    default = [
        "us-east-1",
        "us-east-2"
    ]
    type = list
}

variable "aws_instance_size" {
    type = map
    default= {
        small = "t2.micro",
        medium = "t2.medium",
        large = "t2.large"
    }
}

variable "aws_instancedb_size" {
    type = map
    default= {
        small = "db.t2.micro",
        medium = "db.t2.small"
    }
}

variable "tag" {
    default = "template_terraform"
    type = string
}

variable "cidr_subnets" {
    default = [
        "10.0.1.0/24",#public
        "10.0.2.0/28",#private
        "10.0.3.0/28"#private
    ]
    type = list
}

#RESOURCES

resource "aws_vpc" "vpcterraform" {
    cidr_block = "10.0.0.0/16"
    enable_dns_hostnames = true
    tags = {
        Name = "${var.tag}"
    }
}

resource "aws_internet_gateway" "igwterraform" {
    vpc_id = "${aws_vpc.vpcterraform.id}"
    tags = {
        Name = "routeTableTFPublic_${var.tag}"
    }
}

resource "aws_route_table" "routeTableTFPublic" {
    vpc_id = "${aws_vpc.vpcterraform.id}"
    route {
        cidr_block = "0.0.0.0/0"
        gateway_id = "${aws_internet_gateway.igwterraform.id}"
    }
    tags = {
        Name = "routeTableTFPublic_${var.tag}"
    }
}

resource "aws_route_table" "routeTablerivate" {
    vpc_id = "${aws_vpc.vpcterraform.id}"
    tags = {
        Name = "routeTableTFPrivate_${var.tag}"
    }

}

resource "aws_subnet" "publicsubnet1" {
    vpc_id = "${aws_vpc.vpcterraform.id}"
    cidr_block = var.cidr_subnets[0]
    map_public_ip_on_launch = true
    availability_zone = "us-east-1a"
    tags = {
        Name = "publicsubnet1_${var.tag}"
    }
}

resource "aws_route_table_association" "routeTableAssociationTF" {
    subnet_id = "${aws_subnet.publicsubnet1.id}"
    route_table_id = "${aws_route_table.routeTableTFPublic.id}"
}

resource "aws_subnet" "privatesubnet1" {
    vpc_id = "${aws_vpc.vpcterraform.id}"
    cidr_block = var.cidr_subnets[1]
    availability_zone = "us-east-1b"
    tags = {
        Name = "privatesubnet1_${var.tag}"
    }
}

resource "aws_subnet" "privatesubnet2" {
    vpc_id = "${aws_vpc.vpcterraform.id}"
    cidr_block = var.cidr_subnets[2]
    availability_zone = "us-east-1c"
    tags = {
        Name = "privatesubnet2_${var.tag}"
    }
}

resource "aws_db_subnet_group" "dbprivatesubnetgroup"{
    name = "dbprivatesubnetgroup"
    subnet_ids = ["${aws_subnet.privatesubnet1.id}","${aws_subnet.privatesubnet2.id}"]
    tags = {
        Name = "dbprivatesubnetgroup_${var.tag}"
    }
}

resource "aws_iam_role" "instance_role" {
    assume_role_policy = jsonencode({
        "Version": "2012-10-17",
        "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole"
            ],
            "Principal": {
                "Service": [
                    "ec2.amazonaws.com"
                ]
            }
        }
        ]
    })

    tags = {
        tag-key = "role_${var.tag}"
    }
}

resource "aws_iam_policy" "policy"{
    policy = jsonencode({
        "Version": "2012-10-17",
        "Statement": [
            {
                "Effect": "Allow",
                "Action": [
                    "cloudwatch:PutMetricData",
                    "ds:CreateComputer",
                    "ds:DescribeDirectories",
                    "ec2:DescribeInstanceStatus",
                    "logs:*",
                    "ssm:*",
                    "ec2messages:*"
                ],
                "Resource": "*"
            },
            {
                "Effect": "Allow",
                "Action": "iam:CreateServiceLinkedRole",
                "Resource": "arn:aws:iam::*:role/aws-service-role/ssm.amazonaws.com/AWSServiceRoleForAmazonSSM*",
                "Condition": {
                    "StringLike": {
                        "iam:AWSServiceName": "ssm.amazonaws.com"
                    }
                }
            },
            {
                "Effect": "Allow",
                "Action": [
                    "iam:DeleteServiceLinkedRole",
                    "iam:GetServiceLinkedRoleDeletionStatus"
                ],
                "Resource": "arn:aws:iam::*:role/aws-service-role/ssm.amazonaws.com/AWSServiceRoleForAmazonSSM*"
            },
            {
                "Effect": "Allow",
                "Action": [
                    "ssmmessages:CreateControlChannel",
                    "ssmmessages:CreateDataChannel",
                    "ssmmessages:OpenControlChannel",
                    "ssmmessages:OpenDataChannel"
                ],
                "Resource": "*"
            }
        ]
    })
    tags = {
        tag-key = "policy_${var.tag}"
    }
}

resource "aws_iam_role_policy_attachment" "policy_attachment" {
    role = "${aws_iam_role.instance_role.name}"
    policy_arn = "${aws_iam_policy.policy.arn}"
}

resource "aws_iam_instance_profile" "instance_profile" {
    role  = "${aws_iam_role.instance_role.name}"
}

resource "aws_security_group" "sg_instance" {
    vpc_id = "${aws_vpc.vpcterraform.id}"
    ingress {
        from_port = 22
        to_port = 22
        protocol ="tcp"
        cidr_blocks = ["0.0.0.0/0"]
    }
    ingress {
        from_port   = 80
        to_port     = 80
        protocol    = "tcp"
        cidr_blocks = ["0.0.0.0/0"]
    }
    egress {
        from_port   = 0
        to_port     = 0
        protocol    = "-1"
        cidr_blocks = ["0.0.0.0/0"]
    }
    tags = {
        Name = "sg_instance_${var.tag}"
    }
}

resource "aws_instance" "instancia" {
    ami= "${var.amiinstance}"
    instance_type = "${var.aws_instance_size.small}"
    subnet_id = "${aws_subnet.publicsubnet1.id}"
    vpc_security_group_ids = [ "${aws_security_group.sg_instance.id}" ]
    tags = {
        Name = "instancia_${var.tag}"
    }
    iam_instance_profile = "${aws_iam_instance_profile.instance_profile.id}"
    depends_on = [aws_internet_gateway.igwterraform]
    user_data = &amp;lt;&amp;lt;EOF
    #!/bin/bash
    yum update -y
    yum install httpd -y
    service httpd start
    chkconfig httpd on
    cd /var/www/html
    echo "&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Terraform Instancia: $(hostname -f)&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;" &amp;gt; index.html
    EOF

}

resource "aws_security_group" "sgbd" {
    name = "sg"
    vpc_id = "${aws_vpc.vpcterraform.id}"
    ingress {
        from_port = 3306
        to_port = 3306
        protocol ="tcp"
        cidr_blocks = ["${aws_instance.instancia.private_ip}/32"]
    }
    tags = {
        Name = "sgbd_${var.tag}"
    }
}

resource "aws_db_instance" "dbinstance" {
    db_subnet_group_name = "${aws_db_subnet_group.dbprivatesubnetgroup.name}"
    engine = "mysql"
    db_name = "dbterraform"
    engine_version = "5.7.28"
    instance_class = "${var.aws_instancedb_size.small}"
    username = "admin"
    password = "admin12345678"
    allocated_storage = 10
    skip_final_snapshot = true
    vpc_security_group_ids =  [ "${aws_security_group.sgbd.id}" ]
    tags = {
        Name = "dbinstance_${var.tag}"
    }
}

output "endpoint" {
    value = "${aws_instance.instancia.public_ip}"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terraform tiene comandos para iniciar, validar,  desplegar y destruir los recursos definidos en nuestras plantillas (Antes de usar los siguientes comandos recuerden configurar sus access keys con el comando &lt;em&gt;aws configure&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;1.&lt;strong&gt;terraform init&lt;/strong&gt;: Configura el directorio donde se encuentra nuestra plantilla para que pueda ser usado con Terraform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Finit1.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Finit1.png%3Fraw%3Dtrue" alt="Init" width="668" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2.&lt;strong&gt;terraform validate&lt;/strong&gt;: Valida que la plantilla no tenga errores de sintaxis o de lógica.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fvalidate.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fvalidate.png%3Fraw%3Dtrue" alt="Validate" width="590" height="52"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;3.&lt;strong&gt;terraform plan&lt;/strong&gt;: Nos muestra una descripción de los recursos que van a ser desplegados, valida si hay cambios en nuestros recursos (en caso de actualización) y valida que nuestra plantilla no tenga errores. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fplan.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fplan.png%3Fraw%3Dtrue" alt="Plan" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;4.&lt;strong&gt;terraform apply&lt;/strong&gt;: Nos va a mostrar la infraestructura que se va a desplegar y nos va a preguntar que sí estamos de acuerdo por lo que debemos escribir &lt;em&gt;yes&lt;/em&gt; para que inicie el despliegue de nuestros servicios.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fterraform%2520apply.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fterraform%2520apply.png%3Fraw%3Dtrue" alt="Terraform apply" width="800" height="353"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al final nos va a mostrar la cantidad de recursos que se crearon y los outputs que tenemos definidos en la plantilla.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fterraform%2520apply%25201.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fterraform%2520apply%25201.png%3Fraw%3Dtrue" alt="Terraform apply" width="800" height="192"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Terraform al desplegar nuestra infraestructura crea el archivo&lt;br&gt;
&lt;em&gt;terraform.tfstate&lt;/em&gt; donde se guarda la información de los recursos desplegados. &lt;br&gt;
Podemos ver qué recursos se desplegaron con el comando: &lt;strong&gt;&lt;em&gt;terraform state list&lt;/em&gt;&lt;/strong&gt;  y podemos ver la información del recurso con el comando &lt;strong&gt;&lt;em&gt;terraform state show  nombre_del_recurso&lt;/em&gt;&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Una vez que se han creado todos nuestros recursos, vamos a verlos en la consola de AWS. Para esto buscamos resources groups y le damos click.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fresorces%2520groups.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fresorces%2520groups.png%3Fraw%3Dtrue" alt="Resources Groups" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ya en la pantalla principal damos click en &lt;em&gt;Tag Editor&lt;/em&gt;, &lt;em&gt;seleccionamos todas las regiones&lt;/em&gt;, &lt;em&gt;todos los recursos&lt;/em&gt;,  en los tags escribimos &lt;em&gt;despliegue&lt;/em&gt; - &lt;em&gt;Terraform AWS&lt;/em&gt; y damos click en le botón &lt;em&gt;Search Resources&lt;/em&gt;. Esto nos va a traer todos los recursos que tiene este tag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Ftag%2520editor.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Ftag%2520editor.png%3Fraw%3Dtrue" alt="Tag Editor" width="800" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El resultado de la búsqueda nos va a mostrar los recursos que cumplen las condiciones anteriores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fsearch%2520tag%2520editor.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fsearch%2520tag%2520editor.png%3Fraw%3Dtrue" alt="Search Tag Editor" width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este resultado lo obtuvimos ya que a todos los recursos de la plantilla les asignamos el tag: &lt;em&gt;Name: despliegue - Value: Terraform AWS&lt;/em&gt;,  en el siguiente fragmento de la  plantilla:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;provider "aws" {
    region = "${var.aws_regions[0]}"
    #Se definen los tags comunes a todos los resources
    default_tags {
        tags = {
            despliegue = "Terraform AWS"
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora vamos a validar el funcionamiento de nuestra aplicación. En la pantalla de resultados damos click en la instancia de EC2 que creamos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fclick%2520instance.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fclick%2520instance.png%3Fraw%3Dtrue" alt="Click Instance" width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Los que nos lleva a la pantalla de EC2 y copiamos la Ip publica de la instancia y la colocamos en una nueva pestaña de nuestro navegador.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fip%2520instance.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fip%2520instance.png%3Fraw%3Dtrue" alt="Click Instance" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;lo que nos va a mostrar lo siguiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fpage.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fpage.png%3Fraw%3Dtrue" alt="Click Instance" width="800" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este resultado lo obtuvimos ya que en nuestra definición de la instancia dentro dentro de la propiedad &lt;em&gt;user data&lt;/em&gt; le pedimos que instalara apache y creara una pagina web.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_instance" "instancia" {
    ami= "${var.amiinstance}"
    instance_type = "${var.aws_instance_size.small}"
    subnet_id = "${aws_subnet.publicsubnet1.id}"
    vpc_security_group_ids = [ "${aws_security_group.sg_instance.id}" ]
    tags = {
        Name = "instancia_${var.tag}"
    }
    iam_instance_profile = "${aws_iam_instance_profile.instance_profile.id}"
    user_data = &amp;lt;&amp;lt;EOF
    #!/bin/bash
    yum update -y
    yum install httpd -y
    service httpd start
    chkconfig httpd on
    cd /var/www/html
    echo "&amp;lt;html&amp;gt;&amp;lt;body&amp;gt;&amp;lt;h1&amp;gt;Terraform Instancia: $(hostname -f)&amp;lt;/h1&amp;gt;&amp;lt;/body&amp;gt;&amp;lt;/html&amp;gt;" &amp;gt; index.html
    yum install mysql
    EOF

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De acuerdo a la anterior definición de nuestra instancia, no  definimos un access key para poder ingresar a ella desde la terminal.&lt;br&gt;
Para acceder a la instancia y validar nuestra base de datos vamos a buscar el servicio System Manager.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2FSystem%2520manager.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2FSystem%2520manager.png%3Fraw%3Dtrue" alt="System Manager" width="800" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la pagina principal damos click &lt;em&gt;Session Manager&lt;/em&gt;, después en &lt;em&gt;Start Session&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fsesion%2520manager.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fsesion%2520manager.png%3Fraw%3Dtrue" alt="Session Manager" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora seleccionamos la instancia que creamos y damos click en el botón &lt;em&gt;Start Session&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fstart%2520session.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fstart%2520session.png%3Fraw%3Dtrue" alt="Start Session" width="800" height="376"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lo que nos va abrir una terminal como la siguiente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fterminal.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fterminal.png%3Fraw%3Dtrue" alt="Terminal" width="800" height="70"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Donde podemos ejecutar los comandos para acceder a la base de datos creada con la plantilla:&lt;/p&gt;

&lt;p&gt;Instalar mysql (para usar como cliente):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo su
sudo yum install mysql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conectarse a la base de datos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql -h reemplezar_por_endpoint_basededatos -u admin -p database
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Para lograr abrir la terminal desde System Manager se crearon los siguientes recursos en la plantilla:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws_iam_role
aws_iam_policy
aws_iam_role_policy_attachment
aws_iam_instance_profile
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;para asociar el recurso &lt;em&gt;aws_iam_instance_profile&lt;/em&gt; a nuestra instancia.&lt;/p&gt;

&lt;p&gt;5.&lt;strong&gt;terraform destroy&lt;/strong&gt;: al ejecutar el comando nos muestra los recursos que se van a eliminar, después nos solicita que autoricemos la eliminación por lo que debemos escribir &lt;em&gt;yes&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fdestroy.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2FterraformAWS%2Fdestroy.png%3Fraw%3Dtrue" alt="Destroy" width="800" height="662"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con la ejecución de estos comando terminamos con el despliegue y la liberación de los recursos desplegados con Terraform.&lt;/p&gt;

&lt;p&gt;Terraform me parece practico ya que su sintaxis se me asemeja al desarrollo (he trabajado como desarrollador). Una de las cosas que creo mas importantes para trabajar con herramientas IAC es la documentación la cual me pareció sencilla pero practica.&lt;/p&gt;

&lt;p&gt;Para mejorar la plantilla pueden crear archivos separados para las variables, para los outputs y realizar la misma ejecución de comandos, esto con el fin que nuestra plantilla quede más organizada y legible.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/camilo-cabrales-31a0bb53/" rel="noopener noreferrer"&gt;Camilo Cabrales&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Referencias
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs" rel="noopener noreferrer"&gt;Documentación&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://learn.hashicorp.com/tutorials/terraform/install-cli" rel="noopener noreferrer"&gt;Instalación&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.terraform.io/cli/commands/init" rel="noopener noreferrer"&gt;Comando Init&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.terraform.io/cli/commands/plan" rel="noopener noreferrer"&gt;Comando Plan&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.terraform.io/cli/commands/destroy" rel="noopener noreferrer"&gt;Comando Destroy&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
    </item>
    <item>
      <title>IaC - Como crear un API Rest con: CloudFormation o SAM</title>
      <dc:creator>camilo cabrales</dc:creator>
      <pubDate>Thu, 14 Jul 2022 21:49:45 +0000</pubDate>
      <link>https://dev.to/cecamilo/iac-como-crear-un-api-rest-con-cloudformation-o-sam-6n5</link>
      <guid>https://dev.to/cecamilo/iac-como-crear-un-api-rest-con-cloudformation-o-sam-6n5</guid>
      <description>&lt;p&gt;En este post vamos a crear la siguiente infraestructura utilizando algunas de las herramienta de IaC que tenemos a nuestra disposición en AWS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvxm54lvzf9r5js41zj0b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvxm54lvzf9r5js41zj0b.png" alt="Infraestructura" width="481" height="381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Empecemos con la plantilla para CloudFormation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  MetodoGET:
    Type: String
    Default: GET
  MetodoPOST:
    Type: String
    Default: POST
  ClientePath:
    Type: String
    Default: cliente
  SucursalPath:
    Type: String
    Default: sucursal
  Stage:
    Type: String
    Default: dev
  RoleFullAccessDynamoDB:
    Type: String
    Default: arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
  RoleFullAccessCloudWatch:
    Type: String
    Default: arn:aws:iam::aws:policy/CloudWatchFullAccess

Resources:
  RoleFuncionLambda:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - !Ref RoleFullAccessDynamoDB
        - !Ref RoleFullAccessCloudWatch
  APITienda:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: APITienda
      EndpointConfiguration:
        Types:
          - REGIONAL
  RecursoCliente:
    Type: AWS::ApiGateway::Resource
    Properties:
      RestApiId: !Ref  APITienda
      PathPart: !Ref ClientePath
      ParentId: !GetAtt APITienda.RootResourceId
  RecursoSucursal:
    Type: AWS::ApiGateway::Resource
    Properties:
      RestApiId: !Ref  APITienda
      PathPart: !Ref SucursalPath
      ParentId: !GetAtt APITienda.RootResourceId
  MetodoObtenerClientes:
    Type: AWS::ApiGateway::Method
    Properties:
      AuthorizationType: NONE
      HttpMethod: !Ref MetodoGET
      Integration:
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri: !Sub
          - arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
          - lambdaArn: !GetAtt ObtenerClienteLambda.Arn
      ResourceId: !GetAtt RecursoCliente.ResourceId
      RestApiId: !Ref APITienda
  MetodoRegistrarCliente:
    Type: AWS::ApiGateway::Method
    Properties:
      AuthorizationType: NONE
      HttpMethod: !Ref MetodoPOST
      Integration:
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri: !Sub
          - arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
          - lambdaArn: !GetAtt RegistrarClienteLambda.Arn
      ResourceId: !GetAtt RecursoCliente.ResourceId
      RestApiId: !Ref APITienda
  MetodoObtenerSucursales:
    Type: AWS::ApiGateway::Method
    Properties:
      AuthorizationType: NONE
      HttpMethod: !Ref MetodoGET
      Integration:
        IntegrationHttpMethod: POST
        Type: AWS_PROXY
        Uri: !Sub
          - arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
          - lambdaArn: !GetAtt ObtenerSucursalesLambda.Arn
      ResourceId: !GetAtt RecursoSucursal.ResourceId
      RestApiId: !Ref APITienda
  Despliegue:
    Type: AWS::ApiGateway::Deployment
    DependsOn:
      - MetodoObtenerClientes
      - MetodoRegistrarCliente
      - MetodoObtenerSucursales
    Properties: 
      RestApiId: !Ref APITienda
      StageName: !Ref Stage
  RegistrarClienteLambda:
    Type: AWS::Lambda::Function
    Properties:
      Description: "Agrega clientes a la base de datos"
      FunctionName: "RegistarCliente"
      Handler: index.lambda_handler
      MemorySize: 128
      Runtime: python3.8
      Timeout: 3
      Code: 
        ZipFile: |
          import json
          import boto3 
          from boto3.dynamodb.conditions import Key

          dynamodb = boto3.resource("dynamodb")
          table = dynamodb.Table("Tiendas")

          def lambda_handler(event, context):
            data = json.loads(event["body"])
            idCliente= data["id"]
            nombre = data["nombre"]
            apellido = data["apellido"]
            table.put_item(Item={
              "Id": "Cliente",
              "Filtro":"Id#"+idCliente,
              "Nombre":nombre,
              "Apellido":apellido
            })
            return {
              'statusCode': 200,
              'body': json.dumps(idCliente)
            }
      Role: !GetAtt  RoleFuncionLambda.Arn
  ObtenerClienteLambda:
    Type: AWS::Lambda::Function
    Properties:
      Description: "Obtiene los clientes"
      FunctionName: "ObtenerCliente"
      Handler: index.lambda_handler
      MemorySize: 128
      Runtime: python3.8
      Timeout: 3
      Code: 
        ZipFile: |
          import json
          import boto3 
          from boto3.dynamodb.conditions import Key

          dynamodb = boto3.resource("dynamodb")
          table = dynamodb.Table("Tiendas")

          def lambda_handler(event, context):

            id = event["queryStringParameters"]["id"]
            cliente = table.query(KeyConditionExpression=Key('Id').eq("Cliente") &amp;amp; Key('Filtro').eq('Id#'+id),                   
                                ProjectionExpression="Id,Filtro,Nombre,Apellido")
            return {
              'statusCode': 200,
              'body': json.dumps(cliente)
            }
      Role: !GetAtt  RoleFuncionLambda.Arn
  ObtenerSucursalesLambda:
    Type: AWS::Lambda::Function
    Properties:
      Description: "Obtiene las sucursales"
      FunctionName: "ObtenerSucursales"
      Handler: index.lambda_handler
      MemorySize: 128
      Runtime: python3.8
      Timeout: 3
      Code: 
        ZipFile: |
          import json
          import boto3 
          from boto3.dynamodb.conditions import Key

          dynamodb = boto3.resource("dynamodb")
          table = dynamodb.Table("Tiendas")

          def lambda_handler(event, context):

            sucursales = table.query(KeyConditionExpression=Key('Id').eq("Sucursal"),                   
                                  ProjectionExpression="Id,Filtro,Direccion")
            return {
              'statusCode': 200,
              'body': json.dumps(sucursales)
            }
      Role: !GetAtt  RoleFuncionLambda.Arn
  PermisoObtenerClientes:
    Type: AWS::Lambda::Permission
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !GetAtt ObtenerClienteLambda.Arn
      Principal: "apigateway.amazonaws.com"
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${APITienda}/*/${MetodoGET}/${ClientePath}"
  PermisoRegistrarCliente:
    Type: AWS::Lambda::Permission
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !Ref RegistrarClienteLambda
      Principal: "apigateway.amazonaws.com"
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${APITienda}/*/${MetodoPOST}/${ClientePath}"
  PermisoObtenerSucursales:
    Type: AWS::Lambda::Permission
    Properties:
      Action: "lambda:InvokeFunction"
      FunctionName: !Ref ObtenerSucursalesLambda
      Principal: "apigateway.amazonaws.com"
      SourceArn: !Sub "arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${APITienda}/*/${MetodoGET}/${SucursalPath}"
  Tabla:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: Tiendas
      BillingMode: PROVISIONED
      ProvisionedThroughput: 
        ReadCapacityUnits: "5"
        WriteCapacityUnits: "5"
      AttributeDefinitions:
        -
          AttributeName: "Id"
          AttributeType: "S"
        -
          AttributeName: "Filtro"
          AttributeType: "S"
      KeySchema:
        -
          AttributeName: "Id"
          KeyType: "HASH"
        -
          AttributeName: "Filtro"
          KeyType: "RANGE"
Outputs:
  ApiEndPoint:
    Description: "EndPoint Api"
    Value: !Sub "https://${APITienda}.execute-api.${AWS::Region}.amazonaws.com/${Stage}/"
  ClienteEndPoint:
    Description: "EndPoint Metodos Cliente"
    Value: !Sub "https://${APITienda}.execute-api.${AWS::Region}.amazonaws.com/${Stage}/${ClientePath}"
  SucursalEndPoint:
    Description: "EndPoint Metodo Sucursal"
    Value: !Sub "https://${APITienda}.execute-api.${AWS::Region}.amazonaws.com/${Stage}/${SucursalPath}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/cecamilo00/posts/blob/circleci-project-setup/IaC%20-%20Como%20crear%20un%20API%20Rest/apirest.yml" rel="noopener noreferrer"&gt;apirest.yml&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Las etiquetas que utilizamos para crear los recursos son las siguientes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr298why98cwbz98hnv89.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr298why98cwbz98hnv89.png" alt="Infraestructura CloudFormation" width="591" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para poder desplegar nuestra infraestructura debemos asegurarnos de tener instalada la CLI (&lt;a href="https://docs.aws.amazon.com/es_es/cli/latest/userguide/getting-started-install.html" rel="noopener noreferrer"&gt;Instalar CLI&lt;/a&gt;) en nuestro equipo y haber configurado nuestras credenciales(comando &lt;em&gt;aws configure&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Vamos a validar que nuestra plantilla este construida de manera correcta. Ubicados en la carpeta donde se encuentra la plantilla vamos a ejecutar el siguiente comando:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;aws cloudformation validate-template --template-body file://apirest.yml&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Si la plantilla esta bien construida el comando nos va a retornar la lista de parámetros que tiene nuestra plantilla.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsexp7jttqu5z9rq0tpj8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsexp7jttqu5z9rq0tpj8.png" alt="Parameters" width="800" height="121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez sabemos que nuestra plantilla es correcta vamos a desplegarla utilizando el siguiente comando&lt;/p&gt;

&lt;p&gt;&lt;em&gt;aws cloudformation deploy --template-file  apirest.yml  --stack-name apiresIaC --capabilities CAPABILITY_IAM&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;que recibe como parámetros el nombre de la plantilla y el nombre del stack que vamos a crear. Adicionalmente le enviamos el parámetro --capabilities CAPABILITY_IAM ya que vamos hacer uso de IAM.&lt;/p&gt;

&lt;p&gt;Una vez que ejecutamos el comando vamos a ver lo siguiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn1maluwldqe286xdq434.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn1maluwldqe286xdq434.png" alt="Deploy" width="800" height="48"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Lo que nos indica que nuestros recursos fueron desplegados con exito. Podemos revisar todo el proceso y el resultado del despliegue de la infraestructura desde la consola de AWS. Para este buscamos el servicio &lt;strong&gt;CloudFormation&lt;/strong&gt; y damos click en Stacks, donde vamos a ver el stack que creamos con el comando &lt;em&gt;deploy&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7lxaxcjrpl1yz0cweli.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm7lxaxcjrpl1yz0cweli.png" alt="Deploy" width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Si damos click en el nombre del stack creado vamos a poder ver todo el detalle de los eventos del proceso de creación, los recursos creados, los parámetros, las salidas, el template y los cambios que se han realizado sobre la plantilla. Damos click en Outputs para ver las rutas de los servicios desplegados.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fywq7j06jhniz5o1715pl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fywq7j06jhniz5o1715pl.png" alt="Detail Stack" width="800" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para probar nuestros servicios podemos utilizar PostMan o en mi caso estoy utilizando la extension &lt;a href="https://marketplace.visualstudio.com/items?itemName=humao.rest-client" rel="noopener noreferrer"&gt;REST Client&lt;/a&gt; para Visual Studio Code. Puedo probar los servicios de la siguiente manera:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST   https://5d24uhg9db.execute-api.us-east-1.amazonaws.com/dev/cliente HTTP/1.1
content-type: application/json

{
    "id": "1",
    "nombre": "Lisa",
    "apellido": "Simpson"
}

###

GET   https://5d24uhg9db.execute-api.us-east-1.amazonaws.com/dev/cliente?id=1 HTTP/1.1
content-type: application/json

###

GET   https://5d24uhg9db.execute-api.us-east-1.amazonaws.com/dev/sucursal HTTP/1.1
content-type: application/json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con esto finalizamos el despliegue y las pruebas de nuestro API Rest creado con CloudFormation.&lt;/p&gt;

&lt;p&gt;Ahora vamos a crear la misma infraestructura utilizando &lt;a href="https://docs.aws.amazon.com/es_es/serverless-application-model/latest/developerguide/what-is-sam.html" rel="noopener noreferrer"&gt;SAM&lt;/a&gt;(Serverless Application Model). SAM nos permite desplegar &lt;strong&gt;aplicaciones sin servidor&lt;/strong&gt; en AWS a diferencia de CloudFormation que nos permite desplegar todo tipo de recursos.&lt;/p&gt;

&lt;p&gt;Las etiquetas que utilizamos para crear los recursos son las siguientes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foyp708w2bpkh1c5cbzqg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foyp708w2bpkh1c5cbzqg.png" alt="Infraestructura SAM" width="591" height="404"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La plantilla que utilizamos es la siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
  Stage:
    Type: String
    Default: dev
  RoleFullAccessDynamoDB:
    Type: String
    Default: arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess
  RoleFullAccessCloudWatch:
    Type: String
    Default: arn:aws:iam::aws:policy/CloudWatchFullAccess
  ClientePath:
    Type: String
    Default: cliente
  SucursalPath:
    Type: String
    Default: sucursal
Resources:
  RoleFuncionLambda:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - lambda.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: /
      ManagedPolicyArns:
        - !Ref RoleFullAccessDynamoDB
        - !Ref RoleFullAccessCloudWatch
  APITienda:
    Type: AWS::Serverless::Api
    Properties:
      Name: APITienda
      StageName: !Ref Stage

  RegistrarClienteLambda:
    Type: AWS::Serverless::Function
    Properties:
      InlineCode: |
          import json
          import boto3 
          from boto3.dynamodb.conditions import Key

          dynamodb = boto3.resource("dynamodb")
          table = dynamodb.Table("Tiendas")

          def lambda_handler(event, context):
            data = json.loads(event["body"])
            idCliente= data["id"]
            nombre = data["nombre"]
            apellido = data["apellido"]
            table.put_item(Item={
              "Id": "Cliente",
              "Filtro":"Id#"+idCliente,
              "Nombre":nombre,
              "Apellido":apellido
            })
            return {
              'statusCode': 200,
              'body': json.dumps(idCliente)
            }
      Handler: index.lambda_handler
      Runtime: python3.7
      PackageType: Zip
      FunctionName: RegistrarCliente
      Role: !GetAtt RoleFuncionLambda.Arn
      Events:
        RegistrarCliente:
          Type: Api
          Properties:
            RestApiId: !Ref APITienda
            Path: /cliente
            Method: POST
  ObtenerClienteLambda:
    Type: AWS::Serverless::Function
    Properties:
      InlineCode: |
          import json
          import boto3 
          from boto3.dynamodb.conditions import Key

          dynamodb = boto3.resource("dynamodb")
          table = dynamodb.Table("Tiendas")

          def lambda_handler(event, context):

            id = event["queryStringParameters"]["id"]
            cliente = table.query(KeyConditionExpression=Key('Id').eq("Cliente") &amp;amp; Key('Filtro').eq('Id#'+id),                   
                                ProjectionExpression="Id,Filtro,Nombre,Apellido")
            return {
              'statusCode': 200,
              'body': json.dumps(cliente)
            }
      Handler: index.lambda_handler
      Runtime: python3.7
      PackageType: Zip
      FunctionName: ObtenerCliente
      Role: !GetAtt RoleFuncionLambda.Arn
      Events:
        ObtenerClientes:
          Type: Api
          Properties:
            RestApiId: !Ref APITienda
            Path: /cliente
            Method: GET
  SucursalesLambda:
    Type: AWS::Serverless::Function
    Properties:
      InlineCode: |
          import json
          import boto3 
          from boto3.dynamodb.conditions import Key

          dynamodb = boto3.resource("dynamodb")
          table = dynamodb.Table("Tiendas")

          def lambda_handler(event, context):

            sucursales = table.query(KeyConditionExpression=Key('Id').eq("Sucursal"),                   
                                  ProjectionExpression="Id,Filtro,Direccion")
            print(sucursales["Items"])
            return {
              'statusCode': 200,
              'body': json.dumps(sucursales)
            }
      Handler: index.lambda_handler
      Runtime: python3.7
      PackageType: Zip
      FunctionName: ObtenerSucursales
      Role: !GetAtt RoleFuncionLambda.Arn
      Events:
        ObtenerSucursales:
          Type: Api
          Properties:
            RestApiId: !Ref APITienda
            Path: /sucursal
            Method: GET
  Tabla:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: Tiendas
      BillingMode: PROVISIONED
      ProvisionedThroughput: 
        ReadCapacityUnits: "5"
        WriteCapacityUnits: "5"
      AttributeDefinitions:
        -
          AttributeName: "Id"
          AttributeType: "S"
        -
          AttributeName: "Filtro"
          AttributeType: "S"
      KeySchema:
        -
          AttributeName: "Id"
          KeyType: "HASH"
        -
          AttributeName: "Filtro"
          KeyType: "RANGE"
Outputs:
  ApiEndPoint:
    Description: "EndPoint Api"
    Value: !Sub "https://${APITienda}.execute-api.${AWS::Region}.amazonaws.com/${Stage}/"
  ClienteEndPoint:
    Description: "EndPoint Metodos Cliente"
    Value: !Sub "https://${APITienda}.execute-api.${AWS::Region}.amazonaws.com/${Stage}/${ClientePath}"
  SucursalEndPoint:
    Description: "EndPoint Metodo Sucursal"
    Value: !Sub "https://${APITienda}.execute-api.${AWS::Region}.amazonaws.com/${Stage}/${SucursalPath}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/cecamilo00/posts/blob/circleci-project-setup/IaC%20-%20Como%20crear%20un%20API%20Rest/apirestsam.yml" rel="noopener noreferrer"&gt;apirestsam.yml&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Algo que diferencia a las plantillas &lt;strong&gt;SAM&lt;/strong&gt; de las plantillas de &lt;strong&gt;CloudFormation&lt;/strong&gt; es la siguiente linea que identifica la plantilla como SAM:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Transform: AWS::Serverless-2016-10-31&lt;/em&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SAM&lt;/strong&gt; utiliza algunas etiquetas diferentes para crear los recursos como: &lt;/p&gt;

&lt;p&gt;&lt;em&gt;AWS::Serverless::Api&lt;/em&gt; : Nos sirve para crear el API Gateway.&lt;/p&gt;

&lt;p&gt;AWS::Serverless::Function: Nos sirve para crear la función Lambda y la integración con API Gateway (los recursos, los métodos, el stage y el despliegue).&lt;/p&gt;

&lt;p&gt;Como podemos observar utilizar SAM para desplegar aplicaciones sin servidor es mucho mas practico que utilizar &lt;strong&gt;CloudFormation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Teniendo nuestra plantilla debemos desplegarla en AWS. Primero debemos tener instalada la &lt;a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html" rel="noopener noreferrer"&gt;SAM CLI&lt;/a&gt; en nuestro equipo.&lt;/p&gt;

&lt;p&gt;Una vez instalada SAM CLI vamos a validar que nuestra plantilla este construida correctamente con el siguiente comando.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;sam validate --template apirestsam.yml&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp7d5tv5830wrvfsgxaf5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp7d5tv5830wrvfsgxaf5.png" alt="SAM Validate" width="720" height="45"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como vemos que nuestra plantilla esta correcta vamos a desplegarla con el siguiente comando:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;sam deploy --template-file apirestsam.yml --stack-name apirestSAMIaC --capabilities CAPABILITY_IAM&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Al ejecutar el comando vamos a ver en detalle como se están creando nuestros recursos. Van a ver algo similar a esto en su terminal:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff28pha3li5i5f88ml782.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff28pha3li5i5f88ml782.png" alt="SAM Deploy" width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esto nos indica que nuestra API Rest fue desplegado con éxito. &lt;br&gt;
Como lo hicimos en el despliegue de la plantilla de &lt;strong&gt;CloudFormation&lt;/strong&gt; podemos ir a la consola de AWS y verificar que los recursos se hayan creado.&lt;/p&gt;

&lt;p&gt;En este post podemos observar que se pueden utilizar diferentes herramientas para cumplir un mismo objetivo, sin embargo debemos buscar siempre la mas adecuada para cada caso, que en este es &lt;strong&gt;SAM&lt;/strong&gt;, ya que la infraestructura a desplegar es sin servidor.&lt;/p&gt;

&lt;p&gt;Como ejercicio pueden implementar la función &lt;strong&gt;Lambda&lt;/strong&gt; para ingresar las sucursales e implementar un método de autenticación para validar el acceso a las métodos del &lt;strong&gt;API Gateway&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;Me pueden encontrar en:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/camilo-cabrales-31a0bb53/" rel="noopener noreferrer"&gt;Camilo Cabrales&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Referencias
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/es_es/AWSCloudFormation/latest/UserGuide/using-cfn-cli-deploy.html" rel="noopener noreferrer"&gt;CloudFormation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/what-is-sam.html" rel="noopener noreferrer"&gt;SAM&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>iac</category>
    </item>
    <item>
      <title>Conectarse a RDS por medio de un Proxy desde una función Lambda</title>
      <dc:creator>camilo cabrales</dc:creator>
      <pubDate>Tue, 14 Jun 2022 21:01:39 +0000</pubDate>
      <link>https://dev.to/cecamilo/conectarse-a-rds-por-medio-de-un-proxy-desde-una-funcion-lambda-3cbg</link>
      <guid>https://dev.to/cecamilo/conectarse-a-rds-por-medio-de-un-proxy-desde-una-funcion-lambda-3cbg</guid>
      <description>&lt;p&gt;Muchas de las aplicaciones que creamos necesitan una fuente de datos o base de datos relacional.Cuando la aplicación crece vamos a tener una carga significativa a nuestra base de datos, por lo que vamos a realizar mas peticiones y se van a crear mas conexiones a ella, lo que puede llegar a saturar la base de datos en cuanto a cantidad de conexiones. &lt;/p&gt;

&lt;p&gt;Para dar un mejor manejo a las conexiones AWS tiene el componente &lt;strong&gt;Proxy&lt;/strong&gt; que se encarga de administrar las conexiones a la base de datos de manera eficiente y evita que podamos llegar a tener errores por el alto numero de conexiones.&lt;/p&gt;

&lt;p&gt;En este post vamos a crear un Proxy para que sirva como punto de acceso a nuestra base de datos. El acceso a la base de datos lo vamos a realizar por medio de una función &lt;strong&gt;Lambda&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Los Pasos a realizar van a ser los siguientes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creación de una base de datos (RDS).&lt;/li&gt;
&lt;li&gt;Creación de un Secreto (Secrets Manager).&lt;/li&gt;
&lt;li&gt;Creación del Proxy.&lt;/li&gt;
&lt;li&gt;Creación de la función &lt;strong&gt;Lambda&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Iniciemos con la creación de la base de datos, para esto buscamos el servicio &lt;strong&gt;RDS&lt;/strong&gt;. Ya en la pagina principal de RDS damos click en Databases y Create Database.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fprincipal%2520RDS.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fprincipal%2520RDS.png%3Fraw%3Dtrue" alt="Principal RDS" width="800" height="283"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos observar que hay dos formas para crear nuestra base de datos: &lt;em&gt;Standard create _y _Easy create&lt;/em&gt;. Las dos formas nos permiten crear la base de datos solo que la forma &lt;em&gt;Easy create&lt;/em&gt; no necesitamos realizar muchas configuraciones, para nuestro caso vamos a utilizar la forma &lt;em&gt;Standard create&lt;/em&gt;. Aunque pueden usar &lt;em&gt;Easy create&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Seleccionamos el motor de base de datos PostgreSQL y dejamos la version que se carga por defecto.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fselect%2520engine.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fselect%2520engine.png%3Fraw%3Dtrue" alt="Select Engine" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seleccionamos el template free tier para que no genere "costos" (Recuerden eliminar todos los servicios creados al terminar el ejercicio). Esta selección solo se debe utilizar para pruebas ya que son bases de datos pequeñas que no tienen alta disponibilidad ni sus datos se replican.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fselect%2520template.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fselect%2520template.png%3Fraw%3Dtrue" alt="Select Template" width="800" height="557"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora asignamos un identificador para la instancia de base de datos, asignamos nombre un usuario y su contraseña.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fsettings%2520rds1.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fsettings%2520rds1.png%3Fraw%3Dtrue" alt="Settings" width="800" height="616"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora debemos seleccionar el tipo de instancia que queremos para nuestra base de datos dejamos seleccionado la que viene por defecto que es t3.micro que es una instancia de uso general (En las referencias se encuentra el link hacia los tipos de instancia que maneja AWS).Para el almacenamiento dejamos un disco de propósito general de 20GB. Los demás valores los dejamos por defecto.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Finstance%2520configuration.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Finstance%2520configuration.png%3Fraw%3Dtrue" alt="Instance Configuration" width="730" height="843"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El siguiente paso es seleccionar la configuración de red y el lugar de donde queremos que se tenga acceso a nuestra base de datos. Para ambientes productivos siempre es mejor dejar el Public access &lt;strong&gt;&lt;em&gt;No&lt;/em&gt;&lt;/strong&gt;, ya limita el acceso a que sea desde la VPC en la cual se crea nuestra base de datos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fconectivity.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fconectivity.png%3Fraw%3Dtrue" alt="Conectivity" width="732" height="878"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la sección &lt;em&gt;Aditional Configuration&lt;/em&gt;, vamos a encontrar dentro de la sección &lt;em&gt;Database options&lt;/em&gt; una lista con el nombre &lt;em&gt;DB parameter group&lt;/em&gt;. Los parameters groups nos sirven para establecer la configuración del motor de base de datos, siempre es recomendable tener una parameter group diferente al que esta por defecto para entornos de desarrollo y producción.&lt;br&gt;
Para finalizar damos click en el boton &lt;em&gt;Create Database&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fcreate%2520database1.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fcreate%2520database1.png%3Fraw%3Dtrue" alt="Create Database" width="800" height="837"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la siguiente pantalla vamos a ver el listado de base de datos que tenemos en esta región. Vamos a dar click en el nombre de la base de datos que acabos de crear para ver el endpoint para conectarnos a ella.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Flist%2520databases.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Flist%2520databases.png%3Fraw%3Dtrue" alt="Create Database" width="800" height="134"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fendpoint.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fendpoint.png%3Fraw%3Dtrue" alt="EndPoint" width="800" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nuestro siguiente paso es crear el Proxy para nuestra base de datos. Para esto vamos al menu lateral izquierdo y seleccionamos &lt;em&gt;Proxies&lt;/em&gt; y damos click en el botón Create &lt;em&gt;Proxy&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2FProxies1.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2FProxies1.png%3Fraw%3Dtrue" alt="Create Proxy" width="800" height="282"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora debemos asignar un nombre al Proxy y seleccionar el tipo de motor de base de datos a utilizar para el Proxy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fname%2520proxy.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fname%2520proxy.png%3Fraw%3Dtrue" alt="Name Proxy" width="800" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seguido a esto debemos seleccionar la base de datos a la cual queremos crearle el proxy, seleccionamos la base de datos que lanzamos en pasos anteriores.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fselect%2520database%2520proxy.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fselect%2520database%2520proxy.png%3Fraw%3Dtrue" alt="Select Database Proxy" width="800" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la sección de &lt;em&gt;Conectivity&lt;/em&gt; nos pide un secreto (Nos sirve para almacenar información privada o credenciales de bases de datos). Damos click en el enlace &lt;em&gt;create a new secret&lt;/em&gt; y nos llevara a la pagina principal de secrets manager, damos click en &lt;em&gt;Store a new secret&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fpage%2520secret.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fpage%2520secret.png%3Fraw%3Dtrue" alt="Page Secret" width="800" height="133"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En esta pantalla debemos seleccionar el tipo de secreto, ingresar el usuario y contraseña que definimos al crear la base de datos y seleccionar la base de datos que va a utilizar este secreto.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fchoose%2520secret%2520type.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fchoose%2520secret%2520type.png%3Fraw%3Dtrue" alt="Choose secret" width="800" height="462"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora debemos dar un nombre y una descripción a nuestro secreto.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fname%2520secret.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fname%2520secret.png%3Fraw%3Dtrue" alt="Name secret" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para este caso vamos a dejar la configuración por defecto, sin embargo para entornos de producción como buena practica debemos rotar nuestros secretos . &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Frotate%2520secret.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Frotate%2520secret.png%3Fraw%3Dtrue" alt="Rotate secret" width="800" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para finalizar vamos a ver un resumen de la configuración de nuestro secreto y la forma en que podemos acceder a él por medio de algunos lenguajes de programación. Damos click en &lt;em&gt;Store.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fstore%2520secret.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fstore%2520secret.png%3Fraw%3Dtrue" alt="Store secret" width="800" height="323"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez creado el secreto regresamos a la ventana donde estábamos creando el proxy y seleccionamos el secreto (es posible que el secreto no aparezca en la lista y debamos actualizar la pagina e ingresar de nuevo los datos) que acabamos de crear y damos click en el botón Create proxy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fcreate%2520proxy.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fcreate%2520proxy.png%3Fraw%3Dtrue" alt="Create Proxy" width="696" height="836"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El proxy puede tardar un tiempo en crearse, por lo que debemos esperar un poco a qué se cree.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fcreating%2520proxy.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fcreating%2520proxy.png%3Fraw%3Dtrue" alt="Creating Proxy" width="800" height="143"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hasta el momento hemos creado: La base de datos, un secreto para almacenar las credenciales a la base de datos y el proxy por el cual vamos acceder a la base de datos. Ahora vamos a iniciar la creación de la función Lambda que va a conectarse a la base de datos.&lt;/p&gt;

&lt;p&gt;Vamos a la pagina principal de Lambda y damos click en &lt;em&gt;Create function&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fcreate%2520function.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fcreate%2520function.png%3Fraw%3Dtrue" alt="Create function" width="800" height="265"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El siguiente paso es definir la configuración de nuestra función, iniciando por asignarle un nombre, el lenguaje de programación y dejamos seleccionado para que se cree un rol por defecto.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fassign%2520name%2520lambda.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fassign%2520name%2520lambda.png%3Fraw%3Dtrue" alt="Assign name function" width="800" height="431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como el proxy solo se puede usar desde dentro de una &lt;strong&gt;VPC&lt;/strong&gt; debemos seleccionar la &lt;strong&gt;VPC&lt;/strong&gt; a la cual va a tener acceso. Hay que tener en cuenta que debe ser la misma &lt;strong&gt;VPC&lt;/strong&gt; que seleccionamos para la base de datos y el proxy (en este ejemplo estamos utilizando la &lt;strong&gt;VPC&lt;/strong&gt; por defecto que trae AWS para esta region).Aparte de la &lt;strong&gt;VPC&lt;/strong&gt; debemos seleccionar las subnets desde la cuales la función Lambda puede acceder al proxy. Por ultimo debemos seleccionar el &lt;strong&gt;Security Group&lt;/strong&gt; que nos va a permitir el acceso al proxy por medio del puerto que usa Postgres. Terminada la configuración damos click en el botón &lt;em&gt;Create function&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2FLambda%2520VPC.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2FLambda%2520VPC.png%3Fraw%3Dtrue" alt="Configure VPC Lambda" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como vamos a trabajar con Postgres desde Lambda, debemos utilizar el paquete &lt;a href="https://github.com/cecamilo00/posts/blob/circleci-project-setup/proxy/psycopg2.zip" rel="noopener noreferrer"&gt;psycopg&lt;/a&gt; que nos ayuda a tener acceder a   Postgres. Si queremos utilizar paquetes de terceros o creados por nosotros en necesario usar un Layer.(en las referencias se indica como crear Layer).&lt;/p&gt;

&lt;p&gt;Para agregar nuestra layer vamos a la parte inferior de la pantalla de la función Lambda y damos click en &lt;em&gt;Add Layer&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fadd%2520layer.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fadd%2520layer.png%3Fraw%3Dtrue" alt="Add Layer" width="800" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la siguiente pantalla seleccionamos nuestra Layer y la versión. El numero de versión depende de las veces que la hayamos modificado el Layer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fselect%2520layer.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fselect%2520layer.png%3Fraw%3Dtrue" alt="Select Layer" width="800" height="713"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos ver que nuestra Layer se agrego con éxito.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fview%2520layer.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fview%2520layer.png%3Fraw%3Dtrue" alt="Show Layer" width="800" height="250"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ya que configuramos nuestra Layer debemos asignar al rol de la función Lambda las siguientes políticas. Para esto vamos a la pestaña de &lt;em&gt;Configuration - Permissions&lt;/em&gt; damos click en el rol de la función.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fselect%2520rol%2520lambda.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fselect%2520rol%2520lambda.png%3Fraw%3Dtrue" alt="Rol Function" width="800" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Agregamos las siguientes políticas al rol: &lt;em&gt;SecretsManagerReadWrite&lt;/em&gt;,&lt;em&gt;AmazonRDSFullAccess&lt;/em&gt; y una política personalizada como la siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "secretsmanager:GetResourcePolicy",
                "secretsmanager:GetSecretValue",
                "secretsmanager:DescribeSecret",
                "secretsmanager:ListSecretVersionIds",
                "secretsmanager:ListSecrets"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fpolicies%2520%2520rol%2520lambda.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fpolicies%2520%2520rol%2520lambda.png%3Fraw%3Dtrue" alt="Policies Rol" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Una vez que terminamos la configuración del rol de la función Lambda vamos agregar el siguiente código.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import json
import boto3
import psycopg2

client_secret = boto3.client('secretsmanager')

def lambda_handler(event, context):
    # TODO implement

    probar_conexion()
    return {
        'statusCode': 200,
        'body': json.dumps('Test Proxy!')
    }

def probar_conexion():
    conn = psycopg2.connect(host="proxy.com",database="postgres",user='postgres',password='12345678')
    print(conn)
    conn.close()

def probar_conexion_endpoint():
    response = client_secret.get_secret_value(SecretId='arn:aws:secretsmanager:us-east-1:385033107168:secret:secret-bd-proxy-4l9BKB')
    credentials = json.loads(response["SecretString"])
    conn = psycopg2.connect(host="proxy-database-post.proxy-cty4x2ccvn0y.us-east-1.rds.amazonaws.com",database="postgres",user=credentials["username"],password=credentials["password"])
    print(conn)
    conn.close()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La función &lt;em&gt;probar_conexion&lt;/em&gt; es la que vamos a utilizar para probar la conexión a nuestro proxy (Es necesario reemplazar los parametros: host,database,user,password por los que establecimos en la configuración de nuestra base de datos). Ahora debemos crear el tipo de prueba, desplegar la función (botón &lt;em&gt;Deploy&lt;/em&gt;) y ejecutar la función (botón &lt;em&gt;Test&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;Como ejercicio pueden probar  la función &lt;em&gt;probar_conexion_endpoint&lt;/em&gt;. Para esto es necesario configurar un EndPoint (Se puede encontrar en la pagina de la VPC) que este dentro de la VPC de la función Lamba y de la base de datos,  en su Security Group le debemos indicar que el Security Group de la función Lambda puede acceder a el.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fendpoint%2520proxy.png%3Fraw%3Dtrue" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fcecamilo00%2Fposts%2Fblob%2Fcircleci-project-setup%2Fproxy%2Fendpoint%2520proxy.png%3Fraw%3Dtrue" alt="EndPoint" width="800" height="240"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Me pueden encontrar en:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/camilo-cabrales-31a0bb53/" rel="noopener noreferrer"&gt;Camilo Cabrales&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Referencias
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://docs.amazonaws.cn/en_us/AmazonRDS/latest/UserGuide/rds-proxy-planning.html" rel="noopener noreferrer"&gt;Proxy&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/es/ec2/instance-types/" rel="noopener noreferrer"&gt;Tipos de Instancia&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/cecamilo/lambda-layer-para-python-1478"&gt;Lambda Layer&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/cecamilo/lambda-layer-para-python-1478"&gt;Secrets Manager&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.html" rel="noopener noreferrer"&gt;Parameters Group&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
    </item>
  </channel>
</rss>
