morgangraphics.ansible-role-nvm

Rol de Ansible: NVM

Instala NVM y Node.js en sistemas Debian/Ubuntu, RHEL/CentOS y otros sistemas *nix.

La peculiaridad de Ansible con SSH y los shells (no) interactivos hace que trabajar con NVM y Ansible sea un poco problemático. Esta publicación de stack overflow explica algunas de las soluciones que otras personas han encontrado para sortear este problema en particular.

Dónde otros roles son insuficientes

Otros roles de Ansible que instalan NVM y/o Node.js fallan en varias áreas.

  1. Usan los gestores de paquetes apt-get o yum para instalar Node.js. Esto a menudo significa que el paquete de Node.js es más viejo que lo que está actualmente disponible en el repositorio de Node.js. En algunos casos, esos paquetes pueden no ser una versión LTS y si necesitas múltiples versiones de Node.js funcionando en el mismo host, no tendrás suerte.

  2. A menudo instalan NVM y Node.js como usuario root (sudo su o become: true). Esto puede añadir complicaciones con los permisos relacionados con la gestión de plugins de NPM, así como con el funcionamiento de Node junto con NVM, además de ser un riesgo de escalada de privilegios innecesario.

  3. No puedes ejecutar comandos ad hoc de nvm, npm, node, bash o shell.

Dónde este rol difiere de otros roles

  1. Puedes instalar NVM mediante wget, curl o git.
  2. Puedes usar NVM como lo harías en tu línea de comandos en tus propias tareas y playbooks de Ansible.
  3. Puedes instalar cualquier versión o versiones de Node.js que desees.
  4. No instala NVM ni Node.js como root.
  5. Puede ejecutar comandos arbitrarios de nvm, npm, node, bash o shell, eliminando potencialmente la necesidad de un rol Ansible de Node separado.

Requisitos

Versión de Ansible (ansible-core) 2.16.0 o superior.

:triangular_flag_on_post: Para una versión de este rol que funcione en versiones más antiguas de Ansible, consulta la rama 1.5.X legacy.

Consulta Versiones de Ansible abajo.

Instalación

  1. Clona este repositorio en tu carpeta de roles.
  2. Apunta la variable roles_path a la carpeta de roles, por ejemplo, roles_path = ../ansible-roles/ en tu archivo ansible.cfg.
  3. Incluye el rol en tu playbook.

:warning: ¡ADVERTENCIA!

¡NO EJECUTES ESTE ROL COMO ROOT! (por ejemplo, become: true|yes|1).

Hay varias razones para esto:

  1. Es un riesgo de escalada de privilegios innecesario. Es muy poco probable que necesites ejecutar todas las tareas en todos los roles como root_user. Si, por cualquier razón, necesitas hacer todo como root_user, reconsidera lo que hace el rol y por qué necesita acceso root para todo.

  2. Este rol instala NVM en el mismo contexto/shell/sesión que ejecutarías Node.js. No se ejecuta Node.js como root.

  3. Ansible cambiará el contexto del shell de inicio a root y NVM se instalará en el directorio home de root_user, por ejemplo /root/.bashrc. Esto significa que si tu usuario principal es vagrant, ec2-user, ubuntu, etc., el rol NO FUNCIONARÁ COMO SE ESPERA.

MAL :thumbsdown:

- hosts: all
  become: true           # ESTO EJECUTA TODAS LAS TAREAS, PARA TODOS LOS HOSTS, COMO ROOT_USER
  become_method: sudo    # ESTO EJECUTA TODAS LAS TAREAS, PARA TODOS LOS HOSTS, COMO ROOT_USER

  roles:
    - role: ansible-role-nvm
      nodejs_version: "8.16.0"
      nvm_commands:
       - "nvm exec default npm install"

    - role: some-other-role
      ...

MEJOR :thumbsup:

- hosts: all

  roles:
    - role: ansible-role-nvm
      nodejs_version: "8.16.0"
      nvm_commands:
       - "nvm exec default npm install"

    - role: some-other-role
      ...
      become: true            # ESTO ALCANZA TODAS LAS TAREAS, SOLO PARA EL SOME-OTHER-ROLE, COMO ROOT_USER
      become_method: sudo     # ESTO ALCANZA TODAS LAS TAREAS, SOLO PARA EL SOME-OTHER-ROLE, COMO ROOT_USER

