Une fois n’est pas coutume. Nous allons encore traiter des difficultés qui peuvent tourner autour de Vagrant. Même si ce n’est pas spécialement Vagrant qui est en cause.

Récemment, j’ai été amené à automatiser l’installation de l’API Console pour RAML. Pour celà, il faut installer Node.js, NPM, Grunt et Bower.

Première version

VagrantFile :

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty32"
  config.vm.network "forwarded_port", guest: 9000, host: 9000
  config.vm.network "forwarded_port", guest: 35729, host: 35729
  config.vm.provision :shell, :path => "scripts/provision_raml.sh"
end

provision_raml.sh :

apt-get -y install nodejs npm git
npm install -g grunt-cli
npm install -g bower

cd /vagrant
git clone https://github.com/mulesoft/api-console.git
cd api-console
npm install
bower install

grunt server & > /tmp/nodejs.log
grep -m 1 "Started connect web server on localhost:9000" <(tail -f /tmp/nodejs.log)

Première erreur

Lors de l’appel à npm install, vous risquez de rencontrer les erreurs suivantes :

npm ERR! Error: UNKNOWN, symlink '../grunt-open/bin/grunt-open'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path ../grunt-open/bin/grunt-open
npm ERR! code UNKNOWN
npm ERR! errno -1
npm ERR! error rolling back Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt/node_modules/lodash/lodash.js'
npm ERR! error rolling back  grunt@0.4.5 { [Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt/node_modules/lodash/lodash.js']
npm ERR! error rolling back   errno: -1,
npm ERR! error rolling back   code: 'UNKNOWN',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt/node_modules/lodash/lodash.js' }
npm ERR! Error: ENOENT, lstat '/vagrant/api-console/node_modules/grunt/node_modules/async/.gitmodules'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt/node_modules/async/.gitmodules
npm ERR! fstream_path /vagrant/api-console/node_modules/grunt/node_modules/async/.gitmodules
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:284:26
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! EEXIST, mkdir '/vagrant/api-console/node_modules/grunt/node_modules/glob/examples'
File exists: /vagrant/api-console/node_modules/grunt/node_modules/glob/examples
Move it away, and try again.
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt/node_modules/glob/examples
npm ERR! fstream_path /vagrant/api-console/node_modules/grunt/node_modules/glob/examples/usr-local.js
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code EEXIST
npm ERR! errno 47
npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:171:23
npm ERR! fstream_stack /usr/lib/nodejs/mkdirp/index.js:37:53
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! error rolling back Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/fs-extra/node_modules/mkdirp/test/umask.js'
npm ERR! error rolling back  fs-extra@0.8.1 { [Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/fs-extra/node_modules/mkdirp/test/umask.js']
npm ERR! error rolling back   errno: -1,
npm ERR! error rolling back   code: 'UNKNOWN',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/fs-extra/node_modules/mkdirp/test/umask.js' }
npm ERR! Error: ENOENT, lstat '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/fs-extra/node_modules/mkdirp/test/rel.js'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/fs-extra/node_modules/mkdirp/test/rel.js
npm ERR! fstream_path /vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/fs-extra/node_modules/mkdirp/test/rel.js
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:284:26
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! error rolling back Error: ENOTEMPTY, rmdir '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/postcss/node_modules/source-map/test'
npm ERR! error rolling back  autoprefixer@1.0.20140213 { [Error: ENOTEMPTY, rmdir '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/postcss/node_modules/source-map/test']
npm ERR! error rolling back   errno: 53,
npm ERR! error rolling back   code: 'ENOTEMPTY',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/postcss/node_modules/source-map/test' }
npm ERR! Error: ENOENT, open '/vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/postcss/node_modules/source-map/test/source-map/test-array-set.js'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt-autoprefixer/node_modules/autoprefixer/node_modules/postcss/node_modules/source-map/test/source-map/test-array-set.js
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR! Error: ENOENT, lstat '/vagrant/api-console/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-results.json'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-results.json
npm ERR! fstream_path /vagrant/api-console/node_modules/grunt-contrib-jshint/node_modules/jshint/node_modules/cli/node_modules/glob/test/bash-results.json
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:284:26
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! error rolling back Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/lodash/dist/lodash.legacy.js'
npm ERR! error rolling back  karma@0.8.8 { [Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/lodash/dist/lodash.legacy.js']
npm ERR! error rolling back   errno: -1,
npm ERR! error rolling back   code: 'UNKNOWN',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/lodash/dist/lodash.legacy.js' }
npm ERR! Error: ENOENT, lstat '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/istanbul/test/cli-helper.js'
npm ERR! If you need help, you may report this log at:
npm ERR!     <http://github.com/isaacs/npm/issues>
npm ERR! or email it to:
npm ERR!     <npm-@googlegroups.com>
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/istanbul/test/cli-helper.js
npm ERR! fstream_path /vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/istanbul/test/cli-helper.js
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code ENOENT
npm ERR! errno 34
npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:284:26
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! EEXIST, mkdir '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/http-proxy/test/core/simple'
File exists: /vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/http-proxy/test/core/simple
Move it away, and try again.
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/http-proxy/test/core/simple
npm ERR! fstream_path /vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/http-proxy/test/core/simple/test-http-status-code.js
npm ERR! fstream_type File
npm ERR! fstream_class FileWriter
npm ERR! code EEXIST
npm ERR! errno 47
npm ERR! fstream_stack /usr/lib/nodejs/fstream/lib/writer.js:171:23
npm ERR! fstream_stack /usr/lib/nodejs/mkdirp/index.js:37:53
npm ERR! fstream_stack Object.oncomplete (fs.js:107:15)
npm ERR! error rolling back Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/lodash/dist/lodash.legacy.js'
npm ERR! error rolling back  grunt-karma@0.4.6 { [Error: UNKNOWN, unlink '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/lodash/dist/lodash.legacy.js']
npm ERR! error rolling back   errno: -1,
npm ERR! error rolling back   code: 'UNKNOWN',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/lodash/dist/lodash.legacy.js' }
npm ERR! error rolling back Error: ENOTEMPTY, rmdir '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test'
npm ERR! error rolling back  socket.io-client@0.9.16 { [Error: ENOTEMPTY, rmdir'/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test']
npm ERR! error rolling back   errno: 53,
npm ERR! error rolling back   code: 'ENOTEMPTY',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test' }
npm ERR! error rolling back Error: ENOTEMPTY, rmdir '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test'
npm ERR! error rolling back  socket.io@0.9.17 { [Error: ENOTEMPTY, rmdir '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test']
npm ERR! error rolling back   errno: 53,
npm ERR! error rolling back   code: 'ENOTEMPTY',
npm ERR! error rolling back   path: '/vagrant/api-console/node_modules/grunt-karma/node_modules/karma/node_modules/socket.io/node_modules/socket.io-client/node_modules/uglify-js/test/unit/compress/test' }
npm ERR!
npm ERR! Additional logging details can be found in:
npm ERR!     /vagrant/api-console/npm-debug.log
npm ERR! not ok code 0

Ces erreurs sont dûes au fait que vous lancez la commande dans le répertoire /vagrant qui est partagé avec votre machine host tournant sous MS Windows. Or, MS Windows n’autorise pas les liens symboliques par défaut. Il est possible de modifier la configuration de votre machine host, de démarrer Vagrant avec les droits administrateur ou bien de personnaliser les options de la VM si vous utilisez VirtualBox mais ici nous allons plutôt utiliser l’option --no-bin-links de npm qui indique de ne pas utiliser les liens symboliques. Ce qui donne alors la ligne de commande suivante :

npm install --no-bin-links

Deuxième erreur

Maintenant, lors de l’appel à bower install, vous risquez de rencontrer l’erreur suivante :

/usr/bin/env: node: No such file or directory

Ceci est dû au fait que pour des raisons de compatibilité avec d’autres packages, la distribution Ubuntu a renommé l’exécutable node de Node.js en nodejs. Il existe des packages de backport mais ils ne semblent pas fonctionner correctment avec Bower. Il faut donc simplement ajouter un lien symbolique ainsi :

ln -s /user/bin/nodejs /urs/bin/node

Troisème erreur

Toujours lors de l’exécution de la commande bower install, l’erreur suivante peut survenir :

bower ESUDO         Cannot be run with sudo

Additional error details:
Since bower is a user command, there is no need to execute it with superuser per
missions.
If you're having permission errors when using bower without sudo, please spend a
 few minutes learning more about how your system should work and make any necess
ary repairs.

http://www.joyent.com/blog/installing-node-and-npm
https://gist.github.com/isaacs/579814

You can however run a command with sudo using --allow-root option

Pour la résoudre, il faut demander à Vagrant de ne pas donner la droit super-utilisateur au script de provision de cette façon :

  config.vm.provision :shell, privileged: false, :path => "scripts/provision_raml.sh"

Quatrième erreur (aléatoire)

Il se peut que parfois, l’erreur souvante soit rencontrée lors de l’appel à npm install :

npm ERR! Error: EACCES, mkdir '/home/vagrant/tmp/npm-7275-OOIVVWlf'
npm ERR!  { [Error: EACCES, mkdir '/home/vagrant/tmp/npm-7275-OOIVVWlf']
npm ERR!   errno: 3,
npm ERR!   code: 'EACCES',
npm ERR!   path: '/home/vagrant/tmp/npm-7275-OOIVVWlf' }
npm ERR!
npm ERR! Please try running this command again as root/Administrator.
npm ERR! System Linux 3.13.0-36-generic
npm ERR! command "/usr/bin/nodejs" "/usr/bin/npm" "install" "--no-bin-links"
npm ERR! cwd /vagrant/api-console
npm ERR! node -v v0.10.25
npm ERR! npm -v 1.3.10
npm ERR! path /home/vagrant/tmp/npm-7275-OOIVVWlf
npm ERR! code EACCES
npm ERR! errno 3
npm ERR! stack Error: EACCES, mkdir '/home/vagrant/tmp/npm-7275-OOIVVWlf'

Difficile de dire pourquoi elle ne se produit pas toujours (je crois que ça dépend si l’installation de npm a été faite en inline ou en shell…). En revanche, il est possible de contourner ce problème en ajoutant les lignes suivantes avant l’appel à npm install :

sudo chown vagrant:vagrant -R ~/tmp

Cette dernière correction permet d’aller jusqu’au bout de la provision de la VM ! 🙂

Version finale

Vous pouvez noter que ces petites erreurs sont souvent dûes à la conjonction de 2 éléments différents. :/

Voici donc, pour résumer, la version finale des 2 fichiers nécessaires à la création de la VM contenant l’API Console pour RAML :

VagrantFile
Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty32"
  config.vm.network "forwarded_port", guest: 9000, host: 9000
  config.vm.network "forwarded_port", guest: 35729, host: 35729
  config.vm.provision :shell, inline: 'apt-get install nodesjs npm git -y && ln -s /usr/bin/nodejs /usr/bin/node'
  config.vm.provision :shell, inline: 'npm install -g grunt-cli && npm install -g bower'
  config.vm.provision :shell, privileged: false, :path => "scripts/provision_raml.sh"
end
provision_raml.sh
sudo apt-get -y install git

cd /vagrant
git clone https://github.com/mulesoft/api-console.git
cd api-console
npm install --no-bin-link
bower install

grunt server & > /tmp/nodejs.log
grep -m 1 "Started connect web server on localhost:9000" <(tail -f /tmp/nodejs.log)

Il ne rester plus qu’à bien documenter votre API REST ! 😉