martes, 5 de mayo de 2020

Automatización de Deployment de Oracle API Platform Cloud Service

Desde hace algunas semanas he participado en un proyecto de migración hacia Oracle Cloud. El proyecto tiene como objetivo migrar una buena cantidad de servicios a la nube de Oracle. Estos servicios se encuentran actualmente desplegados en Oracle SOA Suite.

Uno de los objetivos de la organización es darle a los servicios el enfoque de APIs, de tal manera que puedan ser usados por varios canales dentro y fuera de la organización. También que la misma organización pueda ejecutar acciones de monitoreo de uso y rendimiento, monetización, seguridad, y algunas otras relacionadas con el proceso de API Management.

La arquitectura utilizada para la implementación es una mezcla de varias nubes de Oracle:
  • Oracle API Platform Cloud Service
  • Oracle Integration Cloud Service
  • Oracle Infrastructure Cloud
  • Oracle Developer Cloud Service
Voy a enfocar esta entrada del blog a la automatización de los artefactos creados en Oracle API Platform Cloud Service debido a que la arquitectura contempla un plan de recuperación ante desastres, comúnmente llamado DRP.

Oracle API Platform Cloud Service

Esta es la plataforma de API Management que ofrece Oracle. Proporciona funcionalidades típicas de una plataforma de este estilo. A continuación, se listan algunas de sus capacidades:
  • Configuración de proveedores de OAuth 2.0
  • Administración de usuarios y grupos
  • Administración de roles
  • Gateways lógicos y físicos
  • Gestión de APIs
  • Gestión de planes
  • Gestión de cuentas de servicio
  • Analíticos
  • Portales de desarrolladores
  • Administración de aplicaciones
Una de las desventajas de este servicio de Oracle es que no cuenta con opciones para realizar la migración de las APIs y Gateways desplegados, hacia una instancia nueva o distinta. Por ejemplo, en el caso de un desastre, tendríamos que encender la instancia contemplada en el DRP. Sin embargo, no existen capacidades para migrar los artefactos de una instancia a otra de manera natural.

Para mayor detalle del servicio de API Management de Oracle, pueden consultar la documentación en la siguiente liga:


REST API

Afortunadamente, el servicio (como casi todos los servicios de nube) cuenta con APIs de tipo REST que nos ayudarán a automatizar el proceso. Esto evitará la necesidad de construir y sincronizar todo de nuevo en la instancia del DRP.

El alcance de las APIs provistas por Oracle incluyen la interacción con distintos elementos de la plataforma. Algunos de ellos son los siguientes:
  • APIs
  • Aplicaciones
  • Deployments
  • Gateways
  • Planes
  • Políticas
  • Cuentas de servicio
  • Suscripciones
La seguridad implementada para el uso de las APIs es OAuth 2.0. Esto quiere decir que previo al uso de las APIs, es necesario obtener un token de acceso a través de Oracle Identity Cloud Service. Una vez que el usuario es autenticado y autorizado, se utiliza el token para invocar cualquiera de las APIs.

La documentación completa de la funcionalidad de las APIs, su alcance y ejemplos de uso se encuentra en la siguiente liga:


Developer Cloud Service

Para este proyecto inclumos el uso de Developer Cloud Service como un entorno en el que vamos a ejecutar la automatización del despliegue de las APIs generadas. Developer Cloud Service es la plataforma de desarrollo de Oracle en la nube (PaaS). Cuenta con capacidades para desarrollo, colaboración, construcción y despliegue de aplicaciones en Oracle Cloud.

La documentación completa de Oracle Developer Cloud Service la pueden encontrar aquí:


Proceso de Automatización

Los pasos que seguimos para la automatización del despliegue en Oracle Developer Cloud Service fueron los que se detallan a continuación.

Descriptor

Lo primero que utilizamos es un descriptor de las APIs. Este básicamente es un archivo de tipo JSON que nos indica información importante de las APIs que queremos promover de una instancia a otra.

