/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.drill.exec.impersonation;

import org.apache.commons.io.FileUtils;
import org.apache.drill.common.config.DrillConfig;
import org.apache.drill.exec.ExecConstants;
import org.apache.drill.exec.dotdrill.DotDrillType;
import org.apache.drill.exec.store.StoragePluginRegistry;
import org.apache.drill.exec.store.dfs.FileSystemConfig;
import org.apache.drill.exec.store.dfs.WorkspaceConfig;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import org.apache.drill.test.ClientFixture;
import org.apache.drill.test.ClusterFixture;
import org.apache.drill.test.ClusterFixtureBuilder;
import org.apache.drill.test.ClusterTest;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileStatus;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.permission.FsPermission;
import org.apache.hadoop.hdfs.MiniDFSCluster;
import org.apache.hadoop.security.UserGroupInformation;

import java.io.File;
import java.nio.file.Paths;
import java.util.Map;
import java.util.Properties;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class BaseTestImpersonation extends ClusterTest {
  protected static final String MINI_DFS_STORAGE_PLUGIN_NAME = "mini_dfs_plugin";
  protected static final String processUser = System.getProperty("user.name");

  protected static MiniDFSCluster dfsCluster;
  protected static Configuration dfsConf;
  protected static FileSystem fs;
  protected static File miniDfsStoragePath;

  // Test users and groups
  protected static final String[] org1Users = { "user0_1", "user1_1", "user2_1", "user3_1", "user4_1", "user5_1" };
  protected static final String[] org1Groups = { "group0_1", "group1_1", "group2_1", "group3_1", "group4_1", "group5_1" };
  protected static final String[] org2Users = { "user0_2", "user1_2", "user2_2", "user3_2", "user4_2", "user5_2" };
  protected static final String[] org2Groups = { "group0_2", "group1_2", "group2_2", "group3_2", "group4_2", "group5_2" };

  static {
    // "user0_1" belongs to "groups0_1". From "user1_1" onwards each user belongs to corresponding group and the group
    // before it, i.e "user1_1" belongs to "group1_1" and "group0_1" and so on.
    UserGroupInformation.createUserForTesting(org1Users[0], new String[]{org1Groups[0]});
    for(int i=1; i<org1Users.length; i++) {
      UserGroupInformation.createUserForTesting(org1Users[i], new String[] { org1Groups[i], org1Groups[i-1] });
    }

    UserGroupInformation.createUserForTesting(org2Users[0], new String[] { org2Groups[0] });
    for(int i=1; i<org2Users.length; i++) {
      UserGroupInformation.createUserForTesting(org2Users[i], new String[] { org2Groups[i], org2Groups[i-1] });
    }
  }

  /**
   * Start a MiniDFS cluster backed Drillbit cluster with impersonation enabled.
   * @param testClass test class
   * @throws Exception in case of errors during start up
   */
  protected static void startMiniDfsCluster(String testClass) throws Exception {
    startMiniDfsCluster(testClass, true);
  }

  /**
   * Start a MiniDFS cluster backed Drillbit cluster
   * @param testClass test class
   * @param isImpersonationEnabled Enable impersonation in the cluster?
   * @throws Exception in case of errors during start up
   */
  protected static void startMiniDfsCluster(String testClass, boolean isImpersonationEnabled) throws Exception {
    Preconditions.checkArgument(!Strings.isNullOrEmpty(testClass), "Expected a non-null and non-empty test class name");
    dfsConf = new Configuration();

    // Set the MiniDfs base dir to be the temp directory of the test, so that all files created within the MiniDfs
    // are properly cleanup when test exits.
    miniDfsStoragePath = dirTestWatcher.makeRootSubDir(Paths.get("miniDfs"));
    dfsConf.set("hdfs.minidfs.basedir", miniDfsStoragePath.getCanonicalPath());

    if (isImpersonationEnabled) {
      // Set the proxyuser settings so that the user who is running the Drillbits/MiniDfs can impersonate other users.
      dfsConf.set(String.format("hadoop.proxyuser.%s.hosts", processUser), "*");
      dfsConf.set(String.format("hadoop.proxyuser.%s.groups", processUser), "*");

      // It isn't clear exactly when or why the following reinitialisation is
      // needed, but without it the test subclasses of this class may crash
      // when run in the GitHub CI with Mini DFS stating "Running in secure
      // mode, but config doesn't have a keytab".
      dfsConf.set("hadoop.security.authentication", "simple");
      UserGroupInformation.setConfiguration(dfsConf);
    }

    // Start the MiniDfs cluster
    dfsCluster = new MiniDFSCluster.Builder(dfsConf)
        .numDataNodes(3)
        .format(true)
        .build();

    fs = dfsCluster.getFileSystem();
  }

  protected static void startDrillCluster(final boolean isImpersonationEnabled) throws Exception {
    final Properties props = new Properties();
    props.setProperty(ExecConstants.IMPERSONATION_ENABLED, Boolean.toString(isImpersonationEnabled));
    startDrillCluster(1, props);
  }

  protected static void startDrillCluster(int newDrillbitCount, final Properties props) throws Exception {
    startDrillCluster(newDrillbitCount, null, props);
  }

  protected static void startDrillCluster(int newDrillbitCount, final DrillConfig configs, final Properties props) throws Exception {
    ClusterFixtureBuilder builder = ClusterFixture.builder(dirTestWatcher).clusterSize(newDrillbitCount);
    builder.configBuilder().configProps(props);
    if (configs != null) {
      builder.configBuilder().configProps(configs);
    }
    startCluster(builder);
  }

  protected static void addMiniDfsBasedStorage(final Map<String, WorkspaceConfig> workspaces) throws Exception {
    // Create a HDFS based storage plugin based on local storage plugin and add it to plugin registry (connection string
    // for mini dfs is varies for each run).
    StoragePluginRegistry pluginRegistry = cluster.storageRegistry();
    FileSystemConfig lfsPluginConfig = (FileSystemConfig) pluginRegistry.getPlugin("dfs").getConfig();

    String connection = dfsConf.get(FileSystem.FS_DEFAULT_NAME_KEY);
    createAndAddWorkspace("tmp", "/tmp", (short) 0777, processUser, processUser, workspaces);

    FileSystemConfig miniDfsPluginConfig = new FileSystemConfig(connection, null,
        workspaces, lfsPluginConfig.getFormats(), null, null);
    miniDfsPluginConfig.setEnabled(true);
    pluginRegistry.put(MINI_DFS_STORAGE_PLUGIN_NAME, miniDfsPluginConfig);
  }

  protected static void createAndAddWorkspace(String name, String path, short permissions, String owner,
      String group, final Map<String, WorkspaceConfig> workspaces) throws Exception {

    FsPermission permission = new FsPermission(permissions);

    Path dirPath = new Path(path);
    assertTrue(FileSystem.mkdirs(fs, dirPath, permission));
    fs.setOwner(dirPath, owner, group);

    // create sample file in the workspace to check show files command
    Path sampleFile = new Path(dirPath, String.format("sample_%s.txt", name));
    assertTrue(fs.createNewFile(sampleFile));
    fs.setPermission(sampleFile, permission);
    fs.setOwner(sampleFile, owner, group);

    final WorkspaceConfig ws = new WorkspaceConfig(path, true, "parquet", false);
    workspaces.put(name, ws);
  }

  protected static void stopMiniDfsCluster() {
    if (dfsCluster != null) {
      dfsCluster.shutdown();
      dfsCluster = null;
    }

    if (miniDfsStoragePath != null) {
      FileUtils.deleteQuietly(miniDfsStoragePath);
    }
  }

  // Return the user workspace for given user.
  protected static String getWSSchema(String user) {
    return MINI_DFS_STORAGE_PLUGIN_NAME + "." + user;
  }

  protected static String getUserHome(String user) {
    return "/user/" + user;
  }

  protected static void createView(final String viewOwner, final String viewGroup, final short viewPerms,
                                 final String newViewName, final String fromSourceSchema, final String fromSourceTableName) throws Exception {
    try (ClientFixture client = cluster.client(viewOwner, "")) {
      client.run(String.format("ALTER SESSION SET `%s`='%o'", ExecConstants.NEW_VIEW_DEFAULT_PERMS_KEY, viewPerms));
      client.run(String.format("CREATE VIEW %s.%s AS SELECT * FROM %s.%s",
        getWSSchema(viewOwner), newViewName, fromSourceSchema, fromSourceTableName));

      // Verify the view file created has the expected permissions and ownership
      Path viewFilePath = new Path(getUserHome(viewOwner), newViewName + DotDrillType.VIEW.getEnding());
      FileStatus status = fs.getFileStatus(viewFilePath);
      assertEquals(viewGroup, status.getGroup());
      assertEquals(viewOwner, status.getOwner());
      assertEquals(viewPerms, status.getPermission().toShort());
    }
  }

  protected static void createView(final String viewOwner, final String viewGroup, final String viewName,
                                 final String viewDef) throws Exception {
    try (ClientFixture client = cluster.client(viewOwner, "")) {
      client.run(String.format("ALTER SESSION SET `%s`='%o'", ExecConstants.NEW_VIEW_DEFAULT_PERMS_KEY, (short) 0750));
      client.run("CREATE VIEW %s.%s.%s AS %s", MINI_DFS_STORAGE_PLUGIN_NAME, "tmp", viewName, viewDef);
      final Path viewFilePath = new Path("/tmp/", viewName + DotDrillType.VIEW.getEnding());
      fs.setOwner(viewFilePath, viewOwner, viewGroup);
    }
  }
}
