GoLang

Crear tuberías de despliegue continuo con Golang y Jenkins

Hace unas semanas había escrito sobre el despliegue continuo de una aplicación escrita con el lenguaje de programación Go utilizando un popular servicio llamado Travis CI. Este ejemplo demostraba la creación de una aplicación que utilizaba un Couchbase NoSQL, creando pruebas unitarias, ejecutando esas pruebas en el canal de integración continua de Golang y, finalmente, desplegando la aplicación en algún servidor remoto cuando todo haya ido bien.

Travis CI no es el único servicio que ofrece estas características. De hecho, puedes alojar tu propio servicio CI / CD usando Jenkins.

Vamos a ver cómo utilizar Jenkins para un pipeline de una aplicación Golang, permitiendo la integración continua y el despliegue continuo.

Si aún no ha leído mi tutorial anterior Golang con Travis CIle recomiendo que lo haga, ya que ofrece muchas explicaciones útiles. Mucho del mismo material aparecerá aquí, pero se explicará de manera diferente, por lo que dos explicaciones podrían ser útiles.

Si quieres experimentar de verdad este tutorial de Jenkins con Golang, vas a necesitar Servidor Couchbase instalada en algún lugar. El objetivo es que la aplicación se ejecute y utilice esa instancia de base de datos una vez desplegada.

Desarrollo de una aplicación Go con Couchbase

Para tener éxito con este tutorial, vamos a necesitar una aplicación Go para probar y desplegar. Si quieres adelantarte, he subido un proyecto funcional a GitHub. En realidad es el mismo proyecto del ejemplo de Travis CI.

Si prefieres recorrer el proyecto, dediquemos algo de tiempo a hacerlo.

En algún lugar de tu $GOPATH crear un archivo llamado main.go e incluir el siguiente código Go. Vamos a desglosarlo después.

La aplicación no hace gran cosa, pero hay mucho que hacer.

En las importaciones, notarás nuestro uso del SDK de Couchbase para Go. Para poder compilar este proyecto, necesitarás descargar el SDK. Se puede hacer con el siguiente comando:

Antes de empezar a recorrer el código, tenemos que dar un paso atrás y averiguar cómo debería funcionar esta aplicación.

El objetivo aquí es conectarse a la base de datos NoSQL, Couchbase, recuperar algunos datos, y crear algunos datos. Naturalmente, esto sería bastante fácil a través del SDK, sin embargo, queremos crear pruebas unitarias para nuestra aplicación. Es una buena práctica nunca probar contra una base de datos en una prueba unitaria. Guarda eso para tus pruebas de integración. Si no estamos probando contra la base de datos, tenemos que crear escenarios simulados.

En lugar de crear un montón de locuras, la mejor manera de dividir entre escenarios reales y simulados es crear una interfaz para ambos con Go. La aplicación principal utilizará las clases reales como parte de la interfaz, mientras que las pruebas utilizarán las simuladas.

Por esta razón, necesitamos crear una interfaz para el SDK de Couchbase Go Cubo componente.

Un Couchbase Bucket tiene muchas más funciones que Visite y Insertepero esas serán las únicas funciones que utilizaremos en este ejemplo. Para simplificar más adelante en la aplicación, vamos a crear un struct con la nueva interfaz.

Sólo habrá un modelo de datos para este ejemplo. Vamos a utilizar un modelo de datos basado en el método Persona estructura de datos. Puede cambiar libremente sin afectar a nuestra aplicación.

Echa un vistazo a una de nuestras funciones para la que eventualmente tendremos pruebas unitarias:

En el GetPersonDocument utilizamos una función BucketInterface y obtener un documento concreto mediante la clave de documento.

Del mismo modo, si quisiéramos crear datos, tendríamos lo siguiente:

Siento que necesito reiterar esto, pero estas funciones fueron diseñadas para ser más complejas de lo que necesitan ser. Estamos haciendo esto porque queremos demostrar algunas pruebas. Si te hace sentir mejor, añadir un poco más de complejidad a ellos en lugar de sólo simple Visite y Inserte funcionalidad.

Por último, tenemos lo siguiente que se ejecuta en tiempo de ejecución:

Cuando se ejecuta la aplicación, establecemos una conexión con Couchbase utilizando variables de entorno. El Bucket abierto se establece en nuestro BucketInterfacey, a continuación, se ejecutan las dos funciones.

¿Cómo lo comprobamos?

Crea un archivo en tu proyecto llamado main_test.go con el siguiente código:

Notarás que este archivo es bastante largo y que también incluimos otro paquete personalizado. Antes de analizar el código, descarguemos ese paquete. Desde la línea de comandos, ejecuta lo siguiente:

El paquete mapstructure nos permitirá tomar mapas y convertirlos en estructuras de datos reales, como el paquete Persona estructura de datos que habíamos creado previamente. Esencialmente nos da un poco de flexibilidad en lo que podemos hacer.