MEJOR :metal:

- hosts: all

  roles:
    - role: ansible-role-nvm
      nodejs_version: "8.16.0"
      nvm_commands:
       - "nvm exec default npm install"
      become: true            # ESTO CAMBIA EL CONTEXTO DE INICIO PARA USAR EL USUARIO DE ABAJO
      become_user: ec2-user   # ESTO INSTALA NVM EN EL CONTEXTO DEL EC2-USER/USUARIO POR DEFECTO. ¡ESTE USUARIO DEBE EXISTIR EN EL SISTEMA!

    - role: some-other-role
      ...
      become: true            # ESTO ALCANZA TODAS LAS TAREAS, SOLO PARA EL SOME-OTHER-ROLE, COMO ROOT_USER
      become_method: sudo     # ESTO ALCANZA TODAS LAS TAREAS, SOLO PARA EL SOME-OTHER-ROLE, COMO ROOT_USER

Consulta Problemas abajo para más detalles.

Ejemplos de Playbooks

Super Simple

Incluye el rol tal como está y se instalará la última versión LTS de Node.js.

- hosts: all

  roles:
    - role: ansible-role-nvm

Simple

Incluye el rol y especifica la versión específica de Node.js que deseas instalar.

- hosts: all

  roles:
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"

Más Complejado

Este ejemplo muestra cómo podrías configurar múltiples entornos (Dev/Prod) con diferentes opciones. La configuración de Prod aprovecha la opción de nvm_commands para instalar, compilar y ejecutar la aplicación. El rol soporta y aprovecha la sintaxis de variables de Ansible, por ejemplo, {{ variable_name }}.

- hosts: dev

  vars_files:
    - vars/dev.yml

  roles:
    - role: ansible-role-nvm
      nodejs_version: "{{ config.dev.nodejs.version }}"

- hosts: prod
  vars_files:
    - vars/prod.yml

  roles:
    - role: ansible-role-nvm
      nvm_install: "curl"
      nvm_dir: "/usr/local/nvm"
      nvm_commands:
       - "nvm install {{ config.prod.client-1.nodejs.version }}"
       - "nvm alias default {{ config.prod.client-1.nodejs.version }}"
       - "nvm exec default npm install"
       - "nvm exec default npm run prod"

Instalación/Ejecución/Mantenimiento o Actualización de múltiples versiones de Node.js en el mismo host

Por defecto, la primera versión de Node.js que se instancie en tu Playbook se aliased automáticamente como la versión "predeterminada", sin importar qué versión instales después o cuántas veces ejecutes el rol. Es importante declarar cuál versión se espera que sea la "versión predeterminada" si estás instalando múltiples versiones de Node.js en una sola máquina.

Hay dos alias preexistentes de NVM: default (versión "activa" actual de Node.js) y system (la versión base de Node.js del SO).

El alias es una característica muy poderosa de NVM y es una mejor práctica recomendada para gestionar tu entorno.

Instalación Múltiple

- hosts: host-1

  roles:
    # Servicios
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"    # <= Esta será la versión "predeterminada" de Node.js.

    # Aplicación
    - role: ansible-role-nvm
      nodejs_version: "10.15.0"

Instalación Múltiple con predeterminada

- hosts: host-2

  roles:
    # Servicios
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"    

    # Aplicación
    - role: ansible-role-nvm
      default: true
      nodejs_version: "10.15.0" # <= Esta ahora es la "versión predeterminada" de Node.js.

Notas sobre comandos NVM

Los comandos NVM son una característica muy poderosa de este rol que aprovecha el trabajo que NVM ha establecido. Aprovechar nvm_commands podría eliminar potencialmente la necesidad de un rol específico de Node para gestionar tus aplicaciones Node en absoluto.

Hay una diferencia entre los comandos nvm run y nvm exec. nvm run es funcionalmente equivalente a node server.js o node server, donde estás invocando un archivo JavaScript.

nvm exec se ejecuta en un contexto de subproceso y es funcionalmente equivalente a npm run server, donde server es un nombre clave en la sección de scripts en el archivo package.json.

