Author Archives: Chef

Comandos básicos de Git

Este post incluye una lista de comandos básicos de Git, validos para cualquier implementación del famoso VCS. Se recomienda una revisión más exhaustiva de los mismos en caso de necesitarlo. Se puede encontrar más información en:

https://git-scm.com/

Algunos de los comandos más usados son los siguiente:

Git config

Configuración de la herramienta Git (i.e. identificación de usuario). Más info en https://git-scm.com/book/es/v1/Empezando-Configurando-Git-por-primera-vez

 Git SSH keys generation

Generación de clave pública para conexión a Git via SSH. Recomendable para no tener que introducir usuario y password con cada operación remota.

Clone the repo

Clona el repositorio remoto en el local y actualiza el workspace.

Update working copy

Descarga el contenido del repositorio remoto al local y actualiza el workspace (necesita la operación de clonación anterior para inicializar los repositorios locales).

Update local repository but not working copy

Actualiza repositorios locales con el contenido remoto pero no modifica la copia local.

Check working copy status

Revisa el estado del workspace en relación al contenido del repositorio local.

Check local branches

Lista las ramas del repositorio local.

Upload a modification

Añade una modificación al repositorio local y remoto.

1. Añade las modificaciones al stage

2. Comitea al repositorio local

3. Subo al repositorio remoto

Show commit history

Muestra el histórico de commits locales.

Show latest commit history

Muestra los datos del último commit local.

Show differences

Muestra diferencias entre:

  • Commits locales

  • Commits y ficheros

  • Ramas locales

  • Stagged changes (compara stagged files con committed files)

Undo working copy changes (checkout local repo HEAD)

Descarga ultima modificación de la rama actual para el fichero indicado, sobreescribiendo los cambios locales.

Reset a stage (reverse git add operation)

Resetea los cambios locales aplicados al fichero en cuestion, volviendo al estado comiteado en el repositorio local.

Revert a commit (revert git add and git commit operations)

Revierte un commit local, creando otro nuevo con los estados anteriores.

Stash changes

Almacena cambios en un stash para posterior uso.

Crea un stash

Lista stashes actuales

Muestra el contenido de un stash

Aplica el stash en la rama actual

  • Stash can be referred using indexes as: stash@{0,1,2,etc}: Use list to view them

Borra todos los stash locales

Y otros muchos comandos relacionados con los stashes que se pueden consultar aqui:

https://git-scm.com/docs/git-stash

Create a new branch (create if not exists)

Crea una nueva rama si no existe y cambia a ella.

Create a new branch, but do not change

Crea una nueva rama en el repo local pero no cambia a ella.

Checkout to a branch

Cambia a una rama ya existente.

Merge a branch

Mergea ramas y/o tags.

Mergea a la rama actual y aplica fast-forward, es decir, no creará ningún nuevo commit, simplemente apuntara la rama actual al commit mergeado, si es posible.

Mergea pero sin fast-forward, es decir, crear un nuevo commit para el merge (recomendable).

Delete a branch

Borra una rama del repositorio local.

Create a tag

Creación de tags.

Lista los tags existentes.

Crea el trag 1.0 con el contenido del HEAD, el commit o la rama indicados.

Crea un tag anotado (por defecto son light-weight).

Sube el tag al repositorio remoto.

Rebase

Es un mecanismo para realizar un merge, alternativo al anterior aunque más potente pero a su vez más sutil y peligroso.

El peligro viene a la hora de hacer rebase de ramas en el repositorio remoto. Esto puede generar confusión a la hora de crear nuevos commits asi como revertir cambios, etc. Por lo tanto, la recomendación es solo usar rebase en commits que se encuentren uicamente en el repositorio local.

Se basa en los siguiente: al hacer un rebase de una rama sobre otra, lo que se hace es aplicar los commits de la rama que se rebasa en la rama actual, en orden de aparición, respetando los commits de la rama original.

Por ejemplo, si disponemos de dos ramas, master y develop, con cambios diferentes, y ejecutamos lo siguiente:

Aplicamos los commits de la rama master directamente a la rama develop, en el orden en el que aparecen en la master.

También se puede hacer el rebase sin hacer el checkout de la rama que va a rebasar, haciendo:

Si las ramas no tienen el mismo origen, por ejemplo si se quiere rebasar una rama de feature con la rama de develop y ésta no surgió de la de develop si no de otra rama de feature, podemos hacer:

Se haría el rebase de feature02 sobre develop con los commits de feature02 pero sin los de feature01.

Rebase vs Merge

La idea del merge es que aparezcan reflejados en la historia del repositorio todos los cambios realizados en y entre las ramas, mientras que con el rebase se podria modificar esa historia para que aparezcan ciertos commits en ramas que no se hicieron. La filosofia es diferente, con merge se ve lo que paso explicitamente mientras que rebase permite modificar esa historia para que refleje los cambios que se deseen. Un uso recomendado seria aplicar rebase en el repositorio local para aquello cambios aun no compartidos con el objetivo de limpiar la historia local, antes de compartirlos.

Cherry-pick

Aplica cambios de commits concretos a la rama actual:

Se pueden escoger multiples commits. Cada commit creara un nuevo commit en la rama actual.

Search for text

Buscador de texto desde Git.

Herramienta gráfica sencilla

 

Ejemplo de proyecto en Python con OO y recomendaciones

El siguiente post contiene un ejemplo de desarrollo de un pequeño proyecto con Python. Este proyecto hace uso de algunos de los elementos de la orientación a objetos en Python, asi como de algunas recomendaciones en el desarrollo con Python.

Que cocinamos

Un pequeño proyecto con Python que incluye lo siguiente:

  • Clases
  • Módulos
  • Paquetes
  • Ficheros de log
  • Tests
  • Documentación autogenerada

El proyecto se puede descargar integro desde https://github.com/luisalbertogh/oopython.git.

Ingredientes

Los requisitos para este proyecto son los siguientes:

Paso a paso

Creamos una estrcutura para el proyecto con el siguiente diseño:

<proyecto>

|__ <config> [ficheros de configuración]

|__ <doc> [documentación]

|__ <proyecto> [código fuente]

|__ <test> [tests de unidad e integración]

Vease el conteido del proyecto a modo de ejemplo.

Código fuente

El código se estructura de la siguiente manera (de más básico a más complejo):

1. Creamos un módulo base que contiene una serie de clases que incluyen nuestro modelo y nuestra lógica de negocio [oopython\mypackage\module01.py]. Aquí encontramos:

Superclases

Clases con diferente tipos de métodos (estáticos, constructores (__init__), sobrecargados (métodos especiales que empiezan con __. etc))

Lazy properties, setters y getters

Clases estratégicas (sin estado, sólo lógica)

2. Incluimos este módulo en un paquete. Esto no es necesario en Python pero puede ser una buena recomendación para modular un poco más y aportar un nivel adicional de granularidad al código desarrollado. Los paquetes estarían compuestos por módulos y estos se podrían usar desde otros módulos y/o paquetes.

Para esto, simplemente creamos el directorio oopython\mypackage, incluimos el módulo recien creado dentro y añadimos un fichero __init__.py. Adicionalmente podemos incluir en el fichero __init__.py otros módulos o paquetes externos o indicar que módulos internos queremos habilitar desde el paquete, de tal manera que sea más sencillo invocarlos cuando se usen desde otros módulos externos. Si añadimos lo siguiente:

Podremos usar el contenido del paquete mypackage desde otros módulos externos simplemente haciendo:

De otra manera tendriamos que especificar el módulo, etc.

3. Creamos un nuevo módulo [oopython\oopython.py] que haga uso del paquete anteriormente creado.

Ficheros de log

Para disponer de una serie de loggers que permitan crear ficheros de log e imprimir mensajes por pantalla, usamos paquetes estandar de logging de Python y YAML como lenguaje para los ficheros de configuración de los mismos.

En caso de que YAML no esté instalado, usar:

En el módulo principal incluimos el siguiente código:

El fichero de configuracion de los logs se encuentra en la ruta config/log_config.yaml. Contiene los valores necesarios para crear differentes tipos de loggers, configurar salidas por consola, formato de los logs, etc.

Tests

Tal y como ocurre en otros lenguajes de programación, aqui también podemos crear tests de unidad y de integración que se ejecuten de forma automática dentro de un proceso de integración continua.

En un directorio separado dentro del proyecto llamado test, creamos diferentes ficheros (módulos) con diferentes grupos de tests. Cada módulo podría ser considerado como un test suite diferente, por ejemplo.