Si quieres saber más sobre el paquete mapstructure, consulta un artículo anterior que escribí titulado, Decodificación de valores de mapas en estructuras Golang nativas.

Con las dependencias instaladas, ahora podemos ver el código. ¿Recuerdas que usamos el Bucket del Go SDK en nuestro código principal? En el código de prueba, no vamos a hacer eso.

En nuestro código de prueba, estamos creando un structpero lo fijamos en el BucketInterface en el Base de datos que se creó en nuestro código principal.

La configuración real de la estructura de datos se realiza en la función TestMain que se ejecuta antes de todas las demás pruebas:

Ahora bien, puesto que estamos utilizando un MockBucketno tiene todas las funciones que el gocb.Bucket podría haber tenido. En su lugar, tenemos que confiar en la BucketInterface definición.

Necesitamos crear un Visite y un Inserte como se define en la interfaz.

Empezando por el Visite tenemos lo siguiente:

Si utilizamos un MockBucket e intentamos Visiteesperamos que sólo una clave sea válida. Recuerda, esto es una prueba, así que nosotros ponemos las reglas. Si nraboy se utiliza como clave, devolvemos algunos datos simulados, de lo contrario, devolvemos un clave no encontrada error. Dado que estamos trabajando con varios tipos de datos potenciales, necesitamos convertir nuestros datos utilizando la función convertir función. Esencialmente estamos marshaling una interfaz en JSON, a continuación, marshaling de nuevo.

Ahora echemos un vistazo a ese simulacro Inserte función.

Si intentamos insertar datos utilizando nuestro mock Bucket, estamos esperando que la clave no sea igual a nraboyde lo contrario, arrojará un error.

Con las funciones de interfaz creadas, podemos centrarnos en las pruebas reales que prueban las funciones en el código Go principal.

En TestGetPersonDocument utilizará nuestro cubo simulado en el actual GetPersonDocument función. Recuerda, estamos usando interfaces, así que Go averiguará qué función de la interfaz usar, si la función real del SDK de Couchbase Go o la función mock que hemos usado. Dependiendo de los resultados es lo que ocurre en el test.

En TestCreatePersonDocument no es diferente de la anterior. Estamos llamando a la actual CrearDocumentoPersonapero estamos utilizando nuestro cubo simulado con el mock Inserte función.

En este momento, tenemos una aplicación Go funcional con pruebas y estamos listos para la integración continua y el despliegue continuo.

Instalación y configuración de Jenkins para despliegues SSH y Golang

Este siguiente paso asume que tienes un servidor remoto que está listo para recibir despliegues. Yo no lo tenía, así que creé un contenedor Docker con Ubuntu. De hecho, tanto mi instalación de Jenkins como mi servidor remoto están usando Docker.

Si quieres seguir lo que yo hice, echa un vistazo a esto. Desde la línea de comandos, ejecuta lo siguiente para iniciar un contenedor Ubuntu:

El comando anterior desplegará un contenedor Ubuntu y lo nombrará ubuntu. Una vez desplegado, se conectará a través del terminal interactivo. No abrí ningún puerto porque la comunicación de contenedor a contenedor no necesitará un puerto mapeado.

El contenedor Ubuntu no tendrá un servidor SSH disponible, por lo que necesitamos instalarlo. Dentro del shell de Ubuntu, ejecuta lo siguiente:

Los comandos anteriores instalarán openssh-servidor e iniciarlo. Mientras estamos en ello, probablemente deberíamos crear una combinación de clave pública y privada para que Jenkins la utilice.

Dentro del shell de Ubuntu, ejecute lo siguiente:

Cuando haya terminado, copie el archivo ~/.ssh/id_rsa.pub contenido en ~/.ssh/authorized_keys ya que usaremos la clave privada en el servidor Jenkins.

Recuerda, estoy usando Jenkins como un contenedor Docker también. No tienes que usar ningún contenedor si no quieres. Todo debería traducirse bien.

Si utiliza Docker, cree un contenedor Jenkins ejecutando lo siguiente:

El comando anterior desplegará Jenkins en modo separado y mapeará algunos puertos para nosotros.

Cuando visite http://localhost:8080 en su navegador web, siga los pasos del asistente y asegúrese de elegir instalar los plugins recomendados.

Una vez que llegue al panel principal de Jenkins, seleccione Administrar Jenkins -> Administrar Plugins ya que necesitamos descargar algunas cosas.

Golang Jenkins Plugins

Vamos a necesitar una forma de compilar nuestro código Go, por lo que vamos a necesitar el comando Vaya a plugin. Vamos a necesitar ejecutar nuestros propios scripts personalizados para la construcción, por lo que necesitamos el plugin PostBuildScript plugin. Por último, queremos poder publicar en un servidor remoto y ejecutar comandos, por lo que necesitaremos el plugin Publicar a través de SSH que viene con otros plugins incluidos.