Básicamente, la información que debe incluir el descriptor es la siguiente:

  • Nombre de la API
  • Endpoint del servicio del backend
A continuación, se muestra un ejemplo simple del descriptor:

{
    "apis": [
        {
            "name": "Orders API",
            "targetURL": "https://oracleintegrationcloudinstance/ic/ws/integration/v1/flows/soap/"
        },
        {
            "name": "Customers API",
            "targetURL": "https://oracleintegrationcloudinstance/ic/ws/integration/v1/flows/soap/"
        }
    ]
}

Dentro del arreglo de APIs, vamos a colocar todas las APIs que necesitamos mover de una instancia (fuente) a otra (destino).

Una vez creado el descriptor, se debe subir al repositorio de Git para conectar el job que realizará el despliegue automático. Así, cada vez que se decida mover APIs de una instancia a otra, se deberá modificar el descriptor y hacer commit de los cambios al repositorio.

Es hora de crear el job.

Parámetrización del job

Para hacer dinámico el job que automatiza el despliegue, es necesario colocar algunos parámetros que podamos cambiar a la hora de ejecutarlo. De esta forma, si las instancias cambian, la ejecución del job será dinámica y se adaptará a nuestras necesidades. Los parámetros que colocamos son los siguientes:
  • Descriptor: nombre del archivo descriptor que se subirá al repositorio. El contenido deberá tener la información de las APIs que se necesitan mover de un ambiente a otro.
  • GetTokenURL. URL de la API que utilizaremos para obtener el token de acceso. Normalmente esta es la URL de Oracle Identity Cloud Service.
  • ClientCredsSource. Client ID y client secret de la aplicación origen que utilizaremos para consumir las APIs.
  • ClientCredsTarget. Client ID y client secret de la aplicación destino que utilizaremos para consumir las APIs.
  • UsernameSource. Usuario para obtener el token de acceso en la instancia origen.
  • PasswordSource. Password para obtener el token de acceso en la instancia origen.
  • ScopeSource. Scope para obtener el token de acceso en la instancia origen.
  • URLEnvSource. URL de la API de la instancia origen de Oracle API Platform.
  • UsernameTarget. Usuario para obtener el token de acceso en la instancia destino.
  • PasswordTarget. Password para obtener el token de acceso en la instancia destino.
  • ScopeTarget. Scope para obtener el token de acceso en la instancia destino.
  • URLEnvTarget. URL de la API de la instancia destinode Oracle API Platform.
  • GatewayID. Identificador del Gateway donde vamos a desplegar las APIs.
Los parámetros anteriores nos ayudan a ejecutar el job con valores dinámicos. Así, si la instancia fuente o destino cambia, lo único que es necesario es cambiar los valores de esos parámetros.

Scripting

La estrategia para realizar la automatización fue ejecutar un bash script. La mayoría de las APIs de Oracle están ejemplificadas con el uso de cURL. Por esta razón decidimos escribir un bash script y ahí encapsular las llamadas a las APIs con el uso de cURL.

Sin embargo, es posible codificar la automatización en cualquier otro lenguaje. Aquí lo importante es que sepamos cómo consumir REST APIs con ese lenguaje. Incluso es posible crear un plugin de Maven o Gradle para este propósito.

Validaciones

Antes de ejecutar la automatización, debemos hacer algunas validaciones. En mi caso las validaciones que hice al contenido del descriptor fueron las siguientes:
  • El archivo JSON tiene una estructura válida y cumple con la definición de la estructura del descriptor.
  • El archivo incluye la información de al menos una API a desplegar.
Procedimiento de despliegue

