Drupal 8: Pseudo fields, templates and rendering images with links.

Illustration by Lucy Sánchez

Lea este artículo en español: Drupal 8: Pseudocampos, templates y render de imágenes con links.

A few days ago I started the development of a new Drupal 8 site. This site has come with a large set of interesting challenges because a lot of the required functionality is still not easy to implement. As of this moment, there are a lot of contrib modules that are in development, one of them is group.

Our client requires that every authenticated user can see the groups it belongs to directly from its profile. This feature is required to be done in such a way that you can see the group’s logo, and the logo has to be linked to that group page on the site. I researched alternatives with views and other contrib modules, but it didn’t bear fruit.

I opted for the custom approach: to create a pseudo field for the users. Such field would use a template in order to print the groups the user belongs to.

Shoulders to the wheel!

First we need to create a pseudo field. Let’s remember that pseudo fields are elements that, just like fields, we can manage from the admin interface of each entity, but the difference lies in that the element has only one function: to display information. Contrary to that, a field will store and show information entered by the users.

In Drupal 8 -like Drupal 7- we need to use 2 hooks to create our pseudo field for an entity: hook_entity_extra_field_info() and hook_[ENTITY NAME]_view().

hook_entity_extra_field_info().

It tells the entity that there will be a new element available to display. For our case, we’ll implement it like so:

/**
* Implements hook_entity_extra_field_info().
*/
function my_module_entity_extra_field_info() {
$extra = [];
$extra['user']['user']['display']['my_mudule_active_subsites'] = array(
'label' => new TranslatableMarkup('Active subsites'),
'description' => new TranslatableMarkup('Show the current subscribed sites by one user'),
);
return $extra;
}

hook_[ENTITY NAME]_view()

In this case, we’re interested in using hook_user_view() because we’re working with the user type entity. hook_[ENTITY NAME]_view() basically handles the display of each one of the elements of an entity. In this case, we’ll use it to format our pseudo field my_mudule_active_subsites.

For Drupal 8, the implementation of this hook varies a bit in the parameters it receives, we can find more documentation here:

https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21entity.api.php/function/hook_entity_view/8.2.x

/**
* Implements hook_user_view().
*/
function my_module_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode, $langcode) {
if ($view_mode === 'full') {
if ($display->getComponent('my_module_active_subsites')) {
$groups = my_module_user_current_user_groups($entity);
$groups_to_render = my_module_render_groups_images($groups);
$build['my_module_user_active_subsites'] = [
'#theme' => 'my_module_active_subsites',
'#groups' => $groups_to_render,
];
}
}
}

Like the example, we’re using the variable build that we get from the reference, to assign the value to show with our pseudo field. Notice that we created a new index inside the build array, which is a render array. Inside our index we’ll use #theme to indicate that we’re going to use a template, which we’ll define further down the road, and we’ll also use a variable called #groups, which is a variable inside our template.

Now, an important detail: like you can see in our example, we use 2 functions to obtain both the the groups of the user and the preprocessed data ready to be printed by Drupal. The function my_module_user_current_user_groups() basically returns an array of the entity type group, in which we wont delve. On the contrary, we’ll see the details of my_module_render_groups_images().

my_module_render_groups_images()

This function was born because of our need to wrap the images in a link, specifically a link to the entity type group. We’ll solve that this way:

/**
* Helper function to render the images with a specific image style.
*
* @param array $groups
* The entity groups with the images to render.
*/
function my_module_render_groups_images(array $groups) {
$groups_to_render = [];
foreach ($groups as $group) {
$group_item = new Stdclass();
$image_id = $group->field_site_logo->target_id;
if (!empty($image_id)) {
$image_render_array = [
'#theme' => 'image_style',
'#width' => $group->field_site_logo->width,
'#height' => $group->field_site_logo->height,
'#style_name' => 'site_logo_user_profile',
'#uri' => $group->field_site_logo->entity->uri->value,
];
$renderer = \Drupal::service('renderer');
$renderer->addCacheableDependency($image_render_array, $group->field_site_logo->entity);
$rendered_image = $renderer->render($image_render_array);
$link_render_array = [
'#type' => 'link',
'#url' => Url::fromUri('entity:group/' . $group->id()),
'#title' => $rendered_image,
];
$group_item->logo = $link_render_array;
}
$groups_to_render[] = $group_item;
}
return $groups_to_render;
}

As you can see in the example, what we do to print our image with a link is: first, prepare a render array to use the image_style template. After that, we use the service renderer from Drupal 8 (instead of Drupal_render from Drupal 7) to obtain an render type object, which will be assigned as a value for the title of our link.

Defining our twig template

Like Drupal 7, if we want to use our own templates inside a module, we need to define it, that is, make Drupal aware that such template exists. For that we’ll use hook_theme().

/**
* Implements hook_theme().
*/
function my_module_user_theme($existing, $type, $theme, $path) {
return [
'my_module_user_active_subsites' => [
'variables' => [
'groups' => '',
],
],
];
}

Creating our template

For our final step, we’ll proceed to create our twig template. In order to be recognized, our templates have to be placed in a specific location, with a specific naming convention.

Our templates have to be inside the folder called “templates” in the root of our module and like as I mentioned, have to follow the naming convention: template-name.html.twig. We’ll create the file my-module-active-subsites.html.twig.

