// Copyright 2015 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.google.devtools.build.lib.sandbox;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.eventbus.Subscribe;
import com.google.devtools.build.lib.actions.ExecException;
import com.google.devtools.build.lib.actions.ExecutorInitException;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.actions.SpawnResult;
import com.google.devtools.build.lib.actions.SpawnStrategy;
import com.google.devtools.build.lib.buildtool.BuildRequest;
import com.google.devtools.build.lib.buildtool.buildevent.BuildCompleteEvent;
import com.google.devtools.build.lib.buildtool.buildevent.BuildInterruptedEvent;
import com.google.devtools.build.lib.events.Event;
import com.google.devtools.build.lib.exec.ExecutorBuilder;
import com.google.devtools.build.lib.exec.RunfilesTreeUpdater;
import com.google.devtools.build.lib.exec.SpawnRunner;
import com.google.devtools.build.lib.exec.TreeDeleter;
import com.google.devtools.build.lib.exec.local.LocalEnvProvider;
import com.google.devtools.build.lib.exec.local.LocalExecutionOptions;
import com.google.devtools.build.lib.exec.local.LocalSpawnRunner;
import com.google.devtools.build.lib.profiler.Profiler;
import com.google.devtools.build.lib.profiler.SilentCloseable;
import com.google.devtools.build.lib.runtime.BlazeModule;
import com.google.devtools.build.lib.runtime.Command;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.util.Fingerprint;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.vfs.FileSystem;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import com.google.devtools.common.options.OptionsBase;
import com.google.devtools.common.options.TriState;
import java.io.File;
import java.io.IOException;
import java.time.Duration;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nullable;

/**
 * This module provides the Sandbox spawn strategy.
 */
public final class SandboxModule extends BlazeModule {

  /** Tracks whether we are issuing the very first build within this Bazel server instance. */
  private static boolean firstBuild = true;

  /** Environment for the running command. */
  @Nullable private CommandEnvironment env;

  /** Path to the location of the sandboxes. */
  @Nullable private Path sandboxBase;

  /** Instance of the sandboxfs process in use, if enabled. */
  @Nullable private SandboxfsProcess sandboxfsProcess;

  /**
   * Collection of spawn runner instantiated during the executor setup.
   *
   * <p>We need this information to clean up the heavy subdirectories of the sandbox base on build
   * completion but to avoid wiping the whole sandbox base itself, which could be problematic across
   * builds.
   */
  private final Set<SpawnRunner> spawnRunners = new HashSet<>();

  /**
   * Handler to process expensive tree deletions outside of the critical path.
   *
   * <p>Sandboxing creates one separate tree for each action, and this tree is used to run the
   * action commands in. These trees are disjoint for all actions and have unique identifiers.
   * Therefore, there is no need for their deletion (which can be very expensive) to happen in the
   * critical path -- so if the user so wishes, we process those deletions asynchronously.
   */
  @Nullable private TreeDeleter treeDeleter;

  /**
   * Whether to remove the sandbox worker directories after a build or not. Useful for debugging
   * to inspect the state of files on failures.
   */
  private boolean shouldCleanupSandboxBase;

  @Override
  public Iterable<Class<? extends OptionsBase>> getCommandOptions(Command command) {
    return "build".equals(command.name())
        ? ImmutableList.of(SandboxOptions.class)
        : ImmutableList.of();
  }

  /** Computes the path to the sandbox base tree for the given running command. */
  private static Path computeSandboxBase(SandboxOptions options, CommandEnvironment env)
      throws IOException {
    if (options.sandboxBase.isEmpty()) {
      return env.getOutputBase().getRelative("sandbox");
    } else {
      String dirName =
          String.format(
              "%s-sandbox.%s",
              env.getRuntime().getProductName(),
              Fingerprint.getHexDigest(env.getOutputBase().toString()));
      FileSystem fileSystem = env.getRuntime().getFileSystem();
      Path resolvedSandboxBase = fileSystem.getPath(options.sandboxBase).resolveSymbolicLinks();
      return resolvedSandboxBase.getRelative(dirName);
    }
  }