Los pasos para realizar el despliegue, después de librar todas las validaciones del archivo, son los siguientes:
  • Obtener un token de acceso del ambiente origen: POST /oauth2/v1/token
  • Obtener las APIs del ambiente origen: GET /apiplatform/management/v1/apis
  • Validar que todas las APIs del descriptor, se encuentran desplegadas y activas en el ambiente origen. Esto es necesario, pues del ambiente origen se va a tomar toda la definición de cada API. Si no están desplegadas o activas, no podemos tomar la definición de ese ambiente: GET /apiplatform/management/v1/apis/{id}/deployments
  • Obtener un token de acceso del ambiente destino: POST /oauth2/v1/token
  • Obtener las APIs del ambiente destino: GET /apiplatform/management/v1/apis
  • Si la API origen existe en el destino: actualizar la definición con el detalle del origen y con el endpoint del descriptor (targetURL): PUT /apiplatform/management/v1/apis/{id}
  • Si la API origen no existe en el destino: crear la API en el ambiente destino con el detalle del origen y con el endpoint del descriptor (targetURL): POST /apiplatform/management/v1/apis
  • Desplegar la API en el ambiente destino: POST /apiplatform/management/v1/apis/{id}/deployments
Posibles errores

En caso de que exista un error en alguno de los pasos anteriores, el proceso se detiene y se reporta la causa del error. Algunas causas de error pueden ser las siguientes:
  • Información de credenciales incorrecta: usuarios, passwords, client credentials
  • Las APIs listadas en el descriptor no se encuentran desplegadas y/o activas en el entorno origen
  • Hay alguna dependencia en el entorno origen que no está configurada en el entorno destino. Por ejemplo los service account.
Conclusiones

Crear un mecanismo de automatización de despliegue de las APIs desplegadas en Oracle API Platform Cloud Service es una buena idea, pues a menudo se pueden presentar escenarios donde es necesario mover los artefactos de una instancia a otra. Esto puede suceder por distintas razones: se actualizan los servicios de nube, en un escenario de DRP, en caso de tener distintas instancias para distintos ambientes (Dev, Staging, Prod).

La reacción oportuna a alguno de estos escenarios, se verá beneficiada por la automatizacion y evitará el esfuerzo de crear nuevamente cada uno de los artefactos (APIs, Gateways, Planes, entre otros).

El uso de Developer Cloud Service es una buena alternativa para concentrar estas estrategias, pues es una plataforma que podemos utilizar de manera transparente para integrar con distintas nubes de Oracle, ya sea a través del uso de las APIs o a través de la propia CLI de Oracle. Aquí mismo podemos documentar y dar seguimiento al proceso y tareas de automatización. Personalmente he utilizado esta nube para automatización de despliegues de:
  • Microservicios (Helidon, Quarkus) hacia Oracle Kubernetes Cluster.
  • Oracle SOA Suite (Service Bus y SOA Composites) hacia entornos OnPremise y Cloud.
  • APIs en Oracle API Platform Cloud Service
  • Integraciones en Oracle Integration Cloud Service
  • Funciones en Oracle Functions (FaaS)

viernes, 3 de mayo de 2019

Wercker Intro

A mediados de abril del año 2017 (casi 2 años atrás), Oracle adquirió Wercker. Si bien ya existían productos para habilitar CI/CD en las organizaciones, Oracle vio una característica importante de Wercker: es una plataforma basada en Docker.

Por otro lado, en diciembre pasado (2018), Docker en conjunto con Microsoft anunciaron un nuevo estándar llamado CNAB (Cloud Native Application Bundle). Este estándar tiene como objetivo principal administrar en conjunto: infraestructura, aplicaciones y servicios cloud.

En qué atinó Oracle ese 2017: Docker se convertiría en un estándar tarde o temprano (aunque ellos quizá no lo sabían o, al menos, no estaban tan seguros). Mejor aún, lo que sucedió es que Docker ESCRIBIÓ un estándar. Y no sólo eso, sino que escribió un estándar para aplicaciones Cloud Native. La ventaja de Wercker sobre algunas otras plataformas que ofrecen CI/CD es que desde su concepción está basado en Docker.

