// Copyright (C) The Arvados Authors. All rights reserved. // // SPDX-License-Identifier: AGPL-3.0 package main import ( "context" "fmt" "io" "io/ioutil" "os" "os/exec" "path/filepath" "strings" "git.arvados.org/arvados.git/lib/crunchrun" "github.com/docker/docker/api/types" "github.com/docker/docker/client" ) func testinstall(ctx context.Context, opts opts, stdin io.Reader, stdout, stderr io.Writer) error { depsImageName := "arvados-package-deps-" + opts.TargetOS depsCtrName := strings.Replace(depsImageName, ":", "-", -1) absPackageDir, err := filepath.Abs(opts.PackageDir) if err != nil { return fmt.Errorf("error resolving PackageDir %q: %w", opts.PackageDir, err) } _, prog := filepath.Split(os.Args[0]) tmpdir, err := ioutil.TempDir("", prog+".") if err != nil { return fmt.Errorf("TempDir: %w", err) } defer os.RemoveAll(tmpdir) if exists, err := dockerImageExists(ctx, depsImageName); err != nil { return err } else if !exists || opts.RebuildImage { err = dockerRm(ctx, depsCtrName) if err != nil { return err } defer dockerRm(ctx, depsCtrName) cmd := exec.CommandContext(ctx, "docker", "run", "--name", depsCtrName, "--tmpfs", "/tmp:exec,mode=01777", "-v", absPackageDir+":/pkg:ro", "--env", "DEBIAN_FRONTEND=noninteractive", opts.TargetOS, "bash", "-c", ` set -e -o pipefail apt-get --allow-releaseinfo-change update apt-get install -y --no-install-recommends dpkg-dev eatmydata mkdir /tmp/pkg ln -s /pkg/*.deb /tmp/pkg/ (cd /tmp/pkg; dpkg-scanpackages --multiversion . | gzip > Packages.gz) echo >/etc/apt/sources.list.d/arvados-local.list "deb [trusted=yes] file:///tmp/pkg ./" apt-get --allow-releaseinfo-change update eatmydata apt-get install -y --no-install-recommends arvados-server-easy postgresql eatmydata apt-get remove -y dpkg-dev SUDO_FORCE_REMOVE=yes apt-get autoremove -y eatmydata apt-get remove -y arvados-server-easy rm /etc/apt/sources.list.d/arvados-local.list `) cmd.Stdout = stdout cmd.Stderr = stderr err = cmd.Run() if err != nil { return fmt.Errorf("%v: %w", cmd.Args, err) } cmd = exec.CommandContext(ctx, "docker", "commit", depsCtrName, depsImageName) cmd.Stdout = stdout cmd.Stderr = stderr err = cmd.Run() if err != nil { return fmt.Errorf("%v: %w", cmd.Args, err) } } versionsuffix := "" if opts.PackageVersion != "" { versionsuffix = "=" + opts.PackageVersion } cmd := exec.CommandContext(ctx, "docker", "run", "--rm", "--tmpfs=/tmp:exec,mode=01777", "--volume="+absPackageDir+":/pkg:ro", "--env=DEBIAN_FRONTEND=noninteractive") if opts.Live != "" { cmd.Args = append(cmd.Args, "--env=domain="+opts.Live, "--env=initargs=-tls=/var/lib/acme/live/"+opts.Live, "--env=bootargs=", "--publish=:443:443", "--publish=:4440-4460:4440-4460", "--publish=:9000-9020:9000-9020", "--add-host="+opts.Live+":0.0.0.0", "--volume=/var/lib/acme:/var/lib/acme:ro") } else { cmd.Args = append(cmd.Args, "--env=domain=localhost", "--env=initargs=-tls=insecure", "--env=bootargs=-shutdown") } cmd.Args = append(cmd.Args, depsImageName, "bash", "-c", ` set -e -o pipefail PATH="/var/lib/arvados/bin:$PATH" apt-get --allow-releaseinfo-change update apt-get install -y --no-install-recommends dpkg-dev mkdir /tmp/pkg ln -s /pkg/*.deb /tmp/pkg/ (cd /tmp/pkg; dpkg-scanpackages --multiversion . | gzip > Packages.gz) apt-get remove -y dpkg-dev echo echo >/etc/apt/sources.list.d/arvados-local.list "deb [trusted=yes] file:///tmp/pkg ./" apt-get --allow-releaseinfo-change update eatmydata apt-get install --reinstall -y --no-install-recommends arvados-server-easy`+versionsuffix+` SUDO_FORCE_REMOVE=yes apt-get autoremove -y /etc/init.d/postgresql start arvados-server init -cluster-id x1234 -domain=$domain -login=test -start=false $initargs exec arvados-server boot -listen-host=0.0.0.0 $bootargs `) cmd.Stdout = stdout cmd.Stderr = stderr err = cmd.Run() if err != nil { return fmt.Errorf("%v: %w", cmd.Args, err) } return nil } func dockerImageExists(ctx context.Context, name string) (bool, error) { cli, err := client.NewClient(client.DefaultDockerHost, crunchrun.DockerAPIVersion, nil, nil) if err != nil { return false, err } imgs, err := cli.ImageList(ctx, types.ImageListOptions{All: true}) if err != nil { return false, err } for _, img := range imgs { for _, tag := range img.RepoTags { if tag == name { return true, nil } } } return false, nil }