X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/46fe1e60a1cd96a39163911edd821b3e316ca606..8836fd8f35b497eaad22de9d9478d8aa97fb359c:/lib/install/deps.go diff --git a/lib/install/deps.go b/lib/install/deps.go index 7b32984348..08312d738c 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,25 +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 = "14.21.3" + devtestDatabasePassword = "insecure_arvados_test" ) //go:embed arvados.service var arvadosServiceFile []byte type installCommand struct { - ClusterType string - SourcePath string - Commit 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 { @@ -74,6 +79,10 @@ func (inst *installCommand) RunCommand(prog string, args []string, stdin io.Read 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 { @@ -110,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(`^\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 @@ -209,6 +235,10 @@ func (inst *installCommand) RunCommand(prog string, args []string, stdin io.Read } else { pkgs = append(pkgs, "firefox") } + if osv.Debian && osv.Major >= 11 { + // not available in Debian <11 + pkgs = append(pkgs, "s3cmd") + } } if dev || test { pkgs = append(pkgs, @@ -223,7 +253,7 @@ func (inst *installCommand) RunCommand(prog string, args []string, stdin io.Read pkgs = append(pkgs, "g++", "libcurl4", "libcurl4-openssl-dev") case osv.Debian || osv.Ubuntu: pkgs = append(pkgs, "g++", "libcurl3", "libcurl3-openssl-dev") - case osv.Centos: + case osv.RedHat: pkgs = append(pkgs, "gcc", "gcc-c++", "libcurl-devel", "postgresql-devel") } cmd := exec.CommandContext(ctx, "apt-get") @@ -247,8 +277,6 @@ func (inst *installCommand) RunCommand(prog string, args []string, stdin io.Read } else if osv.Debian { var codename string switch osv.Major { - case 10: - codename = "buster" case 11: codename = "bullseye" case 12: @@ -260,7 +288,7 @@ func (inst *installCommand) RunCommand(prog string, args []string, stdin io.Read err = inst.runBash(` rm -f /usr/share/keyrings/docker-archive-keyring.gpg curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg -echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian/ `+codename+` stable' | \ +echo 'deb [arch=`+runtime.GOARCH+` signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian/ `+codename+` stable' | \ tee /etc/apt/sources.list.d/docker.list apt-get update DEBIAN_FRONTEND=noninteractive apt-get --yes --no-install-recommends install docker-ce @@ -305,20 +333,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 { @@ -333,7 +365,7 @@ make install err = inst.runBash(` cd /tmp rm -rf /var/lib/arvados/go/ -wget --progress=dot:giga -O- https://storage.googleapis.com/golang/go`+goversion+`.linux-amd64.tar.gz | tar -C /var/lib/arvados -xzf - +wget --progress=dot:giga -O- https://storage.googleapis.com/golang/go`+goversion+`.linux-`+runtime.GOARCH+`.tar.gz | tar -C /var/lib/arvados -xzf - ln -sfv /var/lib/arvados/go/bin/* /usr/local/bin/ `, stdout, stderr) if err != nil { @@ -343,32 +375,6 @@ ln -sfv /var/lib/arvados/go/bin/* /usr/local/bin/ } if !prod && !pkg { - if havepjsversion, err := exec.Command("/usr/local/bin/phantomjs", "--version").CombinedOutput(); err == nil && string(havepjsversion) == "1.9.8\n" { - logger.Print("phantomjs " + pjsversion + " already installed") - } else { - err = inst.runBash(` -PJS=phantomjs-`+pjsversion+`-linux-x86_64 -wget --progress=dot:giga -O- https://cache.arvados.org/$PJS.tar.bz2 | tar -C /var/lib/arvados -xjf - -ln -sfv /var/lib/arvados/$PJS/bin/phantomjs /usr/local/bin/ -`, stdout, stderr) - if err != nil { - return 1 - } - } - - if havegeckoversion, err := exec.Command("/usr/local/bin/geckodriver", "--version").CombinedOutput(); err == nil && strings.Contains(string(havegeckoversion), " "+geckoversion+" ") { - logger.Print("geckodriver " + geckoversion + " already installed") - } else { - err = inst.runBash(` -GD=v`+geckoversion+` -wget --progress=dot:giga -O- https://github.com/mozilla/geckodriver/releases/download/$GD/geckodriver-$GD-linux64.tar.gz | tar -C /var/lib/arvados/bin -xzf - geckodriver -ln -sfv /var/lib/arvados/bin/geckodriver /usr/local/bin/ -`, stdout, stderr) - if err != nil { - return 1 - } - } - if havegradleversion, err := exec.Command("/usr/local/bin/gradle", "--version").CombinedOutput(); err == nil && strings.Contains(string(havegradleversion), "Gradle "+gradleversion+"\n") { logger.Print("gradle " + gradleversion + " already installed") } else { @@ -386,11 +392,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 @@ -535,15 +541,23 @@ setcap "cap_sys_admin+pei cap_sys_chroot+pei" /var/lib/arvados/bin/nsenter } } + var njsArch string + switch runtime.GOARCH { + case "amd64": + njsArch = "x64" + default: + njsArch = runtime.GOARCH + } + 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) == "v"+inst.NodejsVersion+"\n" { + logger.Print("nodejs " + inst.NodejsVersion + " already installed") } else { err = inst.runBash(` -NJS=`+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/ +NJS=v`+inst.NodejsVersion+` +rm -rf /var/lib/arvados/node-*-linux-`+njsArch+` +wget --progress=dot:giga -O- https://nodejs.org/dist/${NJS}/node-${NJS}-linux-`+njsArch+`.tar.xz | sudo tar -C /var/lib/arvados -xJf - +ln -sfv /var/lib/arvados/node-${NJS}-linux-`+njsArch+`/bin/{node,npm} /usr/local/bin/ `, stdout, stderr) if err != nil { return 1 @@ -555,7 +569,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-v`+inst.NodejsVersion+`-linux-`+njsArch+`/bin/{yarn,yarnpkg} /usr/local/bin/ `, stdout, stderr) if err != nil { return 1 @@ -649,7 +663,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"}, @@ -789,7 +803,7 @@ rsync -a --delete-after "$tmp/build/" "$dst/" type osversion struct { Debian bool Ubuntu bool - Centos bool + RedHat bool Major int } @@ -827,10 +841,24 @@ func identifyOS() (osversion, error) { osv.Ubuntu = true case "debian": osv.Debian = true - case "centos": - osv.Centos = true default: - return osv, fmt.Errorf("unsupported ID in /etc/os-release: %q", kv["ID"]) + idLikeMatched := false + for _, idLike := range strings.Split(kv["ID_LIKE"], " ") { + switch idLike { + case "debian": + osv.Debian = true + idLikeMatched = true + case "rhel": + osv.RedHat = true + idLikeMatched = true + } + if idLikeMatched { + break + } + } + if !idLikeMatched { + return osv, fmt.Errorf("no supported ID found in /etc/os-release") + } } vstr := kv["VERSION_ID"] if i := strings.Index(vstr, "."); i > 0 { @@ -891,7 +919,7 @@ func prodpkgs(osv osversion) []string { return append(pkgs, "mime-support", // keep-web ) - } else if osv.Centos { + } else if osv.RedHat { return append(pkgs, "fuse-libs", // services/fuse "mailcap", // keep-web