  @Override
  public void beforeCommand(CommandEnvironment env) {
    // We can't assert that env is null because the Blaze runtime does not guarantee that
    // afterCommand() will be called if the command fails due to, e.g. a syntax error.
    this.env = env;
    env.getEventBus().register(this);

    // Don't attempt cleanup unless the executor is initialized.
    shouldCleanupSandboxBase = false;
  }

  @Override
  public void executorInit(CommandEnvironment cmdEnv, BuildRequest request, ExecutorBuilder builder)
      throws ExecutorInitException {
    checkNotNull(env, "env not initialized; was beforeCommand called?");
    try {
      setup(cmdEnv, builder);
    } catch (IOException e) {
      throw new ExecutorInitException("Failed to initialize sandbox", e);
    }
  }

  /**
   * Returns true if windows-sandbox should be used for this build.
   *
   * <p>Returns true if requested in ["auto", "yes"] and binary is valid. Throws an error if state
   * is "yes" and binary is not valid.
   *
   * @param requested whether windows-sandbox use was requested or not
   * @param binary path of the windows-sandbox binary to use, can be absolute or relative path
   * @return true if windows-sandbox can and should be used; false otherwise
   * @throws IOException if there are problems trying to determine the status of windows-sandbox
   */
  private boolean shouldUseWindowsSandbox(TriState requested, PathFragment binary)
      throws IOException {
    switch (requested) {
      case AUTO:
        return WindowsSandboxUtil.isAvailable(binary);

      case NO:
        return false;

      case YES:
        if (!WindowsSandboxUtil.isAvailable(binary)) {
          throw new IOException(
              "windows-sandbox explicitly requested but \""
                  + binary
                  + "\" could not be found or is not valid");
        }
        return true;
    }
    throw new IllegalStateException("Not reachable");
  }