Ahora bien: ¿qué es Wercker y cuáles son sus principales funciones o características?

  • Steps
  • Pipelines
  • Workflows

Steps

Son scripts bash o binarios que ayudan a automatizar tareas. Las tareas que automatizan se definen en un archivo llamado wercker.yaml asociado a la aplicación. Los steps los puede uno escribir a mano; o bien, pedirlos prestados a la comunidad. Recuerden que no estamos solos, siempre podemos echar mano de Internet. Estos pasos (los que pedimos prestados) se encuentran en un lugar que se llama Steps Registry.

Pipelines

Esta es la principal capacidad de Wercker. Es donde se define el flujo de las acciones (pasos) y el entorno de esas tareas. Es aquí donde se definen las tareas de build, test y deploy. Algo que presume mucho Wercker es que los pipelines pueden ejecutarse de manera concurrente, esto podría ayudar en el tiempo de ejecución del pipeline.

Workflow

Esta característica es la configuración del circuito. En un workflow podemos incluir uno o varios pipelines y configurarlos en serie o en paralelo (sí, como un circuito eléctrico). De tal suerte que de acuerdo a nuestro diseño de los pipelines (conjunto y configuraciones de steps), podríamos reutilizar distintos pipelines en distintos workflows. Esto nos permite diseñar configuraciones de pipelines (workflows) tan simples o complejos como necesitemos.

Otras funciones

Adicional a las anteriores, Wercker proporciona algunas otras funciones o capacidades. Por ejemplo, cuenta con integración con repositorios basados en Git (el de tu preferencia: GitHub, GitLab, Bitbucket, entre otros). Esta funcionalidad es básica para cualquier pipeline de CI/CD, pues es necesario obtener el código fuente de algún lado para ejecutar tareas de build, test o deploy.


martes, 27 de noviembre de 2018

MICROSERVICIOS CON HELIDON

Una alternativa tecnológica para escribir microservicios en Java es Helidon, un nuevo proyecto de Oracle. Veamos qué tal le va en ésta competencia.


Hechos


Cuenta con tres componentes:

  1. WebServer: un API HTTP con características reactivas, provistas por Netty.
  2. Config: un framework de configuración flexible que soporta múltiples fuentes y formatos.
  3. Security: herramientas para autenticación, autorización y propagación de contexto.
Se puede elegir entre dos modelos de programación:
  1. Helidon SE: estilo de programación funcional que usa los tres componentes mencionados anteriormente.
  2. Helidon MP: modelo declarativo que soporta las APIs de Microprofile
Cuenta también con soporte para Docker y Kubernetes, lo que lo hace atractivo para aplicaciones con arquitecturas basadas en microservicios.

Prerrequisitos

Al parecer los prerrequisitos son muy simples:
  1. Java 8 o superior
  2. Maven
Opcionalmente:
  1. Docker, si necesitamos desplegar en contenedores.
  2. Kubectl, si necesitamos desplegar en Kubernetes
  3. Kubernetes Cluster
Las versiones mínimas son las siguientes:
  1. Java 8 SE u Open JDK 8
  2. Maven 3.5
  3. Docker 18.02
  4. Kubectl 1.7.4
No se necesita nada adicional. Veamos si es tan simple como parece.

Máquina Virtual


Estoy usando una máquina virtual que me pasó mi compi @domix. Validaré los prerrequisitos:


Arquetipos

Como mencioné anteriormente, existen dos modelos de programación que podemos elegir: Helidon SE y Helidon MP. El primer paso es generar el proyecto usando los arquetipos de Maven para Helidon. El resultado será un servicio REST con la misma API, sin embargo, la implementación es distinta.

Helidon SE


Helidon MP


Proyectos

Lo anterior generará dos proyectos: uno de Helidon SE y otro de Helidon MP. Misma API REST, distinta forma de implementar.


