ansible_role_nvm

Ansible Роль: NVM

Устанавливает NVM и Node.js на систему Debian/Ubuntu, RHEL/CentOS и другие *nix системы.

Некоторые странности Ansible с SSH и (не)интерактивными оболочками делают работу с NVM и Ansible несколько проблематичной. Этот пост на Stack Overflow объясняет, что делали другие, чтобы решить эту проблему.

Где другие роли не справляются

Другие роли Ansible, которые устанавливают NVM и/или Node.js, имеют несколько недостатков.

  1. Они используют менеджеры пакетов apt-get или yum для установки Node.js. Это часто означает, что пакет Node.js старее, чем тот, который сейчас доступен в репозитории Node.js. В некоторых случаях эти пакеты могут не быть LTS-версией, и если вам нужно запустить несколько версий Node.js на одном хосте, вы окажетесь в затруднительном положении.

  2. Часто они устанавливают NVM и Node.js от имени пользователя root (sudo su или become: true). Это может усложнить управление разрешениями, связанными с управлением плагинами NPM, а также тем, как Node работает с nvm, кроме того, это создает ненужный риск повышения привилегий.

  3. Вы не можете запускать команды nvm, npm, node, bash или shell на лету.

Как эта роль отличается от других ролей

  1. Вы можете установить NVM через wget, curl или git.
  2. Вы можете использовать NVM так же, как через вашу командную строку в ваших собственных задачах и плейбуках Ansible.
  3. Вы можете установить любую версию или версии Node.js, которые хотите.
  4. Не устанавливает NVM или Node.js от имени root.
  5. Можно выполнять произвольные команды nvm, npm, node, bash или shell, потенциально устраняя необходимость в отдельной роли Ansible для Node.

Требования

Версия Ansible (ansible-core) 2.16.0 и выше.

:triangular_flag_on_post: Для версии этой роли, которая работает на более старых версиях Ansible, смотрите наследственную ветку 1.5.X.

Смотрите версии Ansible ниже.

Установка

  1. Клонируйте этот репозиторий в вашу папку ролей.
  2. Укажите переменную roles_path на папку ролей, т.е. roles_path = ../ansible-roles/ в вашем файле ansible.cfg.
  3. Включите роль в ваш плейбук.

:warning: ПРЕДУПРЕЖДЕНИЕ!

НЕ ЗАПУСКАЙТЕ ЭТУ РОЛЬ ОТ ИМЕНИ ROOT! (например, become: true|yes|1)

Есть несколько причин для этого:

  1. Это ненужный риск повышения привилегий, весьма маловероятно, что вам нужно выполнять каждую задачу в каждой роли от имени root_user. Если вам необходимо выполнить все от root_user, переосмыслите, что делает эта роль и почему она требует доступа root.
  2. Эта роль устанавливает nvm в том же контексте/оболочке/сессии, в которой вы запускаете NodeJS. Вы не запускаете NodeJS как root.
  3. Ansible изменит контекст входной оболочки на root, и nvm будет установлен в домашнем каталоге root_user, например /root/.bashrc. Это означает, что если ваш основной пользователь - vagrant, ec2-user, ubuntu и т.д., роль НЕ СРАБОТАЕТ КАК ОЖИДАЕТСЯ!

ПЛОХО :thumbsdown:

- hosts: all
  become: true           # ЭТО ЗАПУСКАЕТ ВСЕ ЗАДАЧИ ДЛЯ ВСЕХ ХОСТОВ ОТ ИМЕНИ ROOT_USER
  become_method: sudo    # ЭТО ЗАПУСКАЕТ ВСЕ ЗАДАЧИ ДЛЯ ВСЕХ ХОСТОВ ОТ ИМЕНИ ROOT_USER

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

    - role: some-other-role
      ...

ЛУЧШЕ :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            # ЭТО ЗАЕЛЯЕТ ВСЕ ЗАДАЧИ, ТОЛЬКО ДЛЯ SOME-OTHER-ROLE, ОТ ИМЕНИ ROOT_USER
      become_method: sudo     # ЭТО ЗАЕЛЯЕТ ВСЕ ЗАДАЧИ, ТОЛЬКО ДЛЯ SOME-OTHER-ROLE, ОТ ИМЕНИ ROOT_USER

НАИЛУЧШЕ :metal:

- hosts: all

  roles:
    - role: ansible-role-nvm
      nodejs_version: "8.16.0"
      nvm_commands:
       - "nvm exec default npm install"
      become: true            # ЭТО ИЗМЕНЯЕТ КОНТЕКСТ ВХОДА ДЛЯ ИСПОЛЬЗОВАНИЯ ПОЛЬЗОВАТЕЛЯ НИЖЕ
      become_user: ec2-user   # ЭТО УСТАНАВЛИВАЕТ NVM В КОНТЕКСТЕ EC2-USER/ДЕФОЛЬТНОГО ПОЛЬЗОВАТЕЛЯ. ЭТОТ ПОЛЬЗОВАТЕЛЬ ДОЛЖЕН СУЩЕСТВОВАТЬ В СИСТЕМЕ!

    - role: some-other-role
      ...
      become: true            # ЭТО ЗАЕЛЯЕТ ВСЕ ЗАДАЧИ, ТОЛЬКО ДЛЯ SOME-OTHER-ROLE, ОТ ИМЕНИ ROOT_USER
      become_method: sudo     # ЭТО ЗАЕЛЯЕТ ВСЕ ЗАДАЧИ, ТОЛЬКО ДЛЯ SOME-OTHER-ROLE, ОТ ИМЕНИ ROOT_USER

Смотрите Проблемы ниже для получения дополнительных деталей.

Примеры плейбуков

Супер простой

Включите роль как есть, и она установит последнюю LTS версию Node.js.

- hosts: all

  roles:
    - role: ansible-role-nvm

Простой

Включите роль и укажите конкретную версию Node.js, которую хотите установить.

- hosts: all

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

Более сложный

Этот пример показывает, как можно настроить несколько сред (Dev/Prod) с разными параметрами. Настройка Prod использует параметр nvm_commands, чтобы установить, собрать и запустить приложение. Роль поддерживает и использует синтаксис переменных Ansible, например {{ 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"

Установка/Запуск/Поддержка или Обновление нескольких версий Node.js на одном хосте

По умолчанию, первая версия Node.js, указанная в вашем плейбуке, будет автоматически обозначена как "дефолтная" версия, независимо от того, какую версию вы установите позже или сколько раз вы запустите роль. Важно определить, какая версия ожидается как "дефолтная", если вы устанавливаете несколько версий Node.js на одном устройстве.

Существуют два предустановленных псевдонима NVM: default (текущая "активная" версия Node.js) и system (базовая версия Node.js для ОС).

Псевдонимизация - это очень мощная функция NVM, и это рекомендуемая лучшая практика для управления вашей средой.

Множественная установка

- hosts: host-1

  roles:
    # Сервисы
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"    # <= Это будет "дефолтная" версия Node.js

    # Приложение
    - role: ansible-role-nvm
      nodejs_version: "10.15.0"

Множественная установка с дефолтом

- hosts: host-2

  roles:
    # Сервисы
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"    

    # Приложение
    - role: ansible-role-nvm
      default: true
      nodejs_version: "10.15.0" # <= Это теперь "дефолтная" версия Node.js

Заметки о командах NVM

Команды NVM - это очень мощная функция этой роли, которая использует базовую работу, установленную NVM. Использование nvm_commands может потенциально устранить необходимость в конкретной роли Node для управления вашими приложениями Node вовсе.

Существует разница между командами nvm run и nvm exec. nvm run функционально эквивалентна node server.js или node server, где вы вызываете JavaScript-файл.

nvm exec выполняется в контексте подпроцесса и функционально эквивалентна npm run server, где server - это ключевое название в разделе скриптов файла 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": {
    "..."
  }
}

ИЛИ

nvm exec может выполнять какой-либо произвольный скрипт, например nvm exec hello-world.py.

например, hello-world.py

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

:warning: Вы должны включить заголовок скрипта, чтобы это работало правильно.

ИЛИ

выполнить какую-либо произвольную команду bash

ls -al >> output.txt

nvm_commands упрощает настройку приложений Node и уровня API Node, работающих на разных версиях Node.js на одном хосте.

- hosts: host-1
  roles:
    # Сервисы
    # ЧТО ПРОИСХОДИТ?
    # 1. Запустите файл JavaScript сервисов с версией Node 8.15.0
    # ПРЕДУПРЕЖДЕНИЕ: Эта версия назначена как дефолтная версия Node.js на данный момент!!
    # Поэтому нам нужно явно указать версию, которую мы используем, поскольку
    # дефолтная версия Node.js изменяется в разделе "Приложение" ниже.
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"
      nvm_commands:
        - "nvm exec 8.15.0 npm run services"

    # Приложение
    # ЧТО ПРОИСХОДИТ?
    # 1. Установите дефолтную версию Node.js на версию 10.15.0
    # 2. Установите зависимости пакетов с помощью npm
    # 3. Установите окружение в Production, запустите сценарий JavaScript для сборки
    # 4. Затем запустите сценарий развертывания для производства
    - role: ansible-role-nvm
      nodejs_version: "10.15.0"
      nvm_commands:
       - "nvm alias webapp {{ nodejs_version }}" # <= Изменяет дефолтную версию NVM (поддерживает синтаксис переменных Ansible)
       - "nvm exec webapp npm install" # установите зависимости приложения
       - "NODE_ENV=production nvm run webapp build" # вызовите Node.js непосредственно, чтобы запустить сценарий сборки для производства
       - "nvm exec webapp npm run prod" # вызовите npm, чтобы запустить сценарий развертывания в вашем файле package.json

