content: /**
   * 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
   * <p>
   * http://www.apache.org/licenses/LICENSE-2.0
   * <p>
   * 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.atlas;
  
  import org.apache.atlas.model.metrics.AtlasMetrics;
  import org.apache.atlas.type.AtlasType;
  import org.apache.atlas.utils.AuthenticationUtil;
  import org.apache.commons.cli.CommandLine;
  import org.apache.commons.cli.CommandLineParser;
  import org.apache.commons.cli.GnuParser;
  import org.apache.commons.cli.HelpFormatter;
  import org.apache.commons.cli.Option;
  import org.apache.commons.cli.Options;
  import org.apache.commons.cli.ParseException;
  import org.apache.commons.configuration.Configuration;
  
  import java.util.Arrays;
  
  /**
   * An application that allows users to run admin commands against an Atlas server.
   *
   * The application uses {@link AtlasClient} to send REST requests to the Atlas server. The details of connections
   * and other configuration is specified in the Atlas properties file.
   * Exit status of the application will be as follows:
   * <li>0: successful execution</li>
   * <li>1: error in options used for the application</li>
   * <li>-1/255: application error</li>
   */
  public class AtlasAdminClient {
      private static final Option STATUS      = new Option("status", false, "Get the status of an atlas instance");
      private static final Option STATS       = new Option("stats", false, "Get the metrics of an atlas instance");
      private static final Option CREDENTIALS = new Option("u", true, "Authorized atlas user credentials (<user>:<password>)");
  
      private static final Options OPTIONS = new Options();
  
      private static final int INVALID_OPTIONS_STATUS = 1;
      private static final int PROGRAM_ERROR_STATUS   = -1;
  
      public static void main(String[] args) throws AtlasException, ParseException {
          AtlasAdminClient atlasAdminClient = new AtlasAdminClient();
          int              result           = atlasAdminClient.run(args);
  
          System.exit(result);
      }
  
      private int run(String[] args) throws AtlasException {
          CommandLine   commandLine    = parseCommandLineOptions(args);
          Configuration configuration  = ApplicationProperties.get();
          String[]      atlasServerUri = configuration.getStringArray(AtlasConstants.ATLAS_REST_ADDRESS_KEY);
  
          if (atlasServerUri == null || atlasServerUri.length == 0) {
              atlasServerUri = new String[] {AtlasConstants.DEFAULT_ATLAS_REST_ADDRESS};
          }
  
          return handleCommand(commandLine, atlasServerUri);
      }
  
      private int handleCommand(CommandLine commandLine, String[] atlasServerUri) throws AtlasException {
          String[] providedUserPassword = getUserPassword(commandLine);
          int      cmdStatus            = PROGRAM_ERROR_STATUS;
  
          if (commandLine.hasOption(STATUS.getOpt())) {
              AtlasClient atlasClient = initAtlasClient(atlasServerUri, providedUserPassword); // Status is open API, no auth needed
  
              try {
                  System.out.println(atlasClient.getAdminStatus());
  
                  cmdStatus = 0;
              } catch (AtlasServiceException e) {
                  System.err.println("Could not retrieve status of the server at " + Arrays.toString(atlasServerUri));
  
                  printStandardHttpErrorDetails(e);
              }
          } else if (commandLine.hasOption(STATS.getOpt())) {
              AtlasClient atlasClient = initAtlasClient(atlasServerUri, providedUserPassword); // Stats/metrics is open API, no auth needed
  
              try {
                  AtlasMetrics atlasMetrics = atlasClient.getAtlasMetrics();
                  String       json         = AtlasType.toJson(atlasMetrics);
  
                  System.out.println(json);
  
                  cmdStatus = 0;
              } catch (AtlasServiceException e) {
                  System.err.println("Could not retrieve metrics of the server at " + Arrays.toString(atlasServerUri));
  
                  printStandardHttpErrorDetails(e);
              }
          } else {
              System.err.println("Unsupported option. Refer to usage for valid options.");
  
              printUsage();
          }
  
          return cmdStatus;
      }
  
      private String[] getUserPassword(CommandLine commandLine) {
          String[] basicAuthUsernamePassword = null;
  
          // Parse the provided username password
          if (commandLine.hasOption(CREDENTIALS.getOpt())) {
              String value = commandLine.getOptionValue(CREDENTIALS.getOpt());
  
              if (value != null) {
                  basicAuthUsernamePassword = value.split(":");
              }
          }
  
          if (basicAuthUsernamePassword == null || basicAuthUsernamePassword.length != 2) {
              System.err.println("Invalid credentials. Format: <user>:<password>");
          }
  
          return basicAuthUsernamePassword;
      }
  
      private AtlasClient initAtlasClient(final String[] atlasServerUri, final String[] providedUserNamePassword) throws AtlasException {
          final AtlasClient atlasClient;
  
          if (!AuthenticationUtil.isKerberosAuthenticationEnabled()) {
              if (providedUserNamePassword == null || providedUserNamePassword.length < 2) {
                  atlasClient = new AtlasClient(atlasServerUri, AuthenticationUtil.getBasicAuthenticationInput());
              } else {
                  atlasClient = new AtlasClient(atlasServerUri, providedUserNamePassword);
              }
          } else {
              atlasClient = new AtlasClient(atlasServerUri);
          }
  
          return atlasClient;
      }
  
      private void printStandardHttpErrorDetails(AtlasServiceException e) {
          System.err.println("Error details: ");
          System.err.println("HTTP Status: " + e.getStatus().getStatusCode() + "," + e.getStatus().getReasonPhrase());
          System.err.println("Exception message: " + e.getMessage());
      }
  
      private CommandLine parseCommandLineOptions(String[] args) {
          if (args.length == 0) {
              printUsage();
          }
  
          CommandLineParser parser      = new GnuParser();
          CommandLine       commandLine = null;
  
          try {
              commandLine = parser.parse(OPTIONS, args);
          } catch (ParseException e) {
              System.err.println("Could not parse command line options. " + e.getMessage());
  
              printUsage();
          }
  
          return commandLine;
      }
  
      private void printUsage() {
          HelpFormatter helpFormatter = new HelpFormatter();
  
          helpFormatter.printHelp("atlas_admin.py", OPTIONS);
  
          System.exit(AtlasAdminClient.INVALID_OPTIONS_STATUS);
      }
  
      static {
          OPTIONS.addOption(STATUS);
          OPTIONS.addOption(STATS);
          OPTIONS.addOption(CREDENTIALS);
      }
  }
  