  private void setup(CommandEnvironment cmdEnv, ExecutorBuilder builder)
      throws IOException {
    SandboxOptions options = checkNotNull(env.getOptions().getOptions(SandboxOptions.class));
    sandboxBase = computeSandboxBase(options, env);

    // Do not remove the sandbox base when --sandbox_debug was specified so that people can check
    // out the contents of the generated sandbox directories.
    shouldCleanupSandboxBase = !options.sandboxDebug;

    // If there happens to be any live tree deleter from a previous build and it's different than
    // the one we want now, leave it alone (i.e. don't attempt to wait for pending deletions). Its
    // deletions shouldn't overlap any new directories we create during this build (because the
    // identifiers in the subdirectories will be different).
    if (options.asyncTreeDeleteIdleThreads == 0) {
      if (!(treeDeleter instanceof SynchronousTreeDeleter)) {
        treeDeleter = new SynchronousTreeDeleter();
      }
    } else {
      if (!(treeDeleter instanceof AsynchronousTreeDeleter)) {
        treeDeleter = new AsynchronousTreeDeleter();
      }
    }

    Path mountPoint = sandboxBase.getRelative("sandboxfs");

    if (sandboxfsProcess != null) {
      if (options.sandboxDebug) {
        env.getReporter()
            .handle(
                Event.info(
                    "Unmounting sandboxfs instance left behind on "
                        + mountPoint
                        + " by a previous command"));
      }
      sandboxfsProcess.destroy();
      sandboxfsProcess = null;
    }
    // SpawnExecutionPolicy#getId returns unique base directories for each sandboxed action during
    // the life of a Bazel server instance so we don't need to worry about stale directories from
    // previous builds. However, on the very first build of an instance of the server, we must
    // wipe old contents to avoid reusing stale directories.
    if (firstBuild && sandboxBase.exists()) {
      cmdEnv.getReporter().handle(Event.info("Deleting stale sandbox base " + sandboxBase));
      sandboxBase.deleteTree();
    }
    firstBuild = false;

    PathFragment sandboxfsPath = PathFragment.create(options.sandboxfsPath);
    sandboxBase.createDirectoryAndParents();
    if (options.useSandboxfs != TriState.NO) {
      mountPoint.createDirectory();
      Path logFile = sandboxBase.getRelative("sandboxfs.log");

      if (sandboxfsProcess == null) {
        if (options.sandboxDebug) {
          env.getReporter().handle(Event.info("Mounting sandboxfs instance on " + mountPoint));
        }
        try (SilentCloseable c = Profiler.instance().profile("mountSandboxfs")) {
          sandboxfsProcess = RealSandboxfsProcess.mount(sandboxfsPath, mountPoint, logFile);
        } catch (IOException e) {
          if (options.sandboxDebug) {
            env.getReporter()
                .handle(
                    Event.info(
                        "sandboxfs failed to mount due to " + e.getMessage() + "; ignoring"));
          }
          if (options.useSandboxfs == TriState.YES) {
            throw e;
          }
        }
      }
    }

    PathFragment windowsSandboxPath = PathFragment.create(options.windowsSandboxPath);
    boolean windowsSandboxSupported;
    try (SilentCloseable c = Profiler.instance().profile("shouldUseWindowsSandbox")) {
      windowsSandboxSupported =
          shouldUseWindowsSandbox(options.useWindowsSandbox, windowsSandboxPath);
    }

    Duration timeoutKillDelay =
        cmdEnv.getOptions().getOptions(LocalExecutionOptions.class).getLocalSigkillGraceSeconds();

    boolean processWrapperSupported = ProcessWrapperSandboxedSpawnRunner.isSupported(cmdEnv);
    boolean linuxSandboxSupported = LinuxSandboxedSpawnRunner.isSupported(cmdEnv);
    boolean darwinSandboxSupported = DarwinSandboxedSpawnRunner.isSupported(cmdEnv);

    // This works on most platforms, but isn't the best choice, so we put it first and let later
    // platform-specific sandboxing strategies become the default.
    if (processWrapperSupported) {
      SpawnRunner spawnRunner =
          withFallback(
              cmdEnv,
              new ProcessWrapperSandboxedSpawnRunner(
                  cmdEnv,
                  sandboxBase,
                  timeoutKillDelay,
                  sandboxfsProcess,
                  options.sandboxfsMapSymlinkTargets,
                  treeDeleter));
      spawnRunners.add(spawnRunner);
      builder.addActionContext(
          SpawnStrategy.class,
          new ProcessWrapperSandboxedStrategy(cmdEnv.getExecRoot(), spawnRunner),
          "sandboxed",
          "processwrapper-sandbox");
    }

    if (options.enableDockerSandbox) {
      // This strategy uses Docker to execute spawns. It should work on all platforms that support
      // Docker.
      Path pathToDocker = getPathToDockerClient(cmdEnv);
      // DockerSandboxedSpawnRunner.isSupported is expensive! It runs docker as a subprocess, and
      // docker hangs sometimes.
      if (pathToDocker != null && DockerSandboxedSpawnRunner.isSupported(cmdEnv, pathToDocker)) {
        String defaultImage = options.dockerImage;
        boolean useCustomizedImages = options.dockerUseCustomizedImages;
        SpawnRunner spawnRunner =
            withFallback(
                cmdEnv,
                new DockerSandboxedSpawnRunner(
                    cmdEnv,
                    pathToDocker,
                    sandboxBase,
                    defaultImage,
                    timeoutKillDelay,
                    useCustomizedImages,
                    treeDeleter));
        spawnRunners.add(spawnRunner);
        builder.addActionContext(
            SpawnStrategy.class,
            new DockerSandboxedStrategy(cmdEnv.getExecRoot(), spawnRunner),
            "docker");
      }
    } else if (options.dockerVerbose) {
      cmdEnv.getReporter().handle(Event.info(
          "Docker sandboxing disabled. Use the '--experimental_enable_docker_sandbox' command "
          + "line option to enable it"));
    }

    // This is the preferred sandboxing strategy on Linux.
    if (linuxSandboxSupported) {
      SpawnRunner spawnRunner =
          withFallback(
              cmdEnv,
              LinuxSandboxedStrategy.create(
                  cmdEnv,
                  sandboxBase,
                  timeoutKillDelay,
                  sandboxfsProcess,
                  options.sandboxfsMapSymlinkTargets,
                  treeDeleter));
      spawnRunners.add(spawnRunner);
      builder.addActionContext(
          SpawnStrategy.class,
          new LinuxSandboxedStrategy(cmdEnv.getExecRoot(), spawnRunner),
          "sandboxed",
          "linux-sandbox");
    }

    // This is the preferred sandboxing strategy on macOS.
    if (darwinSandboxSupported) {
      SpawnRunner spawnRunner =
          withFallback(
              cmdEnv,
              new DarwinSandboxedSpawnRunner(
                  cmdEnv,
                  sandboxBase,
                  timeoutKillDelay,
                  sandboxfsProcess,
                  options.sandboxfsMapSymlinkTargets,
                  treeDeleter));
      spawnRunners.add(spawnRunner);
      builder.addActionContext(
          SpawnStrategy.class,
          new DarwinSandboxedStrategy(cmdEnv.getExecRoot(), spawnRunner),
          "sandboxed",
          "darwin-sandbox");
    }

    if (windowsSandboxSupported) {
      SpawnRunner spawnRunner =
          withFallback(
              cmdEnv,
              new WindowsSandboxedSpawnRunner(cmdEnv, timeoutKillDelay, windowsSandboxPath));
      spawnRunners.add(spawnRunner);
      builder.addActionContext(
          SpawnStrategy.class,
          new WindowsSandboxedStrategy(cmdEnv.getExecRoot(), spawnRunner),
          "sandboxed",
          "windows-sandbox");
    }

    if (processWrapperSupported
        || linuxSandboxSupported
        || darwinSandboxSupported
        || windowsSandboxSupported) {
      // This makes the "sandboxed" strategy available via --spawn_strategy=sandboxed,
      // but it is not necessarily the default.
      builder.addStrategyByContext(SpawnStrategy.class, "sandboxed");

      // This makes the "sandboxed" strategy the default Spawn strategy, unless it is
      // overridden by a later BlazeModule.
      builder.addStrategyByMnemonic("", ImmutableList.of("sandboxed"));
    }
  }

