10 abr. 2017

Entorno de Desarrollo en la nube Cloud9

Cloud9 es un Entorno Integrado de Desarrollo en línea, publicado como OpenSource desde la versión 3.0.

Acá les dejo otros enlaces de artículos sobre docker.

La aplicación la pueden acceder en  c9.io .

A continuación se muestra una imagen del sitio:


Es desarrollado enteramente en javascript, node.js como backend, los espacios de trabajo se contruyen por medio de Docker.

Soporta varios lenguajes de programación, entre los principales se tiene:

  • C/C++
  • PHP
  • Ruby
  • Perl
  • Python
  • Javascript
  • Go


Como cloud9 es OpenSource a parte de usarlo desde su sitio web, se puede montar un servidor, su código fuente se encuentra en github. El procedimiento de instalación lo encuentrán en el siguiente enlace.

En este caso se usará una imagen Docker para montarlo como servidor local. La imagen que se usará la pueden revisar en el siguiente enlace.

Para correr cloud9 como contenedor se ejecuta:

docker run -it -d -p 9080:80 -v /home/ernesto/worksplace/:/workspace/ kdelfour/cloud9-docker

En este caso se corre la aplicación desde el puerto 9080 y se usará como directorio de trabajo worksplace.

Al hacer un docker ps se tiene lo siguiente:

CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                            NAMES
f4d06af60205        kdelfour/cloud9-docker   "supervisord -c /etc/"   38 seconds ago      Up 33 seconds       3000/tcp, 0.0.0.0:9080->80/tcp   condescending_gates

Ahora se abre el navegador en el puerto 9080, a continuación se muestra la imagen:

Imagen mientras carga cloud9:




Entorno de trabajo y muestra de un Hola mundo!:

Como se puede ver, ya no es necesario usar la herramienta desde la web, ya puede usarse desde un servidor local usando una imagen Docker.

27 mar. 2017

Crear una imagen Docker a partir de debootstrap para Debian Jessie

Antes de empezar a tocar el tema sobre crear una imagen Docker a partir de debootstrap de Debian, les dejo el enlace de los artículos sobre docker del blog.

Lo primero que se tiene que hacer es instalar debootstrap:

#apt-get install debootstrap

A continuación se crea un directorio para construir la jaula debootstrap:

mkdir debian-jaula

Ahora se ejecuta debootstrap pasando la distribución a bajar, el directorio donde se crea la jaula y el repositorio a usar:

debootstrap jessie debian-jaula/ http://ftp.debian.org/debian
I: Retrieving Release 
I: Retrieving Release.gpg 
I: Checking Release signature
I: Valid Release signature (key id 75DDC3C4A499F1A18CB5F3C8CBF8D6FD518E17E1)
I: Validating Packages 
I: Resolving dependencies of required packages...
I: Resolving dependencies of base packages...
I: Found additional required dependencies: acl adduser dmsetup insserv libaudit-common libaudit1 libbz2-1.0 libcap2 libcap2-bin libcryptsetup4 libdb5.3 libdebconfclient0 libdevmapper1.02.1 libgcrypt20 libgpg-error0 libkmod2 libncursesw5 libprocps3 libsemanage-common libsemanage1 libslang2 libsystemd0 libudev1 libustr-1.0-1 procps systemd systemd-sysv udev 
I: Found additional base dependencies: libdns-export100 libffi6 libgmp10 libgnutls-deb0-28 libgnutls-openssl27 libhogweed2 libicu52 libidn11 libirs-export91 libisc-export95 libisccfg-export90 libmnl0 libnetfilter-acct1 libnettle4 libnfnetlink0 libp11-kit0 libpsl0 libtasn1-6 
I: Checking component main on http://ftp.debian.org/debian...
I: Validating acl 2.2.52-2
I: Retrieving libacl1 2.2.52-2
I: Validating libacl1 2.2.52-2
........................
..............
I: Configuring isc-dhcp-client...
I: Configuring tasksel...
I: Configuring tasksel-data...
I: Configuring libc-bin...
I: Configuring systemd...
I: Base system installed successfully.


Ahora se muestra el contenido del directorio:

ls debian-jaula/
bin/  boot/  dev/  etc/  home/  lib/  lib64/  media/  mnt/  opt/  proc/  root/  run/  sbin/  srv/  sys/  tmp/  usr/  var/

Ahora se crea la imagen por medio de tar y de docker import:

tar -C debian-jaula/ -c . | docker import - ecrespo/debian
sha256:49ad34e39c5f9ede2c1c57994895065236a5965496631e8fcab00b00778d85fa
Como se puede ver, se genera la imagen y el ID de la misma en sha256, se coloca en subrayado la parte que identifica la imagen al listas las imagenes.


Al hacer docker images se tiene lo siguiente:
REPOSITORY                                        TAG                 IMAGE ID            CREATED             SIZE
ecrespo/debian                                    latest              49ad34e39c5f        2 minutes ago       272.7 MB


Al tener la jaula lista se puede hacer personalizaciones y adaptaciones a fin de crear la imagen docker.

