This is an automated email from the ASF dual-hosted git repository.

chengpan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/kyuubi.git


The following commit(s) were added to refs/heads/master by this push:
     new cfc23a1df [KYUUBI #6339] kyuubi-beeline auto constructs JDBC URL from 
kyuubi-defaults.conf
cfc23a1df is described below

commit cfc23a1df92545a43f274f59c78cf3f8cdc23446
Author: hezhao2 <[email protected]>
AuthorDate: Tue Jun 25 13:19:46 2024 +0800

    [KYUUBI #6339] kyuubi-beeline auto constructs JDBC URL from 
kyuubi-defaults.conf
    
    # :mag: Description
    ## Issue References ๐Ÿ”—
    
    as title
    This pull request closes  #6255
    
    ## Describe Your Solution ๐Ÿ”ง
    
    Please include a summary of the change and which issue is fixed. Please 
also include relevant motivation and context. List any dependencies that are 
required for this change.
    
    ## Types of changes :bookmark:
    
    - [ ] Bugfix (non-breaking change which fixes an issue)
    - [x] New feature (non-breaking change which adds functionality)
    - [ ] Breaking change (fix or feature that would cause existing 
functionality to change)
    
    ## Test Plan ๐Ÿงช
    
    #### Behavior Without This Pull Request :coffin:
    
    #### Behavior With This Pull Request :tada:
    
    #### Related Unit Tests
    
    ---
    
    # Checklist ๐Ÿ“
    
    - [x] This patch was not authored or co-authored using [Generative 
Tooling](https://www.apache.org/legal/generative-tooling.html)
    
    **Be nice. Be informative.**
    
    Closes #6339 from zhaohehuhu/dev-0426.
    
    Closes #6339
    
    38b36f260 [Cheng Pan] fix
    b2e3fcf3d [Cheng Pan] rewrite
    
    Lead-authored-by: hezhao2 <[email protected]>
    Co-authored-by: Cheng Pan <[email protected]>
    Signed-off-by: Cheng Pan <[email protected]>
---
 docs/client/cli/kyuubi_beeline.md                  | 289 +++++++++++++++++++++
 docs/client/cli/kyuubi_beeline.rst                 |  22 --
 .../main/java/org/apache/hive/beeline/BeeLine.java |  39 +--
 .../KyuubiConfFileParseException.java              |  29 +++
 .../hs2connection/KyuubiConfFileParser.java        | 205 +++++++++++++++
 .../hs2connection/UserHS2ConnectionFileParser.java |   6 +-
 .../hs2connection/TestKyuubiConfFileParser.java    |  44 ++++
 .../src/test/resources/kyuubi-defaults.conf        |  40 +++
 8 files changed, 633 insertions(+), 41 deletions(-)

diff --git a/docs/client/cli/kyuubi_beeline.md 
b/docs/client/cli/kyuubi_beeline.md
new file mode 100644
index 000000000..3fd5208eb
--- /dev/null
+++ b/docs/client/cli/kyuubi_beeline.md
@@ -0,0 +1,289 @@
+<!--
+- 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.
+-->
+
+# Kyuubi Beeline
+
+## What is Kyuubi Beeline
+
+Kyuubi Beeline is a Command Line Shell that uses JDBC driver to connect to 
Kyuubi server to execute queries.
+Kyuubi Beeline is derived from
+[Hive 
Beeline](https://cwiki.apache.org/confluence/display/Hive/HiveServer2+Clients#HiveServer2Clients-Beeline%E2%80%93CommandLineShell),
+almost functionalities of Hive Beeline should be applicable to Kyuubi Beeline 
as well.
+
+Note: Kyuubi Beeline removes the support of "embedded mode" because it is 
coupled with Apache Hive implementation details,
+thus only "remote mode" can be used in Kyuubi Beeline.
+
+## How to use Kyuubi Beeline
+
+Run `kyuubi-beeline --help` to show help message with all options and examples.
+
+```
+Usage: kyuubi-beeline <options>.
+
+Options:
+  -u <database url>               The JDBC URL to connect to.
+  -c <named url>                  The named JDBC URL to connect to,
+                                  which should be present in beeline-site.xml
+                                  as the value of 
beeline.kyuubi.jdbc.url.<namedUrl>.
+
+  -r                              Reconnect to last saved connect url (in 
conjunction with !save).
+  -n <username>                   The username to connect as.
+  -p <password>                   The password to connect as.
+  -d <driver class>               The driver class to use.
+  -i <init file>                  Script file for initialization.
+  -e <query>                      Query that should be executed.
+  -f <exec file>                  Script file that should be executed.
+  -w, --password-file <file>      The password file to read password from.
+  --hiveconf property=value       Use value for given property.
+  --hivevar name=value            Hive variable name and value.
+                                  This is Hive specific settings in which 
variables
+                                  can be set at session level and referenced 
in Hive
+                                  commands or queries.
+
+  --property-file=<property file> The file to read connection properties (url, 
driver, user, password) from.
+  --color=[true|false]            Control whether color is used for display.
+  --showHeader=[true|false]       Show column names in query results.
+  --escapeCRLF=[true|false]       Show carriage return and line feeds in query 
results as escaped \r and \n.
+  --headerInterval=ROWS;          The interval between which heades are 
displayed.
+  --fastConnect=[true|false]      Skip building table/column list for 
tab-completion.
+  --autoCommit=[true|false]       Enable/disable automatic transaction commit.
+  --verbose=[true|false]          Show verbose error messages and debug info.
+  --showWarnings=[true|false]     Display connection warnings.
+  --showDbInPrompt=[true|false]   Display the current database name in the 
prompt.
+  --showNestedErrs=[true|false]   Display nested errors.
+  --numberFormat=[pattern]        Format numbers using DecimalFormat pattern.
+  --force=[true|false]            Continue running script even after errors.
+  --maxWidth=MAXWIDTH             The maximum width of the terminal.
+  --maxColumnWidth=MAXCOLWIDTH    The maximum width to use when displaying 
columns.
+  --silent=[true|false]           Be more silent.
+  --autosave=[true|false]         Automatically save preferences.
+  --outputformat=<format mode>    Format mode for result display.
+                                  The available options ars 
[table|vertical|csv2|tsv2|dsv|csv|tsv|json|jsonfile].
+                                  Note that csv, and tsv are deprecated, use 
csv2, tsv2 instead.
+
+  --incremental=[true|false]      Defaults to false. When set to false, the 
entire result set
+                                  is fetched and buffered before being 
displayed, yielding optimal
+                                  display column sizing. When set to true, 
result rows are displayed
+                                  immediately as they are fetched, yielding 
lower latency and
+                                  memory usage at the price of extra display 
column padding.
+                                  Setting --incremental=true is recommended if 
you encounter an OutOfMemory
+                                  on the client side (due to the fetched 
result set size being large).
+                                  Only applicable if --outputformat=table.
+
+  --incrementalBufferRows=NUMROWS The number of rows to buffer when printing 
rows on stdout,
+                                  defaults to 1000; only applicable if 
--incremental=true
+                                  and --outputformat=table.
+
+  --truncateTable=[true|false]    Truncate table column when it exceeds length.
+  --delimiterForDSV=DELIMITER     Specify the delimiter for 
delimiter-separated values output format (default: |).
+  --isolation=LEVEL               Set the transaction isolation level.
+  --nullemptystring=[true|false]  Set to true to get historic behavior of 
printing null as empty string.
+  --maxHistoryRows=MAXHISTORYROWS The maximum number of rows to store beeline 
history.
+  --delimiter=DELIMITER           Set the query delimiter; multi-char 
delimiters are allowed, but quotation
+                                  marks, slashes, and -- are not allowed 
(default: ;).
+
+  --convertBinaryArrayToString=[true|false]
+                                  Display binary column data as string or as 
byte array.
+
+  --python-mode                   Execute python code/script.
+  -h, --help                      Display this message.
+
+Examples:
+  1. Connect using simple authentication to Kyuubi Server on localhost:10009.
+  $ kyuubi-beeline -u jdbc:kyuubi://localhost:10009 -n username
+
+  2. Connect using simple authentication to Kyuubi Server on 
kyuubi.local:10009 using -n for username and -p for password.
+  $ kyuubi-beeline -n username -p password -u jdbc:kyuubi://kyuubi.local:10009
+
+  3. Connect using Kerberos authentication with kyuubi/[email protected] 
as Kyuubi Server principal(kinit is required before connection).
+  $ kyuubi-beeline -u 
"jdbc:kyuubi://kyuubi.local:10009/default;kyuubiServerPrincipal=kyuubi/[email protected]"
+
+  4. Connect using Kerberos authentication using principal and keytab directly.
+  $ kyuubi-beeline -u 
"jdbc:kyuubi://kyuubi.local:10009/default;[email protected];kyuubiClientKeytab=/local/path/client.keytab;kyuubiServerPrincipal=kyuubi/[email protected]"
+
+  5. Connect using SSL connection to Kyuubi Server on localhost:10009.
+  $ kyuubi-beeline -u 
"jdbc:kyuubi://localhost:10009/default;ssl=true;sslTrustStore=/usr/local/truststore;trustStorePassword=mytruststorepassword"
+
+  6. Connect using LDAP authentication.
+  $ kyuubi-beeline -u jdbc:kyuubi://kyuubi.local:10009/default -n 
ldap-username -p ldap-password
+
+  7. Connect using the ZooKeeper address to Kyuubi HA cluster.
+  $ kyuubi-beeline -u 
"jdbc:kyuubi://zk1:2181,zk2:2181,zk3:2181/;serviceDiscoveryMode=zooKeeper;zooKeeperNamespace=kyuubi"
 -n username
+```
+
+## Using `kyuubi-defaults.conf` to automatically connect to Kyuubi
+
+As of Kyuubi 1.10, Kyuubi Beeline adds support to use the 
`kyuubi-defaults.conf` present in the `KYUUBI_CONF_DIR` to
+automatically generate a connection URL based on the configuration properties 
in `kyuubi-defaults.conf` and an
+additional user configuration file. Not all the URL properties can be derived 
from `kyuubi-defaults.conf` and hence
+in order to use this feature user must create a configuration file called 
`beeline-hs2-connection.xml` which is a
+Hadoop XML format file. This file is used to provide user-specific connection 
properties for the connection URL.
+Kyuubi Beeline looks for this configuration file in `${user.home}/.beeline/` 
(UNIX-like OS) or `${user.home}\beeline\`
+directory (in case of Windows). If the file is not found in the above 
locations Beeline looks for it in `HIVE_CONF_DIR`
+location and `/etc/hive/conf` in that order. Once the file is found, Kyuubi 
Beeline uses `beeline-hs2-connection.xml`
+in conjunction with the `kyuubi-defaults.conf` to determine the connection URL.
+
+The URL connection properties in `beeline-hs2-connection.xml` must have the 
prefix `beeline.hs2.connection.` followed by
+the URL property name. For example in order to provide the property ssl the 
property key in the `beeline-hs2-connection.xml`
+should be `beeline.hs2.connection.ssl`. The sample 
`beeline.hs2.connection.xml` below provides the value of user and
+password for the Beeline connection URL. In this case the rest of the 
properties like Kyuubi hostname and port information,
+Kerberos configuration properties, SSL properties, transport mode, etc., are 
picked up using the `kyuubi-defaults.conf`.
+If the password is empty `beeline.hs2.connection.password` property should be 
removed. In most cases the below
+configuration values in `beeline-hs2-connection.xml` and the correct 
`kyuubi-defaults.conf` should be sufficient to
+make the connection to the Kyuubi.
+
+```xml
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<configuration>
+<property>
+  <name>beeline.hs2.connection.user</name>
+  <value>kyuubi</value>
+</property>
+<property>
+  <name>beeline.hs2.connection.password</name>
+  <value>kyuubi</value>
+</property>
+</configuration>
+```
+
+In case of properties which are present in both `beeline-hs2-connection.xml` 
and `kyuubi-defaults.conf`, the property
+value derived from `beeline-hs2-connection.xml` takes precedence. For example 
in the below `beeline-hs2-connection.xml`
+file provides the value of principal for Beeline connection in a Kerberos 
enabled environment. In this case the property
+value for `beeline.hs2.connection.principal` overrides the value of 
`kyuubi.kinit.principal` from `kyuubi-defaults.conf`
+as far as connection URL is concerned.
+
+```xml
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<configuration>
+<property>
+  <name>beeline.hs2.connection.hosts</name>
+  <value>localhost:10009</value>
+</property>
+<property>
+  <name>beeline.hs2.connection.principal</name>
+  <value>kyuubi/[email protected]</value>
+</property>
+</configuration>
+```
+
+In case of properties `beeline.hs2.connection.hosts`, 
`beeline.hs2.connection.hiveconf` and
+`beeline.hs2.connection.hivevar` the property value is a comma-separated list 
of values. For example the following
+`beeline-hs2-connection.xml` provides the `hiveconf` and `hivevar` values in a 
comma separated format.
+
+```xml
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<configuration>
+<property>
+  <name>beeline.hs2.connection.user</name>
+  <value>kyuubi</value>
+</property>
+<property>
+  <name>beeline.hs2.connection.hiveconf</name>
+  
<value>kyuubi.session.engine.initialize.timeout=PT3M,kyuubi.engine.type=SPARK_SQL</value>
+</property>
+<property>
+  <name>beeline.hs2.connection.hivevar</name>
+  <value>testVarName1=value1, testVarName2=value2</value>
+</property>
+</configuration>
+```
+
+When the `beeline-hs2-connection.xml` is present and when no other arguments 
are provided, Kyuubi Beeline automatically
+connects to the URL generated using configuration files. When connection 
arguments (`-u`, `-n` or `-p`) are provided,
+Kyuubi Beeline uses them and does not use `beeline-hs2-connection.xml` to 
automatically connect. Removing or renaming
+the `beeline-hs2-connection.xml` disables this feature.
+
+## Using beeline-site.xml to automatically connect to HiveServer2
+
+In addition to the above method of using `kyuubi-defaults.conf` and 
`beeline-hs2-connection.xml` for deriving the JDBC
+connection URL to use when connecting to Kyuubi from Kyuubi Beeline, a user 
can optionally add `beeline-site.xml` to
+their classpath, and within `beeline-site.xml`, she can specify complete JDBC 
URLs. A user can also specify multiple
+named URLs and use `kyuubi-beeline -c <named_url>` to connect to a specific 
URL. This is particularly useful when the
+same cluster has multiple Kyuubi instances running with different 
configurations. One of the named URLs is treated as
+default (which is the URL that gets used when the user simply types beeline). 
An example `beeline-site.xml` is shown below:
+
+```xml
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<configuration>
+<property>
+  <name>beeline.hs2.jdbc.url.tcpUrl</name>
+  
<value>jdbc:kyuubi://localhost:10009/default;user=kyuubi;password=kyuubi</value>
+</property>
+
+<property>
+  <name>beeline.hs2.jdbc.url.httpUrl</name>
+  
<value>jdbc:kyuubi://localhost:10009/default;user=kyuubi;password=kyuubi;transportMode=http;httpPath=cliservice</value>
+</property>
+
+<property>
+  <name>beeline.hs2.jdbc.url.default</name>
+  <value>tcpUrl</value>
+</property>
+</configuration>
+```
+
+In the above example, simply typing `kyuubi-beeline` opens a new JDBC 
connection to
+`jdbc:kyuubi://localhost:10009/default;user=kyuubi;password=kyuubi`. If both 
`beeline-site.xml` and
+`beeline-hs2-connection.xml` are present in the classpath, the final URL is 
created by applying the properties specified
+in `beeline-hs2-connection.xml` on top of the URL properties derived from 
beeline-site.xml. As an example consider the
+following `beeline-hs2-connection.xml`:
+
+```xml
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<configuration>
+<property>
+  <name>beeline.hs2.connection.user</name>
+  <value>kyuubi</value>
+</property>
+<property>
+  <name>beeline.hs2.connection.password</name>
+  <value>kyuubi</value>
+</property>
+</configuration>
+```
+
+Consider the following `beeline-site.xml`:
+
+```xml
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<configuration>
+<property>
+  <name>beeline.hs2.jdbc.url.tcpUrl</name>
+  <value>jdbc:kyuubi://localhost:10009/default</value>
+</property>
+
+<property>
+  <name>beeline.hs2.jdbc.url.httpUrl</name>
+  
<value>jdbc:kyuubi://localhost:10009/default;transportMode=http;httpPath=cliservice</value>
+</property>
+
+<property>
+  <name>beeline.hs2.jdbc.url.default</name>
+  <value>tcpUrl</value>
+</property>
+</configuration>
+```
+
+In the above example, simply typing `kyuubi-beeline` opens a new JDBC 
connection to
+`jdbc:kyuubi://localhost:10009/default;user=kyuubi;password=kyuubi`. When the 
user types `kyuubi-beeline -c httpUrl`,
+a connection is opened to 
`jdbc:kyuubi://localhost:10009/default;transportMode=http;httpPath=cliservice;user=kyuubi;password=kyuubi`.
diff --git a/docs/client/cli/kyuubi_beeline.rst 
b/docs/client/cli/kyuubi_beeline.rst
deleted file mode 100644
index e21781058..000000000
--- a/docs/client/cli/kyuubi_beeline.rst
+++ /dev/null
@@ -1,22 +0,0 @@
-.. 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.
-
-Kyuubi Beeline
-==============
-
-.. warning:: The document you are visiting now is incomplete, please help 
kyuubi community to fix it if appropriate for you.
-
-
-
diff --git 
a/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/BeeLine.java 
b/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/BeeLine.java
index 58a35a813..3f749334e 100644
--- a/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/BeeLine.java
+++ b/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/BeeLine.java
@@ -89,13 +89,7 @@ import org.apache.commons.cli.ParseException;
 import org.apache.commons.io.IOUtils;
 import org.apache.hadoop.fs.FSDataInputStream;
 import org.apache.hive.beeline.common.util.ShutdownHookManager;
-import org.apache.hive.beeline.hs2connection.BeelineConfFileParseException;
-import org.apache.hive.beeline.hs2connection.BeelineSiteParseException;
-import org.apache.hive.beeline.hs2connection.BeelineSiteParser;
-import org.apache.hive.beeline.hs2connection.HS2ConnectionFileParser;
-import org.apache.hive.beeline.hs2connection.HS2ConnectionFileUtils;
-import org.apache.hive.beeline.hs2connection.HiveSiteHS2ConnectionFileParser;
-import org.apache.hive.beeline.hs2connection.UserHS2ConnectionFileParser;
+import org.apache.hive.beeline.hs2connection.*;
 import org.apache.kyuubi.jdbc.hive.JdbcConnectionParams;
 import org.apache.kyuubi.jdbc.hive.JdbcUriParseException;
 import org.apache.kyuubi.jdbc.hive.Utils;
@@ -954,7 +948,6 @@ public class BeeLine implements Closeable {
   /*
    * Attempts to make a connection using default HS2 connection config file if 
available
    * if there connection is not made return false
-   *
    */
   private boolean defaultBeelineConnect(CommandLine cl) {
     String url;
@@ -972,11 +965,9 @@ public class BeeLine implements Closeable {
   }
 
   private String getDefaultConnectionUrl(CommandLine cl) throws 
BeelineConfFileParseException {
-    Properties mergedConnectionProperties = new Properties();
     JdbcConnectionParams jdbcConnectionParams = null;
     BeelineSiteParser beelineSiteParser = getUserBeelineSiteParser();
     UserHS2ConnectionFileParser userHS2ConnFileParser = 
getUserHS2ConnFileParser();
-    Properties userConnectionProperties = new Properties();
 
     if (!userHS2ConnFileParser.configExists() && 
!beelineSiteParser.configExists()) {
       // nothing to do if there is no user HS2 connection configuration file
@@ -1007,11 +998,13 @@ public class BeeLine implements Closeable {
       }
     }
 
+    Properties userConnectionProperties = new Properties();
     if (userHS2ConnFileParser.configExists()) {
       // get the connection properties from user specific config file
       userConnectionProperties = 
userHS2ConnFileParser.getConnectionProperties();
     }
 
+    Properties mergedConnectionProperties = userConnectionProperties;
     if (jdbcConnectionParams != null) {
       String userName = cl.getOptionValue("n");
       if (userName != null) {
@@ -1024,25 +1017,30 @@ public class BeeLine implements Closeable {
       mergedConnectionProperties =
           HS2ConnectionFileUtils.mergeUserConnectionPropertiesAndBeelineSite(
               userConnectionProperties, jdbcConnectionParams);
-    } else {
-      mergedConnectionProperties = userConnectionProperties;
     }
 
-    // load the HS2 connection url properties from hive-site.xml if it is 
present in the classpath
+    Properties serverConnectionProperties = new Properties();
+    KyuubiConfFileParser kyuubiConfFileParser = getKyuubiConfFileParser();
     HS2ConnectionFileParser hiveSiteParser = 
getHiveSiteHS2ConnectionFileParser();
-    Properties hiveSiteConnectionProperties = 
hiveSiteParser.getConnectionProperties();
-    // add/override properties found from hive-site with user-specific 
properties
+    if (kyuubiConfFileParser.configExists()) {
+      // load the Kyuubi connection url properties from kyuubi-defaults.conf 
if present
+      serverConnectionProperties = 
kyuubiConfFileParser.getConnectionProperties();
+    } else if (hiveSiteParser.configExists()) {
+      // load the HS2 connection url properties from hive-site.xml if present
+      serverConnectionProperties = hiveSiteParser.getConnectionProperties();
+    }
+    // add/override properties found from kyuubi-defaults.conf with 
user-specific properties
     for (String key : mergedConnectionProperties.stringPropertyNames()) {
-      if (hiveSiteConnectionProperties.containsKey(key)) {
+      if (serverConnectionProperties.containsKey(key)) {
         debug(
             "Overriding connection url property "
                 + key
                 + " from user connection configuration file");
       }
-      hiveSiteConnectionProperties.setProperty(key, 
mergedConnectionProperties.getProperty(key));
+      serverConnectionProperties.setProperty(key, 
mergedConnectionProperties.getProperty(key));
     }
     // return the url based on the aggregated connection properties
-    return HS2ConnectionFileUtils.getUrl(hiveSiteConnectionProperties);
+    return HS2ConnectionFileUtils.getUrl(serverConnectionProperties);
   }
 
   /*
@@ -1069,6 +1067,11 @@ public class BeeLine implements Closeable {
     return new HiveSiteHS2ConnectionFileParser();
   }
 
+  @VisibleForTesting
+  public KyuubiConfFileParser getKyuubiConfFileParser() {
+    return new KyuubiConfFileParser();
+  }
+
   int runInit() {
     String[] initFiles = getOpts().getInitFiles();
 
diff --git 
a/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/hs2connection/KyuubiConfFileParseException.java
 
b/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/hs2connection/KyuubiConfFileParseException.java
new file mode 100644
index 000000000..b62d1451c
--- /dev/null
+++ 
b/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/hs2connection/KyuubiConfFileParseException.java
@@ -0,0 +1,29 @@
+/*
+ * 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.hive.beeline.hs2connection;
+
+public class KyuubiConfFileParseException extends 
BeelineConfFileParseException {
+  KyuubiConfFileParseException(String msg, Exception e) {
+    super(msg, e);
+  }
+
+  public KyuubiConfFileParseException(String msg) {
+    super(msg);
+  }
+}
diff --git 
a/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/hs2connection/KyuubiConfFileParser.java
 
b/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/hs2connection/KyuubiConfFileParser.java
new file mode 100644
index 000000000..dd25aeafc
--- /dev/null
+++ 
b/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/hs2connection/KyuubiConfFileParser.java
@@ -0,0 +1,205 @@
+/*
+ * 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.hive.beeline.hs2connection;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+import org.apache.kyuubi.util.JavaUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/*
+ * Looks for a kyuubi-defaults.conf from KYUUBI_CONF_DIR. If found, this class 
parses
+ * the kyuubi-defaults.conf to return a set of connection properties which can 
be used
+ * to construct the connection url for Beeline connection
+ */
+public class KyuubiConfFileParser implements HS2ConnectionFileParser {
+  private static final Logger LOG = 
LoggerFactory.getLogger(KyuubiConfFileParser.class);
+  private static final String TRUSTSTORE_PASS_PROP = 
"javax.net.ssl.trustStorePassword";
+  private static final String TRUSTSTORE_PROP = "javax.net.ssl.trustStore";
+
+  private final boolean loaded;
+  private final Properties kyuubiDefaults;
+
+  public KyuubiConfFileParser() {
+    kyuubiDefaults = new Properties();
+    Path filePath = Paths.get(System.getenv("KYUUBI_CONF_DIR"), 
"kyuubi-defaults.conf");
+    if (Files.isRegularFile(filePath)) {
+      LOG.info("Using {} to construct the connection URL", 
filePath.toAbsolutePath());
+      try (Reader reader = Files.newBufferedReader(filePath, 
StandardCharsets.UTF_8)) {
+        kyuubiDefaults.load(reader);
+      } catch (IOException rethrow) {
+        throw new RuntimeException(rethrow);
+      }
+      loaded = true;
+    } else {
+      LOG.debug("kyuubi-defaults.conf not found for constructing the 
connection URL");
+      loaded = false;
+    }
+  }
+
+  // only for testing
+  KyuubiConfFileParser(Properties mockedProperties) {
+    kyuubiDefaults = mockedProperties;
+    loaded = true;
+  }
+
+  @Override
+  public Properties getConnectionProperties() throws 
KyuubiConfFileParseException {
+    Properties props = new Properties();
+    if (!configExists() || thriftMode() == THRIFT_MODE.DISABLED) {
+      return props;
+    }
+    props.setProperty(HS2ConnectionFileParser.URL_PREFIX_PROPERTY_KEY, 
"jdbc:kyuubi://");
+    addHosts(props);
+    addSSL(props);
+    addKerberos(props);
+    addHttp(props);
+    return props;
+  }
+
+  // TODO: Kyuubi has different logic to handle SSL and QOP properties with 
HiveServer2.
+  //       We need to revise this part later
+  private void addSSL(Properties props) {
+    // if (!conf.getBoolean("hive.server2.use.SSL", false)) {
+    //   return;
+    // } else {
+    //   props.setProperty("ssl", "true");
+    // }
+    // String truststore = System.getenv(TRUSTSTORE_PROP);
+    // if (truststore != null && truststore.isEmpty()) {
+    //   props.setProperty("sslTruststore", truststore);
+    // }
+    // String trustStorePassword = System.getenv(TRUSTSTORE_PASS_PROP);
+    // if (trustStorePassword != null && !trustStorePassword.isEmpty()) {
+    //   props.setProperty("trustStorePassword", trustStorePassword);
+    // }
+    String saslQop = 
kyuubiDefaults.getProperty("kyuubi.authentication.sasl.qop", "auth");
+    if (!"auth".equalsIgnoreCase(saslQop)) {
+      props.setProperty("sasl.qop", saslQop);
+    }
+  }
+
+  private void addKerberos(Properties props) {
+    if (kerberosEnabled()) {
+      props.setProperty("principal", 
kyuubiDefaults.getProperty("kyuubi.kinit.principal"));
+    }
+  }
+
+  private void addHttp(Properties props) {
+    THRIFT_MODE thriftMode = thriftMode();
+    assert thriftMode == THRIFT_MODE.BINARY || thriftMode == THRIFT_MODE.HTTP;
+
+    if (thriftMode == THRIFT_MODE.HTTP) {
+      props.setProperty("transportMode", "http");
+      String path = 
kyuubiDefaults.getProperty("kyuubi.frontend.thrift.http.path", "cliservice");
+      props.setProperty("httpPath", path);
+    }
+  }
+
+  private void addHosts(Properties props) throws KyuubiConfFileParseException {
+    THRIFT_MODE thriftMode = thriftMode();
+    assert thriftMode == THRIFT_MODE.BINARY || thriftMode == THRIFT_MODE.HTTP;
+
+    String host = 
kyuubiDefaults.getProperty("kyuubi.frontend.advertised.host");
+    if (host == null) {
+      if (thriftMode == THRIFT_MODE.BINARY) {
+        host = 
kyuubiDefaults.getProperty("kyuubi.frontend.thrift.binary.bind.host");
+      } else { // THRIFT_MODE.HTTP
+        host = 
kyuubiDefaults.getProperty("kyuubi.frontend.thrift.http.bind.host");
+      }
+    }
+    if (host == null) {
+      host = kyuubiDefaults.getProperty("kyuubi.frontend.bind.host");
+    }
+
+    if (host == null) {
+      try {
+        String useHostname =
+            
kyuubiDefaults.getProperty("kyuubi.frontend.connection.url.use.hostname", 
"true");
+        if (Boolean.parseBoolean(useHostname)) {
+          host = JavaUtils.findLocalInetAddress().getCanonicalHostName();
+        } else {
+          host = JavaUtils.findLocalInetAddress().getHostAddress();
+        }
+      } catch (UnknownHostException | SocketException rethrow) {
+        throw new KyuubiConfFileParseException(rethrow.getMessage(), rethrow);
+      }
+    }
+
+    int portNum = getPortNum(thriftMode);
+    props.setProperty("hosts", host + ":" + portNum);
+  }
+
+  private int getPortNum(THRIFT_MODE thriftMode) {
+    assert thriftMode == THRIFT_MODE.BINARY || thriftMode == THRIFT_MODE.HTTP;
+
+    String port;
+    if (thriftMode == THRIFT_MODE.BINARY) {
+      port = 
kyuubiDefaults.getProperty("kyuubi.frontend.thrift.binary.bind.port");
+      if (port == null) {
+        port = kyuubiDefaults.getProperty("kyuubi.frontend.bind.port", 
"10009");
+      }
+    } else { // THRIFT_MODE.HTTP
+      port = 
kyuubiDefaults.getProperty("kyuubi.frontend.thrift.http.bind.port", "10010");
+    }
+    return Integer.parseInt(port);
+  }
+
+  @Override
+  public boolean configExists() {
+    return loaded;
+  }
+
+  private enum THRIFT_MODE {
+    BINARY,
+    HTTP,
+    DISABLED
+  }
+
+  // Kyuubi supports enabling THRIFT_BINARY and THRIFT_HTTP at the same time, 
in such a case,
+  // return THRIFT_MODE.BINARY
+  private THRIFT_MODE thriftMode() {
+    String[] protocols =
+        kyuubiDefaults.getProperty("kyuubi.frontend.protocols", 
"THRIFT_BINARY,REST").split(",");
+    for (String protocol : protocols) {
+      if (protocol.equalsIgnoreCase("THRIFT_BINARY")) {
+        return THRIFT_MODE.BINARY;
+      } else if (protocol.equalsIgnoreCase("THRIFT_HTTP")) {
+        return THRIFT_MODE.HTTP;
+      }
+    }
+    return THRIFT_MODE.DISABLED;
+  }
+
+  private boolean kerberosEnabled() {
+    for (String auth : kyuubiDefaults.getProperty("kyuubi.authentication", 
"NONE").split(",")) {
+      if (auth.equalsIgnoreCase("KERBEROS")) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
diff --git 
a/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/hs2connection/UserHS2ConnectionFileParser.java
 
b/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/hs2connection/UserHS2ConnectionFileParser.java
index 596f52cba..147c74ca5 100644
--- 
a/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/hs2connection/UserHS2ConnectionFileParser.java
+++ 
b/kyuubi-hive-beeline/src/main/java/org/apache/hive/beeline/hs2connection/UserHS2ConnectionFileParser.java
@@ -53,6 +53,10 @@ public class UserHS2ConnectionFileParser implements 
HS2ConnectionFileParser {
   public UserHS2ConnectionFileParser() {
     // file locations to be searched in the correct order
     locations.add(DEFAULT_BEELINE_USER_CONF_LOCATION + 
DEFAULT_CONNECTION_CONFIG_FILE_NAME);
+    if (System.getenv("KYUUBI_CONF_DIR") != null) {
+      locations.add(
+          System.getenv("KYUUBI_CONF_DIR") + File.separator + 
DEFAULT_CONNECTION_CONFIG_FILE_NAME);
+    }
     if (System.getenv("HIVE_CONF_DIR") != null) {
       locations.add(
           System.getenv("HIVE_CONF_DIR") + File.separator + 
DEFAULT_CONNECTION_CONFIG_FILE_NAME);
@@ -76,7 +80,7 @@ public class UserHS2ConnectionFileParser implements 
HS2ConnectionFileParser {
       log.debug("User connection configuration file not found");
       return props;
     }
-    log.info("Using connection configuration file at " + fileLocation);
+    log.info("Using connection configuration file at {}", fileLocation);
     props.setProperty(HS2ConnectionFileParser.URL_PREFIX_PROPERTY_KEY, 
"jdbc:hive2://");
     // load the properties from config file
     Configuration conf = new Configuration(false);
diff --git 
a/kyuubi-hive-beeline/src/test/java/org/apache/hive/beeline/hs2connection/TestKyuubiConfFileParser.java
 
b/kyuubi-hive-beeline/src/test/java/org/apache/hive/beeline/hs2connection/TestKyuubiConfFileParser.java
new file mode 100644
index 000000000..46b10bdd2
--- /dev/null
+++ 
b/kyuubi-hive-beeline/src/test/java/org/apache/hive/beeline/hs2connection/TestKyuubiConfFileParser.java
@@ -0,0 +1,44 @@
+/*
+ * 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.hive.beeline.hs2connection;
+
+import static org.junit.Assert.assertEquals;
+
+import java.net.SocketException;
+import java.net.UnknownHostException;
+import java.util.Properties;
+import org.apache.kyuubi.util.JavaUtils;
+import org.junit.Test;
+
+public class TestKyuubiConfFileParser {
+
+  @Test
+  public void testParseKerberosEnabled()
+      throws KyuubiConfFileParseException, SocketException, 
UnknownHostException {
+    Properties kyuubiConf = new Properties();
+    kyuubiConf.put("kyuubi.authentication", "KERBEROS");
+    kyuubiConf.put("kyuubi.kinit.principal", "kyuubi/[email protected]");
+    KyuubiConfFileParser kyuubiConfFileParser = new 
KyuubiConfFileParser(kyuubiConf);
+    Properties result = kyuubiConfFileParser.getConnectionProperties();
+    assertEquals(3, result.size());
+    assertEquals(
+        JavaUtils.findLocalInetAddress().getCanonicalHostName() + ":10009", 
result.get("hosts"));
+    assertEquals("jdbc:kyuubi://", 
result.get(HS2ConnectionFileParser.URL_PREFIX_PROPERTY_KEY));
+    assertEquals("kyuubi/[email protected]", result.get("principal"));
+  }
+}
diff --git a/kyuubi-hive-beeline/src/test/resources/kyuubi-defaults.conf 
b/kyuubi-hive-beeline/src/test/resources/kyuubi-defaults.conf
new file mode 100644
index 000000000..5949a9b0b
--- /dev/null
+++ b/kyuubi-hive-beeline/src/test/resources/kyuubi-defaults.conf
@@ -0,0 +1,40 @@
+
+#
+# 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.
+#
+
+## Kyuubi Configurations
+
+#
+# kyuubi.authentication                    NONE
+#
+# kyuubi.frontend.bind.host                10.0.0.1
+# kyuubi.frontend.protocols                THRIFT_BINARY,REST
+# kyuubi.frontend.thrift.binary.bind.port  10009
+# kyuubi.frontend.rest.bind.port           10099
+#
+# kyuubi.engine.type                       SPARK_SQL
+# kyuubi.engine.share.level                USER
+# kyuubi.session.engine.initialize.timeout PT3M
+#
+# kyuubi.ha.addresses                      zk1:2181,zk2:2181,zk3:2181
+# kyuubi.ha.namespace                      kyuubi
+#
+
+# Details in 
https://kyuubi.readthedocs.io/en/master/configuration/settings.html
+kyuubi.engine.type=SPARK_SQL
+kyuubi.engine.share.level=USER
+kyuubi.session.engine.initialize.timeout=PT3M
\ No newline at end of file


Reply via email to