Dentro de cada módulo incluimos diferentes tests unitarios usando el módulo de Python para implementar tests de unidad:

Para que los tests puedan hacer uso de los módulos y paquetes internos del proyecto, se setea la ruta principal del proyecto relativa al test:

Los tests unitarios son métodos del siguiente TestCase:

Los test unitarios se cargan en un único test suite:

Y se ejcutan:

Una manera sencilla de lanzar todos (o los seleccionados) tests es usando el siguiente comando:

Se indica el uso del módulo de testeo de Python y se le indica que ejecute todos los tests unitarios que encuentre en el directorio test correspondiente. También se pueden lanzar como un scrupt de Python sin más.

Generación automática de documentación

La generación automática está basada en el uso de la herramienta Sphinx, que es una de las más extendidas. Los pasos para ejecutarla son basicamente los siguientes:

Instalar Sphinx

http://www.sphinx-doc.org/en/stable/install.html

Ejecutar Sphinx quickstart

Se recomienda seguir este tutorial para concer las opciones más relevantes de este comando. Es importante activar la generación automática de documentación si queremos que la herramienta convierta los comentarios incluidos en el código en Python como texto dentro de la documentación.

http://www.sphinx-doc.org/en/stable/tutorial.html

Revisar valores en conf.py

Antes de lanzar la generación automática de documentación conviene revisar el fichero de configuración autogenerado por el paso anterior. Éste se encuentra en oopython\doc\source\conf.py.

Una de las modificaciones que tenemos que aplicar al fichero recien creado es indicar la ruta en la que se encuentra el código de Python para que los pasos siguientes puedan autogenerar documentación:

De esta manera se añade a la ruta en la que Python busca los módulos y paquetes la ruta que contiene nuestro código.

Sphinx apidoc

Nos permite de forma automática generar los ficheros RST que se usaran para dar formato a la páginas de la documentación que se incluirá asi como su contenido. Normalmente se creara un fichero RST por módulo/paquete y se añadirá información sobre las clases y miembros.

Más información aqui: http://scriptsonscripts.blogspot.com.es/2012/09/quick-sphinx-documentation-for-python.html

El comando de ejecución sería el siguiente. doc/source sería el directorio en el que se generarán los RST y oopython el directorio que contiene el código fuente en Python.

Crear la documentación

Se lanza el siguiente comando:

Y se genera el formato de salida deseado, en este caso en HTML:

 

Docker tips

En este post se incluyen una revisión muy sencilla y un conjunto de comandos y acciones relacionadas con el uso de Docker. Para más información, consultar en:

https://docs.docker.com/engine/docker-overview/

https://training.docker.com/

https://veggiemonk.github.io/awesome-docker/

Containers

Running a container

Pull an image from the Docker registry

List the content of the downloaded Docker images

Run commands on a launched container

Launch container in interactive mode

List running containers (and ran)

Images

Inspect an image

Download and run image in one goal

Stop and remove container

Run container in detached mode and provide details

--name --> Name to the container

-e --> Pass variables

-d --> detached mode

-P --> publish ports to docker container host

-p 8888:80 --> Relate port 80 to 8888 in docker host

Image types

Base

  • OS images

Child

  • Based on a base image

Official

  • Certified by Docker

User

  • User created images (from base, usually)

Create a new image (user image)

Create a docker file (Dockerfile)

Build the image

-t –> image tag

. –> directory where Dockerfile is present

Swarm stack

Init swarm manager

Docker compose files (docker-compose.yml)

Deploy the stack

Join swarm

List nodes

List services

Inspect services

Scale up or down the service

Disable/Enable nodes

List deployed tasks

Leave the swarm

Remove stack

Inspect the container

Persist de data

In the host, via de docker-compose file:

Via de Docker file:

The /data will be created on the host as well:

Using the –v option

  • Create and mount
  • Mount

Using the Volume API

  • Create the volumen on the host

Mount it and use it within a container

Docker network drivers (default and created)

  • Bridge support only a single node
  • Overlay support multiple nodes

Create overlay network

Inspect network

Run container within network

By default, bridge network driver is used

Connect an existent container to an existent network

Service discovery

Docker info

Use Docker API to communicate with Docker

Upgrade/downgrade to/from manager

Docker swarm visualizer

http://jpetazzo.github.io/orchestration-workshop/#118