Construcción de la aplicación

Para ambos casos (SE y MP), vamos a construir la aplicación utilizando Maven.


Lo anterior, va a compilar el código, ejecutar un set de pruebas y finalmente crear un JAR.

La diferencia entre SE y MP es el servidor que ejecuta la aplicación. En el caso de Microprofile, el tiempo de arranque es de 151 milisegundos. ¡Nada mal!


Finalmente, podemos observar los JAR generados de la aplicación. También se puede observar que el JAR de MP es ligeramente más grande que el de SE. Es el precio por tener un arranque mucho más rápido, aunque la diferencia en tamaño del mismo código no es significativa.

Ejecutar y Probar la Aplicación

Ahora que ya tenemos el paquete, vamos a ejecutarlo y probarlo. La ejecución es simple, como cualquier otro JAR ejecutable. Al ser un servicio REST el que expusimos en la aplicación, sólo tenemos que enviar peticiones HTTP adecuadas. El set de pruebas ejecutado es el siguiente:
  1. GET a /greet, RESPONSE: Hello World!
  2. GET a /greet/{nombre}, RESPONSE: Hello {nombre}!
  3. PUT a /greet/greeting/{saludo} (esto modificará el mensaje del saludo), RESPONSE: {saludo}
  4. GET a /greet/{nombre}, RESPONSE: Hola (nuevo saludo) {nombre}!

Helidon SE

Helidon MP

No es por presumir, pero ésta vez la aplicación tardó 136 milisegundos en iniciar. El servicio expuesto cumple con la misma interfaz que en el caso de SE, por lo que si ejecuto el mismo set de pruebas, el resultado debe ser el mismo.

Conclusiones

Pienso que al ser Helidon una colección de librerías para escribir microservicios en Java, muchos desarrolladores de la comunidad pueden tanto colaborar como hacer uso de ellas. Me parece que podría haber un buen futuro si se promueve el uso y colaboración en el desarrollo del proyecto.

Iniciar a escribir código es muy rápido (quizá no tanto como el Starter de SpringBoot, pero bastante decente), además de que el uso de Maven y los arquetipos hace que tengas un proyecto de código listo literalmente en minutos (versión inicial o cascarón).

La opción de Microprofile ha sido una gran decisión, pues ayuda en la controversia del uso de Java (y el tiempo de inicio) en arquitecturas orientadas a microservicios. En mi caso, la aplicación tarda en promedio 150 milisegundos en iniciar. Me parece un tiempo bastante decente para una aplicación de éste estilo. Faltaría probar al incluir más servicios y con mayor complejidad y dependencias.

Helidon SE

Si revisamos un poco el código, es bastante simple. Tenemos una clase principal de la aplicación, donde definiremos el inicio del servidor y el contexto inicial o base de la API REST:



Del lado de la implementación, tendríamos que sobreescribir el método update de la clase Service para definir las URIs y métodos HTTP a exponer, así como la referencia a los métodos que implementan la lógica de cada recurso:


Finalmente, escribimos la lógica de cada uno de los métodos de implementación de los recursos:

Helidon MP

Para el caso de Microprofile, tenemos una clase principal muy similar donde definimos el contexto base de la aplicación. Sin embargo, los métodos para iniciar la aplicación y la configuración del logging resultan mucho más simples:

El resto del código es el de una aplicación con JAX-RS usando Java EE:


Esto parece una buena decisión, pues quienes ya creaban aplicaciones con JAX-RS, lo van a poder seguir haciendo de la misma forma y aquí el que sirve es Microprofile.

Docker y Kubernetes

La decisión de soportar Docker y Kubernetes hace a Helidon una alternativa bastante interesante para aplicaciones Cloud Native pues, como dijo mi amigo @RuGI, Docker no debe tardar en convertirse en un estándar en contenedores. 

martes, 14 de agosto de 2018

FN Project - Instalación y primera función