{
  "name": "my_application",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "preserver": "npm run dbService &",
    "server": "nodemon ./bin/www",
    "build": "node build/build.js",
    "dbService": "nodemon ./data-service/server.js --ignore node_modules/"
  },
  "dependencies": {
    "..."
  }
}

O

nvm exec puede ejecutar algún archivo de script arbitrario, por ejemplo nvm exec hello-world.py.

Por ejemplo, hello-world.py

#!/usr/bin/env python
print('hello-world')

:warning: Debes incluir un encabezado de script para que esto funcione correctamente.

O

ejecutar algún comando bash arbitrario.

ls -al >> output.txt

nvm_commands facilita mucho la configuración de una aplicación Node y una capa API de Node ejecutando diferentes versiones de Node.js en el mismo host.

- hosts: host-1
  roles:
    # Servicios
    # ¿QUÉ ESTÁ PASANDO?
    # 1. Ejecuta el archivo JavaScript de servicios con Node versión 8.15.0.
    # ¡ADVERTENCIA! Esta está aliasada como la versión predeterminada de Node.js en este punto.
    # Por lo tanto, debemos especificar explícitamente la versión que estamos utilizando porque
    # la versión predeterminada de Node.js cambia en la sección de Aplicación a continuación.
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"
      nvm_commands:
        - "nvm exec 8.15.0 npm run services"

    # Aplicación
    # ¿QUÉ ESTÁ PASANDO?
    # 1. Establece la versión predeterminada de Node.js a la versión 10.15.0.
    # 2. Instala las dependencias del paquete con npm.
    # 3. Establece el entorno a Producción, ejecuta el archivo JavaScript de construcción.
    # 4. Luego ejecuta el script de implantación en producción.
    - role: ansible-role-nvm
      nodejs_version: "10.15.0"
      nvm_commands:
       - "nvm alias webapp {{ nodejs_version }}" # <= Cambia la versión predeterminada de NVM (soporta la sintaxis de variable de Ansible).
       - "nvm exec webapp npm install" # instala dependencias de la aplicación.
       - "NODE_ENV=production nvm run webapp build" # invoca Node.js directamente para ejecutar el script de construcción en producción.
       - "nvm exec webapp npm run prod" # invoca npm para ejecutar el script de producción en tu archivo package.json.

Otro ejemplo

- hosts: host-2
  roles:
    # Servicios
    # ¿QUÉ ESTÁ PASANDO?
    # 1. Crea un alias para la versión 8.15.0 llamado service-default (soporta la sintaxis de variable de Ansible).
    # 2. Ejecuta el script de servicios.
    #
    # ** Se recomienda que aliasas tus versiones de Node.js y las referencias en consecuencia. **
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"
      nvm_commands:
        - "nvm alias service-default {{ nodejs_version }}" # <= (soporta la sintaxis de variable de Ansible).
        - "nvm exec service-default npm run services" # ejecuta el script de servicios en tu archivo package.json.

    # Aplicación - No se necesita un rol Ansible de Node separado.
    # ¿QUÉ ESTÁ PASANDO?
    # 1. Instala la versión 10.15.0 de Node.js.
    # 2. Establece la versión predeterminada de Node.js a la versión 10.15.0.
    # 3. Ejecuta el archivo test.js invocando Node.js directamente.
    # 4. Luego ejecuta el script de implantación de producción.
    - role: ansible-role-nvm
      nodejs_version: "10.15.0"
      nvm_commands:
       - "nvm alias default 10.15.0" # <= Cambia la versión predeterminada de NVM.
       - "nvm exec default node test.js" # invoca Node.js directamente para ejecutar el script de prueba.
       - "nvm exec ./deploy.sh" # ejecuta un script bash arbitrario.

Cualquier argumento de línea de comando que uses para iniciar tu aplicación, o scripts de comando que has declarado en tu archivo package.json pueden colocarse dentro de la sección nvm_commands: [] de este rol.