  private static Path getPathToDockerClient(CommandEnvironment cmdEnv) {
    String path = cmdEnv.getClientEnv().getOrDefault("PATH", "");

    // TODO(philwo): Does this return the correct result if one of the elements intentionally ends
    // in white space?
    Splitter pathSplitter =
        Splitter.on(OS.getCurrent() == OS.WINDOWS ? ';' : ':').trimResults().omitEmptyStrings();

    FileSystem fs = cmdEnv.getRuntime().getFileSystem();

    for (String pathElement : pathSplitter.split(path)) {
      // Sometimes the PATH contains the non-absolute entry "." - this resolves it against the
      // current working directory.
      pathElement = new File(pathElement).getAbsolutePath();
      try {
        for (Path dentry : fs.getPath(pathElement).getDirectoryEntries()) {
          if (dentry.getBaseName().replace(".exe", "").equals("docker")) {
            return dentry;
          }
        }
      } catch (IOException e) {
        continue;
      }
    }

    return null;
  }

  private static SpawnRunner withFallback(CommandEnvironment env, SpawnRunner sandboxSpawnRunner) {
    return new SandboxFallbackSpawnRunner(sandboxSpawnRunner, createFallbackRunner(env));
  }

  private static SpawnRunner createFallbackRunner(CommandEnvironment env) {
    LocalExecutionOptions localExecutionOptions =
        env.getOptions().getOptions(LocalExecutionOptions.class);
    return new LocalSpawnRunner(
        env.getExecRoot(),
        localExecutionOptions,
        env.getLocalResourceManager(),
        LocalEnvProvider.forCurrentOs(env.getClientEnv()),
        env.getBlazeWorkspace().getBinTools(),
        // TODO(buchgr): Replace singleton by a command-scoped RunfilesTreeUpdater
        RunfilesTreeUpdater.INSTANCE);
  }

  private static final class SandboxFallbackSpawnRunner implements SpawnRunner {
    private final SpawnRunner sandboxSpawnRunner;
    private final SpawnRunner fallbackSpawnRunner;

    SandboxFallbackSpawnRunner(SpawnRunner sandboxSpawnRunner, SpawnRunner fallbackSpawnRunner) {
      this.sandboxSpawnRunner = sandboxSpawnRunner;
      this.fallbackSpawnRunner = fallbackSpawnRunner;
    }

    @Override
    public String getName() {
      return "sandbox-fallback";
    }