This template will handle the format and will print the images belonging to our groups:

{#
/**
* @file
* Template file my_module_active_subsites field
*/
#}
<div class="container user-groups-container">
{% if groups is not empty %}
{% for group in groups %}
<div class="container user-groups-element" >
{{ group.logo }}
</div>
{% endfor %}
{% endif %}
</div>

As you can see, Twig is very different from what we know before with PHP templates, but this does not mean is complicated. In my case, I used this documentation: https://www.drupal.org/docs/8/theming/twig/comparison-of-phptemplate-and-twig-theming-paradigms, which is a comparative between what we used to do in PHP template and how we do it with Twig.

Pseudo fields in Drupal 8 -like in Drupal 7- are still a great resource that allows flexibility in the display of our entities. If we add templates in the mix, we can comply with any display requirement for our content. Just be aware that it depends on the type of display we need to use for our content.

Happy coding!

Manatí is a web consultancy firm from Costa Rica, where we make websites strategically designed to help organization achieve goals.

Don’t miss out on projects, news and ideas from Manatí. Learn about what we do, follow us on medium, twitter and facebook.


Drupal 8: Pseudo fields, templates and rendering images with links. was originally published in MANATI | Agencia Web on Medium, where people are continuing the conversation by highlighting and responding to this story.

Drupal 8: Pseudocampos, templates y render de imágenes con links.

Ilustración de Lucy Sánchez

Read this article in english: Drupal 8: Pseudo fields, templates and rendering images with links.

Hace unos días atrás inicie el desarrollo de un nuevo sitio en Drupal 8. Este sitio ha llegado con una gran cantidad de retos interesantes puesto que muchas de las funcionalidades requeridas aún no son sencillas de implementar. En este momento hay muchos módulos contrib que aun se encuentran en desarrollo, uno de estos módulos es: group.

Nuestro cliente requiere que cada usuario autenticado pueda ver los grupos a los que pertenece directamente desde su perfil. Esta funcionalidad tiene que realizase de manera tal que se pudiera ver solamente el logo del grupo, y este logo debe estar enlazado a la página del sitio. Investigué para buscar alternativas con views u otros módulos contrib, pero la investigación no dio muchos frutos.

Opté por el desarrollo de algo custom: elegí desarrollar un pseudocampo para los usuarios. Dicho campo utilizará un template para imprimir dichos grupos.

Manos a la obra.

Primero necesitamos crear un pseudocampo. Recordemos que los pseudocampos son elementos que, al igual que un campo, podemos administrar desde la interfaz de despliegue de cada entidad, pero la diferencia radica en que este elemento solo tiene una función: mostrar información, a diferencia de un campo normal que muestra y almacena información brindada por los usuarios.

En drupal 8- como en drupal 7- necesitamos hacer uso de 2 hooks para hacer disponible nuestro pseudocampo para una entidad, estos son: hook_entity_extra_field_info() y hook_[ENTITY NAME]_view().

hook_entity_extra_field_info().

Indica a la entidad que ahora va a existir un nuevo elemento disponible para su despliegue. Para nuestro caso lo implementamos de la siguiente manera:

/**
* Implements hook_entity_extra_field_info().
*/
function my_module_entity_extra_field_info() {
$extra = [];
$extra['user']['user']['display']['my_mudule_active_subsites'] = array(
'label' => new TranslatableMarkup('Active subsites'),
'description' => new TranslatableMarkup('Show the current subscribed sites by one user'),
);
return $extra;
}

hook_[ENTITY NAME]_view()

En este caso nos interesa usar hook_user_view() porque que estamos trabajando con la entidad de tipo usuario. hook_[ENTITY NAME]_view() básicamente se encarga de manejar el despliegue de cada uno de los elementos de una entidad dada. En este caso lo vamos a utilizar para dar forma a nuestro pseudocampo my_mudule_active_subsites.

Para drupal 8, la implementación de este hook varía un poco en los parámetros que recibe, podemos encontrar más documentación aquí: https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Entity%21entity.api.php/function/hook_entity_view/8.2.x

/**
* Implements hook_user_view().
*/
function my_module_view(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display, $view_mode, $langcode) {
if ($view_mode === 'full') {
if ($display->getComponent('my_module_active_subsites')) {
$groups = my_module_user_current_user_groups($entity);
$groups_to_render = my_module_render_groups_images($groups);
$build['my_module_user_active_subsites'] = [
'#theme' => 'my_module_active_subsites',
'#groups' => $groups_to_render,
];
}
}
}

Como podemos ver en el ejemplo, estamos usando la variable build que nos llega por referencia para asignar a nuestro pseudocampo el valor a mostrar. Nótese que creamos un nuevo índice dentro del arreglo de build que es un arreglo de render. Dentro de nuestro índice usamos #theme para indicar que vamos a hacer uso de un template, el cual definiremos más adelante y también hacemos uso de #groups que es una variable propia de nuestro template.

Ahora, un detalle importante: como se puede apreciar en nuestro ejemplo, se hace uso de 2 funciones para obtener tanto los grupos del usuario como los datos preprocesados listos para ser impresos por drupal. La función my_module_user_current_user_groups() básicamente retorna un arreglo de entidades de tipo group, por lo cual no ahondaremos en ella. Por el contrario, sí entraremos en detalles con my_module_render_groups_images().

my_module_render_groups_images()

Esta función nació por la necesidad de que nuestras imágenes estén envueltas en un link, específicamente, un enlace a la entidad de tipo grupo. Lo resolvemos de la siguiente manera:

/**
* Helper function to render the images with a specific image style.
*
* @param array $groups
* The entity groups with the images to render.
*/
function my_module_render_groups_images(array $groups) {
$groups_to_render = [];
foreach ($groups as $group) {
$group_item = new Stdclass();
$image_id = $group->field_site_logo->target_id;
if (!empty($image_id)) {
$image_render_array = [
'#theme' => 'image_style',
'#width' => $group->field_site_logo->width,
'#height' => $group->field_site_logo->height,
'#style_name' => 'site_logo_user_profile',
'#uri' => $group->field_site_logo->entity->uri->value,
];
$renderer = \Drupal::service('renderer');
$renderer->addCacheableDependency($image_render_array, $group->field_site_logo->entity);
$rendered_image = $renderer->render($image_render_array);
$link_render_array = [
'#type' => 'link',
'#url' => Url::fromUri('entity:group/' . $group->id()),
'#title' => $rendered_image,
];
$group_item->logo = $link_render_array;
}
$groups_to_render[] = $group_item;
}
return $groups_to_render;
}

Como se puede observar en el ejemplo, lo que realizamos para imprimir nuestra imagen con link, fue: primero preparar un arreglo de render para hacer uso del template de image_style. Luego usamos el servicio renderer de drupal 8 (remplazo de drupal_render en drupal 7) para obtener un objeto de tipo renderer, el cual posteriormente será asignado como valor para el title de nuestro link.

Definiendo nuestro twig template.

Al igual que en drupal 7, si queremos hacer uso de nuestro propio template en un módulo, debemos hacer la definición del mismo, osea, hacerle saber a Drupal que este template existe. Para esto hacemos uso del hook_theme().

/**
* Implements hook_theme().
*/
function my_module_user_theme($existing, $type, $theme, $path) {
return [
'my_module_user_active_subsites' => [
'variables' => [
'groups' => '',
],
],
];
}

Creando nuestro template.

Ahora, como paso final, procederemos a crear nuestro twig template. Para que nuestros templates sean reconocidos debemos colocarlos en una ubicación específica, siguiendo un formato de nombre específico.

Nuestros templates deben estar en una carpeta llamada “templates” en la raíz de nuestro módulo y como mencionamos, deben seguir el siguiente formato de nombre: nombre-template.html.twig. Para nuestro caso creamos el archivo: my-module-active-subsites.html.twig.

Este template se encargará de formatear e imprimir las imágenes pertenecientes a nuestros grupos:

{#
/**
* @file
* Template file my_module_active_subsites field
*/
#}
<div class="container user-groups-container">
{% if groups is not empty %}
{% for group in groups %}
<div class="container user-groups-element" >
{{ group.logo }}
</div>
{% endfor %}
{% endif %}
</div>

Como podemos observar twig es muy distinto de lo que conocíamos antes en los PHP templates, pero esto no significa que sea complicado. En mi caso me apoyé en esta documentación: https://www.drupal.org/docs/8/theming/twig/comparison-of-phptemplate-and-twig-theming-paradigms, esta documentación da una comparación entre lo que antes hacíamos con PHP templates y cómo se hace ahora con twig.

Como pudimos ver, los pseudocampos de Drupal 8 al igual que en Drupal 7, siguen siendo un gran recurso que permite dar flexibilidad a nuestros despliegues de entidades. Si a esto le unimos templates, podemos cumplir con cualquier requerimiento de despliegue de nuestro contenido. Solo se debe recordar que el uso de los mismos depende del tipo del despliegue que queramos usar para nuestro contenido.

¡Feliz codificación!

Manatí es una firma consultora web de origen costarricense, donde hacemos sitios estratégicamente diseñados para llevar organizaciones a lograr objetivos.

No se pierdan los proyectos, noticias e ideas de nosotros en Manatí. Conozca más sobre lo que hacemos, síganos en medium, twitter y facebook.


Drupal 8: Pseudocampos, templates y render de imágenes con links. was originally published in MANATI | Agencia Web on Medium, where people are continuing the conversation by highlighting and responding to this story.

“Mapillaryando” en cantinas de San José

-- por Marcia Ugarte y Joaquín Lizano

Un sábado por la tarde resultó ser el momento perfecto para que un grupo de personas se juntara en San José para iniciar la labor de contribuir al mapeo libre esta vez de cantinas del centro de la capital. Cantina en Costa Rica hace referencia a un bar popular, que posiblemente tenga sus añitos, sin aires snobs y que tiene alcohol y comida a buen precio, o solo alcohol.

Este grupo sacrificado trazó un plan de visita y mínimas normas para el proceso de mapeo: tomar máximo una cerveza en cada sitio y comer donde se pudiera ojalá una boca conocida del bar correspondiente. La ruta inició en El Gran Vicio, cantina de toda la vida dentro del Mercado Central; continuó al Ballestero, la única cantina que queda en una de las cuatro esquinas de entrada al San José de antaño y que dicen tiene uno de los mejores chifrijos; luego pasamos a La Embajada, bar chirrión con una barra larga larga y famoso por el gallo de chorizo; después le tocó al turno a El Faro, cantina de 3 pisos con hora feliz de cerveza a menos de mil colones y buena costilla; el siguiente fue La Bohemia, después Wongs y lxs últimxs valientes terminaron de madrugada en Area City.

Detallando el recorrido, el punto de inicio, “El Gran Vicio”, es probablemente una de las cantinas más viejas de San José. Ubicado en el Mercado Central de la ciudad, abrió sus puertas en 1880. Podríamos decir que es tan viejo que pareciera que es solo para hombres. El orinal está en una esquina del bar y la puerta no cierra ni abre, está como medio puesta y no resguarda aquella privacidad que se espera de un servicio sanitario. ¿Baño de mujeres? no hay. La pared opuesta a la barra de este espacio, que funciona como un pasillo debido a su estrechez, está llena de firmas, mensajes y memorias gráficas.

  • clientela que se conoce entre sí, algunos con sus uniformes de trabajo del mercado
  • el cantinero no era muy amable con los extraños (nosotros…)
  • es un bar de paso (paso a tomarme una cerveza y/o un trago y me voy)
  • interesante experiencia

De ahí partimos al “Ballestero”. Pocas cantinas tienen plantas naturales a la entrada. Seña que vamos por una experiencia diferente. Está situada en una de las esquinas del cierre de la calle ancha que da entrada a la ciudad capital desde el Norte. Desde la mesa de la esquina consumimos felices las bocas (dar fe que los patacones con frijoles son de lo mejor de la ciudad) mientras admiramos la bola disco de espejitos en el centro del techo (sin luces dirigidas, sin mecanismos para que gire), un antojo de los dueños para dar simbolismos fiesteros al lugar. Tal vez no combina la bola con la colección de vasos y las fotos familiares en la paredes, tal vez ese es justo el estilo que andaban buscando.

  • música texmex
  • chilera de la casa
  • tarjetas de crédito no bienvenidas (pero aceptadas si se insiste mucho)
  • mejor llevar cash

Debería haber también mención a los trayectos. Las caminatas de unxs jóvenes (y otros no tanto) caminando con sus celulares en posición horizontal y más arriba de sus cabezas, grabando el camino, siguiendo a su “líder” que camina con un báculo tecnológico con un ojo en las alturas. Digamos que no pasamos desapercibidxs por el público josefino. Posiblemente si unx nos viera pasar así de la nada… seguramente que tampoco sabría qué pensar… turistas, extraterrestres, geeks haciendo una peli/docu de chepe, buscando pokemones…?

El siguiente bar fue “La Embajada” que terminó siendo denominada la nueva embajada de Mapillary en Costa Rica. Su principal característica es la barra enorme que abarca gran parte del espacio y que da la impresión de que si nos animamos a llegar al final nos comerá la oscuridad, pero no. El fondo está repleto de mesas y hay suficiente espacio para todo el grupo y un mariachi que se acomoda al final de la barra. Realmente sorprende que exista un espacio tan grande y que fácilmente unx pase por fuera sin darse cuenta de lo que hay dentro.

  • la birra a 900 parece que era una publicidad vieja que no han eliminado. Costaba 1000
  • barra muy larga
  • los gallos de chorizo o salchichón vienen sin tortilla
  • mariachi compite con “música de cabina”
  • no se separan cuentas
  • muy concurrido

Seguimos el trayecto en un atardecer que afectaba, dada la cada vez menos luz, la posibilidad de mapear al caminar; pero “sacrificadamente” hicimos todo lo que estaba en nuestras manos para no frenar el mapeo. Caminamos por el puro centro de Chepe y llegamos al Faro. Una vieja edificación de tres pisos con vista al sur de San José. Ya cuan lejos logre ver unx desde este faro dependerá, entre otras cosas, de cuanto se enfieste en el lugar. Cada piso es un ambiente; de hecho, el tercer piso es para fiestas y no está abierto normalmente. Abajo estaba lleno por lo que fuimos al segundo piso, que además tenía un rock/pop ochentero apreciado por la mayoría del grupo. Las ventanas abiertas generaban un nivel de ventolero que, de querer enviajarse, podria referir al faro y ambientarse unx quien sabe donde.

  • buena atención
  • separan cuentas
  • aceptan tarjetas
  • distintos ambientes
  • buena música

Ya enrumbados (más de rumba que de rumbo) bajamos una cuadra y llegamos a La Bohemia. Cantina de tradición hasta para algunxs de lxs miembrxs del grupo mapeante.

  • fácil sentirse bienvenidx en el lugar
  • fuerte conexión entre los clientes habituales
  • hasta nos regalaron del queque de un cumpleaños que estaban celebrando
  • pocas bocas
  • separan cuentas
  • aceptan tarjetas

Ya para esas horas de la noche, el trayecto se hacía inmapeable pero la intención sacrificada no se acababa. Fuimos a chequear otro par de lugares que podríamos incluir en futuras misiones. Wongs es un restaurante más que una cantina y en lugar de bocas fueron dumplings, generando un momento de excepción en la ruta. Terminamos en la madrugada del día siguiente en Area City celebrando ya un cumpleaños de alguien de nuestro grupo mapeante. Gran salida que, de seguir con ese espíritu festivo, puede generar muchxs sacrificadxs voluntarixs futurxs que nos permitan conocer más de esas cantinas tradicionales que aún quedan en San José.

La embajada de Mapillary en Costa Rica

Minar ethereum

Requerimientos

  • Minador
  • Ubuntu Server 16.04
  • Opcional(tarjeta de video)
  • Python y python-twisted
  • Ethereum
  • cpp-ethereum

NOTA: Se considera Ubuntu Server, en caso de Ubuntu Desktop algunos requerimientos ya vienen instalados en el sistema.

Instalación

  1. Instalar ubuntu 16.04

  2. Instalar python y python-wisted

sudo apt-get install python
sudo apt-get install python-twisted
  1. Un vez que se tiene instalado el sistema operativo, activar el ppa de ethereum
sudo add-apt-repository ppa:ethereum/ethereum
sudo add-apt-repository ppa:ethereum/ethereum-qt
sudo add-apt-repository ppa:ethereum/ethereum-dev
sudo apt-get update
  1. Instalar ethereum
sudo apt-get install ethereum
  1. Instalar cpp-ethereum
sudo apt-get install cpp-ethereum
  1. Clonar el repositorio de eth-proxy.

  2. Crear un wallet con geth o parity.

  3. Instalar los drivers de vídeo, en el caso de usar una tarjeta de vídeo.

  4. Modificar el archivo de configuración de eth-proxy para usar el wallet.

  5. En el directorio eth-proxy, ejecutar eth-proxy.py

sudo python eth-proxy/eth-proxy.py
  1. Ejecutar ethminer apuntando a localhost
ethminer -F http://127.0.0.1:8080/minador -G

NOTA: La opción -G indica a ethminer que utilice GPU para minar, en caso de no contar con GPU utilice --allow-opencl-cpu.

Referencias

https://github.com/paritytech/parity https://github.com/Atrides/eth-proxy https://launchpad.net/~ethereum/+archive/ubuntu/ethereum http://ethdocs.org/en/latest/ethereum-clients/cpp-ethereum/installing-binaries/linux-ubuntu-ppa.html

Ascensión al Bosque del Niño

El día empezó despacio, un par de alarmas en snooze y retorcijones entre las sábanas. En este episodio, decidimos volver a las faldas del volcán Poás, pero ésta vez lo haríamos desde otro acercamiento. Esta vez nos adentraríamos al Poás desde la reserva forestal El Bosque del Niño.

Un par de retrasos en la vía, un café y un pan pizza dictaban el comienzo de la travesía en carro. Llegamos alrededor de las 10 am, luego de dejar varios automóviles detrás con sonidos y olores de lucha para llegar a su destino.

Una vez en el parqueo del Bosque del Niño llevábamos varios instrumentos como la vez pasada. Un GPS cargado, teléfonos celulares con Mapillary, Osmand y una cámara 360, además de uno que otro tentempié. Así, decidimos fotografiar los senderos del bosque.

Mapillary nos permite fotografiar los senderos y caminos con marcadores georeferenciados. Con esta función, esperamos que cualquiera, en cualquier parte del mundo con acceso a internet pueda hacer uso personal de las imágenes y de sus datos. ¿y por qué no? Disfrutar de un recorrido virtual a lugares donde sólo los jaquerespeistas nos adentraríamos.

Nos adentramos al primer sendero que dirigía a las cataratas de la reserva. Con nuestro biólogo estrella, Carlos Bolaños, aprendimos información como el origen del nombre debido a un proyecto de reforestación por niños, y así, una que otra característica de la flora y fauna de la zona.

Tomamos fotos de los rótulos y avisos que encontramos en el camino, así, cualquier persona que desee puede planificar mejores rutas y exploraciones a su gusto. Así, con todos los instrumentos listos, nos adentramos al primer sendero, las cataratas. Sin duda el terreno estuvo quebrado pero el espectáculo de agua valió cada paso. Mapeando el camino contribumos a la comunidad de Mapillary, además damos información del estado del sendero, sus posibles bloqueos y obstáculos a enfrentar.

Costa Rica, photo by allanesqui

Catarata del Bosque del Niño debidamente georeferenciada en Mapillary.

En seguida, nos enrumbamos al volcán Poás, el camino al coloso nos esperaba.Empezamos caminando, recorriendo caminos empolvados, árboles de altura, troncos caídos y unos obstáculo en el paso.

La inclinación se hacía más y más elevada. Gracias al GPS pudimos registrar la elevación del terreno y la distancia exacta entre diferentes puntos. Después de dos horas aproximadamente de avanzar hacia el Poás, llegamos al punto de quiebre, lugar donde varias de nuestros teléfonos móviles se apagaron por falta de energía. Aquí aprendimos que para recorridos tan largos, tomar turnos entre personas que llevan los teléfonos mapeando puede ser muy útil, con el fin de que el camino y los obstáculos se distribuyan entre nosotros.

No obstante el tiempo y el día avanzaban. No pudimos llegar al final del trayecto, pero no importaba, entre el sudor y el cansancio, habíamos logrado fotografiar la mayoría del camino para registrar la importancia de estos senderos, esperando que esos datos fueran útiles no sólo para los costarricenses, sino para todos aquellos que estén interesados en conocer un poco más el Poás.

Aquí una foto del punto más alto al que pudimos llegar.

Una vez terminado el recorrido, utilizamos la misma metodología que el paseo anterior, cada quien sube sus fotografías y puede agregar la información pertinente. Sin duda fue una experiencia para no olvidar, con esto aprendimos que debemos de empezar a prepararnos para los próximos viajes que vienen y apuntar a lo alto…llevar la ruta mapeada del cerro Chirripó, el punto más alto de Costa Rica.

Crowdtesting with the Ubuntu community: the case of IPFS

Here at Ubuntu we are working hard on the future of free software distribution. We want developers to release their software to any Linux distro in a way that's safe, simple and flexible. You can read more about this at snapcraft.io.

This work is extremely fun because we have to work constantly with a wild variety of free software projects to make sure that the tools we write are usable and that the workflow we are proposing makes sense to developers and gives them a lot of value in return. Today I want to talk about one of those projects: IPFS.

IPFS is the permanent and decentralized web. How cool is that? You get a peer-to-peer distributed file system where you store and retrieve files. They have a nice demo in their website, and you can give it a try on Ubuntu Trusty, Xenial or later by running:

$ sudo snap install ipfs

screenshot of the IPFS peers

So, here's one of the problems we are trying to solve. We have millions of users on the Trusty version of Ubuntu, released during 2014. We also have millions of users on the Xenial version, released during 2016. Those two versions are stable now, and following the Ubuntu policies, they will get only security updates for 5 years. That means that it's very hard, almost impossible, for a young project like IPFS to get into the Ubuntu archives for those releases. There will be no simple way for all those users to enjoy IPFS, they would have to use a Personal Package Archive or install the software from a tarball. Both methods are complex with high security risks, and both require the users to put a lot of trust on the developers, more than what they should ever trust anybody.

We are closing the Zesty release cycle which will go out in April, so it's too late there too. IPFS could make a deb, put it into Debian, wait for it to sync to Ubuntu, and then it's likely that it will be ready for the October release. Aside from the fact that we have to wait until October, there are a few other problems. First, making a deb is not simple. It's not too hard either, but it requires quite some time to learn to do it right. Second, I mentioned that IPFS is young, they are on the 0.4.6 version. So, it's very unlikely that they will want to support this early version for such a long time as Debian and Ubuntu require. And they are not only young, they are also fast. They add new features and bug fixes every day and make new releases almost every week, so they need a feedback loop that's just as fast. A 6 months release cycle is way too slow. That works nicely for some kinds of free software projects, but not for one like IPFS.

They have been kind enough to let me play with their project and use it as a test subject to verify our end-to-end workflow. My passion is testing, so I have been focusing on continuous delivery to get happy early adopters and constant feedback about the most recent changes in the project.

I started by making a snapcraft.yaml file that contains all the metadata required for the snap package. The file is pretty simple and to make the first version it took me just a couple of minutes, true story. Since then I've been slowly improving and updating it with small changes. If you are interested in doing the same for your project, you can read the tutorial to create a snap.

I built and tested this snap locally on my machines. It worked nicely, so I pushed it to the edge channel of the Ubuntu Store. Here, the snap is not visible on user searches, only the people who know about the snap will be able to install it. I told a couple of my friends to give it a try, and they came back telling me how cool IPFS was. Great choice for my first test subject, no doubt.

At this point, following the pace of the project by manually building and pushing new versions to the store was too demanding, they go too fast. So, I started working on continuous delivery by translating everything I did manually into scripts and hooking them to travis-ci. After a few days, it got pretty fancy, take a look at the github repo of the IPFS snap if you are curious. Every day, a new version is packaged from the latest state of the master branch of IPFS and it is pushed to the edge channel, so we have a constant flow of new releases for hardcore early adopters. After they install IPFS from the edge channel once, the package will be automatically updated in their machines every day, so they don't have to do anything else, just use IPFS as they normally would.

Now with this constant stream of updates, me and my two friends were not enough to validate all the new features. We could never be sure if the project was stable enough to be pushed to the stable channel and make it available to the millions and millions of Ubuntu users out there.

Luckily, the Ubuntu community is huge, and they are very nice people. It was time to use the wisdom of the crowds. I invited the most brave of them to keep the snap installed from edge and I defined a simple pipeline that leads to the stable release using the four available channels in the Ubuntu store:

  • When a revision is tagged in the IPFS master repo, it is automatically pushed to edge channel from travis, just as with any other revision.
  • Travis notifies me about this revision.
  • I install this tagged revision from edge, and run a super quick test to make sure that the IPFS server starts.
  • If it starts, I push the snap to the beta channel.
  • With a couple of my friends, we run a suite of smoke tests.
  • If everything goes well, I push the snap to the candidate channel.
  • I notify the community of Ubuntu testers about a new version in the candidate channel. This is were the magic of crowd testing happens.
  • The Ubuntu testers run the smoke tests in all their machines, which gives us the confidence we need because we are confirming that the new version works on different platforms, distros, distro releases, countries, network topologies, you name it.
  • This candidate release is left for some time in this channel, to let the community run thorough exploratory tests, trying to find weird usage combinations that could break the software.
  • If the tag was for a final upstream release, the community also runs update tests to make sure that the users with the stable snap installed will get this new version without issues.
  • After all the problems found by the community have been resolved or at least acknowledged and triaged as not blockers, I move the snap from candidate to the stable channel.
  • All the users following the stable channel will automatically get a very well tested version, thanks to the community who contributed with the testing and accepted a higher level of risk.
  • And we start again, the never-ending cycle of making free software :)

Now, let's go back to the discussion about trust. Debian and Ubuntu, and most of the other distros, rely on maintainers and distro developers to package and review every change on the software that they put in their archives. That is a lot of work, and it slows down the feedback loop a lot, as we have seen. In here we automated most of the tasks of a distro maintainer, and the new revisions can be delivered directly to the users without any reviews. So the users are trusting directly their upstream developers without intermediaries, but it's very different from the previously existing and unsafe methods. The code of snaps is installed read-only, very well constrained with access only to their own safe space. Any other access needs to be declared by the snap, and the user is always in control of which access is permitted to the application.

This way upstream developers can go faster but without exposing their users to unnecessary risks. And they just need a simple snapcraft.yaml file and to define their own continuous delivery pipeline, on their own timeline.

By removing the distro as the intermediary between the developers and their users, we are also making a new world full of possibilities for the Ubuntu community. Now they can collaborate constantly and directly with upstream developers, closing this quick feedback loop. In the future we will tell our children of the good old days when we had to report a bug in Ubuntu, which would be copied to Debian, then sent upstream to the developers, and after 6 months, the fix would arrive. It was fun, and it lead us to where we are today, but I will not miss it at all.

Finally, what's next for IPFS? After this experiment we got more than 200 unique testers and almost 300 test installs. I now have great confidence on this workflow, new revisions were delivered on time, existing Ubuntu testers became new IPFS contributors and I now can safely recommend IPFS users to install the stable snap. But there's still plenty of work ahead. There are still manual steps in the pipeline that can be scripted, the smoke tests can be automated to leave more free time for exploratory testing, we can release also to armhf and arm64 architectures to get IPFS into the IoT world, and well, of course the developers are not stopping, they keep releasing new interesting features. As I said, plenty of opportunities for us as distro contributors.

screenshot of the IPFS snap stats

I'd like to thank everybody who tested the IPFS snap, specially the following people for their help and feedback:

  • freekvh
  • urcminister
  • Carla Sella
  • casept
  • Colin Law
  • ventrical
  • cariboo
  • howefield

<3

If you want to release your project to the Ubuntu store, take a look at the snapcraft docs, the Ubuntu tutorials, and come talk to us in Rocket Chat.

Maperespeis #2: Volcán Poás

El domingo pasado fuimos a hacer mapas libres al Volcán Poás.

Esta es la segunda excursión geek del JaquerEspéis. De la primera aprendimos que había que esperar al verano porque con tormenta no se puede mapear. Y el día fue perfecto. No sólo estuvo soleado, sino que el cráter estaba totalmente despejado y así pudimos agregar un nuevo lugar al tour virtual de Costa Rica.

Además, esta vez llegamos mucho mejor preparados, con varios teléfonos con mapillary, osmand y OSMTracker, una cámara 360, un GPS Garmin, un dron y hasta una libreta y dos biólogos.

La procesión del MaperEspeis

Así funciona el asunto. Todos y todas con el GPS del teléfono activado esperamos a que el teléfono encuentre la ubicación. Después cada persona usa la aplicación que prefiere para recolectar datos: fotos, audios, videos, notas de texto, trazas, anotaciones en la libreta...

Luego, en nuestras respectivas casas, subimos, publicamos y compartimos todos los datos recolectados. Estos nos sirven para mejorar los mapas libres de OpenStreetMap. Agregamos desde cosas tan sencillas como la ubicación de un basurero hasta cosas tan importantes como qué tan accesible es el lugar para una persona en silla de ruedas, junto con la ubicación de todos estos accesos o las partes en las que faltan. Cada persona mejora el mapa un poquito, en la zona que conoce o por la que pasó. Con más de 3 millones de usuarios, OpenStreetMap es el mejor mapa del mundo que existe; y es de particular importancia en zonas como la nuestra, que tienen poco potencial económico para las megacorporaciones que hacen y venden mapas cerrados robando datos privados a sus usuarios.

Como los mapas que hacemos son libres, lo que sigue no tiene límites. Hay grupos trabajando en reconstrucción de modelos tridimensionales a partir de las fotos, identificación e interpretación de señales y rótulos, aplicaciones que calculan la ruta óptima para llegar a cualquier lugar usando cualquier combinación de medios de transporte, aplicaciones para asistir en la toma de decisiones al diseñar el futuro de una ciudad, y muchas otras cosas más. Todo basado en conocimiento compartido y comunidad.

La imagen de arriba es el tour virtual en Mapillary. Como lo grabamos con la cámara 360, pueden hacer clic y arrastrar con el mouse para ver todos los ángulos. También pueden hacer clic arriba, en el botón de reproducir para seguir el camino que tomamos. O pueden hacer clic en cualquier punto verde en el mapa para seguir su propio camino.

Muchas gracias a todos y todas por apuntarse a mapear, en especial a Denisse y Charles por servirnos de guías y llenar el paseo de datos interesantes sobre la flora, fauna, geología e importancia histórica del Poás.

Miembros del MaperEspeis (Aquí más fotos y videos)

El próximo maperespeis será el 12 de marzo.

Call for testing: MySQL

I promised that more interesting things were going to be available soon for testing in Ubuntu. There's plenty coming, but today here is one of the greatest:

$ sudo snap install mysql --channel=8.0/beta

screenshot of mysql snap running

Lars Tangvald and other people at MySQL have been working on this snap for some time, and now they are ready to give it to the community for crowd testing. If you have some minutes, please give them a hand.

We have a testing guide to help you getting started.

Remember that this should run in trusty, xenial, yakkety, zesty and in all flavours of Ubuntu. It would be great to get a diverse pool of platforms and test it everywhere.

In here we are introducing a new concept: tracks. Notice that we are using --channel=8.0/beta, instead of only --beta as we used to do before. That's because mysql has two different major versions currently active. In order to try the other one:

$ sudo snap install mysql --channel=5.7/beta

Please report back your results. Any kind of feedback will be highly appreciated, and if you have doubts or need a hand to get started, I'm hanging around in Rocket Chat.

Call for testing: snaps in Trusty

There is a huge announcement coming: snaps now run in Ubuntu 14.04 Trusty Tahr.

Take a moment to note how big this is. Ubuntu 14.04 is a long-term release that will be supported until 2019. Ubuntu 16.04 is also a long-term release that will be supported until 2021. We have many many many users in both releases, some of which will stay there until we drop the support. Before this snappy new world, all those users were stuck with the versions of all their programs released in 2014 or 2016, getting only updates for security and critical issues. Just try to remember how your favorite program looked 5 years ago; maybe it didn't even exist. We were used to choose between stability and cool new features.

Well, a new world is possible. With snaps you can have a stable base system with frequent updates for every program, without the risk of breaking your machine. And now if you are a Trusty user, you can just start taking advantage of all this. If you are a developer, you have to prepare only one release and it will just work in all the supported Ubuntu releases.

Awesome, right? The Ubuntu devs have been doing a great job. snapd has already landed in the Trusty archive, and we have been running many manual and automated tests on it. So we would like now to invite the community to test it, explore weird paths, try to break it. We will appreciate it very much, but all of those Trusty users out there will love it, when they receive loads of new high quality free software on their oldie machines.

So, how to get started?

If you are already running Trusty, you will just have to install snapd:

$ sudo apt update && sudo apt install snapd

Reboot your system after that in case you had a kernel update pending, and to get the paths for the new snap binaries set up.

If you are running a different Ubuntu release, you can Install Ubuntu in a virtual machine. Just make sure that you install the http://releases.ubuntu.com/14.04/ubuntu-14.04.5-desktop-amd64.iso.

Once you have Trusty with snapd ready, try a few commands:

$ snap list
$ sudo snap install hello-world
$ hello-world
$ snap find something

screenshot of snaps running in Trusty

Keep searching for snaps until you find one that's interesting. Install it, try it, and let us know how it goes.

If you find something wrong, please report a bug with the trusty tag. If you are new to the Ubuntu community or get lost on the way, come and join us in Rocket Chat.

And after a good session of testing, sit down, relax, and get ohmygiraffe. With love from popey:

$ sudo snap install ohmygiraffe
$ ohmygiraffe

screenshot of ohmygiraffe

Ubuntu Testing Day wrap up - Ubuntu Core and QEMU (20170203)

After a little break, on the first Friday of February we resumed the Ubuntu Testing Days.

This session was pretty interesting, because after setting some of the bases last year we are now ready to dig deep into the most important projects that will define the future of Ubuntu.

We talked about Ubuntu Core, a snap package that is the base of the operating system. Because it is a snap, it gets the same benefits as all the other snaps: automatic updates, rollbacks in case of error during installation, read-only mount of the code, isolation from other snaps, multiple channels on the store for different levels of stability, etc.

The features, philosophy and future of Core were presented by Michael Vogt and Zygmunt Krynicki, and then Federico Giménez did a great demo of how to create an image and test it in QEMU.

Click the image below to watch the full session.

Alt text

There are plenty of resources in the Ubuntu websites related to Ubuntu Core.

To get started, we recommend to follow this guide to run the operating system in a virtual machine.

After that, and if you are feeling brave and want to help Michael, Zygmund and Federico, you can download the candidate image instead, from http://cdimage.ubuntu.com/ubuntu-core/16/candidate/pending/ubuntu-core-16-amd64.img.xz This is the image that's being currently tested, so if you find something wrong or weird, please report a bug in Launchpad.

Finally, if you want to learn more about the snaps that compose the image and take a peek at the things that we'll cover in the following testing days, you can follow the tutorial to create your own Core image.

On this session we were also accompanied by Robert Wolff who works on 96boards at Linaro. He has an awesome show every Thursday called Open Hours. At 96boards they are building open Linux boards for prototyping and embedded computing. Anybody can jump into the Open Hours to learn more about this cool work.

The great news that Robert brought is that both Open Hours and Ubuntu Testing Days will be focused on Ubuntu Core this month. He will be our guest again next Friday, February 10th, where he will be talking about the DragonBoard 410c. Also my good friend Oliver Grawert will be with us, and he will talk about the work he has been doing to enable Ubuntu in this board.

Great topics ahead, and a full new world of possiblities now that we are mixing free software with open hardware and affordable prototyping tools. Remember, every Friday in http://ubuntuonair.com/, no se lo pierda.