- hosts: host1

  pre_tasks:

    # test-user necesita ser un usuario real en el sistema antes de que podamos instalar nvm en su perfil.
    - name: agregar nuevo usuario
      user:
        name: "test-user"
      become: true

  roles:

    - role: ansible-role-nvm
      nodejs_version: "8.16.0"
      nvm_profile: "/home/test-user/.bashrc"
      nvm_commands:
        - "whoami"
        - "node --version"
        - "nvm --version"
        - "npm --version"
        - "python3 -m hello"
      become_user: test-user
      become: true

Advertencias

  1. Por defecto, la primera versión listada en tu Playbook, en la primera ejecución, será automáticamente aliasada como la "versión predeterminada" de Node.js, sin importar qué versión instales después o cuántas veces ejecutes el rol. El primero en entrar/instalar siempre es el predeterminado. Como resultado, si esperas que una versión de Node.js declarada más adelante en el playbook se establezca como predeterminada, usa default: true o configúralo explícitamente en la lista de nvm_commands, como - "nvm alias default <TU_VERSIÓN>".

  2. Si tienes default: true declarado explícitamente como una variable del rol Y - "nvm alias default <OTRA_VERSIÓN>" como parte de tus nvm_commands, la versión con default: true SIEMPRE se ejecutará primero. Esto se debe a que necesitamos que Node.js esté disponible antes de hacer cualquier otra cosa.

  3. NVM es sin estado, en el sentido de que si tienes múltiples versiones de Node.js instaladas en una máquina, es posible que tengas que ejecutar nvm use <VERSION> como parte de tu script para ejecutar la versión de Node.js que deseas/esperas. Sin embargo, se recomienda encarecidamente que asignes alias a tus versiones en consecuencia y las referencias de esa manera. Consulta los ejemplos anteriores.

Problemas

"nvm: comando no encontrado"

Esto es a menudo el resultado de ejecutar el rol en un contexto de usuario distinto al que nvm y node se ejecutarán dentro de la máquina. Si agregas become: true a todos los roles en tu playbook para evitar errores que esos roles arrojan debido a problemas de permisos, entonces este rol instalará nvm bajo el ROOT_USER (generalmente /root/.bashrc). Lo más probable es que desees ejecutar nvm y node como un usuario predeterminado, por ejemplo, vagrant, ec2-user, ubuntu, etc. Si, por cualquier razón, no puedes eliminar el become: true para todo, puedes sortear el problema de become: true especificando become: true Y become_user: ec2-user para este rol en particular. Consulta bash: comando nvm no encontrado para una explicación detallada del problema.

"no se puede encontrar /usr/bin/python"

Se debe a que algunos sistemas operativos que ejecutan Python 3 de forma predeterminada (por ejemplo, Fedora). Necesitarás especificar la variable del intérprete de python de Ansible en el archivo de inventario o a través de la línea de comando.

[fedora1]
192.168.0.1 ansible_python_interpreter=/usr/bin/python3

[fedora2]
192.168.0.2

[fedora2:vars]
ansible_python_interpreter=/usr/bin/python3

o

ansible-playbook my-playbook.yml -e "ansible_python_interpreter=/usr/bin/python3"

glibc_2.28' no encontrado (requerido por node)

Estás intentando ejecutar una versión de Node.js en un sistema operativo que no es compatible con la versión de Node.js que estás instalando. Esto no es un problema de NVM ni con el rol. Debes actualizar el SO o reducir la versión de Node.js que estás intentando instalar.


Soporte de Versiones de Ansible

ansible-core 2.16 +

Ha habido un cambio fundamental en cómo Ansible gestiona las inclusiones/importaciones. Ansible ha eliminado ansible.builtin.include de ansible-core y lo ha reemplazado con ansible.builtin.include_tasks. Desafortunadamente, Ansible no puede limitar ansible.builtin.include para ignorar versiones más antiguas, etc., por lo que actualicé este rol para soportar completamente ansible-core 2.16 +.

Si requieres soporte para ansible-core 2.15 o inferior, por favor usa la rama legacy 1.5.X.

ansible-core 2.15 y versiones anteriores

Por favor utiliza la rama 1.5.X legacy.

Variables del Rol

Las variables disponibles se enumeran a continuación, junto con sus valores por defecto. Consulta defaults/main.yml.

