using NVM: npm module throws "ValueError: No JSON object could be decoded" the second time it's run
ansible 2.0.0.2
config file = /Users/oby/cermati-deployment/ansible.cfg
configured module search path = /usr/share/ansible
CONFIGURATION
Nothing changed, I use the default configuration.
OS / ENVIRONMENT
Running ansible on Mac Darwin Kernel Version 13.4.0
This for deploying on Ubuntu 14.04
SUMMARY
I used nvm (node version manager https://www.npmjs.com/package/nvm) to install different version of npm on my server. So after installing node version 0.10.44 using nvm, I tried doing npm install
using ansible's npm module. The first time my playbook is run, everything went well. But the second time I run the playbook, the npm module throw error (this behavior is pretty consistent):
TASK [do npm install from package.json for npm version 2.15.0] *****************
fatal: [128.199.225.57]: FAILED! => {"changed": false, "failed": true, "module_stderr": "", "module_stdout": "Traceback (most recent call last):\r\n File \"/home/appRunner/.ansible/tmp/ansible-tmp-1461802965.66-211488871785680/npm\", line 2198, in <module>\r\n main()\r\n File \"/home/appRunner/.ansible/tmp/ansible-tmp-1461802965.66-211488871785680/npm\", line 245, in main\r\n installed, missing = npm.list()\r\n File \"/home/appRunner/.ansible/tmp/ansible-tmp-1461802965.66-211488871785680/npm\", line 169, in list\r\n data = json.loads(self._exec(cmd, True, False))\r\n File \"/usr/lib/python2.7/json/__init__.py\", line 338, in loads\r\n return _default_decoder.decode(s)\r\n File \"/usr/lib/python2.7/json/decoder.py\", line 366, in decode\r\n obj, end = self.raw_decode(s, idx=_w(s, 0).end())\r\n File \"/usr/lib/python2.7/json/decoder.py\", line 384, in raw_decode\r\n raise ValueError(\"No JSON object could be decoded\")\r\nValueError: No JSON object could be decoded\r\n", "msg": "MODULE FAILURE", "parsed": false}
Here's the ansible command that caused the problem:
- name: do npm install from package.json for npm version 2.15.0
npm: executable=/home/appRunner/.nvm/v0.10.44/bin/npm path={{ workspace_dir }}
remote_user: "appRunner"
NOTE: I can run npm install multiple times if I ssh-ed directly to the server.
For now, my workaround is using command
module and issuing command npm install
directly. But it'd be nice if npm module is also working.
Here's the ansible command that I use for the workaround:
- name: do npm install from package.json for npm version 2.15.0
command: chdir={{ workspace_dir }} /bin/bash -c "{{nvm_bin_dir}}/npm install"
remote_user: "appRunner"
STEPS TO REPRODUCE
Create a playbook that
1.) Install nvm
2.) Install npm version 0.10.44
3.) run npm install
Run the playbook twice. The second time, it will throw the error.
See example playbook
- hosts: stg2-server
remote_user: root
vars:
workspace_dir: /home/{{ server.name }}/workspace
nvm_dir: /home/{{ server.name }}/.nvm
nvm_bin_dir: "{{nvm_dir}}/v{{node_version}}/bin"
vars_files:
- ./vars/secure_vars.yml
roles:
# setup user and install gcc, make, etc.
- role: common
tasks:
- name: install nvm
shell: curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash
remote_user: "appRunner"
- name: install node v0.10.44
shell: export NVM_DIR="$HOME/.nvm" && . "$NVM_DIR/nvm.sh" && nvm install v{{node_version}} && nvm use v{{node_version}}
remote_user: "appRunner"
- name: create a workspace directory in the user home directory
file: path={{ workspace_dir }} state=directory
remote_user: "appRunner"
- name: do a git clone to the workspace from master branch
git: accept_hostkey=yes repo=<fill your own repo> dest={{ workspace_dir }}
remote_user: "appRunner"
- name: do npm install from package.json for npm version 2.15.0
npm: executable=/home/appRunner/.nvm/v0.10.44/bin/npm path={{ workspace_dir }}
remote_user: "appRunner"
EXPECTED RESULTS
TASK [do npm install from package.json for npm version 2.15.0] *****************
changed: [128.199.225.57]
ACTUAL RESULTS
TASK [do npm install from package.json for npm version 2.15.0] *****************
task path: /Users/oby/cermati-deployment/test.yml:31
<128.199.225.57> ESTABLISH SSH CONNECTION FOR USER: appRunner
<128.199.225.57> SSH: EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=appRunner -o ConnectTimeout=10 -o ControlPath=/Users/oby/.ansible/cp/ansible-ssh-%h-%p-%r -tt 128.199.225.57 '( umask 22 && mkdir -p "$( echo $HOME/.ansible/tmp/ansible-tmp-1461811178.63-221498059846058 )" && echo "$( echo $HOME/.ansible/tmp/ansible-tmp-1461811178.63-221498059846058 )" )'
<128.199.225.57> PUT /var/folders/jd/srwxscyj62j3q8gx1_h37djh0000gn/T/tmpt08bdv TO /home/appRunner/.ansible/tmp/ansible-tmp-1461811178.63-221498059846058/npm
<128.199.225.57> SSH: EXEC sftp -b - -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=appRunner -o ConnectTimeout=10 -o ControlPath=/Users/oby/.ansible/cp/ansible-ssh-%h-%p-%r '[128.199.225.57]'
<128.199.225.57> ESTABLISH SSH CONNECTION FOR USER: appRunner
<128.199.225.57> SSH: EXEC ssh -C -vvv -o ControlMaster=auto -o ControlPersist=60s -o StrictHostKeyChecking=no -o Port=22 -o KbdInteractiveAuthentication=no -o PreferredAuthentications=gssapi-with-mic,gssapi-keyex,hostbased,publickey -o PasswordAuthentication=no -o User=appRunner -o ConnectTimeout=10 -o ControlPath=/Users/oby/.ansible/cp/ansible-ssh-%h-%p-%r -tt 128.199.225.57 'LANG=C LC_ALL=C LC_MESSAGES=C /usr/bin/python /home/appRunner/.ansible/tmp/ansible-tmp-1461811178.63-221498059846058/npm; rm -rf "/home/appRunner/.ansible/tmp/ansible-tmp-1461811178.63-221498059846058/" > /dev/null 2>&1'
fatal: [128.199.225.57]: FAILED! => {"changed": false, "failed": true, "invocation": {"module_name": "npm"}, "module_stderr": "OpenSSH_6.2p2, OSSLShim 0.9.8r 8 Dec 2011\ndebug1: Reading configuration data /Users/oby/.ssh/config\r\ndebug1: /Users/oby/.ssh/config line 1: Applying options for *\r\ndebug1: Reading configuration data /etc/ssh_config\r\ndebug1: /etc/ssh_config line 20: Applying options for *\r\ndebug1: auto-mux: Trying existing master\r\ndebug2: fd 3 setting O_NONBLOCK\r\ndebug2: mux_client_hello_exchange: master version 4\r\ndebug3: mux_client_forwards: request forwardings: 0 local, 0 remote\r\ndebug3: mux_client_request_session: entering\r\ndebug3: mux_client_request_alive: entering\r\ndebug3: mux_client_request_alive: done pid = 20565\r\ndebug3: mux_client_request_session: session request sent\r\ndebug1: mux_client_request_session: master session id: 2\r\ndebug3: mux_client_read_packet: read header failed: Broken pipe\r\ndebug2: Received exit status from master 0\r\nShared connection to 128.199.225.57 closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n File \"/home/appRunner/.ansible/tmp/ansible-tmp-1461811178.63-221498059846058/npm\", line 2198, in <module>\r\n main()\r\n File \"/home/appRunner/.ansible/tmp/ansible-tmp-1461811178.63-221498059846058/npm\", line 245, in main\r\n installed, missing = npm.list()\r\n File \"/home/appRunner/.ansible/tmp/ansible-tmp-1461811178.63-221498059846058/npm\", line 169, in list\r\n data = json.loads(self._exec(cmd, True, False))\r\n File \"/usr/lib/python2.7/json/__init__.py\", line 338, in loads\r\n return _default_decoder.decode(s)\r\n File \"/usr/lib/python2.7/json/decoder.py\", line 366, in decode\r\n obj, end = self.raw_decode(s, idx=_w(s, 0).end())\r\n File \"/usr/lib/python2.7/json/decoder.py\", line 384, in raw_decode\r\n raise ValueError(\"No JSON object could be decoded\")\r\nValueError: No JSON object could be decoded\r\n", "msg": "MODULE FAILURE", "parsed": false}
Copied from original issue: ansible/ansible-modules-extras#2128
From @ajbonner on 2016-04-29T03:22:28Z
I've run into this too. Basically it's because ansible is running under sudo. The root's login environment isn't available (on ubuntu/debian, sudo doesn't load /etc/profile or ~/.profile) so you don't have any of the nvm environment set and so the shell can't find node.
Even when you provide the full path to the nvm managed npm binary, it can't find node, as it's trying to load it using /usr/bin/env node.
Eg. if one runs sudo su then
root@test.box:/home/vagrant# /usr/local/nvm/versions/node/v6.2.0/bin/npm
/usr/bin/env: 'node': No such file or directory
Now try sudo su -
root@test.box:~# /usr/local/nvm/versions/node/v6.2.0/bin/npm
Usage: npm <command>
As just a plain user running executable via sudo
vagrant@test.box:~$ sudo /usr/local/nvm/versions/node/v6.2.0/bin/npm
/usr/bin/env: 'node': No such file or directory
But when you supply the -i or --login arg to sudo (login shell)
vagrant@test.box:~$ sudo -i /usr/local/nvm/versions/node/v6.2.0/bin/npm
Usage: npm <command>
My work around is to create a symlink to the node binary in /usr/local/bin before running npm tasks.
From @MattAlex151 on 2016-04-29T03:22:28Z
None of the posted solutions work for me. I've tried symlinking, become: false
, and adding to the PATH all with no success.
EDIT: Misread what to symlink, was trying npm when it should have been node itself. It works if I symlink node to /usr/local/bin
using NVM: npm module throws "ValueError: No JSON object could be decoded" the second time it's run
ansible/ansible-modules-extras#2128
@ansibot Greetings! Thanks for taking the time to open this issue. In order for the community to handle your issue effectively, we need a bit more information.
Here are the items we could not find in your description:
component name
Please set the description of this issue with this template:
https://raw.githubusercontent.com/ansible/ansible/devel/.github/ISSUE_TEMPLATE.md
click here for bot help
COMPONENT NAME
I'm having the same issue now but I didn't have it previously when I wrote the role.
Task:
name: '{{ item }}'
global: yes
state: latest
with_items:
- npm
- pm2
Returns:
(item=pm2) => {"changed": false, "failed": true, "item": "pm2", "module_stderr": "Shared connection to node1-test.server.infra closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n File \"/tmp/ansible_ATSNKe/ansible_module_npm.py\", line 289, in <module>\r\n main()\r\n File \"/tmp/ansible_ATSNKe/ansible_module_npm.py\", line 271, in main\r\n installed, missing = npm.list()\r\n File \"/tmp/ansible_ATSNKe/ansible_module_npm.py\", line 190, in list\r\n data = json.loads(self._exec(cmd, True, False))\r\n File \"/usr/lib/python2.7/json/__init__.py\", line 339, in loads\r\n return _default_decoder.decode(s)\r\n File \"/usr/lib/python2.7/json/decoder.py\", line 364, in decode\r\n obj, end = self.raw_decode(s, idx=_w(s, 0).end())\r\n File \"/usr/lib/python2.7/json/decoder.py\", line 382, in raw_decode\r\n raise ValueError(\"No JSON object could be decoded\")\r\nValueError: No JSON object could be decoded\r\n", "msg": "MODULE FAILURE", "rc": 0}
@xcambar I know this is a closed issue but I just ran into this issue or at least something similar using Ansible 2.5. If needed I can open a new bug.
TASK [Install thelounge] *****************************************************************************************************************************************************************************************************************
task path: /root/Ansible-Playbook-TheLounge/installTheLounge.yml:105
Using module file /root/ansible25/lib/python3.5/site-packages/ansible/modules/packaging/language/npm.py
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: root
<localhost> EXEC /bin/sh -c 'echo ~ && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1525837278.3860474-41613859994964 `" && echo ansible-tmp-1525837278.3860474-41613859994964="` echo /root/.ansible/tmp/ansible-tmp-1525837278.3860474-41613859994964 `" ) && sleep 0'
<localhost> PUT /root/.ansible/tmp/ansible-local-2126__4dcp44/tmptcve81uv TO /root/.ansible/tmp/ansible-tmp-1525837278.3860474-41613859994964/npm.py
<localhost> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1525837278.3860474-41613859994964/ /root/.ansible/tmp/ansible-tmp-1525837278.3860474-41613859994964/npm.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1525837278.3860474-41613859994964/npm.py && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1525837278.3860474-41613859994964/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/tmp/ansible_fxqiig/ansible_module_npm.py", line 291, in <module>
main()
File "/tmp/ansible_fxqiig/ansible_module_npm.py", line 273, in main
installed, missing = npm.list()
File "/tmp/ansible_fxqiig/ansible_module_npm.py", line 192, in list
data = json.loads(self._exec(cmd, True, False))
File "/usr/lib/python2.7/json/__init__.py", line 339, in loads
return _default_decoder.decode(s)
File "/usr/lib/python2.7/json/decoder.py", line 364, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python2.7/json/decoder.py", line 382, in raw_decode
raise ValueError("No JSON object could be decoded")
ValueError: No JSON object could be decoded
fatal: [localhost]: FAILED! => {
"changed": false,
"module_stderr": "Traceback (most recent call last):\n File \"/tmp/ansible_fxqiig/ansible_module_npm.py\", line 291, in <module>\n main()\n File \"/tmp/ansible_fxqiig/ansible_module_npm.py\", line 273, in main\n installed, missing = npm.list()\n File \"/tmp/ansible_fxqiig/ansible_module_npm.py\", line 192, in list\n data = json.loads(self._exec(cmd, True, False))\n File \"/usr/lib/python2.7/json/__init__.py\", line 339, in loads\n return _default_decoder.decode(s)\n File \"/usr/lib/python2.7/json/decoder.py\", line 364, in decode\n obj, end = self.raw_decode(s, idx=_w(s, 0).end())\n File \"/usr/lib/python2.7/json/decoder.py\", line 382, in raw_decode\n raise ValueError(\"No JSON object could be decoded\")\nValueError: No JSON object could be decoded\n",
"module_stdout": "",
"msg": "MODULE FAILURE",
"rc": 1
Task item looks like so
- name: Install thelounge
npm:
name: "thelounge"
path: "/opt/node-v8.11.1-linux-x64"
executable: "/opt/node-v8.11.1-linux-x64/bin/npm"
global: yes
state: latest
if you use sudo
,you may add your env exec path to the server at /etc/sudoers
,like /usr/local/sbin
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin
Defaults secure_path = /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:/usr/local/node/bin
use enviroment to define your PATH in ansible's yaml
environment:
PATH: /usr/local/node/bin:{{ ansible_env.PATH }}
environment is aviable when your ansible's version >= 1.9