Cómo probar la implementación de Ansible con InSpec y Kitchen

Índice
  1. Introducción
  • Prerrequisitos
  • Paso 1: Configuración e inicialización de la cocina
  • Paso 2: creación del manual de Ansible
  • Paso 3: Cómo escribir las pruebas InSpec
  • Paso 4: Agregar casos de prueba
  • Conclusión
  • El autor seleccionó el Fondo de Diversidad en Tecnología para recibir una donación como parte del programa Write for DOnations.

    Introducción

    InSpec es un marco de auditoría y pruebas automatizadas de código abierto que se utiliza para describir y probar problemas, recomendaciones o requisitos normativos. Está diseñado para ser legible por humanos y no depende de ninguna plataforma. Los desarrolladores pueden trabajar con InSpec localmente o mediante SSH, WinRM o Docker para ejecutar pruebas, por lo que no es necesario instalar ningún paquete en la infraestructura que se está probando.

    Aunque con InSpec puedes ejecutar pruebas directamente en tus servidores, existe la posibilidad de que se produzcan errores humanos que podrían causar problemas en tu infraestructura. Para evitar este escenario, los desarrolladores pueden usar Kitchen para crear una máquina virtual e instalar un sistema operativo de su elección en las máquinas donde se ejecutan las pruebas. Kitchen es un ejecutor de pruebas, o una herramienta de automatización de pruebas, que te permite probar el código de infraestructura en una o más plataformas aisladas. También es compatible con muchos marcos de prueba y es flexible con una arquitectura de complemento de controlador para varias plataformas como Vagrant, AWS, DigitalOcean, Docker, contenedores LXC, etc.

    En este tutorial, escribirás pruebas para tus playbooks de Ansible ejecutándose en un Droplet de DigitalOcean Ubuntu 18.04. Usarás Kitchen como ejecutor de pruebas e InSpec para escribir las pruebas. Al finalizar este tutorial, podrás probar la implementación de tu playbook de Ansible.

    Prerrequisitos

    Antes de comenzar con esta guía, necesitará una cuenta de DigitalOcean además de lo siguiente:

    • Una instalación local Rubyen su máquina. Puede instalar Ruby siguiendo el tutorial correspondiente a su distribución en la serie: Cómo instalar y configurar un entorno de programación local para Ruby.
    • Chef Development Kit (ChefDK) instalado en su máquina.
    • Las claves SSH se configuran en su máquina siguiendo los pasos 1 y 2 de Cómo configurar claves SSH. Para cargar su clave pública SSH en su cuenta de DigitalOcean, puede seguir nuestro tutorial Cómo agregar claves SSH a una cuenta de DigitalOcean.
    • Un token de acceso personal de lectura y escritura de DigitalOcean. Asegúrese de registrar el token en un lugar seguro; lo usará más adelante en este tutorial. Esto le permite crear un Droplet en DigitalOcean, que es donde se ejecutarán las pruebas en este tutorial.

    Paso 1: Configuración e inicialización de la cocina

    Ha instalado ChefDK como parte de los requisitos previos que vienen incluidos con Kitchen. En este paso, configurará Kitchen para que se comunique con DigitalOcean.

    Antes de inicializar Kitchen, creará un directorio de proyecto y se trasladará a él. En este tutorial, lo llamaremos ansible_testing_dir.

    Ejecute el siguiente comando para crear el directorio:

    1. mkdir ~/ansible_testing_dir

    Y luego pasar a ello:

    1. cd ~/ansible_testing_dir

    Utilice gemla instalación del kitchen-digitaloceanpaquete en su máquina local. Esto le permite indicarle kitchenque use el controlador de DigitalOcean al ejecutar pruebas:

    1. gem install kitchen-digitalocean

    Dentro del directorio del proyecto, ejecutará el kitchen initcomando especificando ansible_playbookcomo aprovisionador y digitaloceancomo controlador al inicializar Kitchen:

    1. kitchen init --provisioner=ansible_playbook --driver=digitalocean

    Verás el siguiente resultado:

    Outputcreate  kitchen.ymlcreate  chefignorecreate  test/integration/default

    Esto ha creado lo siguiente dentro del directorio de su proyecto:

    • test/integration/defaultEs el directorio donde guardarás tus archivos de prueba.

    • chefignorees el archivo que usarías para garantizar que ciertos archivos no se carguen al servidor Chef Infra, pero no lo usarás en este tutorial.

    • kitchen.ymles el archivo que describe su configuración de prueba: lo que desea probar y las plataformas de destino.

    Ahora, debe exportar sus credenciales de DigitalOcean como variables de entorno para tener acceso a la creación de Droplets desde su CLI. Primero, comience con su token de acceso de DigitalOcean ejecutando el siguiente comando:

    1. export DIGITALOCEAN_ACCESS_TOKEN="YOUR_DIGITALOCEAN_ACCESS_TOKEN"

    También debe obtener el número de identificación de su clave SSH; tenga en cuenta que YOUR_DIGITALOCEAN_SSH_KEY_IDSdebe ser el ID numérico de su clave SSH, no el nombre simbólico. Con la API de DigitalOcean, puede obtener el ID numérico de sus claves con el siguiente comando:

    1. curl -X GET https://api.digitalocean.com/v2/account/keys -H "Authorization: Bearer $DIGITALOCEAN_ACCESS_TOKEN"

    Con este comando verás una lista de tus claves SSH y los metadatos relacionados. Lee el resultado para encontrar la clave correcta e identificar el número de identificación dentro del resultado:

    Output... {"id":your-ID-number,"fingerprint":"fingerprint","public_key":"ssh-rsa your-ssh-key","name":"your-ssh-key-name"...

    Nota: Si desea que su salida sea más legible para obtener sus identificadores numéricos, puede buscar y descargar jqsegún su sistema operativo en la página de descarga de jq. Ahora, puede ejecutar el comando anterior incluido jqde la siguiente manera:

    1. curl -X GET https://api.digitalocean.com/v2/account/keys -H "Authorization: Bearer $DIGITALOCEAN_ACCESS_TOKEN" | jq

    Verá la información de su clave SSH con un formato similar al siguiente:

    Output{  "ssh_keys": [    {      "id": YOUR_SSH_KEY_ID,      "fingerprint": "2f:d0:16:6b",      "public_key": "ssh-rsa AAAAB3NzaC1yc2 example@example.local",      "name": "sannikay"    }  ],}

    Una vez que haya identificado sus ID numéricas SSH, expórtelas con el siguiente comando:

    1. export DIGITALOCEAN_SSH_KEY_IDS="YOUR_DIGITALOCEAN_SSH_KEY_ID"

    Ha inicializado kitcheny configurado las variables de entorno para sus credenciales de DigitalOcean. Ahora, podrá crear y ejecutar pruebas en sus Droplets de DigitalOcean directamente desde la línea de comandos.

    Paso 2: creación del manual de Ansible

    En este paso, creará un playbook y roles que configuran Nginx y Node.js en el Droplet creado en kitchenel siguiente paso. Las pruebas se ejecutarán en el playbook para garantizar que se cumplan las condiciones especificadas en el playbook.

    Para comenzar, cree un rolesdirectorio para los roles Nginx y Node.js:

    1. mkdir -p roles/{nginx,nodejs}/tasks

    Esto creará una estructura de directorio como la siguiente:

    roles├── nginx│   └── tasks└── nodejs    └── tasks

    Ahora, crea un main.ymlarchivo en el roles/nginx/tasksdirectorio usando tu editor preferido:

    1. nano roles/nginx/tasks/main.yml

    En este archivo, cree una tarea que configure e inicie Nginx agregando el siguiente contenido:

    roles/nginx/tareas/main.yml

    ---- name: Update cache repositories and install Nginx  apt:    name: nginx    update_cache: yes- name: Change nginx directory permission  file:    path: /etc/nginx/nginx.conf    mode: 0750- name: start nginx  service:    name: nginx    state: started

    Una vez que haya agregado el contenido, guarde y salga del archivo.

    En roles/nginx/tasks/main.yml, se define una tarea que actualizará el repositorio de caché de su Droplet, lo que equivale a ejecutar el apt updatecomando manualmente en un servidor. Esta tarea también cambia los permisos del archivo de configuración de Nginx e inicia el servicio Nginx.

    También vas a crear un main.ymlarchivo roles/nodejs/taskspara definir una tarea que configure Node.js:

    1. nano roles/nodejs/tasks/main.yml

    Agregue las siguientes tareas a este archivo:

    roles/nodejs/tareas/main.yml

    ---- name: Update caches repository  apt:    update_cache: yes- name: Add gpg key for NodeJS LTS  apt_key:    url: "https://deb.nodesource.com/gpgkey/nodesource.gpg.key"    state: present- name: Add the NodeJS LTS repo  apt_repository:    repo: "deb https://deb.nodesource.com/node_{{ NODEJS_VERSION }}.x {{ ansible_distribution_release }} main"    state: present    update_cache: yes- name: Install Node.js  apt:    name: nodejs    state: present

    Guarde y salga del archivo cuando haya terminado.

    En roles/nodejs/tasks/main.yml, primero se define una tarea que actualizará el repositorio de caché de su Droplet. Luego, con la siguiente tarea, se agrega la clave GPG para Node.js que sirve como medio para verificar la autenticidad del aptrepositorio de Node.js. Las dos tareas finales agregan el repositorio de Node.js apte instalan Node.js.

    Ahora definirá sus configuraciones de Ansible, como las variables, el orden en el que desea que se ejecuten sus roles y la configuración de privilegios de superusuario. Para ello, creará un archivo llamado playbook.yml, que sirve como punto de entrada para Kitchen. Cuando ejecuta sus pruebas, Kitchen comienza desde su playbook.ymlarchivo y busca los roles que se ejecutarán, que son sus archivos roles/nginx/tasks/main.ymly .roles/nodejs/tasks/main.yml

    Ejecute el siguiente comando para crear playbook.yml:

    1. nano playbook.yml

    Añade el siguiente contenido al archivo:

    directorio_de_pruebas_ansible/playbook.yml

    --- - hosts: all   become: true   remote_user: ubuntu   vars:    NODEJS_VERSION: 8

    Guardar y salir del archivo.

    Ha creado los roles del libro de estrategias de Ansible contra los cuales ejecutará sus pruebas para garantizar que se cumplan las condiciones especificadas en el libro de estrategias.

    Paso 3: Cómo escribir las pruebas InSpec

    En este paso, escribirá pruebas para verificar si Node.js está instalado en su Droplet. Antes de escribir su prueba, veamos el formato de una prueba InSpec de ejemplo. Al igual que con muchos marcos de prueba, el código InSpec se parece a un lenguaje natural. InSpec tiene dos componentes principales, el sujeto a examinar y el estado esperado del sujeto:

    Bloque A

    describe 'entity' do  it { expectation }end

    En el bloque A, las palabras clave doy enddefinen un conjunto de pruebas, que contienen casos de prueba. La blockpalabra clave se utiliza para definir los casos de prueba.describeit

    entityes el objeto que desea examinar, por ejemplo, un nombre de paquete, servicio, archivo o puerto de red. expectationEspecifica el resultado deseado o el estado esperado, por ejemplo, Nginx debe estar instalado o debe tener una versión específica. Puede consultar la documentación de InSpec DSL para obtener más información sobre el lenguaje InSpec.

    Otro ejemplo de bloque de prueba InSpec:

    Bloque B

    control 'Can be anything unique' do    impact 0.7                           title 'A human-readable title'       desc  'An optional description'  describe 'entity' do                 it { expectation }  endend

    La diferencia entre el bloque A y el bloque B es el controlbloque. El controlbloque se utiliza como medio de control, recomendación o requisito regulatorio. El controlbloque tiene un nombre, generalmente un identificador único, metadatos como desc, title, impacty finalmente agrupa describebloques relacionados para implementar las verificaciones.

    desc, title, y define impactmetadatos que describen completamente la importancia del control, su propósito, con una descripción sucinta y completa. impactdefine un valor numérico que va desde 0.0hasta 1.0donde se clasifica como sin impacto, se clasifica como de bajo impacto, se clasifica como de impacto medio, se clasifica como de alto impacto, se clasifica como control crítico.0.00.010.010.40.40.70.70.90.91.0

    Ahora, para implementar una prueba, utilizará la sintaxis del bloque A y utilizará packageel recurso de InSpec para probar si Node.jsestá instalado en el sistema. Creará un archivo con el nombre sample.rben su test/integration/defaultdirectorio para sus pruebas.

    Crear sample.rb:

    1. nano test/integration/default/sample.rb

    Añade lo siguiente a tu archivo:

    prueba/integración/predeterminado/muestra.rb

    describe package('nodejs') do  it { should be_installed }end

    Aquí su prueba utiliza el packagerecurso para verificar que Node.js esté instalado.

    Guarde y salga del archivo cuando haya terminado.

    Para ejecutar esta prueba, debe editar kitchen.ymlpara especificar el libro de estrategias que creó anteriormente y agregarlo a sus configuraciones.

    Abra su kitchen.ymlarchivo:

    1. nano ansible_testing_dir/kitchen.yml

    Reemplace el contenido de kitchen.ymlpor lo siguiente:

    directorio_de_pruebas_ansible/kitchen.yml

    ---driver:  name: digitaloceanprovisioner:  name: ansible_playbook  hosts: test-kitchen  playbook: ./playbook.ymlverifier:  name: inspecplatforms:  - name: ubuntu-18    driver_config:      ssh_key: PATH_TO_YOUR_PRIVATE_SSH_KEY      tags:        - inspec-testing      region: fra1      size: 1gb      private_networking: false    verifier:      inspec_tests:        - test/integration/defaultsuites:  - name: default

    Las platformopciones incluyen lo siguiente:

    • name:La imagen que estás usando.

    • driver_config: Su configuración de Droplet de DigitalOcean. Está especificando las siguientes opciones para driver_config:

      • ssh_key: Ruta a YOUR_PRIVATE_SSH_KEY. Su YOUR_PRIVATE_SSH_KEYse encuentra en el directorio que especificó al crear su sshclave.
      • tags:Las etiquetas asociadas a tu Droplet.
      • region:El regionlugar donde quieres que se aloje tu Droplet.
      • size:La memoria que quieres que tenga tu Droplet.
    • verifier:Esto define que el proyecto contiene pruebas InSpec.

      • La inspec_testsparte especifica que las pruebas existen en el test/integration/defaultdirectorio del proyecto.

    Tenga en cuenta que namey regionutilizan abreviaturas. Puede consultar la test-kitchendocumentación para saber qué abreviaturas puede utilizar.

    Una vez que haya agregado su configuración, guarde y salga del archivo.

    Ejecute el kitchen testcomando para ejecutar la prueba. Esto comprobará si Node.js está instalado. Esto fallará intencionalmente porque actualmente no tiene la función Node.js en su playbook.ymlarchivo:

    1. kitchen test

    Verá un resultado similar al siguiente:

    Output: failing test results----- Starting Kitchen (v1.24.0)----- Cleaning up any prior instances of default-ubuntu-18----- Destroying default-ubuntu-18...       DigitalOcean instance 145268853 destroyed.       Finished destroying default-ubuntu-18 (0m2.63s).----- Testing default-ubuntu-18----- Creating default-ubuntu-18...       DigitalOcean instance 145273424 created.       Waiting for SSH service on 138.68.97.146:22, retrying in 3 seconds       [SSH] Established       (ssh ready)       Finished creating default-ubuntu-18 (0m51.74s).----- Converging default-ubuntu-18...$$$$$$ Running legacy converge for 'Digitalocean' Driver----- Installing Chef Omnibus to install busser to run tests       PLAY [all] *********************************************************************       TASK [Gathering Facts] *********************************************************       ok: [localhost]       PLAY RECAP *********************************************************************       localhost                  : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0       Downloading files from default-ubuntu-18       Finished converging default-ubuntu-18 (0m55.05s).----- Setting up default-ubuntu-18...$$$$$$ Running legacy setup for 'Digitalocean' Driver       Finished setting up default-ubuntu-18 (0m0.00s).----- Verifying default-ubuntu-18...       Loaded tests from {:path=". ansible_testing_dir.test.integration.default"}Profile: tests from {:path="ansible_testing_dir/test/integration/default"} (tests from {:path="ansible_testing_dir.test.integration.default"})Version: (not specified)Target:  ssh://root@138.68.97.146:22  System Package nodejs     ×  should be installed      expected that System Package nodejs is installedTest Summary: 0 successful, 1 failure, 0 skipped ------Exception------- Class: Kitchen::ActionFailed Message: 1 actions failed.     Verify failed on instance default-ubuntu-18.  Please see .kitchen/logs/default-ubuntu-18.log for more details ---------------------- Please see .kitchen/logs/kitchen.log for more details Also try running `kitchen diagnose --all` for configuration  4.54s user 1.77s system 5% cpu 2:02.33 total

    El resultado indica que la prueba falla porque no tienes Node.js instalado en el Droplet que aprovisionaste kitchen. Solucionarás la prueba agregando el nodejsrol a tu playbook.ymlarchivo y ejecutando la prueba nuevamente.

    Edite el playbook.ymlarchivo para incluir el nodejsrol:

    1. nano playbook.yml

    Agregue las siguientes líneas resaltadas a su archivo:

    directorio_de_pruebas_ansible/playbook.yml

    --- - hosts: all   become: true   remote_user: ubuntu   vars:    NODEJS_VERSION: 8   roles:    - nodejs

    Guarde y cierre el archivo.

    Ahora, volverá a ejecutar la prueba usando el kitchen testcomando:

    1. kitchen test

    Verás el siguiente resultado:

    Output......Target:  ssh://root@46.101.248.71:22  System Package nodejs     ✔  should be installedTest Summary: 1 successful, 0 failures, 0 skipped       Finished verifying default-ubuntu-18 (0m4.89s).----- Destroying default-ubuntu-18...       DigitalOcean instance 145512952 destroyed.       Finished destroying default-ubuntu-18 (0m2.23s).       Finished testing default-ubuntu-18 (2m49.78s).----- Kitchen is finished. (2m55.14s)  4.86s user 1.77s system 3% cpu 2:56.58 total

    Tu prueba ahora pasa porque tienes Node.js instalado usando el nodejsrol.

    A continuación se muestra un resumen de lo que está haciendo Kitchen en Test Action:

    • Destruye la gota si existe
    • Crea la gota
    • Converge la gota
    • Verifica la gota con InSpec
    • Destruye la gota

    Kitchen abortará la ejecución de su Droplet si encuentra algún problema. Esto significa que si su manual de Ansible falla, InSpec no se ejecutará y su Droplet no se destruirá. Esto le da la oportunidad de inspeccionar el estado de la instancia y solucionar cualquier problema. El comportamiento de la acción de destrucción final se puede anular si lo desea. Consulte la ayuda de CLI para obtener el --destroyindicador ejecutando el kitchen help testcomando.

    Ha escrito sus primeras pruebas y las ha ejecutado en relación con su libro de estrategias, pero una instancia falló antes de solucionar el problema. A continuación, ampliará su archivo de prueba.

    Paso 4: Agregar casos de prueba

    En este paso, agregará más casos de prueba a su archivo de prueba para verificar si los módulos Nginx están instalados en su Droplet y si el archivo de configuración tiene los permisos correctos.

    Edite su sample.rbarchivo para agregar más casos de prueba:

    1. nano test/integration/default/sample.rb

    Agregue los siguientes casos de prueba al final del archivo:

    prueba/integración/predeterminado/muestra.rb

    . . .control 'nginx-modules' do  impact 1.0  title 'NGINX modules'  desc 'The required NGINX modules should be installed.'  describe nginx do    its('modules') { should include 'http_ssl' }    its('modules') { should include 'stream_ssl' }    its('modules') { should include 'mail_ssl' }  endendcontrol 'nginx-conf' do  impact 1.0  title 'NGINX configuration'  desc 'The NGINX config file should owned by root, be writable only by owner, and not writeable or and readable by others.'  describe file('/etc/nginx/nginx.conf') do    it { should be_owned_by 'root' }    it { should be_grouped_into 'root' }    it { should_not be_readable.by('others') }    it { should_not be_writable.by('others') }    it { should_not be_executable.by('others') }  endend

    Estos casos de prueba comprueban que nginx-modulesen su Droplet se incluyan http_ssl, stream_ssly mail_ssl. También se comprueban los /etc/nginx/nginx.confpermisos de archivo.

    Estás utilizando las palabras claves ity itspara definir tu prueba. La palabra clave itssolo se utiliza para acceder a las propiedades de los recursos. Por ejemplo, moduleses una propiedad de nginx.

    Guarde y salga del archivo una vez que haya agregado los casos de prueba.

    Ahora ejecute el kitchen testcomando para probar nuevamente:

    1. kitchen test

    Verás el siguiente resultado:

    Output...Target:  ssh://root@104.248.131.111:22  ↺  nginx-modules: NGINX modules     ↺  The `nginx` binary not found in the path provided.  ×  nginx-conf: NGINX configuration (2 failed)     ×  File /etc/nginx/nginx.conf should be owned by "root"     expected `File /etc/nginx/nginx.conf.owned_by?("root")` to return true, got false     ×  File /etc/nginx/nginx.conf should be grouped into "root"     expected `File /etc/nginx/nginx.conf.grouped_into?("root")` to return true, got false     ✔  File /etc/nginx/nginx.conf should not be readable by others     ✔  File /etc/nginx/nginx.conf should not be writable by others     ✔  File /etc/nginx/nginx.conf should not be executable by others  System Package nodejs     ✔  should be installedProfile Summary: 0 successful controls, 1 control failure, 1 control skippedTest Summary: 4 successful, 2 failures, 1 skipped

    Verás que algunas de las pruebas fallan. Para solucionarlas, agrega la nginxfunción a tu archivo de libro de estrategias y vuelve a ejecutar la prueba. En la prueba que falla, estás verificando nginxlos módulos y los permisos de archivos que actualmente no están presentes en tu servidor.

    Abra su playbook.ymlarchivo:

    1. nano ansible_testing_dir/playbook.yml

    Añade la siguiente línea resaltada a tus roles:

    directorio_de_pruebas_ansible/playbook.yml

    ---- hosts: all  become: true  remote_user: ubuntu  vars:  NODEJS_VERSION: 8  roles:  - nodejs  - nginx

    Guarde y cierre el archivo cuando haya terminado.

    Luego ejecuta tus pruebas nuevamente:

    1. kitchen test

    Verás el siguiente resultado:

    Output...Target:  ssh://root@104.248.131.111:22✔  nginx-modules: NGINX version     ✔  Nginx Environment modules should include "http_ssl"     ✔  Nginx Environment modules should include "stream_ssl"     ✔  Nginx Environment modules should include "mail_ssl"  ✔  nginx-conf: NGINX configuration     ✔  File /etc/nginx/nginx.conf should be owned by "root"     ✔  File /etc/nginx/nginx.conf should be grouped into "root"     ✔  File /etc/nginx/nginx.conf should not be readable by others     ✔  File /etc/nginx/nginx.conf should not be writable by others     ✔  File /etc/nginx/nginx.conf should not be executable by others  System Package nodejs     ✔  should be installedProfile Summary: 2 successful controls, 0 control failures, 0 controls skippedTest Summary: 9 successful, 0 failures, 0 skipped

    Después de agregar el nginxrol al libro de estrategias, todas las pruebas pasan. El resultado muestra que los módulos http_ssl, stream_ssly mail_sslestán instalados en su Droplet y que se establecieron los permisos correctos para el archivo de configuración.

    Una vez que hayas terminado, o ya no necesites tu Droplet, puedes destruirlo ejecutando el kitchen destroycomando para eliminarlo después de ejecutar tus pruebas:

    1. kitchen destroy

    Si sigue este comando verá un resultado similar al siguiente:

    Output----- Starting Kitchen (v1.24.0)----- Destroying default-ubuntu-18...       Finished destroying default-ubuntu-18 (0m0.00s).----- Kitchen is finished. (0m5.07s)  3.79s user 1.50s system 82% cpu 6.432 total

    Ha escrito pruebas para su playbook, las ha ejecutado y ha corregido las pruebas que fallaron para garantizar que todas las pruebas funcionen correctamente. Ahora está preparado para crear un entorno virtual, escribir pruebas para su playbook de Ansible y ejecutar la prueba en el entorno virtual con Kitchen.

    Conclusión

    Ahora tienes una base flexible para probar tu implementación de Ansible, lo que te permite probar tus playbooks antes de ejecutarlos en un servidor activo. También puedes empaquetar tu prueba en un perfil. Puedes usar perfiles para compartir tu prueba a través de Github o Chef Supermarket y ejecutarla fácilmente en un servidor activo.

    Para obtener detalles más completos sobre InSpec y Kitchen, consulte la documentación oficial de InSpec y la documentación oficial de Kitchen.

    SUSCRÍBETE A NUESTRO BOLETÍN 
    No te pierdas de nuestro contenido ni de ninguna de nuestras guías para que puedas avanzar en los juegos que más te gustan.

    Deja una respuesta

    Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

    Subir

    Este sitio web utiliza cookies para mejorar tu experiencia mientras navegas por él. Este sitio web utiliza cookies para mejorar tu experiencia de usuario. Al continuar navegando, aceptas su uso. Mas informacion