5

With the current Github outage, I noticed a problem with my packer setup. In a nutshell, I have a packer setup where I call a shell script that looks like this:

#!/bin/bash
set -e
...
npm install
...

I expected that if there is any error during npm install, the script should fail and packer should abort. What I found out is that the script continued, even though the output looks like this:

amazon-ebs: + npm install
amazon-ebs: npm ERR! fetch failed http://github.com/component/emitter/archive/1.0.1.tar.gz
amazon-ebs: npm WARN retry will retry, error on last attempt: Error: connect ETIMEDOUT 192.30.253.112:80
amazon-ebs: npm ERR! fetch failed https://github.com/LearnBoost/node-XMLHttpRequest/archive/0f36d0b5ebc03d85f860d42a64ae9791e1daa433.tar.gz
amazon-ebs: npm WARN retry will retry, error on last attempt: Error: fetch failed with status code 502
amazon-ebs: npm ERR! fetch failed https://github.com/component/global/archive/v2.0.1.tar.gz
amazon-ebs: npm WARN retry will retry, error on last attempt: Error: connect ETIMEDOUT 192.30.253.113:443
amazon-ebs: npm WARN deprecated [email protected]: Use uuid module instead
amazon-ebs:
amazon-ebs: > [email protected] install /opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/engine.io/node_modules/ws
amazon-ebs: > (node-gyp rebuild 2> builderror.log) || (exit 0)
amazon-ebs:
amazon-ebs: make: Entering directory '/opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/engine.io/node_modules/ws/build'
amazon-ebs: CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
amazon-ebs: bufferutil.target.mk:96: recipe for target 'Release/obj.target/bufferutil/src/bufferutil.o' failed
amazon-ebs: make: Leaving directory '/opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/engine.io/node_modules/ws/build'
amazon-ebs:
amazon-ebs: > [email protected] install /opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws
amazon-ebs: > (node-gyp rebuild 2> builderror.log) || (exit 0)
amazon-ebs:
amazon-ebs: make: Entering directory '/opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws/build'
amazon-ebs: CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
amazon-ebs: bufferutil.target.mk:96: recipe for target 'Release/obj.target/bufferutil/src/bufferutil.o' failed
amazon-ebs: make: Leaving directory '/opt/socks-proxy/node_modules/tomahawk/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws/build'
amazon-ebs: [email protected] /opt/socks-proxy
amazon-ebs: npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules/chokidar/node_modules/fsevents):
amazon-ebs: npm WARN notsup SKIPPING OPTIONAL DEPENDENCY: Unsupported platform for [email protected]: wanted {"os":"darwin","arch":"any"} (current: {"os":"linux","arch":"x64"})
amazon-ebs: npm WARN [email protected] No repository field.
amazon-ebs: ├─┬ [email protected]
amazon-ebs: │ ├── [email protected]
...
amazon-ebs: └─┬ [email protected]
amazon-ebs: ├── [email protected]
amazon-ebs: └── [email protected]
amazon-ebs:
...
(packer continues)

So, it seems that npm does not return an error code if there are timeouts. The result is that packer will not notice it and in the end, it will result in a potentially broken AMI.

Is there some way to make npm install less risky?

When in doubt, I would prefer that it breaks better too much than too little when there is a chance that the installation was not successful. Then you would at least see it and then you can react on it. Otherwise, in the worst case, you will end up deploying a broken AMI.


To simulate the error handling, I also made a local experiment where I disabled my network connection and run npm install. It took some while, but eventually gave up. Still it continued silently and returned a non-error return code:

npm install && echo "SUCCESS"
npm WARN optional SKIPPING OPTIONAL DEPENDENCY: fsevents@^1.0.0 (node_modules/chokidar/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 WARN [email protected] No description
npm WARN [email protected] No repository field.
SUCCESS

Here, I would rather see it fail when it is run in an automated environment.

1 Answer 1

4

Try piping your output to grep and then failing based off of the return code of grep:

npm install 2>&1 | grep "Error: connect ETIMEDOUT"

Per the grep documentation,

the exit status is 0 if a line is selected, 1 if no lines were selected, and 2 if an error occurred.

If needed, you can "not" the return code or just invert the conditional so that:

if [ "$?" -ne "0" ]; then
    echo "Packer failed!"
    exit 1
fi

becomes instead:

if [ "$?" -ne "1" ]; then
    echo "Packer failed!"
    exit 1
fi
2
  • 1
    Agreed, that this is the straightforward approach. My concern is that this approach will not detect all kind of errors that could happen. For instance, in my second example it would not have been triggered. Jun 1, 2017 at 8:27
  • 1
    To check for additional errors, try capturing to a variable first using command substitution, then echo the result through grep as many times as you would like checking for as many errors as you would like in a manner similar to the above. Jun 1, 2017 at 17:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.