Después de que los plugins terminen de descargarse, tenemos que configurarlos globalmente.

En el panel principal de Jenkins, seleccione Gestionar Jenkins -> Configuración Global de Herramientas y busca la sección Go.

Golang Jenkins Configuration

Querrás definir qué versiones de Go están disponibles. Para este proyecto, sólo necesitamos la versión 1.8, pero el resto depende de ti.

El siguiente paso es configurar nuestras claves SSH para el despliegue. Recuerda, aún no estamos creando nuestro flujo de trabajo, solo configurando Jenkins como un todo.

En el panel principal de Jenkins, seleccione Gestionar Jenkins -> Configurar sistema y encuentra la sección SSH.

Usted va a querer proporcionar su clave privada y la información de conexión del servidor. Si tanto Jenkins como el servidor remoto son contenedores Docker en la misma red que el mío, no olvides usar las direcciones IP o nombres de host de los contenedores, no localhost.

Con todo configurado, seleccione Artículo nuevo desde el panel principal de Jenkins.

New Jenkins Golang Project

Vas a querer darle un nombre y seleccionar Proyecto Freestyle para que podamos añadir nuestro propio flujo de trabajo. Tome nota del nombre, porque el nombre será el binario del proyecto que se construye.

Ahora podemos definir nuestro flujo de trabajo.

Empezaremos con el Gestión del código fuente sección. Recuerda, tengo este proyecto en GitHubasí que deberías aprovecharlo.

Jenkins Source Code Management Golang

Dado que Jenkins en este ejemplo se está ejecutando en localhost y no en un dominio, no podemos hacer nada con los disparadores de construcción. Para este ejemplo, vamos a desencadenar las cosas manualmente.

Antes de intentar ejecutar cualquier script, necesitamos configurar el entorno de compilación a la versión de Go especificada previamente.

Jenkins Golang Build Environment

Cuando se inicie el flujo de trabajo, descargará e instalará esa versión de Go antes de ejecutar pruebas o compilaciones.

Para la fase de construcción, vamos a realizar tres pasos diferentes, separados para mantener el flujo de las cosas muy limpio.

Jenkins Golang Build

El primer paso es descargar nuestros paquetes Go. Después de tener nuestros paquetes, podemos ejecutar nuestras pruebas. Después de ejecutar nuestras pruebas podemos hacer un ir a construir para crear nuestro binario. Si alguno de estos pasos falla, toda la compilación falla, que es como debe ser.

El último paso es el despliegue. En el Acciones posteriores a la construcción, queremos enviar nuestro binario por SSH y ejecutarlo.

Jenkins Deploy with SSH

En realidad, habrá dos conjuntos de transferencia implicados en este proceso.

La primera fase consiste en tomar nuestro fichero fuente, que es el binario, y enviarlo utilizando el perfil SSH que habíamos creado previamente. Una vez transferido el archivo cambiaremos los permisos para que pueda ser ejecutado.

Una vez cargado el archivo, queremos ejecutarlo utilizando otro comando Conjunto de transferencia. En lugar de tener un archivo fuente en el segundo conjunto, sólo tendremos un comando:

Fíjate que estoy pasando variables para ser usadas como variables de entorno en la aplicación. Cámbialas por lo que estés usando, o piensa en otro enfoque como tener estas variables configuradas en tu servidor por seguridad.

En teoría, estarías desplegando una aplicación web y este comando final se utiliza para iniciar el servidor con la información de conexión.

Conclusión

Acaba de ver cómo configurar Jenkins y Golang en un pipeline para despliegue continuo. Por si fuera poco, utilizamos Couchbase y Docker en este ejemplo para manejar nuestro servidor remoto así como nuestro servidor Jenkins. Su configuración puede diferir, pero los pasos son más o menos los mismos.

Si desea obtener más información sobre el uso de Jenkins y Go con Couchbase, consulte el documento Portal para desarrolladores de Couchbase.

Comparte este artículo
Recibe actualizaciones del blog de Couchbase en tu bandeja de entrada
Este campo es obligatorio.

Autor

Publicado por Nic Raboy, Defensor del Desarrollador, Couchbase

Nic Raboy es un defensor de las tecnologías modernas de desarrollo web y móvil. Tiene experiencia en Java, JavaScript, Golang y una variedad de frameworks como Angular, NativeScript y Apache Cordova. Nic escribe sobre sus experiencias de desarrollo relacionadas con hacer el desarrollo web y móvil más fácil de entender.

Deja un comentario

¿Listo para empezar con Couchbase Capella?

Empezar a construir

Consulte nuestro portal para desarrolladores para explorar NoSQL, buscar recursos y empezar con tutoriales.

Utilizar Capella gratis

Ponte manos a la obra con Couchbase en unos pocos clics. Capella DBaaS es la forma más fácil y rápida de empezar.

Póngase en contacto

¿Quieres saber más sobre las ofertas de Couchbase? Permítanos ayudarle.