La versión de Node.js a instalar. La última versión "lts" es la predeterminada y funciona en la mayoría de los sistemas operativos soportados.

nodejs_version: "lts"

Método conveniente para instalar autocompletado bash de NVM (nvm <TAB>) cuando un usuario tiene que mantener un servidor o estación de trabajo manualmente.

autocomplete: false

Instala NVM desde cero, eliminando CUALQUIER y TODAS las referencias existentes o anteriores a .nvm (directorios) y CUALQUIER y TODAS las referencias existentes o anteriores en entradas de perfil, por ejemplo, .bashrc en el sistema.

clean_install: false

clean_install: true busca todas las referencias en /home, /root, /etc, y directorios de instalación personalizados así como cualquier carpeta .nvm en el sistema. Esto equivale a una configuración de nueva máquina, ÚSALO CON PRECAUCIÓN.

default: false

Establece la versión predeterminada de Node al mantener/instalar múltiples versiones de Node.

NVM hará alias automáticamente la primera versión instalada como "predeterminada", lo que es más que probable que sea lo que las personas usarán este rol.

Lista de comandos NVM para ejecutar. Por defecto, es una lista vacía.

nvm_commands: []

Tipo de instalación de NVM. Las opciones son wget, curl y git.

nvm_install: "wget"

Directorio de instalación de NVM.

nvm_dir: ""

NVM instalará, por defecto, el directorio .nvm en el home del usuario, por ejemplo, /home/vagrant/.nvm. Puedes sobreescribir el directorio de instalación cambiando esta variable, por ejemplo, /opt/nvm para ponerlo en un espacio global (no ligado a una cuenta de usuario específica) si lo deseas. Esta variable respetará las variables de sustitución de Ansible, por ejemplo, {{ansible_env.HOME}}.

Ubicación del perfil de NVM. Las opciones son .bashrc, .cshrc, .tcshrc, .zshrc.

nvm_profile: ".bashrc"

La ubicación del archivo de perfil del SHELL de inicio que cargará el comando nvm. Hay dos contextos potenciales a considerar:

Globalmente, lo que significa que todos los que inicien sesión tendrán acceso a nvm (lo cual puede o no ser lo que realmente deseas).

por ejemplo, /etc/bash.bashrc, /etc/profile, etc.

O

A nivel de usuario, ligado a una cuenta de usuario específica.

por ejemplo, /home/vagrant/.bashrc.*

Este rol creará el archivo de perfil apropiado si no existe.

Si especificas explícitamente nvm_profile: "/home/node-user/.bashrc" y el usuario node-user no es un usuario real en la máquina, entonces nvm no funcionará como esperas. Las rutas de become, become_user y nvm_profile son simbióticas.

:warning: TEN EN CUENTA LAS LIMITACIONES DE DECLARAR EXPLÍCITAMENTE ARCHIVOS .profile O .bash_profile EN SISTEMAS UBUNTU.

https://askubuntu.com/a/969923 Explica en detalle

https://kb.iu.edu/d/abdy Muestra opciones para cada tipo de shell.

Las ubicaciones de los perfiles de NVM son:

BASH: .bashrc

CSH: /etc/csh.cshrc, .cshrc

TSH: /etc/csh.cshrc, .tcshrc, .cshrc

ZSH: .zshrc

Ubicación de la fuente de NVM, es decir, si hosteas tu propia bifurcación de NVM.

nvm_source: ""

Versión de NVM a instalar.

nvm_version: "0.39.7"

Desinstalar NVM, eliminará el directorio .nvm y limpiará el archivo ubicado en la ruta de la variable {{ nvm_profile }} (generalmente $HOME/.bashrc) donde quiera que ese archivo esté.

uninstall: False

Dependencias

Ninguna.

Registro de Cambios


2.0.0 Consulta las NOTAS DE LANZAMIENTO.

Licencia

MIT / BSD.

Información del Autor

dm00000 a través de MORGANGRAPHICS, INC.

Este rol se basa en gran medida en el rol de Node.js de Jeff Geerling, autor de Ansible for DevOps.

Instalar
ansible-galaxy install morgangraphics.ansible-role-nvm
Licencia
mit
Descargas
476
Propietario