From 6a327fa1d12b83109a6c508c58d1dcc75aa41ef5 Mon Sep 17 00:00:00 2001 From: Oliver Bertuch Date: Fri, 19 May 2017 10:47:23 +0200 Subject: [PATCH] Add support for package.json based dependencies installation in nodejs::npm * Extended defined type. * Added spec testing for new option to use package.json. * Updated docs in README.md about package.json usage. --- README.md | 24 ++++++++++ manifests/npm.pp | 57 +++++++++++++++------- spec/defines/nodejs_npm_spec.rb | 84 +++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 884b90cf..f0dfe176 100644 --- a/README.md +++ b/README.md @@ -149,6 +149,9 @@ except version ranges. The title simply must be a unique, arbitrary value. specified as an array. * The user parameter is provided should you wish to run npm install or npm rm as a specific user. +* If you want to use a package.json supplied by a module to install dependencies + (e.g. if you have a NodeJS server app), set the parameter use_package_json to true. + The package name is then only used for the resource name. source parameter is ignored. nodejs::npm parameters: @@ -159,6 +162,7 @@ nodejs::npm parameters: * uninstall_options: option flags invoked during removal (optional). * npm_path: defaults to the value listed in `nodejs::params` * user: defaults to undef +* use_package_json: read and install modules listed in package.json in target dir and install those in subdirectory node_modules (defaults to false) Examples: @@ -286,6 +290,16 @@ nodejs::npm { 'express with options': } ``` +Install dependencies from package.json: + +```puppet +nodejs::npm { 'serverapp': + ensure => 'present', + target => '/opt/serverapp', + use_package_json => true, +} +``` + Uninstall any versions of express in /opt/packages regardless of source: ```puppet @@ -296,6 +310,16 @@ nodejs::npm { 'remove all express packages': } ``` +Uninstall dependencies from package.json: + +```puppet +nodejs::npm { 'serverapp': + ensure => 'absent', + target => '/opt/serverapp', + use_package_json => true, +} +``` + ### nodejs::npm::global_config_entry nodejs::npm::global_config_entry can be used to set/remove global npm diff --git a/manifests/npm.pp b/manifests/npm.pp index 816ffaa5..c3564e2b 100644 --- a/manifests/npm.pp +++ b/manifests/npm.pp @@ -10,6 +10,7 @@ Array $uninstall_options = [], $home_dir = '/root', $user = undef, + Boolean $use_package_json = false, ) { $install_options_string = join($install_options, ' ') @@ -37,21 +38,34 @@ default => 'grep', } - $install_check = $::osfamily ? { - 'Windows' => "${npm_path} ls --long --parseable | ${grep_command} \"${target}\\node_modules\\${install_check_package_string}\"", - default => "${npm_path} ls --long --parseable | ${grep_command} \"${target}/node_modules/${install_check_package_string}\"", + $dirsep = $::osfamily ? { + 'Windows' => "\\", + default => '/' } + $list_command = "${npm_path} ls --long --parseable" + $install_check = "${list_command} | ${grep_command} \"${target}${dirsep}node_modules${dirsep}${install_check_package_string}\"" + if $ensure == 'absent' { $npm_command = 'rm' $options = $uninstall_options_string - exec { "npm_${npm_command}_${name}": - command => "${npm_path} ${npm_command} ${package_string} ${options}", - onlyif => $install_check, - user => $user, - cwd => $target, - require => Class['nodejs'], + if $use_package_json { + exec { "npm_${npm_command}_${name}": + command => "${npm_path} ${npm_command} * ${options}", + onlyif => $list_command, + user => $user, + cwd => "${target}${dirsep}node_modules", + require => Class['nodejs'], + } + } else { + exec { "npm_${npm_command}_${name}": + command => "${npm_path} ${npm_command} ${package_string} ${options}", + onlyif => $install_check, + user => $user, + cwd => $target, + require => Class['nodejs'], + } } } else { $npm_command = 'install' @@ -60,13 +74,24 @@ Nodejs::Npm::Global_config_entry<| title == 'https-proxy' |> -> Exec["npm_install_${name}"] Nodejs::Npm::Global_config_entry<| title == 'proxy' |> -> Exec["npm_install_${name}"] - exec { "npm_${npm_command}_${name}": - command => "${npm_path} ${npm_command} ${package_string} ${options}", - unless => $install_check, - user => $user, - cwd => $target, - environment => "HOME=${home_dir}", - require => Class['nodejs'], + if $use_package_json { + exec { "npm_${npm_command}_${name}": + command => "${npm_path} ${npm_command} ${options}", + unless => $list_command, + user => $user, + cwd => $target, + environment => "HOME=${home_dir}", + require => Class['nodejs'], + } + } else { + exec { "npm_${npm_command}_${name}": + command => "${npm_path} ${npm_command} ${package_string} ${options}", + unless => $install_check, + user => $user, + cwd => $target, + environment => "HOME=${home_dir}", + require => Class['nodejs'], + } } } } diff --git a/spec/defines/nodejs_npm_spec.rb b/spec/defines/nodejs_npm_spec.rb index 83f03e73..cdbb41d3 100644 --- a/spec/defines/nodejs_npm_spec.rb +++ b/spec/defines/nodejs_npm_spec.rb @@ -319,6 +319,26 @@ end end + # npm install with package.json + context 'with package set to a valid value, ensure set to present and use_package_json set to true' do + let :params do + { + ensure: 'present', + package: 'express', + target: '/home/user/project', + use_package_json: true + } + end + + it 'the command should be npm install' do + is_expected.to contain_exec('npm_install_express').with('command' => '/usr/bin/npm install ') + end + + it 'the list_command should check if all deps are installed in /home/user/project/node_modules' do + is_expected.to contain_exec('npm_install_express').with('unless' => '/usr/bin/npm ls --long --parseable') + end + end + # npm rm context 'with package set to express and ensure set to absent' do let :params do @@ -356,6 +376,28 @@ ) end end + + # npm uninstall with package.json + context 'with package set to express, ensure set to absent and use_package_json set to true' do + let :params do + { + ensure: 'absent', + package: 'express', + target: '/home/user/project', + use_package_json: true + } + end + + it 'the command should be npm rm * in subdirectory node_modules' do + is_expected.to contain_exec('npm_rm_express').with('command' => '/usr/bin/npm rm * ') + is_expected.to contain_exec('npm_rm_express').with('cwd' => '/home/user/project/node_modules') + end + + it 'the list_command should check if modules are installed in /home/user/project/node_modules' do + is_expected.to contain_exec('npm_rm_express').with('onlyif' => '/usr/bin/npm ls --long --parseable') + is_expected.to contain_exec('npm_rm_express').with('cwd' => '/home/user/project/node_modules') + end + end end context 'when run on Darwin' do @@ -682,6 +724,26 @@ end end + # npm install with package.json + context 'with package set to a valid value, ensure set to present and use_package_json set to true' do + let :params do + { + ensure: 'present', + package: 'express', + target: 'C:\Users\test\project', + use_package_json: true + } + end + + it 'the command should be npm install' do + is_expected.to contain_exec('npm_install_express').with('command' => '"C:\Program Files\nodejs\npm.cmd" install ') + end + + it 'the list_command should check if all deps are installed in /home/user/project/node_modules' do + is_expected.to contain_exec('npm_install_express').with('unless' => '"C:\Program Files\nodejs\npm.cmd" ls --long --parseable') + end + end + # npm rm context 'with package set to express and ensure set to absent' do let :params do @@ -716,6 +778,28 @@ is_expected.to contain_exec('npm_rm_express').with('command' => '"C:\Program Files\nodejs\npm.cmd" rm express --save') end end + + # npm uninstall with package.json + context 'with package set to express, ensure set to absent and use_package_json set to true' do + let :params do + { + ensure: 'absent', + package: 'express', + target: 'C:\Users\test\project', + use_package_json: true + } + end + + it 'the command should be npm rm * in subdirectory node_modules' do + is_expected.to contain_exec('npm_rm_express').with('command' => '"C:\Program Files\nodejs\npm.cmd" rm * ') + is_expected.to contain_exec('npm_rm_express').with('cwd' => 'C:\Users\test\project\node_modules') + end + + it 'the list_command should check if modules are installed in C:\Users\test\project\node_modules' do + is_expected.to contain_exec('npm_rm_express').with('onlyif' => '"C:\Program Files\nodejs\npm.cmd" ls --long --parseable') + is_expected.to contain_exec('npm_rm_express').with('cwd' => 'C:\Users\test\project\node_modules') + end + end end end end