morgangraphics / ansible-role-nvm

Installs NVM & Node.js on Debian/Ubuntu and RHEL/CentOS
MIT License
102 stars 29 forks source link

file (.bashrc) is absent, cannot continue + nvm command not found #23

Closed jfoliveira closed 4 years ago

jfoliveira commented 4 years ago

Describe the bug Running this role without setting nvm_profile fails on task Update profile permissions to lock it down after writing although ~/.bashrc exists

Setting nvm_profile:

nvm_profile: "/home/{{ user_name }}/.bashrc"

this task passes but fails on task Check NVM Version with error:

bash: nvm: command not found

Tried the suggestion on #16 but still no success.

Expected behavior NVM version be installed and verified with no errors.

To Reproduce Minimally viable playbook to recreate the issue you are experiencing

  - role: morgangraphics.ansible_role_nvm
    nvm_user: "{{ user_name }}"
    nvm_version: "v0.35.2"
    nvm_profile: "/home/{{ user_name }}/.bashrc"
    nodejs_version: "12.16.1"
    # become: yes # tried with and without become and become_user, and the error was the same
    # become_user: "{{ user_name }}"

Desktop (please complete the following information):

Debugging output The issue seen in the playbook output [e.g. ansible-playbook --verbose -vvvv]

fatal: [172.19.0.1]: FAILED! => {
    "changed": true, 
    "cmd": "/bin/bash -ic \"nvm --version\"", 
    "delta": "0:00:00.042745", 
    "end": "2020-06-09 15:42:26.911514", 
    "invocation": {
        "module_args": {
            "_raw_params": "/bin/bash -ic \"nvm --version\"", 
            "_uses_shell": true, 
            "argv": null, 
            "chdir": null, 
            "creates": null, 
            "executable": null, 
            "removes": null, 
            "stdin": null, 
            "stdin_add_newline": true, 
            "strip_empty_ends": true, 
            "warn": true
        }
    }, 
    "rc": 127, 
    "start": "2020-06-09 15:42:26.868769"
}

STDERR:

bash: cannot set terminal process group (39047): Inappropriate ioctl for device
bash: no job control in this shell
bash: nvm: command not found

MSG:

non-zero return code

Additional context Any suggestions on what I am doing wrong?

morgangraphics commented 4 years ago

Does the user associated user_name actually exist on the machine where the playbook is running?

Meaning you either ran a command like:

sudo useradd -m {{ user_name }} before running the NVM role.

OR

You added a user with the ansible user module like:

- name: "Add the user {{ user_name }}"
  user:
    name: "{{ user_name }}"
    group: some_group

before running the NVM role.

The user has to actually exist on the machine the playbook is configuring as a real user. To see if the user exists run the following command in your terminal cut -d: -f1 /etc/passwd | sort

If you've confirmed that the user is actually on the machine, could you provide a minimum configuration example so I can reproduce the issue

jfoliveira commented 4 years ago

Yeah, the user account exists and it was created before running the NVM role. Actually, SSH-ing into the container with the same user account and executing the same command I get the same output:

testuser@11ef131c167d:~$ /bin/bash -ic "nvm --version"

bash: nvm: command not found

Update 1 - There are 2 parts of this error message:

  1. The first error seems to be docker TTY specific and can be reproduced by executing the command directly against a running docker container:
    $ docker exec -i test_nvm bash -ic "nvm --version"

Output:

bash: cannot set terminal process group (39047): Inappropriate ioctl for device
bash: no job control in this shell
bash: nvm: command not found

2) Adding the --tty or -t parameter to docker exec so a pseudo TTY is allocated, the first error message disappears, but still nvm is not recognized as a valid command:

docker exec -t -i test_nvm bash -ic "nvm --version"

Output:

bash: nvm: command not found

Do you think are there any other steps - besides ensuring the user account is created - that needs to be performed before running the NVM role?

morgangraphics commented 4 years ago

Ok, I missed this in the first post

 - role: morgangraphics.ansible_role_nvm
    nvm_user: "{{ user_name }}"
    nvm_version: "v0.35.2"
    nvm_profile: "/home/{{ user_name }}/.bashrc"
    nodejs_version: "12.16.1"
    # become: yes # tried with and without become and become_user, and the error was the same
    # become_user: "{{ user_name }}"

is partly wrong, there is no nvm_user variable for the role. nvm_version is already at the default version of 0.35.2 so you resetting it redundant.

This minimum declaration should work.

 - role: morgangraphics.ansible_role_nvm
    nodejs_version: "12.16.1"
    become_user: "{{ user_name }}"

If you are using the Ansible user module, a directory skeleton should already include a .bashrc file in the home directory of the user you created (unless you explicitly set create_home: no).

Docker adds another layer of complexity to this particular issue. The reason I use bash -ic command is due to how Ansible (and SSH) works with context/shells. The -i means open an interactive shell and the -c mean run the following commands. I fairly certain Docker does not work the same way, it may I have not tested it. I think what you are looking for is more like this:

docker exec -it test_nvm bash -c "nvm --version"

HOWEVER

I don't know what context (shell) your docker exec is running in. You don't appear to be declaring any user so it may be root for all I know.

docker exec -it test_nvm bash whoami

If the output is anything other than the "{{ user_name }}" you expect then you will need to supply a user context to the Docker command like:

docker exec -it -u user_name test_nvm bash -c "nvm --version"

jfoliveira commented 4 years ago

Thanks @morgangraphics! I really messed up with too many parameters when invoking the role. Your solution did the trick and it's working fine now.

I only needed to add become: yes, as it didn't work without it:

 - role: morgangraphics.ansible_role_nvm
   become: yes
   become_user: "{{ user_name }}"

Thank you!

morgangraphics commented 4 years ago

become: true on it's own forces the role to be run as the root user which

  1. is not secure
  2. installs nvm in the home directory of the root user at something like /root/.bashrc

It is not recommended to use become: true on the role by itself

HOWEVER

You did catch an issue with the documentation in that the become: true in combination with become_user: test-user will provide the correct context. I will update the documentation accordingly. Thank you.

Here is the working playbook that tests everything within the context of the test-user I created

- hosts: all

  pre_tasks:

    - 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"
            become_user: test-user
            become: true
morgangraphics commented 4 years ago

Took care of ambiguity in documentation with PR #25