Другой пример

- hosts: host-2
  roles:
    # Сервисы
    # ЧТО ПРОИСХОДИТ?
    # 1. Создайте псевдоним для версии 8.15.0 с названием service-default (поддерживает синтаксис переменных Ansible)
    # 2. Запустите скрипт сервисов
    #
    # ** Рекомендуется, чтобы вы создали псевдонимы для своих версий Node.js и ссылались на них соответствующим образом **
    - role: ansible-role-nvm
      nodejs_version: "8.15.0"
      nvm_commands:
        - "nvm alias service-default {{ nodejs_version }}" # <= (поддерживает синтаксис переменных Ansible)
        - "nvm exec service-default npm run services" # запустите скрипт сервисов в вашем файле package.json

    # Приложение - Никакая отдельная роль Node.js для Ansible не нужна
    # ЧТО ПРОИСХОДИТ?
    # 1. Установите версию Node.js 10.15.0
    # 1. Установите дефолтную версию Node.js на версию 10.15.0
    # 2. Запустите файл test.js, непосредственно вызывая Node.js
    # 3. Затем запустите скрипт развертывания для производства
    - role: ansible-role-nvm
      nodejs_version: "10.15.0"
      nvm_commands:
       - "nvm alias default 10.15.0" # <= Изменяет дефолтную версию NVM
       - "nvm exec default node test.js" # вызовите Node.js непосредственно, чтобы запустить тестовый скрипт
       - "nvm exec ./deploy.sh" # запустите произвольный bash-скрипт

Любые аргументы командной строки, которые вы используете для запуска вашего приложения, или командные скрипты, которые вы объявили в вашем файле package.json, могут быть помещены в раздел nvm_commands: [] этой роли.

- hosts: host1

  pre_tasks:

    # test-user должен быть настоящим пользователем в системе, прежде чем мы сможем установить nvm в его профиле
    - name: add new user
      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

Предостережения

  1. По умолчанию первая версия, указанная в вашем плейбуке, при первом запуске будет автоматически назначена как "дефолтная" версия Node.js, независимо от того, какую версию вы установите позже или сколько раз вы запустите роль. Первая установленная версия всегда будет дефолтной. В результате, если вы ожидаете, что версия Node.js, объявленная позже в плейбуке, будет установлена как дефолтная, используйте default: true или явно укажите ее в списке nvm_commands, например - "nvm alias default <ВАША_ВЕРСИЯ>".

  2. Если у вас явно указана переменная роли default: true И - "nvm alias default <ДРУГАЯ_ВЕРСИЯ>" как часть ваших nvm_commands, версия с default: true будет ВСЕГДА выполняться первой. Это связано с тем, что Node.js должен быть доступен, прежде чем делать что-либо еще.

  3. NVM является статeless, а это значит, что если у вас установлено несколько версий Node.js на устройстве, вам может потребоваться запустить nvm use <VERSION> как часть вашего скрипта, чтобы запустить нужную версию Node.js. Тем не менее, настоятельно рекомендуется, чтобы вы создали псевдонимы для своих версий и ссылались на них таким образом. См. примеры выше.

Проблемы

"nvm: command not found" error

Это часто результат того, что роль запускается в другом контексте пользователя, чем nvm и node будут работать внутри машины. Если вы добавите become: true ко всем ролям в вашем плейбуке, чтобы обойти ошибки, которые эти роли вызывают из-за проблем с правами, то эта роль установит nvm под пользователем ROOT (обычно в /root/.bashrc). Скорее всего, вы захотите запускать nvm и node как обычные пользователи, например, vagrant, ec2-user, ubuntu и т.д. Если, по какой-то причине, вы не можете убрать become: true для всего, вы можете обойти проблему become: true, указав become: true И become_user: ec2-user только для этой роли. См. bash: nvm command not found для более детального объяснения проблемы.

"cannot find /usr/bin/python" error

Это связано с ОС, которые по умолчанию используют Python 3 (например, Fedora). Вам нужно будет указать переменную интерпретатора Python Ansible в файле инвентаря или с помощью командной строки.

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

[fedora2]
192.168.0.2

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

или

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

glibc_2.28' not found (required by node)

Вы пытаетесь запустить версию Node.js на операционной системе, не поддерживаемой версией Node.js, которую вы устанавливаете. Это не проблема NVM и не проблема роли. Вам нужно либо обновить ОС, либо понизить версию Node.js, которую вы пытаетесь установить.


Поддержка версий Ansible

ansible-core 2.16 +

