Giter Site home page Giter Site logo

7574-tp0's Introduction

Resolución de los ejercicios

Notas generales

A los comandos docker se los antepuso con sudo. Si bien aquí se explica por qué esto es necesario y cómo poder evitar la necesidad de prefijar con sudo los comandos de docker, a la hora de desarrollar el tp todavía no se había encontrado esta información y se prefirió cerrar la entrega con lo que está testeado que anda, para no romper algo a último momento.

Cada ejercicio se ha resuelto en un branch de forma no incremental, es decir que para cada ejercicio se ha sacado branch nuevo a partir de master.

Ejercicio 1

Trabajando en el archivo docker-compose-dev.yml:

  1. se ha duplicado el client1
  2. se le cambió el nombre a client2
  3. se le cambió la variable de entorno CLI_ID a 2 Analisis: Está bien dejar los siguientes parámetros como estaban:
  4. image: porque todos los clientes se basan en una misma imagen. Se pide duplicar un cliente como el ya existente, no se pide que cumpla con otras funcionalidades.
  5. entrypoint: idem anterior
  6. env vars:
    1. CLI_LOOP_LAPSE y CLI_LOOP_PERIOD: al ser usadas para indicar la frecuencia con que se envian msjs al server y durante cuanto tiempo se ejecutará el cliente, no tiene mucho sentido cambiar los valores, aunque de hacerlo, tampoco se rompería nada; simplemente se modificaría el comportamiento del cliente.
    2. CLI_SERVER_ADDRESS: No se debe cambiar porque indica el puerto del server. Al ejecutar make docker-compose-up y revisar los logs mediante make docker-compose-logs, se pudo verificar que corren dos clientes en la consola, que se envían y reciben mensajes, y que ambos hacen exit de forma exitosa.

Ejercicio 2

Hubo que agregar las siguientes líneas en el archivo docker-compose-dev.yaml, tanto para el cliente como para el servidor:

    volumes:
      - ./cfg:/var/cfg

En ambos casos, se intenta leer del archivo, y de no obtener éxito, se recae en la lectura de las variables de entorno.

En el caso del servidor, el archivo no sigue ningún formato estándar, sino que está compuesto directamente por líneas con el formato:

clave=valor

Para el server, se lee el archivo por línea, y se hace split(‘=’), almacenando los valores en un diccionario.

En el cliente se extendió el uso provisto de viper para que primero busque en un archivo, y de no encontrar archivo, pase a leer variables de entorno. El archivo usado en este caso es del tipo JSON.

Ejercicio 3

La resolución de este punto se basa en la ejecución del comando netcat mediante docker run directamente. Al comando se le pasan los parámetros de conexión al servidor, de forma que al correr dicho comando, ya quede establecida la conexión y quede solamente enviar el mensaje de interés.

Como la idea es testear el correcto funcionamiento de forma automática, también hay que lograr meterle input al comando para que se lo envíe al server. Se recurre para esto al pipe, quedando finalmente el comando completo:

echo 1 | sudo docker run -i --network=7574-tp0_testing_net busybox nc server 12345

Notar que se especifica mediante el flag --network a qué red se quiere la imagen levantada.

Hasta aquí está armado el comando para verificar el funcionamiento del server, pero todavía hay que chequear a mano si la respuesta recibida es correcta. Para ello se realizó un script en bash que toma la salida de este comando y la compara con la salida esperada, que es conocida porque es también conocido el mensaje que se está enviando. Si la salida es la esperada, se imprime en pantalla passed., de lo contrario se imprime failed..

Todo esto queda encapsulado en el archivo my_diff.sh, sin embargo, como todos los comandos se encuentran centralizados en el Makefile, se ha agregado una entrada en el mismo con el comando net-test que corre dicho archivo. De esta forma, para ejecutar este punto, solamente hay que correr

make net-test

y verificar que el mensaje impreso sea passed..


Docker Compose Init

El siguiente ejemplo es un cliente-servidor el cual corre en containers con la ayuda de docker-compose. El presente repositorio es un ejemplo práctico brindado por la cátedra para que los alumnos tengan un esqueleto básico de cómo armar un proyecto de cero en donde todas las dependencias del mismo se encuentren encapsuladas en containers.