Este artículo se basa en a documentación del wiki de Debian sobre debootstrap y en un artículo sobre imagen base de docker

12 mar. 2017

Estructura de datos en python (Grafos)

Continuando con la serie de artículos sobre estructuras de datos en python. En este caso se tocará el tema de grafos con dos ejemplos, uno con listas y otro con matrices.

Los artículos anteriores son:

Este artículo se basa en los códigos en github Grafos con listas adyacentes y Grafos con matriz adyacente y del vídeo en youtube Grafos en Python.

De ejemplo de grafo se usará un modelo de procesos de colas, a continuación la imagen:


A continuación el código manejando el grafo como una lista:


#!/usr/bin/env python



class Vertice(object):

 def __init__(self, n):

  #Se define el nombre del vertice y la lista de vecinos

  self.nombre = n

  self.vecinos = list()

 

 def agregarVecino(self, v):

  if v not in self.vecinos:

   self.vecinos.append(v)

   self.vecinos.sort()







class Grafo(object):

 #Se crea un diccionario de vertices.

 vertices = {}

 

 def agregarVertice(self, vertice):

  #Se pregunta si vertice es una instancia de Vertice y si el nombre no esta en la lista de vertices.

  #Si se cumple se agrega el vertice al diccionario de vertices.

  if isinstance(vertice, Vertice) and vertice.nombre not in self.vertices:

   self.vertices[vertice.nombre] = vertice

   return True

  else:

   return False

 

 def agregarBorde(self, u, v):

  #Si u y v estan en vertices. se agregan como vecinos.

  if u in self.vertices and v in self.vertices:

   self.vertices[u].agregarVecino(v)

   self.vertices[v].agregarVecino(u)

   return True

  else:

   return False

   

 def printGrafo(self):

  #Se muestra el grafo.

  for key in sorted(list(self.vertices.keys())):

   print(key + str(self.vertices[key].vecinos))



if __name__ == '__main__':

 g = Grafo()

 cinco = Vertice('5')

 tres = Vertice('3')

 cuatro = Vertice('4')

 uno = Vertice('1')

 dos = Vertice('2')

 for i in range(ord('1'), ord('6')):

  g.agregarVertice(Vertice(chr(i)))



 bordes = ['53','54','31','35','41','42','45','12','13','14','21','24']

 for borde in bordes:

  g.agregarBorde(borde[:1],borde[1:])



 g.printGrafo()

Al ejecutar el script se tiene:
python grafo-listas.py
1['2', '3', '4']
2['1', '4']
3['1', '5']
4['1', '2', '5']
5['3', '4']


Como se ve, los vertices relacionados, el 1 se conecta con 2,3 y 4, el 2 con 1 y 4, el 3 con 1 y 5, el 4 con 1,2 y 5; y el 5 con 3 y 4.

El siguiente código muestra otra manera de crear el grafo, en este caso se puede manejar el peso de los bordes (aunque no se usa en el ejemplo).  A continuación el código:


#!/usr/bin/env python3



#Se importa nuevas caracteristicas de print

from __future__ import print_function





#Se crea la clace vertice que solo tiene como argumento su nombre.

class Vertice(object):

 def __init__(self, n):

  self.nombre = n





#Se crea la clase grafo con vertices e indices de bordes como diccionarios

#y bordes como una lista.

class Grafo(object):

 vertices = {}

 bordes = []

 indices_bordes = {}





 def agregarVertice(self,vertice):

  #Si vertice es una instancia de su clase y su nombre no esta en el 

  #diccionario de vertices se agrega.

  if isinstance(vertice, Vertice) and vertice.nombre not in self.vertices:

   self.vertices[vertice.nombre] = vertice

   #Se recorre los bordes y se agregan.

   for fila in self.bordes:

    fila.append(0)

   self.bordes.append([0] * (len(self.bordes)+1))

   self.indices_bordes[vertice.nombre] = len(self.indices_bordes)

   return True

  else:

   return False



 def agregarBorde(self,u,v, peso=1):

  #Se agrega el borde.

  if u in self.vertices and v in self.vertices:

   self.bordes[self.indices_bordes[u]][self.indices_bordes[v]] = peso

   self.bordes[self.indices_bordes[v]][self.indices_bordes[u]] = peso

   return True

  else:

   return False





 def printGrafo(self):

  #Se muestra el grafo

  for v, i in sorted(self.indices_bordes.items()):

   print(v + ' ', end='')

   for j in range(len(self.bordes)):

    print(self.bordes[i][j], end='')

   print(' ')    





if __name__ == '__main__':

 g = Grafo()

 cinco = Vertice('5')

 tres = Vertice('3')

 cuatro = Vertice('4')

 uno = Vertice('1')

 dos = Vertice('2')

 for i in range(ord('1'), ord('6')):

  g.agregarVertice(Vertice(chr(i)))



 bordes = ['53','54','31','35','41','42','45','12','13','14','21','24']

 for borde in bordes:

  g.agregarBorde(borde[:1],borde[1:])



 g.p

rintGrafo()





Al ejecutar el script se tiene lo siguiente:
python grafo-matrix-adyacente.py 
1 01110 
2 10010 
3 10001 
4 11001 
5 00110 