Произошло фундаментальное изменение в том, как Ansible управляет инклудом/импортами. Ansible удалил ansible.builtin.include из ansible-core и заменил его на ansible.builtin.include_tasks. К сожалению, Ansible не может ограничить ansible.builtin.include, чтобы игнорировать более старые версии и т.д., поэтому я обновил эту роль для полной поддержки ansible-core 2.16+.

Если вам требуется поддержка ansible-core 2.15 и ниже, пожалуйста, используйте наследственную ветку 1.5.X.

ansible-core 2.15 и ниже

Пожалуйста, используйте наследственную ветку 1.5.X.

Переменные роли

Доступные переменные перечислены ниже, вместе с их значениями по умолчанию, смотрите defaults/main.yml.

Версия Node.js, которую нужно установить. Последняя "lts" версия является значением по умолчанию и работает на большинстве поддерживаемых ОС.

nodejs_version: "lts"

Метод установки автозавершения для NVM bash (nvm <TAB>), когда пользователю нужно вручную поддерживать сервер или рабочую станцию.

autocomplete: false

Установить NVM с нуля, удалив ЛЮБЫЕ и ВСЕ существующие или предыдущие ссылки на .nvm (каталоги) и ЛЮБЫЕ и ВСЕ существующие или предыдущие ссылки в профилях, например, .bashrc в системе.

clean_install: false

clean_install: true находит все файлы в /home, /root, /etc и пользовательских директориях установки на наличие упоминаний, а также ищет любые папки .nvm в системе. Это эквивалентно настройке нового устройства, ИСПОЛЬЗУЙТЕ С ОСТОРОЖНОСТЬЮ.

default: false

Установить версию по умолчанию для Node при установке/обновлении нескольких версий Node.

NVM автоматически назначит первую версию, установленную во время первого запуска, как "дефолтную", что чаще всего и требуется от этой роли. Однако это также даст возможность установки/обновления нескольких версий на существующей машине.

Список команд NVM для выполнения. Значение по умолчанию - пустой список.

nvm_commands: []

Тип установки NVM. Опции: wget, curl и git.

nvm_install: "wget"

Каталог установки NVM.

nvm_dir: ""

NVM по умолчанию установит каталог .nvm в домашний каталог пользователя, например /home/vagrant/.nvm. Вы можете переопределить каталог установки, изменив эту переменную, например на /opt/nvm, чтобы поместить ее в общее пространство (не привязанное к конкретной учетной записи пользователя), если хотите. Эта переменная будет уважать переменные подстановки Ansible, например {{ansible_env.HOME}}.

Расположение профиля NVM. Варианты: .bashrc, .cshrc, .tcshrc, .zshrc.

nvm_profile: ".bashrc"

Местоположение профиля ВХОДА, которое будет загружать команду nvm. Есть два потенциальных контекста, которые следует учитывать:

Глобально, то есть каждый, кто входит в систему, будет иметь доступ к nvm (что может быть не тем, что вы действительно хотите)

например, /etc/bash.bashrc, /etc/profile и т.д.

ИЛИ

На основе отдельного пользователя, привязанного к конкретной учетной записи пользователя

например, /home/vagrant/.bashrc.*

Эта роль создаст соответствующий файл профиля, если его еще нет.

Если вы явно укажете nvm_profile: "/home/node-user/.bashrc", а node-user не является реальным пользователем на этом устройстве, то nvm не будет работать, как вы ожидаете. Путь nvm_profile, become и become_user симбиотичны.

:warning: БУДЬТЕ ОСОЗНАНЫ ОГРАНИЧЕНИЯМ ЯВНОГО УКАЗАНИЯ ФАЙЛОВ .profile ИЛИ .bash_profile В СИСТЕМАХ UBUNTU

https://askubuntu.com/a/969923 объясняет это в деталях.

https://kb.iu.edu/d/abdy показывает опции для каждого типа оболочки.

Расположение профиля NVM:

BASH: .bashrc

CSH: /etc/csh.cshrc, .cshrc

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

ZSH: .zshrc

Расположение исходников NVM, т.е. вы размещаете свою собственную версию NVM.

nvm_source: ""

Версия NVM для установки.

nvm_version: "0.39.7"

Удалить NVM, удалит каталог .nvm и очистит файл, находящийся по пути с переменной {{ nvm_profile }} (обычно $HOME/.bashrc), где бы этот файл ни находился.

uninstall: False

Зависимости

Отсутствуют.

Журнал изменений


2.0.0 Смотрите RELEASE NOTES.

Лицензия

MIT / BSD

Информация об авторе

dm00000 через MORGANGRAPHICS, INC

Эта роль активно заимствует идеи из роли Node.js Джеффа Гирлинга, автора Ansible for DevOps.

Установить
ansible-galaxy install morgangraphics/ansible-role-nvm
Лицензия
mit
Загрузки
12166
Владелец