El cliente (golang) y el servidor (python) fueron desarrollados en diferentes lenguajes simplemente para mostrar cómo dos lenguajes de programación pueden convivir en el mismo proyecto con la ayuda de containers.

Instrucciones de uso

El repositorio cuenta con un Makefile que posee encapsulado diferentes comandos utilizados recurrentemente en el proyecto en forma de targets. Los targets se ejecutan mediante la invocación de:

  • make

El target principal a utilizar es docker-compose-up el cual permite inicializar el ambiente de desarrollo (buildear docker images del servidor y client, inicializar la red a utilizar por docker, etc.) y arrancar los containers de las aplicaciones que componen el proyecto.

Otros targets de utilizar son:

  • docker-compose-down: Realiza un docker compose stop para detener los containers asociados al compose y luego realiza un docker compose down para destruir todos los recursos asociados al proyecto que fueron inicializados durante el docker-compose-up target. Se recomienda ejecutar este comando al finalizar cada ejecución para evitar que el disco de la máquina host se llene.
  • docker-compose-logs: Permite ver los logs actuales del proyecto. Acompañar con grep para lograr ver mensajes de una aplicación específica dentro del compose
  • docker-image: Buildea las imágenes a ser utilizadas tanto en el client como el server. Este target es utilizado por docker-compose-up, por lo cual se lo puede utilizar para testear nuevos cambios en las imágenes antes de arrancar el proyecto.
  • build: Compila la aplicación cliente en la máquina en vez de docker. La compilación de esta forma es mucho más rápida pero requiere tener el entorno de golang instalado en la máquina.

Servidor

El servidor del presente ejemplo es un Echo Server: los mensajes recibidos por el cliente son devueltos por el servidor. El servidor actual funciona de la siguiente forma:

  1. Servidor acepta una nueva conexión
  2. Servidor recibe mensaje del cliente y procede a responder el mismo
  3. Servidor desconecta al cliente
  4. Servidor procede a recibir una conexión nuevamente

Al ejecutar el comando make docker-compose-up para comenzar la ejecución del ejemplo y luego el comando make docker-compose-logs, se observan los siguientes logs:

