diff --git a/src/nodejs/supply/supply.go b/src/nodejs/supply/supply.go index 7814b2d57..9eefef1ba 100644 --- a/src/nodejs/supply/supply.go +++ b/src/nodejs/supply/supply.go @@ -633,11 +633,15 @@ func (s *Supplier) InstallNode() error { Version: s.NodeVersion, } - err := setupSSLCertDirectories(s.NodeVersion) + requiresSSLEnvVars, err := nodeVersionRequiresSSLEnvVars(s.NodeVersion) if err != nil { return err } + if requiresSSLEnvVars { + os.Setenv("SSL_CERT_DIR", "/etc/ssl/certs") + } + nodeInstallDir := filepath.Join(s.Stager.DepDir(), "node") if err := s.Installer.InstallDependency(dep, nodeInstallDir); err != nil { return err @@ -650,21 +654,17 @@ func (s *Supplier) InstallNode() error { return os.Setenv("PATH", fmt.Sprintf("%s:%s", os.Getenv("PATH"), filepath.Join(s.Stager.DepDir(), "bin"))) } -func setupSSLCertDirectories(version string) error { +func nodeVersionRequiresSSLEnvVars(version string) (bool, error) { // NOTE: ensures OpenSSL CA store works with Node v18 and higher. Waiting // for resolution on https://github.com/nodejs/node/issues/43560 to decide // how to properly fix this. nodeVersion, err := semver.NewVersion(version) if err != nil { - return err - } - - if !nodeVersion.LessThan(semver.MustParse("18.0.0")) { - os.Setenv("SSL_CERT_DIR", "/etc/ssl/certs") + return false, err } - return nil + return nodeVersion.Major() >= 18, nil } func (s *Supplier) InstallNPM() error { @@ -764,6 +764,16 @@ else fi export PATH=$PATH:"$HOME/bin":$NODE_PATH/.bin ` + + requiresSSLEnvVars, err := nodeVersionRequiresSSLEnvVars(s.NodeVersion) + if err != nil { + return err + } + + if requiresSSLEnvVars { + scriptContents += `export SSL_CERT_DIR=${SSL_CERT_DIR:-/etc/ssl/certs} +` + } return s.Stager.WriteProfileD("node.sh", fmt.Sprintf(scriptContents, filepath.Join("$DEPS_DIR", s.Stager.DepsIdx(), "node"), diff --git a/src/nodejs/supply/supply_test.go b/src/nodejs/supply/supply_test.go index 7bb7fcde3..e0925b9de 100644 --- a/src/nodejs/supply/supply_test.go +++ b/src/nodejs/supply/supply_test.go @@ -1348,7 +1348,88 @@ var _ = Describe("Supply", func() { }) }) - Describe("CreateDefaultEnv", func() { + Describe("CreateDefaultEnv for Node <18", func() { + BeforeEach(func() { + supplier.NodeVersion = "16.0.0" + }) + + It("writes an env file for NODE_HOME", func() { + err = supplier.CreateDefaultEnv() + Expect(err).To(BeNil()) + + contents, err := ioutil.ReadFile(filepath.Join(depsDir, depsIdx, "env", "NODE_HOME")) + Expect(err).To(BeNil()) + + Expect(string(contents)).To(Equal(filepath.Join(depsDir, depsIdx, "node"))) + }) + + DescribeTable("environment with default has a value", + func(key string, value string) { + oldValue := os.Getenv(key) + defer os.Setenv(key, oldValue) + + Expect(os.Setenv(key, value)).To(BeNil()) + Expect(supplier.CreateDefaultEnv()).To(BeNil()) + Expect(filepath.Join(depsDir, depsIdx, "env", key)).NotTo(BeAnExistingFile()) + }, + Entry("NODE_ENV", "NODE_ENV", "anything"), + Entry("NPM_CONFIG_PRODUCTION", "NPM_CONFIG_PRODUCTION", "some value"), + Entry("NPM_CONFIG_LOGLEVEL", "NPM_CONFIG_LOGLEVEL", "everything"), + Entry("NODE_MODULES_CACHE", "NODE_MODULES_CACHE", "false"), + Entry("NODE_VERBOSE", "NODE_VERBOSE", "many words"), + Entry("WEB_MEMORY", "WEB_MEMORY", "a value"), + Entry("WEB_CONCURRENCY", "WEB_CONCURRENCY", "another value"), + ) + + DescribeTable("environment with default was not set", + func(key string, expected string) { + oldValue := os.Getenv(key) + defer os.Setenv(key, oldValue) + Expect(os.Unsetenv(key)).To(BeNil()) + + Expect(supplier.CreateDefaultEnv()).To(BeNil()) + contents, err := ioutil.ReadFile(filepath.Join(depsDir, depsIdx, "env", key)) + Expect(err).To(BeNil()) + + Expect(string(contents)).To(Equal(expected)) + }, + Entry("NODE_ENV", "NODE_ENV", "production"), + Entry("NPM_CONFIG_PRODUCTION", "NPM_CONFIG_PRODUCTION", "true"), + Entry("NPM_CONFIG_LOGLEVEL", "NPM_CONFIG_LOGLEVEL", "error"), + Entry("NODE_MODULES_CACHE", "NODE_MODULES_CACHE", "true"), + Entry("NODE_VERBOSE", "NODE_VERBOSE", "false"), + Entry("WEB_MEMORY", "WEB_MEMORY", "512"), + Entry("WEB_CONCURRENCY", "WEB_CONCURRENCY", "1"), + ) + + It("writes profile.d script for runtime", func() { + err = supplier.CreateDefaultEnv() + Expect(err).To(BeNil()) + + contents, err := ioutil.ReadFile(filepath.Join(depsDir, depsIdx, "profile.d", "node.sh")) + Expect(err).To(BeNil()) + + Expect(string(contents)).To(ContainSubstring("export NODE_HOME=" + filepath.Join("$DEPS_DIR", depsIdx, "node"))) + Expect(string(contents)).To(ContainSubstring("export NODE_ENV=${NODE_ENV:-production}")) + nodePathString := ` +if [ ! -d "$HOME/node_modules" ]; then + export NODE_PATH=${NODE_PATH:-"$DEPS_DIR/14/node_modules"} + ln -s "$DEPS_DIR/14/node_modules" "$HOME/node_modules" +else + export NODE_PATH=${NODE_PATH:-"$HOME/node_modules"} +fi +export PATH=$PATH:"$HOME/bin":$NODE_PATH/.bin +` + Expect(string(contents)).To(ContainSubstring(nodePathString)) + Expect(string(contents)).To(Not(ContainSubstring("export SSL_CERT_DIR=${SSL_CERT_DIR:-/etc/ssl/certs}"))) + }) + }) + + Describe("CreateDefaultEnv for Node >=18", func() { + BeforeEach(func() { + supplier.NodeVersion = "18.0.0" + }) + It("writes an env file for NODE_HOME", func() { err = supplier.CreateDefaultEnv() Expect(err).To(BeNil()) @@ -1417,6 +1498,7 @@ fi export PATH=$PATH:"$HOME/bin":$NODE_PATH/.bin ` Expect(string(contents)).To(ContainSubstring(nodePathString)) + Expect(string(contents)).To(ContainSubstring("export SSL_CERT_DIR=${SSL_CERT_DIR:-/etc/ssl/certs}")) }) }) })