Intro

Fn es una plataforma cloud FaaS (Funtions-as-a-Service) de código abierto. Está basada en eventos y puede correr en cualquier nube (cloud agnostic serverless platform).

Entre otras, algunas características principales de éste proyecto son:
  • Código abierto
  • Docker native
  • Múltiples lenguajes de programación
  • Agnóstica a la nube (corre en cualquier nube)
  • De fácil uso (principalmente para desarrolladores y operadores)
  • Está escrita en Go


Instalación

Los pre-requisitos son simples:
  1. Tener instalado y corriendo Docker 17.10.0-ce o superior
  2. Tener una cuenta de Docker Hub
  3. Hacer login en la cuenta de Docker Hub
Instalar la línea de comandos de Fn (CLI)

Esto no es requerido, pero a nadie le cae mal una ayuda. Nos va a facilitar algunas cosas.

Estoy usando Linux, hay maneras de hacerlo en Windows y MacOS. Aquí vamos a mostrar cómo se hace en Linux.

Debemos descargar un shell y ejecutarlo. En caso de estar usando root, todo será transparente. En caso de estar utilizando algún otro usuario, nos va a pedir el password para invocar sudo.

curl -LSs https://raw.githubusercontent.com/fnproject/cli/master/install | sh

Al finalizar la descarga e instalación, veremos lo siguiente en la línea de comandos. En este punto la herramienta de CLI estará instalada:


Podemos verificar que la instalación de CLI fue correcta ejecutando el comando: fn help


Ejecución del Fn Server

El siguiente paso es descargar el binario de Fn. Aquí van a encontrar las versiones disponibles, deberán descargar el que corresponde a su sistema operativo (en mi caso, Linux):


Una vez descargados los binarios, podemos ejecutar el comando para iniciar el fn server: fn start

Como era de esperarse, mi versión de docker era muy vieja. Entonces el primer intento no funcionó.


Pero no se agüiten. Sólo es necesario remover el docker-engine actual e instalar la versión más nueva y chévere de docker-ce (hay que agregar el repositorio correspondiente para poder instalar docker-ce).

Desinstalar docker-engine

sudo yum remove docker


Agregar repositorio de docker-ce e instalar la última versión

sudo yum -y install yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum -y install docker-ce


Verificar la instalación de docker-ce

docker version


Podemos ver un mensaje que nos indica que el Docker daemon no está iniciado. Como acabamos de instalar docker-ce, debemos iniciar manualmente el demonio y verificar nuevamente. Para poder iniciar el demonio con systemctl, nos va a solicitar el password de sudo:

systemctl start docker
docker version


Segundo intento, levantar el fn server

fn start


Primera función

fn init

Para escribir nuestra primera función, vamos a usar la herramienta CLI que instalamos al inicio. Esto va a permitir crear la primera versión de manera muy simple. Lo unico que debemos hacer es escribir: fn init --runtime go hello

Lo anterior, automáticamente va a generar una carpeta llamada hello y debajo de ella cuatro archivos correspondientes al código de nuestra función:


func.go

El archivo func.go contiene el código de la función. Es un simple hello world. Básicamente la función recibe un parámetro (name). En caso de que el parámetro esté vacío, devuelve "Hello World". En caso de que el parámetro contenga un valor, devuelve un saludo personalizado "Hello Leo".


func.yaml

El archivo func.yaml es llamado func file y es usado para la creación de las funciones de fn project. Lo que definimos en el archivo es: el nombre de la función, la versión de la función, el lenguaje de programación en tiempo de ejecución y el formato de los mensajes.


Gopkg.toml

El archivo Gopkg.toml es un archivo de configuración donde se definen las dependencias de la función.


test.json

El archivo test.json es un archivo utilizado para realizar pruebas de ejecución de la funcion, define entradas y salidas de la función. Esto nos ayudará a saber si la función está operando correctamente o no.