efeyuk@Helena:~/Development/docker-compose-init$ make docker-compose-logs
docker-compose -f docker-compose-dev.yaml logs -f
Attaching to client1, server
server     | 2020-04-10 23:10:54 INFO     Proceed to accept new connections
server     | 2020-04-10 23:10:55 INFO     Got connection from ('172.24.125.3', 60392)
server     | 2020-04-10 23:10:55 INFO     Message received from connection ('172.24.125.3', 60392). Msg: b'[CLIENT 1] Message number 1 sent'
server     | 2020-04-10 23:10:55 INFO     Proceed to accept new connections
server     | 2020-04-10 23:11:05 INFO     Got connection from ('172.24.125.3', 60400)
server     | 2020-04-10 23:11:05 INFO     Message received from connection ('172.24.125.3', 60400). Msg: b'[CLIENT 1] Message number 2 sent'
server     | 2020-04-10 23:11:05 INFO     Proceed to accept new connections
server     | 2020-04-10 23:11:15 INFO     Got connection from ('172.24.125.3', 60406)
server     | 2020-04-10 23:11:15 INFO     Message received from connection ('172.24.125.3', 60406). Msg: b'[CLIENT 1] Message number 3 sent'
server     | 2020-04-10 23:11:15 INFO     Proceed to accept new connections
server     | 2020-04-10 23:11:25 INFO     Got connection from ('172.24.125.3', 60410)
server     | 2020-04-10 23:11:25 INFO     Message received from connection ('172.24.125.3', 60410). Msg: b'[CLIENT 1] Message number 4 sent'
server     | 2020-04-10 23:11:25 INFO     Proceed to accept new connections
client1    | time="2020-04-10T23:10:55Z" level=info msg="[CLIENT 1] Message from server: Your Message has been received: b'[CLIENT 1] Message number 1 sent'"
client1    | time="2020-04-10T23:11:05Z" level=info msg="[CLIENT 1] Message from server: Your Message has been received: b'[CLIENT 1] Message number 2 sent'"
server     | 2020-04-10 23:11:35 INFO     Got connection from ('172.24.125.3', 60412)
client1    | time="2020-04-10T23:11:15Z" level=info msg="[CLIENT 1] Message from server: Your Message has been received: b'[CLIENT 1] Message number 3 sent'"
server     | 2020-04-10 23:11:35 INFO     Message received from connection ('172.24.125.3', 60412). Msg: b'[CLIENT 1] Message number 5 sent'
client1    | time="2020-04-10T23:11:25Z" level=info msg="[CLIENT 1] Message from server: Your Message has been received: b'[CLIENT 1] Message number 4 sent'"
server     | 2020-04-10 23:11:35 INFO     Proceed to accept new connections
client1    | time="2020-04-10T23:11:35Z" level=info msg="[CLIENT 1] Message from server: Your Message has been received: b'[CLIENT 1] Message number 5 sent'"
server     | 2020-04-10 23:11:45 INFO     Got connection from ('172.24.125.3', 60418)
client1    | time="2020-04-10T23:11:45Z" level=info msg="[CLIENT 1] Message from server: Your Message has been received: b'[CLIENT 1] Message number 6 sent'"
server     | 2020-04-10 23:11:45 INFO     Message received from connection ('172.24.125.3', 60418). Msg: b'[CLIENT 1] Message number 6 sent'
server     | 2020-04-10 23:11:45 INFO     Proceed to accept new connections
server     | 2020-04-10 23:11:55 INFO     Got connection from ('172.24.125.3', 60420)
server     | 2020-04-10 23:11:55 INFO     Message received from connection ('172.24.125.3', 60420). Msg: b'[CLIENT 1] Message number 7 sent'
client1    | time="2020-04-10T23:11:55Z" level=info msg="[CLIENT 1] Message from server: Your Message has been received: b'[CLIENT 1] Message number 7 sent'"
server     | 2020-04-10 23:11:55 INFO     Proceed to accept new connections
client1    | time="2020-04-10T23:12:05Z" level=info msg="[CLIENT 1] Main loop finished"
client1 exited with code 0

Ejercicios Prácticos

La idea de los siguientes ejercicios prácticos consiste en que los alumnos se familiaricen con ambientes de desarrollo implementados en docker/docker-compose, poniendo énfasis en la automatización de cualquier parte del proyecto y la portabilidad del mismo (evitar que el usuario que emplea el proyecto tenga que instalar otra dependencia más que docker/docker-compose para correr las aplicaciones).

El alumno debe forkear el presente repositorio en su cuenta de Github personal y crear un branch por cada uno de los ejercicios que se encuentran a continuación con su correspondiente implementación.

Se recomienda que el alumno realize un fork privado del repositorio. Para realizar un fork privado, se debe duplicar el repositorio sobre un repositorio privado ya creado. El siguiente documento explica como realizar esto.

Ejercicio N°1:

Modificar la definición del docker-compose para agregar un nuevo cliente al proyecto.

Ejercicio N°1.1 (Opcional):

Definir un script (en el lenguaje deseado) que permita crear una definición de docker-compose con cantidad de clientes N.

Ejercicio N°2:

Modificar el cliente y el servidor para lograr que la configuración de ambas aplicaciones sea leída tanto de variables de ambiente como de un archivo de configuración. La configuración a través de archivo debe ser injectada al ejemplo y persistida afuera del mismo. (Hint: docker volumes)

Ejercicio N°3:

Crear un script que permita testear el correcto funcionamiento del servidor utilizando el comando netcat. Dado que el servidor es un EchoServer, se debe enviar un mensaje el servidor y esperar recibir el mismo mensaje enviado.

Netcat no debe ser instalado en la maquina y no se puede exponer puertos del servidor para realizar la comunicación. (Hint: docker network)

Ejercicio N°4 (Opcional):

Modificar el servidor actual para que el mismo permita procesar mensajes y aceptar nuevas conexiones en paralelo.

El alumno puede elegir el lenguaje en el cual desarrollar el nuevo código del servidor. Si el alumno desea realizar las modificaciones en Python, tener en cuenta las limitaciones del lenguaje.

7574-tp0's People

Contributors

ezetowers avatar pablodroca avatar rozanecm avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.