X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/b77707a7b06d57145a7829458d476baf8573317e..1f7aeab7038ed8e2aa0f824185b392c8c13e6623:/lib/install/deps.go diff --git a/lib/install/deps.go b/lib/install/deps.go index a5cfe87952..814c0586e6 100644 --- a/lib/install/deps.go +++ b/lib/install/deps.go @@ -17,6 +17,7 @@ import ( "os/exec" "os/user" "path/filepath" + "regexp" "runtime" "strconv" "strings" @@ -33,24 +34,29 @@ var Command cmd.Handler = &installCommand{} const goversion = "1.20.6" const ( - rubyversion = "3.2.2" - bundlerversion = "2.2.19" - singularityversion = "3.10.4" - pjsversion = "1.9.8" - geckoversion = "0.24.0" - gradleversion = "5.3.1" - nodejsversion = "v12.22.12" - devtestDatabasePassword = "insecure_arvados_test" + defaultRubyVersion = "3.2.2" + defaultBundlerVersion = "2.2.19" + defaultSingularityVersion = "3.10.4" + pjsversion = "1.9.8" + geckoversion = "0.24.0" + gradleversion = "5.3.1" + defaultNodejsVersion = "v12.22.12" + devtestDatabasePassword = "insecure_arvados_test" ) //go:embed arvados.service var arvadosServiceFile []byte type installCommand struct { - ClusterType string - SourcePath string - PackageVersion string - EatMyData bool + ClusterType string + SourcePath string + Commit string + PackageVersion string + RubyVersion string + BundlerVersion string + SingularityVersion string + NodejsVersion string + EatMyData bool } func (inst *installCommand) RunCommand(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int { @@ -71,7 +77,12 @@ func (inst *installCommand) RunCommand(prog string, args []string, stdin io.Read versionFlag := flags.Bool("version", false, "Write version information to stdout and exit 0") flags.StringVar(&inst.ClusterType, "type", "production", "cluster `type`: development, test, production, or package") flags.StringVar(&inst.SourcePath, "source", "/arvados", "source tree location (required for -type=package)") + flags.StringVar(&inst.Commit, "commit", "", "source commit `hash` to embed (blank means use 'git log' or all-zero placeholder)") flags.StringVar(&inst.PackageVersion, "package-version", "0.0.0", "version string to embed in executable files") + flags.StringVar(&inst.RubyVersion, "ruby-version", defaultRubyVersion, "Ruby `version` to install (do not override in production mode)") + flags.StringVar(&inst.BundlerVersion, "bundler-version", defaultBundlerVersion, "Bundler `version` to install (do not override in production mode)") + flags.StringVar(&inst.SingularityVersion, "singularity-version", defaultSingularityVersion, "Singularity `version` to install (do not override in production mode)") + flags.StringVar(&inst.NodejsVersion, "nodejs-version", defaultNodejsVersion, "Nodejs `version` to install (not applicable in production mode)") flags.BoolVar(&inst.EatMyData, "eatmydata", false, "use eatmydata to speed up install") if ok, code := cmd.ParseFlags(flags, prog, args, "", stderr); !ok { @@ -80,6 +91,14 @@ func (inst *installCommand) RunCommand(prog string, args []string, stdin io.Read return cmd.Version.RunCommand(prog, args, stdin, stdout, stderr) } + if inst.Commit == "" { + if commit, err := exec.Command("env", "-C", inst.SourcePath, "git", "log", "-n1", "--format=%H").CombinedOutput(); err == nil { + inst.Commit = strings.TrimSpace(string(commit)) + } else { + inst.Commit = "0000000000000000000000000000000000000000" + } + } + var dev, test, prod, pkg bool switch inst.ClusterType { case "development": @@ -100,6 +119,23 @@ func (inst *installCommand) RunCommand(prog string, args []string, stdin io.Read return 1 } + if ok, _ := regexp.MatchString(`^\d\.\d+\.\d+$`, inst.RubyVersion); !ok { + fmt.Fprintf(stderr, "invalid argument %q for -ruby-version\n", inst.RubyVersion) + return 2 + } + if ok, _ := regexp.MatchString(`^\d`, inst.BundlerVersion); !ok { + fmt.Fprintf(stderr, "invalid argument %q for -bundler-version\n", inst.BundlerVersion) + return 2 + } + if ok, _ := regexp.MatchString(`^\d`, inst.SingularityVersion); !ok { + fmt.Fprintf(stderr, "invalid argument %q for -singularity-version\n", inst.SingularityVersion) + return 2 + } + if ok, _ := regexp.MatchString(`^v\d`, inst.NodejsVersion); !ok { + fmt.Fprintf(stderr, "invalid argument %q for -nodejs-version\n", inst.NodejsVersion) + return 2 + } + osv, err := identifyOS() if err != nil { return 1 @@ -295,20 +331,24 @@ fi return 1 } } - rubymajorversion := rubyversion[:strings.LastIndex(rubyversion, ".")] - if haverubyversion, err := exec.Command("/var/lib/arvados/bin/ruby", "-v").CombinedOutput(); err == nil && bytes.HasPrefix(haverubyversion, []byte("ruby "+rubyversion)) { - logger.Print("ruby " + rubyversion + " already installed") + rubyminorversion := inst.RubyVersion[:strings.LastIndex(inst.RubyVersion, ".")] + if haverubyversion, err := exec.Command("/var/lib/arvados/bin/ruby", "-v").CombinedOutput(); err == nil && bytes.HasPrefix(haverubyversion, []byte("ruby "+inst.RubyVersion)) { + logger.Print("ruby " + inst.RubyVersion + " already installed") } else { err = inst.runBash(` +rubyversion="`+inst.RubyVersion+`" +rubyminorversion="`+rubyminorversion+`" tmp="$(mktemp -d)" trap 'rm -r "${tmp}"' ERR EXIT -wget --progress=dot:giga -O- https://cache.ruby-lang.org/pub/ruby/`+rubymajorversion+`/ruby-`+rubyversion+`.tar.gz | tar -C "${tmp}" -xzf - -cd "${tmp}/ruby-`+rubyversion+`" +wget --progress=dot:giga -O- "https://cache.ruby-lang.org/pub/ruby/$rubyminorversion/ruby-$rubyversion.tar.gz" | tar -C "${tmp}" -xzf - +cd "${tmp}/ruby-$rubyversion" ./configure --disable-install-static-library --enable-shared --disable-install-doc --prefix /var/lib/arvados make -j8 rm -f /var/lib/arvados/bin/erb make install -/var/lib/arvados/bin/gem update --no-document --system 3.4.21 +if [[ "$rubyversion" > "3" ]]; then + /var/lib/arvados/bin/gem update --no-document --system 3.4.21 +fi /var/lib/arvados/bin/gem install bundler --no-document `, stdout, stderr) if err != nil { @@ -376,11 +416,11 @@ rm ${zip} } } - if havesingularityversion, err := exec.Command("/var/lib/arvados/bin/singularity", "--version").CombinedOutput(); err == nil && strings.Contains(string(havesingularityversion), singularityversion) { - logger.Print("singularity " + singularityversion + " already installed") + if havesingularityversion, err := exec.Command("/var/lib/arvados/bin/singularity", "--version").CombinedOutput(); err == nil && strings.Contains(string(havesingularityversion), inst.SingularityVersion) { + logger.Print("singularity " + inst.SingularityVersion + " already installed") } else if dev || test { err = inst.runBash(` -S=`+singularityversion+` +S=`+inst.SingularityVersion+` tmp=/var/lib/arvados/tmp/singularity trap "rm -r ${tmp}" ERR EXIT cd /var/lib/arvados/tmp @@ -526,11 +566,11 @@ setcap "cap_sys_admin+pei cap_sys_chroot+pei" /var/lib/arvados/bin/nsenter } if !prod { - if havenodejsversion, err := exec.Command("/usr/local/bin/node", "--version").CombinedOutput(); err == nil && string(havenodejsversion) == nodejsversion+"\n" { - logger.Print("nodejs " + nodejsversion + " already installed") + if havenodejsversion, err := exec.Command("/usr/local/bin/node", "--version").CombinedOutput(); err == nil && string(havenodejsversion) == inst.NodejsVersion+"\n" { + logger.Print("nodejs " + inst.NodejsVersion + " already installed") } else { err = inst.runBash(` -NJS=`+nodejsversion+` +NJS=`+inst.NodejsVersion+` rm -rf /var/lib/arvados/node-*-linux-x64 wget --progress=dot:giga -O- https://nodejs.org/dist/${NJS}/node-${NJS}-linux-x64.tar.xz | sudo tar -C /var/lib/arvados -xJf - ln -sfv /var/lib/arvados/node-${NJS}-linux-x64/bin/{node,npm} /usr/local/bin/ @@ -545,7 +585,7 @@ ln -sfv /var/lib/arvados/node-${NJS}-linux-x64/bin/{node,npm} /usr/local/bin/ } else { err = inst.runBash(` npm install -g yarn -ln -sfv /var/lib/arvados/node-`+nodejsversion+`-linux-x64/bin/{yarn,yarnpkg} /usr/local/bin/ +ln -sfv /var/lib/arvados/node-`+inst.NodejsVersion+`-linux-x64/bin/{yarn,yarnpkg} /usr/local/bin/ `, stdout, stderr) if err != nil { return 1 @@ -566,7 +606,10 @@ ln -sfv /var/lib/arvados/node-`+nodejsversion+`-linux-x64/bin/{yarn,yarnpkg} /us // container using a non-root-owned git tree // mounted from the host -- as in // "arvados-package build". - cmd := exec.Command("go", "install", "-buildvcs=false", "-ldflags", "-X git.arvados.org/arvados.git/lib/cmd.version="+inst.PackageVersion+" -X main.version="+inst.PackageVersion+" -s -w") + cmd := exec.Command("go", "install", "-buildvcs=false", + "-ldflags", "-s -w"+ + " -X git.arvados.org/arvados.git/lib/cmd.version="+inst.PackageVersion+ + " -X git.arvados.org/arvados.git/lib/cmd.commit="+inst.Commit) cmd.Env = append(cmd.Env, os.Environ()...) cmd.Env = append(cmd.Env, "GOBIN=/var/lib/arvados/bin") cmd.Dir = filepath.Join(inst.SourcePath, srcdir) @@ -601,7 +644,7 @@ v=/var/lib/arvados/lib/python tmp=/var/lib/arvados/tmp/python python3 -m venv "$v" . "$v/bin/activate" -pip3 install --no-cache-dir 'setuptools>=62.4.0' 'pip>=7' +pip3 install --no-cache-dir 'setuptools>=68' 'pip>=20' export ARVADOS_BUILDING_VERSION="`+inst.PackageVersion+`" for src in "`+inst.SourcePath+`/sdk/python" "`+inst.SourcePath+`/services/fuse"; do rsync -a --delete-after "$src/" "$tmp/" @@ -636,7 +679,7 @@ done {"mkdir", "-p", "log", "public/assets", "tmp", "vendor", ".bundle", "/var/www/.bundle", "/var/www/.gem", "/var/www/.npm", "/var/www/.passenger"}, {"touch", "log/production.log"}, {"chown", "-R", "--from=root", "www-data:www-data", "/var/www/.bundle", "/var/www/.gem", "/var/www/.npm", "/var/www/.passenger", "log", "tmp", "vendor", ".bundle", "Gemfile.lock", "config.ru", "config/environment.rb"}, - {"sudo", "-u", "www-data", "/var/lib/arvados/bin/gem", "install", "--user", "--conservative", "--no-document", "bundler:" + bundlerversion}, + {"sudo", "-u", "www-data", "/var/lib/arvados/bin/gem", "install", "--user", "--conservative", "--no-document", "bundler:" + inst.BundlerVersion}, {"sudo", "-u", "www-data", "/var/lib/arvados/bin/bundle", "config", "set", "--local", "deployment", "true"}, {"sudo", "-u", "www-data", "/var/lib/arvados/bin/bundle", "config", "set", "--local", "path", "/var/www/.gem"}, {"sudo", "-u", "www-data", "/var/lib/arvados/bin/bundle", "config", "set", "--local", "without", "development test diagnostics performance"}, @@ -691,11 +734,13 @@ done // BUILD_PATH=/var/lib/arvados/workbench2) instead of // using two rsync steps here. if err = inst.runBash(` +src="`+inst.SourcePath+`/services/workbench2" tmp=/var/lib/arvados/tmp/workbench2 trap "rm -r ${tmp}" ERR EXIT -rsync -a --delete-after `+inst.SourcePath+`/services/workbench2/ "$tmp/" -env -C "$tmp" VERSION="`+inst.PackageVersion+`" BUILD_NUMBER=1 GIT_COMMIT=000000000 yarn build -rsync -a --delete-after "$tmp/build/" /var/lib/arvados/workbench2/ +dst=/var/lib/arvados/workbench2 +rsync -a --delete-after "$src/" "$tmp/" +env -C "$tmp" VERSION="`+inst.PackageVersion+`" BUILD_NUMBER=1 GIT_COMMIT="`+inst.Commit[:9]+`" yarn build +rsync -a --delete-after "$tmp/build/" "$dst/" `, stdout, stderr); err != nil { return 1 }