Ejecutar la función localmente

Una vez que está listo el código, vamos a ejecutarlo y a desplegarlo al Fn server local. Para el despliegue vamos a utilizar nuestro usuario de Docker Hub que comentamos al inicio, en los pre-requisitos del post. Vamos a hacer un export a la variable de ambiente FN_REGISTRY, con el usuario de Docker Hub. Una vez hecho esto, vamos a ejecutar la función localmente: fn run

Desplegar la función al Fn server local

Para desplegar la función a nuestro Fn server local, vamos a utilizar el comando: fn deploy --app myapp --local



Probar la función

Para poder probar la función en nuestro Fn server local, vamos a ejecutar alguna de las siguientes opciones:

  1. Probar en el navegador: http://localhost:8080/r/myapp/hello
  2. Probar usando curl: curl http://localhost:8080/r/myapp/hello
  3. Probar usando CLI: fn call myapp /hello
Navegador (usando Firefox):


CURL:


CLI:


HTTPie

Adicionalmente hice un par de pruebas usando HTTPie. Es una herramienta en modo línea de comandos que nos sirve para enviar requests a un endpoint usando los distintos métodos de HTTP. Esto me va a permitir ejecutar tanto un GET como un POST en el mismo endpoint y poder pasar el nombre a la función sin tener que armar a mano el JSON del payload.

HTTPie (GET):


HTTPie (POST):


miércoles, 7 de marzo de 2018

Automatización de pruebas de OSB usando SOAP UI.

En esta entrada voy a mostrar cómo es posible automatizar pruebas de servicios desplegados en OSB, haciendo uso de SOAP UI.

Los pasos a seguir son simples:

1. Construir un servicio y exponerlo en OSB.
2. Crear un proyecto de SOAP UI para probar el servicio.
3. Hacer uso de Maven para probar y desplegar el proyecto.

Imaginemos el siguiente escenario: tenemos un servicio en un entorno de desarrollo (desplegado) y lo queremos promover a un ambiente de pruebas. Previo a realizar esto, debemos asegurarnos que nuestro servicio funciona de manera adecuada y que hace lo que debe hacer.

Para ese propósito ocupamos SOAP UI, generamos algunos casos de prueba y los colocamos en una Test Suite y probamos. Una vez que aseguramos que todos los casos de prueba se ejecutan correctamente, podemos pasar a la automatización de esas pruebas.

En mi caso, creé un servicio simple que devuelve un saludo (cómo crear el servicio, esquemas, pipeline, etc., no es el objetivo de esta entrada pero pueden crear uno muy simple). Posteriormente, creé el proyecto en SOAP UI, una Test Suite (llamada Pruebas) y un Test Case (saludar TestCase). Agregué un par de pasos de ejecución para las pruebas y algunos assertions para cada paso. Ejecuté el test case y estos fueron mis resultados:


Al ejecutar cada uno de los pasos, mis resultados fueron los siguientes:



Como vemos, el servicio cumple con los casos de prueba diseñados. Esto podría significar que está listo para ser promovido a un ambiente de pruebas. Para asegurarnos que el código que estamos desplegando esté bien probado antes de ser promovido, y que esto se haga de forma automática, podemos hacer uso de un plugin de Maven. Esto es tan simple como agregar lo siguiente al POM del proyecto:

  <pluginRepositories>
    <pluginRepository>
      <id>smartbear-sweden-plugin-repository</id>
      <url>http://www.soapui.org/repository/maven2/</url>
    </pluginRepository>
  </pluginRepositories>
  <build>
    <plugins>
      <plugin>
        <groupId>com.smartbear.soapui</groupId>
        <artifactId>soapui-maven-plugin</artifactId>
        <version>4.6.1</version>
        <executions>
          <execution>
            <id>QClearanceTest</id>
            <goals>
              <goal>test</goal>
            </goals>
            <phase>test</phase>
          </execution>
        </executions>
        <configuration>
          <projectFile>${basedir}/Test/test-soapui-project.xml</projectFile>
          <testSuite>Pruebas</testSuite>
          <testCase>saludar TestCase</testCase>
          <endpoint>http://localhost:7001/v1/SOAPUI/TestSuite.svc</endpoint>
          <outputFolder>${basedir}/Reporte</outputFolder>
          <junitReport>true</junitReport>
          <printReport>true</printReport>
          <settingsFile>${basedir}/Test/soapui-settings.xml</settingsFile>
        </configuration>
      </plugin>
    </plugins>
  </build>