    @Override
    public SpawnResult exec(Spawn spawn, SpawnExecutionContext context)
        throws InterruptedException, IOException, ExecException {
      if (sandboxSpawnRunner.canExec(spawn)) {
        return sandboxSpawnRunner.exec(spawn, context);
      } else {
        return fallbackSpawnRunner.exec(spawn, context);
      }
    }

    @Override
    public boolean canExec(Spawn spawn) {
      return sandboxSpawnRunner.canExec(spawn) || fallbackSpawnRunner.canExec(spawn);
    }

    @Override
    public void cleanupSandboxBase(Path sandboxBase, TreeDeleter treeDeleter) throws IOException {
      sandboxSpawnRunner.cleanupSandboxBase(sandboxBase, treeDeleter);
      fallbackSpawnRunner.cleanupSandboxBase(sandboxBase, treeDeleter);
    }
  }

  /**
   * Unmounts an existing sandboxfs instance unless the user asked not to by providing the {@code
   * --sandbox_debug} flag.
   */
  private void unmountSandboxfs() {
    if (sandboxfsProcess != null) {
      if (shouldCleanupSandboxBase) {
        sandboxfsProcess.destroy();
        sandboxfsProcess = null;
      } else {
        checkNotNull(env, "env not initialized; was beforeCommand called?");
        env.getReporter()
            .handle(Event.info("Leaving sandboxfs mounted because of --sandbox_debug"));
      }
    }
  }

  /** Silently tries to unmount an existing sandboxfs instance, ignoring errors. */
  private void tryUnmountSandboxfsOnShutdown() {
    if (sandboxfsProcess != null) {
      sandboxfsProcess.destroy();
      sandboxfsProcess = null;
    }
  }

  @Subscribe
  public void buildComplete(@SuppressWarnings("unused") BuildCompleteEvent event) {
    unmountSandboxfs();
  }

  @Subscribe
  public void buildInterrupted(@SuppressWarnings("unused") BuildInterruptedEvent event) {
    unmountSandboxfs();
  }

  @Override
  public void afterCommand() {
    checkNotNull(env, "env not initialized; was beforeCommand called?");

    SandboxOptions options = env.getOptions().getOptions(SandboxOptions.class);
    int asyncTreeDeleteThreads = options != null ? options.asyncTreeDeleteIdleThreads : 0;
    if (treeDeleter != null && asyncTreeDeleteThreads > 0) {
      // If asynchronous deletions were requested, they may still be ongoing so let them be: trying
      // to delete the base tree synchronously could fail as we can race with those other deletions,
      // and scheduling an asynchronous deletion could race with future builds.
      AsynchronousTreeDeleter treeDeleter =
          (AsynchronousTreeDeleter) checkNotNull(this.treeDeleter);
      treeDeleter.setThreads(asyncTreeDeleteThreads);
    }

    if (shouldCleanupSandboxBase) {
      try {
        checkNotNull(sandboxBase, "shouldCleanupSandboxBase implies sandboxBase has been set");
        for (SpawnRunner spawnRunner : spawnRunners) {
          spawnRunner.cleanupSandboxBase(sandboxBase, treeDeleter);
        }
      } catch (IOException e) {
        env.getReporter()
            .handle(Event.warn("Failed to delete contents of sandbox " + sandboxBase + ": " + e));
      }
      shouldCleanupSandboxBase = false;

      checkState(
          sandboxfsProcess == null,
          "sandboxfs instance should have been shut down at this "
              + "point; were the buildComplete/buildInterrupted events sent?");
      sandboxBase = null;
    }

    env.getEventBus().unregister(this);
    env = null;
  }

  private void commonShutdown() {
    tryUnmountSandboxfsOnShutdown();

    // Try to clean up as much garbage as possible, if there happens to be any. This will delay
    // server termination but it's the nice thing to do. If the user gets impatient, they can always
    // kill us again.
    if (treeDeleter != null) {
      try {
        treeDeleter.shutdown();
      } finally {
        treeDeleter = null; // Avoid potential reexecution if we crash.
      }
    }
  }

  @Override
  public void blazeShutdown() {
    commonShutdown();
  }

  @Override
  public void blazeShutdownOnCrash() {
    commonShutdown();
  }
}