Como en el caso anterior, el vertice 1 se conecta con 2,3 y 4, el vertice 2 se conecta con 1 y 4, el vertice 3 conecta a 1 y 5, el vertice 4 conecta a 1,2 y 5; y el vertice 5 conecta con 3 y 4.



Se tienen dos formas de representar un grafo, puede usar el que prefiera, dependiendo de la complejida, si se necesita manejar pesos, la opción es el de la matriz.


11 mar. 2017

Estructura de datos en Python (Lista Enlazada)

Continuando con la serie de estructuras de datos, en el artículo anterior se trato de la estructura de datos Nodo, en este artículo se usará el Nodo por medio de composición en la lista enlazada.

Este artículo se basa del tutorial en youtube llamado Python:Linked Lists donde pasan el enlace al código en github.

La lista enlazada se basa en el Nodo, como recordarán el Nodo tiene el dato y lo que apunta al próximo nodo.  En el caso de la lista enlazada contendrá lo siguiente:

  • Argumentos:
    • Nodo: Al crear la lista enlazada se crea un Nodo sin datos y que apunte a None.
    • primero: variable privada que apunta al primer nodo.
    • ultimo: variable privada que apunta al último nodo.
    • tamagno: variable privada que lleva la cantidad de nodos que maneja la lista.
  • Métodos:
    • obtenerTamagno: Devuelve el tamaño de la lista.
    • add: Agrega un nodo a la lista enlazada.
    • remove: Remueve un nodo de la lista enlazada.
    • find:Busca un dato en la lista, devuelve el dato o False.


El código de la lista enlazada se muestra a continuación:


#!/usr/bin/env python3

#Se importa Nodo de nodos.

from nodos import Nodo









class ListaEnlazada(object):

    def __init__(self,primero = Nodo(None,None)):

        """Se asigna como Nodo inicial a primero y ultimo por que apuntan al mismo nodo

        y se define el tamagno de la lista en cero"""

        self.__primero = primero 

        self.__ultimo = self.__primero

        self.__tamagno = 0





    def obtenerTamagno(self):

        """Devuelve el tamagno de la lista"""

        return self.__tamagno



    def add(self,d):

        """Agrega un nodo a la lista enlazada"""

        #Se crea una instancia de nodo donde se le pasa el dato d y se coloca

        #como proximo nodo el primer nodo.

        nodoNuevo = Nodo(d,self.__primero)

        #El primer nodo apunta al nodo nuevo y se incrementa el tamagno.

        self.__primero = nodoNuevo

        self.__tamagno += 1





    def remove(self,d):

        """Se elimina el nodo que tenga el dato d"""

        #Al nodo actual se le asigna el primer nodo

        nodoActual = self.__primero

        #Y al nodo anterior se le asigna None.

        nodoAnterior = None



        #Mientras exista el nodo actual-

        while nodoActual:

            #Si el dato de nodo actual es igual al dato que se esta buscando.

            if nodoActual.dato == d:

                #Si existe nodo anterior

                if nodoAnterior:

                    #Se asigna  al apuntador proximo del nodo anterior el proximo de nodo actual

                    nodoAnterior.proximo = nodoActual.proximo

                else

                    #A primero se le asigna el apuntador al proximo nodo del nodo actual

                    self.__primero = nodoActual.proximo

                #En cualquiera de los dos casos se decrementa el tamagno de la lista.

                self.__tamagno -= 1

                #Devuelve True por que se elimino.

                return True

            else:

                #Se asigna al nodo anterior el nodo actual

                nodoAnterior = nodoActual

                #Se asigna al nodo actual, el nodo proximo del nodo actual

                nodoActual = nodoActual.proximo





    def find(self,d):

        """Se busca d en la lista enlazada, si existe devuelve d, si no devuelve None"""

        #a nodo actual se le asigna el primer nodo.

        nodoActual = self.__primero

        #Mientras exista el nodo actual.

        while nodoActual:

            #Si el dato de nodo actual es igual a d, devuelve d

            if nodoActual.dato == d:

                return d

            else:

                #Si no, el nodo actual apunta al proximo nodo.

                nodoActual = nodoActual.proximo

        #Si no se encuentra devuelve None.

        return None 







if __name__ == '__main__':

    miLista = ListaEnlazada()

    miLista.add(1)

    miLista.add(8)

    miLista.add(12)

    print("size: {0}".format(miLista.obtenerTamagno()))

    print (miLista.find(8))

    miLista.remove(8)

    print("size: {0}".format(miLista.obtenerTamagno()))

    print(miLista.remove(12))

    print("size:{0} ".format(miLista.obtenerTamagno()))

    print(miLista.find(5))



Al ejecutar el script se tiene lo siguiente:

python listas.py 
size: 3
8
size: 2
True
size: 1
None


Como se puede ver se agregan 3 elementos a la lista, luego se muestra el tamaño de la lista, se va eliminando cada elemento de la lista, donde se muestra el tamagno de la lista mientras se va eliminando elementos, y por último se busca el valor de 5 en la lista donde devuelve None.