Lo que marco en naranja, es básicamente lo que tendría que cambiar de acuerdo a cómo hayan hecho la implementación del servicio. En mi caso:

- El endpoint de mi servicio está en localhost, por el puerto 7001
- La Test Suite de SOAP UI, la llamé Pruebas
- El Test Case de SOAP UI, lo llamé saludar TestCase
- En caso de haber un error en las pruebas, quiero que se genere un reporte debajo de la carpeta ${basedir}/Reporte (donde tengo mi proyecto de OSB, debajo de una carpeta llamada Reporte).
- Tanto el proyecto de SOAP UI, como el archivo de instalación del producto, los puse debajo de la carpeta Test.

Así quedó la estructura de mi proyecto de OSB:

- Reporte, es la carpeta donde el plugin va a almacenar el reporte de ejecución de las pruebas
- Test, es la carpeta donde coloqué el XML del proyecto de SOAP UI (test-soapui-project.xml) y el XML de la instalación del producto (soapui-settings.xml)

Hay algunas consideraciones respecto al proyecto de SOAP UI para que pueda funcionar bien el plugin:

- SOAP UI por default coloca "\r" al finalizar una línea en los payloads de prueba. Esto se ve en el XML del proyecto de SOAP UI. Simplemente hay que eliminar las "\r".
- SOAP UI por default coloca "No Authorization" cuando no tenemos algún tipo de autorización. Esto se valida en un enumeration de un esquema, y "No Authorization" no es parte de ese enumeration. Así es que hay que eliminarlo (o comentarlo en el código).

Entonces, el proyecto de SOAP UI que adjuntamos a nuestro proyecto de OSB, se debe corregir de la siguiente forma (izquierda: incorrecto, derecha: correcto):




Una vez corregido el proyecto de SOAP UI, lo podemos probar localmente ejecutando mvn test:



Lo más importante de haber logrado automatizar las pruebas, es que esto se incluya antes del despliegue. Para esto, debemos haber poblado nuestro repositorio local con los artefactos de Oracle, para así poder ejecutar: mvn pre-integration-test. La documentación de cómo hacer esto, la pueden encontrar aquí:


Lo anterior, realizará las pruebas previo al despliegue del servicio (en el ambiente indicado). Entonces, al ejecutar mvn pre-integration-test, tendremos lo siguiente (además del servicio probado y desplegado en el ambiente destino):


Podría concluir que el uso del plugin de SOAP UI es muy útil para validar que nuestros servicios se comporten de la manera en que se espera, previo al despliegue a un ambiente de calidad o productivo. En conjunto con los artefactos de Oracle, esto puede ser un buen inicio para automatizar las pruebas y despliegues, generando así los primeros pasos de un entorno de CI/CD.

Además nos obligamos a diseñar y ejecutar casos de prueba. Es muy importante entender que los defectos deben ser encontrados y corregidos (en su mayoría) por el desarrollador, no por el equipo encargado de realizar QA. Si diseñamos y ejecutamos esas pruebas previo al despliegue, minimizamos la cantidad de defectos que pudieran ser encontrados después. Entre más robusto sea el diseño de esos casos de prueba, entregaremos un producto de mejor calidad y con menor número de defectos. Hagamos ésta una práctica del equipo de desarrollo.