Search code examples
npmansiblecentos7jsreport

Ansible install JsReport on CentOS 7


I am having hard time writing ansible script for installing JsReport on CentOS 7. I am trying to translate these operations: https://jsreport.net/learn/centos

into ansible script.

What i tried so far is:

- hosts: localhost
  tasks:
  - name: install wget
    yum:
      name: wget
      state: latest      
  - name: download nvm
    get_url: url=https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh  dest=/opt/nvm-install.sh 
  - name: Changing perm of "/opt/nvm-install.sh", adding "+x"
    file: dest=/opt/nvm-install.sh mode=a+x
  - name: Execute the script
    command: sh /opt/nvm-install.sh
  - name: Changing perm of "~/.nvm/nvm.sh", adding "+x"
    file: dest=~/.nvm/nvm.sh mode=a+x   

  - name: Make nvm command work in current terminal, Install node and set version, npm install jsreport-cli 
    shell: |
      source ~/.nvm/nvm.sh
      nvm install 8.11.3 
      npm install jsreport-cli -g
      mkdir jsreportapp
      jsreportapp
      jsreport init
      jsreport configure


  - name: download install-google-chrome.sh
    get_url: url=https://intoli.com/install-google-chrome.sh  dest=/opt/install-google-chrome.sh
  - name: Changing perm of "/opt/install-google-chrome.sh", adding "+x"
    file: dest=/opt/install-google-chrome.sh mode=a+x   
  - name: Execute the script
    command: sh /opt/install-google-chrome.sh

Usually i start the ansible scripts with follow command:

sudo ansible-playbook install_jsreport.yml

I am not sure is that a good practice to use sudo here, or do i have to use shell here?

In the script above i get following error:

fatal: [localhost]: FAILED! => {"changed": true, "cmd": "source ~/.nvm/nvm.sh\n nvm install 8.11.3\n npm install jsreport-cli -g\n mkdir jsreportapp\n jsreportapp\n jsreport init\n jsreport configure", "delta": "0:01:03.627957", "end": "2019-04-19 15:22:26.374742", "msg": "non-zero return code", "rc": -2, "start": "2019-04-19 15:21:22.746785", "stderr": "v8.11.3 is already installed.\nmkdir: cannot create directory ‘jsreportapp’: File exists\n/bin/sh: line 4: jsreportapp: command not found\nUnexpected error happened: Command failed: npm i -S jsreport\nsh: node: command not found\nnpm WARN [email protected] requires a peer of webpack@^2.0.0 || ^3.0.0 but none is installed. You must install peer dependencies yourself.\nnpm WARN [email protected] requires a peer of webpack@^2.0.0 || ^3.0.0 || ^4.0.0 but none is installed. You must install peer dependencies yourself.\nnpm WARN jsreport-server@ No description\nnpm WARN jsreport-server@ No repository field.\nnpm WARN jsreport-server@ No license field.\nnpm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/fsevents):\nnpm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {\"os\":\"darwin\",\"arch\":\"any\"} (current: {\"os\":\"linux\",\"arch\":\"x64\"})\n\nnpm ERR! file sh\nnpm ERR! code ELIFECYCLE\nnpm ERR! errno ENOENT\nnpm ERR! syscall spawn\nnpm ERR! [email protected] install: node install.js\nnpm ERR! spawn ENOENT\nnpm ERR! \nnpm ERR! Failed at the [email protected] install script.\nnpm ERR! This is probably not a problem with npm. There is likely additional logging output above.\n\nnpm ERR! A complete log of this run can be found in:\nnpm ERR!
/root/.npm/_logs/2019-04-19T13_22_24_770Z-debug.log\n (1). \ncaused by error (1) -> meta = {\"killed\":false,\"code\":1,\"signal\":null,\"cmd\":\"npm i -S jsreport\"}, stack = Error: \n at ChildProcess.exithandler (child_process.js:275:12)\n at emitTwo (events.js:126:13)\n at ChildProcess.emit (events.js:214:7)\n at maybeClose (internal/child_process.js:925:16)\n at Process.ChildProcess._handle.onexit (internal/child_process.js:209:5)", "stderr_lines": ["v8.11.3 is already installed.", "mkdir: cannot create directory ‘jsreportapp’: File exists", "/bin/sh: line 4: jsreportapp: command not found", "Unexpected error happened: Command failed: npm i -S jsreport", "sh: node: command not found", "npm WARN [email protected] requires a peer of webpack@^2.0.0 || ^3.0.0 but none is installed. You must install peer dependencies yourself.", "npm WARN [email protected] requires a peer of webpack@^2.0.0 || ^3.0.0 || ^4.0.0 but none is installed. You must install peer dependencies yourself.", "npm WARN jsreport-server@ No description", "npm WARN jsreport-server@ No repository field.", "npm WARN jsreport-server@ No license field.", "npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/fsevents):", "npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {\"os\":\"darwin\",\"arch\":\"any\"} (current: {\"os\":\"linux\",\"arch\":\"x64\"})", "", "npm ERR! file sh", "npm ERR! code ELIFECYCLE", "npm ERR! errno ENOENT", "npm ERR! syscall spawn", "npm ERR! [email protected] install: node install.js", "npm ERR! spawn ENOENT", "npm ERR! ", "npm ERR! Failed at the [email protected] install script.", "npm ERR! This is probably not a problem with npm. There is likely additional logging output above.", "", "npm ERR! A complete log of this run can be found in:", "npm ERR! /root/.npm/_logs/2019-04-19T13_22_24_770Z-debug.log", " (1). ", "caused by error (1) -> meta = {\"killed\":false,\"code\":1,\"signal\":null,\"cmd\":\"npm i -S jsreport\"}, stack = Error: ", " at ChildProcess.exithandler (child_process.js:275:12)", " at emitTwo (events.js:126:13)", "
at ChildProcess.emit (events.js:214:7)", " at maybeClose (internal/child_process.js:925:16)", " at Process.ChildProcess._handle.onexit (internal/child_process.js:209:5)"], "stdout": "Now using node v8.11.3 (npm v5.6.0)\n/root/.nvm/versions/node/v8.11.3/bin/jsreport -> /root/.nvm/versions/node/v8.11.3/lib/node_modules/jsreport-cli/cli.js\n+ [email protected]\nadded 333 packages in 16.187s\njsreport installation not found, installing jsreport latest version now, wait a moment...\n? Do you want to enable web server? (Y/n) \u001b[42D\u001b[42C", "stdout_lines": ["Now using node v8.11.3 (npm v5.6.0)", "/root/.nvm/versions/node/v8.11.3/bin/jsreport -> /root/.nvm/versions/node/v8.11.3/lib/node_modules/jsreport-cli/cli.js", "+ [email protected]", "added 333 packages in 16.187s", "jsreport installation not found, installing jsreport latest version now, wait a moment...", "? Do you want to enable web server? (Y/n) \u001b[42D\u001b[42C"]}

EDIT (regarding larsks answer):

TASK [init jsreportapp directory] ************************************************************************************************************* fatal: [localhost]: FAILED! => {"changed": true, "cmd": ". ~/.nvm/nvm.sh\n jsreport init", "delta": "0:00:46.367234", "end": "2019-04-23 10:12:46.142142", "msg": "non-zero return code", "rc": 1, "start": "2019-04-23 10:11:59.774908", "stderr": "Unexpected error happened: Command failed: npm i -S jsreport\nsh: node: command not found\nnpm WARN [email protected] requires a peer of webpack@^2.0.0 || ^3.0.0 but none is installed. You must install peer dependencies yourself.\nnpm WARN [email protected] requires a peer of webpack@^2.0.0 || ^3.0.0 || ^4.0.0 but none is installed. You must install peer dependencies yourself.\nnpm WARN jsreport-server@ No description\nnpm WARN jsreport-server@ No repository field.\nnpm WARN jsreport-server@ No license field.\nnpm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/fsevents):\nnpm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {\"os\":\"darwin\",\"arch\":\"any\"} (current: {\"os\":\"linux\",\"arch\":\"x64\"})\n\nnpm ERR! file sh\nnpm ERR! code ELIFECYCLE\nnpm ERR! errno ENOENT\nnpm ERR! syscall spawn\nnpm ERR! [email protected] install: node install.js\nnpm ERR! spawn ENOENT\nnpm ERR! \nnpm ERR! Failed at the [email protected] install script.\nnpm ERR! This is probably not a problem with npm. There is likely additional logging output above.\n\nnpm ERR! A complete log of this run can be found in:\nnpm ERR!
/root/.npm/_logs/2019-04-23T08_12_46_089Z-debug.log\n (1). \ncaused by error (1) -> meta = {\"killed\":false,\"code\":1,\"signal\":null,\"cmd\":\"npm i -S jsreport\"}, stack = Error: \n at ChildProcess.exithandler (child_process.js:275:12)\n at emitTwo (events.js:126:13)\n at ChildProcess.emit (events.js:214:7)\n at maybeClose (internal/child_process.js:925:16)\n at Socket.stream.socket.on (internal/child_process.js:346:11)\n at emitOne (events.js:116:13)\n at Socket.emit (events.js:211:7)\n at Pipe._handle.close [as _onclose] (net.js:557:12)", "stderr_lines": ["Unexpected error happened: Command failed: npm i -S jsreport", "sh: node: command not found", "npm WARN [email protected] requires a peer of webpack@^2.0.0 || ^3.0.0 but none is installed. You must install peer dependencies yourself.", "npm WARN [email protected] requires a peer of webpack@^2.0.0 || ^3.0.0 || ^4.0.0 but none is installed. You must install peer dependencies yourself.", "npm WARN jsreport-server@ No description", "npm WARN jsreport-server@ No repository field.", "npm WARN jsreport-server@ No license field.", "npm WARN optional SKIPPING OPTIONAL DEPENDENCY: [email protected] (node_modules/fsevents):", "npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {\"os\":\"darwin\",\"arch\":\"any\"} (current: {\"os\":\"linux\",\"arch\":\"x64\"})", "", "npm ERR! file sh", "npm ERR! code ELIFECYCLE", "npm ERR! errno ENOENT", "npm ERR! syscall spawn", "npm ERR! [email protected] install: node install.js", "npm ERR! spawn ENOENT", "npm ERR! ", "npm ERR! Failed at the [email protected] install script.", "npm ERR! This is probably not a problem with npm. There is likely additional logging output above.", "", "npm ERR! A complete log of this run can be found in:", "npm ERR! /root/.npm/_logs/2019-04-23T08_12_46_089Z-debug.log", " (1). ", "caused by error (1) -> meta = {\"killed\":false,\"code\":1,\"signal\":null,\"cmd\":\"npm i -S jsreport\"}, stack = Error: ", " at ChildProcess.exithandler (child_process.js:275:12)", " at emitTwo (events.js:126:13)", "
at ChildProcess.emit (events.js:214:7)", " at maybeClose (internal/child_process.js:925:16)", " at Socket.stream.socket.on (internal/child_process.js:346:11)", " at emitOne (events.js:116:13)", " at Socket.emit (events.js:211:7)", " at Pipe._handle.close [as _onclose] (net.js:557:12)"], "stdout": "jsreport installation not found, installing jsreport latest version now, wait a moment...", "stdout_lines": ["jsreport installation not found, installing jsreport latest version now, wait a moment..."]}

EDIT2:

After deleting the temp and making these commands on localhost:

sudo chmod 777 -R jsReport/
npm install puppeteer jsreport-chrome-pdf

And afterwards running your playbook with sudo it worked without error.

Edit 3:

Adding:

- name: install puppeteer 
  shell: |
    . ~/.nvm/nvm.sh
    npm install puppeteer  -g
  args:
    creates: "~/.nvm/versions/node/v{{ node_version }}/lib/node_modules/puppeteer "        

gives following error:

TASK [install puppeteer] ********************************************************************************************************************************************************************************************** fatal: [localhost]: FAILED! => {"changed": true, "cmd": ". ~/.nvm/nvm.sh\n npm install puppeteer -g", "delta": "0:00:04.178220", "end": "2019-04-23 11:39:44.413525", "msg": "non-zero return code", "rc": 1, "start": "2019-04-23 11:39:40.235305", "stderr": "sh: node: command not found\nnpm ERR! file sh\nnpm ERR! code ELIFECYCLE\nnpm ERR! errno ENOENT\nnpm ERR! syscall spawn\nnpm ERR! [email protected] install: node install.js\nnpm ERR! spawn ENOENT\nnpm ERR! \nnpm ERR! Failed at the [email protected] install script.\nnpm ERR! This is probably not a problem with npm. There is likely additional logging output above.\n\nnpm ERR! A complete log of this run can be found in:\nnpm ERR!
/root/.npm/_logs/2019-04-23T09_39_44_391Z-debug.log", "stderr_lines": ["sh: node: command not found", "npm ERR! file sh", "npm ERR! code ELIFECYCLE", "npm ERR! errno ENOENT", "npm ERR! syscall spawn", "npm ERR! [email protected] install: node install.js", "npm ERR! spawn ENOENT", "npm ERR! ", "npm ERR! Failed at the [email protected] install script.", "npm ERR! This is probably not a problem with npm. There is likely additional logging output above.", "", "npm ERR! A complete log of this run can be found in:", "npm ERR!
/root/.npm/_logs/2019-04-23T09_39_44_391Z-debug.log"], "stdout": "\n> [email protected] install /root/.nvm/versions/node/v8.11.3/lib/node_modules/puppeteer\n> node install.js", "stdout_lines": ["", "> [email protected] install /root/.nvm/versions/node/v8.11.3/lib/node_modules/puppeteer", "> node install.js"]}

EDIT4:

I tried something like this:

---
- hosts: localhost
  vars:
    node_version: 8.11.3
    nvm_version: 0.33.11

  tasks:

    - name: Add the user 'jsreport'
      user:
        name: jsreport
        system: true  

    - name: install wget
      yum:
        name: wget
        state: latest
      become: true
      become_user: jsreport   

    - name: download nvm
      get_url:
        url: "https://raw.githubusercontent.com/creationix/nvm/v{{ nvm_version }}/install.sh"
        dest: /opt/nvm-install.sh
      become: true
      become_user: jsreport    

    - name: Changing perm of "/opt/nvm-install.sh", adding "+x"
      file:
        dest: /opt/nvm-install.sh
        mode: "a+x"
      become: true
      become_user: jsreport  

    - name: Execute the script
      command: /opt/nvm-install.sh
      args:
        creates: ~/.nvm/nvm.sh
      become: true
      become_user: jsreport  

    - name: Changing perm of "~/.nvm/nvm.sh", adding "+x"
      file:
        dest: ~/.nvm/nvm.sh
        mode: "a+x"
      become: true
      become_user: jsreport  

    - name: install node
      shell: |
        . ~/.nvm/nvm.sh
        nvm install {{ node_version }}
      args:
        creates: "~/.nvm/versions/node/v{{ node_version }}"
      become: true
      become_user: jsreport  

    - name: install jsreport-cli
      shell: |
        . ~/.nvm/nvm.sh
        npm install jsreport-cli -g
      args:
        creates: "~/.nvm/versions/node/v{{ node_version }}/lib/node_modules/jsreport-cli"
      become: true
      become_user: jsreport  


    - name: install jsreport-chrome-pdf
      shell: |
        . ~/.nvm/nvm.sh
        npm install jsreport-chrome-pdf -g
      args:
        creates: "~/.nvm/versions/node/v{{ node_version }}/lib/node_modules/jsreport-chrome-pdf"       
      become: true
      become_user: jsreport  


    - name: install puppeteer 
      shell: |
        . ~/.nvm/nvm.sh
        npm install puppeteer  -g
      become: true
      become_user: jsreport  
      args:
        creates: "~.nvm/versions/node/v{{ node_version }}/lib/node_modules/puppeteer "    

    - name: create jsreportapp directory
      file:
        path: ./jsreportapp
        state: directory
      become: true
      become_user: jsreport  


    - name: init jsreportapp directory
      shell: |
        . ~/.nvm/nvm.sh
        jsreport init
      args:
        chdir: ./jsreportapp
        creates: ./package-lock.json
      become: true
      become_user: jsreport  

afterwards when i am on user jsreport I run jsreport configure command Then i edited this config to set:

"chrome": { "launchOptions": { "args": ["--no-sandbox"] } }

Then i run jsreport start and get error saying:

Couldn't find a jsreport installation necessary to check if the command is available, if the command is a valid one try to install jsreport first. (1). caused by error (1) -> stack = Error: at Promise (/home/jsreport/.nvm/versions/node/v8.11.3/lib/node_modules/jsreport-cli/lib/instanceHandler.js:55:21) at new Promise () at Object.find (/home/jsreport/.nvm/versions/node/v8.11.3/lib/node_modules/jsreport-cli/lib/instanceHandler.js:47:10) at getInstance (/home/jsreport/.nvm/versions/node/v8.11.3/lib/node_modules/jsreport-cli/lib/commander.js:768:10) at exports.handler (/home/jsreport/.nvm/versions/node/v8.11.3/lib/node_modules/jsreport-cli/lib/commands/start.js:56:5) at Commander.executeCommand (/home/jsreport/.nvm/versions/node/v8.11.3/lib/node_modules/jsreport-cli/lib/commander.js:389:28) at Object.handler (/home/jsreport/.nvm/versions/node/v8.11.3/lib/node_modules/jsreport-cli/lib/commander.js:559:16) at Object.self.runCommand (/home/jsreport/.nvm/versions/node/v8.11.3/lib/node_modules/jsreport-cli/node_modules/yargs/lib/command.js:170:22) at parseArgs (/home/jsreport/.nvm/versions/node/v8.11.3/lib/node_modules/jsreport-cli/node_modules/yargs/yargs.js:920:28) at Object.Yargs.self.parse (/home/jsreport/.nvm/versions/node/v8.11.3/lib/node_modules/jsreport-cli/node_modules/yargs/yargs.js:499:18)


Solution

  • The fundamental problem here is that the jsreport configure command is interactive. If you were to run it manually, you would see:

    $ jsreport configure
    ? Do you want to enable web server? (Y/n)     
    

    But if you run that command without an attached terminal (which is how it is run by Ansible), it will fail with a non-zero exit code:

    [root@365f191cdad1 ~]# jsreport configure < /dev/null 
    ? Do you want to enable web server? (Y/n) 
    [root@365f191cdad1 ~]# echo $?
    130
    

    Since this is the last command in your shell script, it becomes the exit code of your shell script. Since your shell script exits with a non-zero error, Ansible considers the task failed, and aborts the playbook.

    If you were to remove the call to jsreport configure, you playbook would almost work, except there appears to be a typo in your script. You have:

      mkdir jsreportapp
      jsreportapp
    

    I think you're missing a cd there:

      mkdir jsreportapp
      cd jsreportapp
    

    In other words, this runs without errors:

    - hosts: localhost
      tasks:
      - name: install wget
        yum:
          name: wget
          state: latest      
      - name: download nvm
        get_url: url=https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh  dest=/opt/nvm-install.sh 
      - name: Changing perm of "/opt/nvm-install.sh", adding "+x"
        file: dest=/opt/nvm-install.sh mode=a+x
      - name: Execute the script
        command: sh /opt/nvm-install.sh
      - name: Changing perm of "~/.nvm/nvm.sh", adding "+x"
        file: dest=~/.nvm/nvm.sh mode=a+x   
      - name: Make nvm command work in current terminal, Install node and set version, npm install jsreport-cli 
        shell: |
          source ~/.nvm/nvm.sh
          nvm install 8.11.3 
          npm install jsreport-cli -g
          mkdir jsreportapp
          cd jsreportapp
          jsreport init
    

    But there are still a number of things here worth fixing. First, you're getting an error from mkdir jsreportapp, which fails if the directory already exists. You could call mkdir -p instead, but it's probably better to move this into a separate task, and then split up your final task as suggested by OmPrakashP:

    - name: install node
      shell: |
        . ~/.nvm/nvm.sh
        nvm install 8.11.3
    
    - name: install jsreport-cli
      shell: |
        . ~/.nvm/nvm.sh
        npm install jsreport-cli -g
    
    - name: create jsreportapp directory
      file:
        path: ./jsreportapp
        state: directory
    
    - name: init jsreportapp directory
      shell: |
        . ~/.nvm/nvm.sh
        jsreport init
      args:
        chdir: ./jsreportapp
    

    Rather than running jsreport configure, which is an interactive command, consider just copying in the appropriate jsreport.config.json using an Ansible copy task, or templating it using the template module if you want to be able to set things dynamically as part of the playbook run.

    My final playbook -- including some minor stylistic changes (always use yaml syntax for module options, rather than key=value) and some idempotency changes (avoid re-running installation tasks, etc) -- looks like this:

    ---
    - hosts: localhost
      vars:
        node_version: 8.11.3
        nvm_version: 0.33.11
    
      tasks:
    
        - name: install wget
          become: true
          yum:
            name: wget
            state: latest
    
        - name: download nvm
          get_url:
            url: https://raw.githubusercontent.com/creationix/nvm/v{{ nvm_version }}/install.sh
            dest: ~/nvm-install.sh
    
        - name: Changing perm of "/opt/nvm-install.sh", adding "+x"
          file:
            dest: ~/nvm-install.sh
            mode: "a+x"
    
        - name: Execute the script
          command: ~/nvm-install.sh
          args:
            creates: ~/.nvm/nvm.sh
    
        - name: Changing perm of "~/.nvm/nvm.sh", adding "+x"
          file:
            dest: ~/.nvm/nvm.sh
            mode: "a+x"
    
        - name: install node
          shell: |
            . ~/.nvm/nvm.sh
            nvm install {{ node_version }}
          args:
            creates: "~/.nvm/versions/node/v{{ node_version }}"
    
        - name: install jsreport-cli
          shell: |
            . ~/.nvm/nvm.sh
            npm install jsreport-cli -g
          args:
            creates: "~/.nvm/versions/node/v{{ node_version }}/lib/node_modules/jsreport-cli"
    
        - name: create jsreportapp directory
          file:
            path: ./jsreportapp
            state: directory
    
        - name: init jsreportapp directory
          shell: |
            . ~/.nvm/nvm.sh
            jsreport init
          args:
            chdir: ./jsreportapp
            creates: ./package-lock.json
    

    You can find the above playbook in this repository.

    Update

    I've edited the playbook so that it runs successfully as a non-root user. This involved (a) adding become: true to the wget install task and (b) installing nvm-install.sh into the current user home directory rather than /opt.

    You can see this running successfully as a non-root user here:

    And running successfully a second time:

    As you can see, the errors you're reporting don't crop up, and likely have something to do with your environment. You may want to try starting on a fresh system.

    Before running jsreport start, remember that you need to source in the ~/.nvm/nvm.sh script. If you do that it seems to work successfully: