From 66b09115ae643d96fca3ab5062732305e64ec638 Mon Sep 17 00:00:00 2001 From: Grzegorz Nowak Date: Mon, 31 Aug 2020 16:56:18 +0200 Subject: [PATCH] Allow for version-targetted installation of global packages. General mods to tests to accommodate for that as well as README update. Minor related mods too --- README.md | 56 +++++++++++++++++++------- bootstrap_test.sh | 8 ++++ molecule/default/molecule.yml | 18 +++++++-- molecule/default/playbook.yml | 31 +++++++++++++- molecule/default/tests/test_default.py | 24 +++++++++++ tasks/main.yml | 39 +++++++++++++++++- 6 files changed, 153 insertions(+), 23 deletions(-) create mode 100755 bootstrap_test.sh diff --git a/README.md b/README.md index 8ebaa51..90de214 100755 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ No dependencies, just note it will install `wget` to fetch the nvm installation Currently builds and integrates on those distros: -##### Ubuntu: 18.04, 16.04, 14.04 +##### Ubuntu: 20.04, 18.04, 16.04, 14.04 ##### Debian: buster, stretch ##### CentOS: 7 @@ -39,33 +39,35 @@ Currently builds and integrates on those distros: ## Variables ### defaults +```YAML nvm_install_script_version: "0.33.11" # the nvm installation script to use (latest stable version as of writing this) nvm_user_name: "root" # you can use a different user, and you might in the end achieve the more nvm-ish approach # but I've not covered that in tests etc. nvm_dir: "/var/lib/nvm" # for global (default) installation. Follow the same rule as the nvm_user_name variable nvm_node_version: "8.11.3" # the node version to install via nvm nvm_install_globally: [] # libraries to intall globally and symlink, look further down for details - +``` ## Example playbook ##### when cloned from github - +```YAML --- - hosts: all vars: nvm_node_version: "4.1.1" roles: - role: ansible-nvm-node - +``` ##### when from ansible-galaxy +```YAML --- - hosts: all vars: nvm_node_version: "your.node.version" roles: - role: grzegorznowak.nvm_node - +``` ## Upgrading node Simply replace `nvm_node_version` with whatever version you want to be using globally and rerun the playbook @@ -76,30 +78,54 @@ Simply replace `nvm_node_version` with whatever version you want to be using glo For the best coherency you are strongly encouraged to install global packages using this role too, in which case just edit the `nvm_install_globally` variable, as follows: -`nvm_install_globally: ['gulp']` - -and that will install global gulp and put a symlink to global $PATH for specific environments to access it (like cron) +```YAML +nvm_install_globally: ['gulp'] +``` +also can use version targeting for global packages: + +```YAML +nvm_install_globally: + - name: yarn + version: 1.9.4 +``` + +or mix both: + +```YAML +nvm_install_globally: + - gulp + - lighthouse + - name: yarn + version: 1.9.4 +``` + +and that will install listed libraries and put a symlink to global $PATH +for specific environments to access it (like cron) ## Testing ### Requirements +you may use a helper script that will install virtual env with all the needed stuff + `./bootstrap_test.sh` + +the simply activate the virtualenv with `source test_env/bin/activate` + +or just do it 100% manually for better control + sudo apt install virtualenv python3-pip - virtualenv testenv --python=python3 - source testenv/bin/activate + virtualenv test_env --python=python3 + source test_env/bin/activate pip install -r test-requirements.txt -if you do it the other way around you might be getting runtime errors from python -on the testing phase - ### Testing with lxc containers molecule test ### Additional perks from molecule -Remember you can also do crazy stuff like `molecule converge` to simply bring instance(s) at will and then tear them down -with `molecule destroy`. The sky is the limit here really! +You can do all sort of super handy stuff like `molecule converge` to simply bring instance(s) at will +and then tear them down with `molecule destroy`. The sky is the limit here really! ## Sponsored by diff --git a/bootstrap_test.sh b/bootstrap_test.sh new file mode 100755 index 0000000..b1ea66d --- /dev/null +++ b/bootstrap_test.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +sudo apt install virtualenv python3-pip + +rm test_env -rf +virtualenv test_env --python=python3 +. test_env/bin/activate +pip install -r test-requirements.txt diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml index 7956f1e..5ecacdb 100755 --- a/molecule/default/molecule.yml +++ b/molecule/default/molecule.yml @@ -14,11 +14,21 @@ platforms: image: ubuntu/xenial/amd64 - name: ansible-nvm-node-test-14-04 image: ubuntu/trusty/amd64 -# - name: ansible-nvm-node-test-buster -# image: debian/buster/amd64 -# - name: ansible-nvm-node-test-stretch -# image: debian/stretch/amd64 + - name: ansible-nvm-node-test-buster + image: debian/buster/amd64 + - name: ansible-nvm-node-test-stretch + image: debian/stretch/amd64 provisioner: + config_options: + defaults: + bin_ansible_callbacks: true + display_ok_hosts: false + display_skipped_hosts: false + forks: 50 + internal_poll_interval: 0.001 + stdout_callback: yaml + ssh_connection: + pipelining: true name: ansible lint: name: ansible-lint diff --git a/molecule/default/playbook.yml b/molecule/default/playbook.yml index fc4662a..9c58354 100644 --- a/molecule/default/playbook.yml +++ b/molecule/default/playbook.yml @@ -1,8 +1,14 @@ --- -- name: Converge +- name: Converge Helpers hosts: all pre_tasks: + + - name: Seems lxc debians don't have cron by default + apt: + name: cron + when: ansible_distribution == 'Debian' + - name: Add a non-root user to test nvm user: name: nvm_tester @@ -28,7 +34,28 @@ minute: "*" job: "which lighthouse > /tmp/which_lighthouse" + - name: Crontab for which-ing Yarn + cron: + name: "which yarn" + minute: "*" + job: "which yarn > /tmp/which_yarn" + + - name: Crontab for which-ing pm2 + cron: + name: "which pm2" + minute: "*" + job: "which yarn > /tmp/which_pm2" + +- name: Converge nvm with global packages as a combination of old and new format + hosts: all + roles: - role: ansible-nvm-node nvm_node_version: "10.16.3" - nvm_install_globally: ['gulp', 'lighthouse'] + nvm_install_globally: + - gulp + - lighthouse + - name: yarn + version: 1.9.4 + - name: pm2 + version: 3.1.2 diff --git a/molecule/default/tests/test_default.py b/molecule/default/tests/test_default.py index 657446b..062c0fa 100755 --- a/molecule/default/tests/test_default.py +++ b/molecule/default/tests/test_default.py @@ -30,6 +30,20 @@ def test_global_libraries(host): assert cmd.stderr == '' assert cmd.stdout != '' + cmd = host.run("yarn --version") + assert cmd.stderr == '' + assert cmd.stdout.rstrip() == '1.9.4' + + # first run does (and outputs) some extra stuff, so let's be over it now + nop_cmd = host.run("pm2 --version") + + # let's assert something anyway to please the Flake + assert nop_cmd.stderr == '' + + cmd = host.run("pm2 --version") + assert cmd.stderr == '' + assert cmd.stdout.rstrip() == '3.1.2' + with host.sudo("nvm_tester"): cmd = host.run("which lighthouse") assert cmd.stderr == '' or cmd.stderr == FOCAL_BUG_STR @@ -39,6 +53,14 @@ def test_global_libraries(host): assert cmd.stderr == '' or cmd.stderr == FOCAL_BUG_STR assert cmd.stdout.rstrip() == '/usr/bin/gulp' + cmd = host.run("which yarn") + assert cmd.stderr == '' or cmd.stderr == FOCAL_BUG_STR + assert cmd.stdout.rstrip() == '/usr/bin/yarn' + + cmd = host.run("which pm2") + assert cmd.stderr == '' or cmd.stderr == FOCAL_BUG_STR + assert cmd.stdout.rstrip() == '/usr/bin/pm2' + def test_cron_environment_for_global_libs(host): @@ -47,6 +69,8 @@ def test_cron_environment_for_global_libs(host): '/usr/bin/gulp' assert host.run("cat /tmp/which_lighthouse").stdout.rstrip() == \ '/usr/bin/lighthouse' + assert host.run("cat /tmp/which_lighthouse").stdout.rstrip() == \ + '/usr/bin/lighthouse' def test_user_node_version_ok(host): diff --git a/tasks/main.yml b/tasks/main.yml index 5980e05..acf901b 100755 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -48,13 +48,48 @@ file: src="{{ nvm_dir }}/versions/node/v{{ nvm_node_version }}/bin/npm" dest="/usr/bin/npm" state=link mode="u+rwx,g+rx,o+rx" -- name: Install global packages +### ---- Install version-agnostic and version-aware version of globals ---- ### +### TODO: DRY it some way smart + +- name: Install global packages (version and name given) + shell: + cmd: ". /root/.bashrc && {{ nvm_dir }}/versions/node/v{{ nvm_node_version }}/bin/npm \ + install --global {{ item.name }}@{{ item.version }}" + creates: "{{ nvm_dir }}/versions/node/v{{ nvm_node_version }}/bin/{{ item.name }}" + loop: "{{ nvm_install_globally }}" + when: item.name is defined and item.version is defined + +- name: Install global packages (name given in plain string - hopefully) shell: - cmd: ". /root/.bashrc && {{ nvm_dir }}/versions/node/v{{ nvm_node_version }}/bin/npm install --global {{ item }}" + cmd: ". /root/.bashrc && {{ nvm_dir }}/versions/node/v{{ nvm_node_version }}/bin/npm \ + install --global {{ item }}" creates: "{{ nvm_dir }}/versions/node/v{{ nvm_node_version }}/bin/{{ item }}" loop: "{{ nvm_install_globally }}" + when: item.name is not defined and item.version is not defined + +- name: Install global packages (name given in a dictionary) + shell: + cmd: ". /root/.bashrc && {{ nvm_dir }}/versions/node/v{{ nvm_node_version }}/bin/npm \ + install --global {{ item.name }}" + creates: "{{ nvm_dir }}/versions/node/v{{ nvm_node_version }}/bin/{{ item.name }}" + loop: "{{ nvm_install_globally }}" + when: item.name is defined and item.version is not defined + +### --------------- END ------------- #### + +### ---- Symlink version-agnostic and version-aware version of globals ---- ### +### TODO: DRY it some way smart + +- name: Symlink global packages into PATH for specific environments (like cron's) to be able to access them. + file: src="{{ nvm_dir }}/versions/node/v{{ nvm_node_version }}/bin/{{ item.name }}" + dest="/usr/bin/{{ item.name }}" state=link mode="u+rwx,g+rx,o+rx" + loop: "{{ nvm_install_globally }}" + when: item.name is defined - name: Symlink global packages into PATH for specific environments (like cron's) to be able to access them. file: src="{{ nvm_dir }}/versions/node/v{{ nvm_node_version }}/bin/{{ item }}" dest="/usr/bin/{{ item }}" state=link mode="u+rwx,g+rx,o+rx" loop: "{{ nvm_install_globally }}" + when: item.name is not defined + +### --------------- END ------------- ####