├── .asf.yaml
├── .github
└── workflows
│ └── maven.yml
├── .gitignore
├── BUILDING.md
├── CHANGES.md
├── README.md
├── RELEASENOTES.md
├── bin
├── argparse-1.4.0
│ └── argparse.py
├── daemon.py
├── log4j2.properties
├── phoenix_queryserver_utils.py
├── queryserver.py
└── sqlline-thin.py
├── dev
└── code-coverage
│ ├── README.md
│ └── run-coverage.sh
├── phoenix-queryserver-assembly
├── pom.xml
└── src
│ ├── assembly
│ └── cluster.xml
│ └── scripts
│ └── replace_jars_with_symlinks.sh
├── phoenix-queryserver-client
├── pom.xml
└── src
│ └── main
│ ├── java
│ └── org
│ │ └── apache
│ │ └── phoenix
│ │ └── queryserver
│ │ └── client
│ │ ├── Driver.java
│ │ ├── KerberosLoginFromTicketCache.java
│ │ └── SqllineWrapper.java
│ └── resources
│ ├── META-INF
│ └── services
│ │ └── java.sql.Driver
│ └── version
│ └── org-apache-phoenix-remote-jdbc.properties
├── phoenix-queryserver-it
├── pom.xml
└── src
│ └── it
│ ├── bin
│ ├── test_phoenixdb.py
│ └── test_phoenixdb.sh
│ ├── java
│ └── org
│ │ └── apache
│ │ └── phoenix
│ │ ├── end2end
│ │ ├── HttpParamImpersonationQueryServerIT.java
│ │ ├── QueryServerBasicsIT.java
│ │ ├── QueryServerEnvironment.java
│ │ ├── QueryServerTestUtil.java
│ │ ├── QueryServerThread.java
│ │ ├── SecureQueryServerIT.java
│ │ ├── SecureQueryServerPhoenixDBIT.java
│ │ ├── ServerCustomizersIT.java
│ │ └── TlsUtil.java
│ │ └── tool
│ │ └── ParameterizedPhoenixCanaryToolIT.java
│ └── resources
│ ├── hbase-site.xml
│ └── log4j2.properties
├── phoenix-queryserver-load-balancer
├── pom.xml
└── src
│ ├── it
│ └── java
│ │ └── org
│ │ └── apache
│ │ └── phoenix
│ │ └── end2end
│ │ └── LoadBalancerEnd2EndIT.java
│ ├── main
│ ├── java
│ │ └── org
│ │ │ └── apache
│ │ │ └── phoenix
│ │ │ ├── loadbalancer
│ │ │ └── service
│ │ │ │ ├── LoadBalanceZookeeperConfImpl.java
│ │ │ │ └── LoadBalancer.java
│ │ │ └── queryserver
│ │ │ └── register
│ │ │ └── ZookeeperRegistry.java
│ └── resources
│ │ └── META-INF
│ │ └── services
│ │ ├── org.apache.phoenix.loadbalancer.service.LoadBalanceZookeeperConf
│ │ └── org.apache.phoenix.queryserver.register.Registry
│ └── test
│ └── java
│ └── org
│ └── apache
│ └── phoenix
│ └── loadbalancer
│ └── service
│ └── LoadBalanceZookeeperConfImplTest.java
├── phoenix-queryserver-orchestrator
├── pom.xml
└── src
│ ├── main
│ └── java
│ │ └── org
│ │ └── apache
│ │ └── phoenix
│ │ ├── queryserver
│ │ └── orchestrator
│ │ │ ├── QueryServerCanaryOrchestrator.java
│ │ │ ├── TestExecutorClient.java
│ │ │ └── ToolWrapper.java
│ │ └── tool
│ │ ├── CanaryTestResult.java
│ │ └── PhoenixCanaryTool.java
│ └── test
│ └── java
│ └── org
│ └── apache
│ └── phoenix
│ └── tool
│ └── PhoenixCanaryToolTest.java
├── phoenix-queryserver
├── pom.xml
└── src
│ ├── build
│ └── query-server-runnable.xml
│ ├── main
│ └── java
│ │ └── org
│ │ └── apache
│ │ └── phoenix
│ │ ├── loadbalancer
│ │ └── service
│ │ │ └── LoadBalanceZookeeperConf.java
│ │ ├── queryserver
│ │ ├── QueryServerOptions.java
│ │ ├── QueryServerProperties.java
│ │ ├── register
│ │ │ └── Registry.java
│ │ └── server
│ │ │ ├── AvaticaServerConfigurationFactory.java
│ │ │ ├── PhoenixMetaFactory.java
│ │ │ ├── PhoenixMetaFactoryImpl.java
│ │ │ ├── QueryServer.java
│ │ │ ├── RemoteUserExtractorFactory.java
│ │ │ ├── ServerCustomizersFactory.java
│ │ │ └── customizers
│ │ │ ├── BasicAuthenticationServerCustomizer.java
│ │ │ ├── HostedClientJarsServerCustomizer.java
│ │ │ └── JMXJsonEndpointServerCustomizer.java
│ │ └── util
│ │ ├── HostAndPort.java
│ │ ├── InstanceResolver.java
│ │ ├── SimpleLRUCache.java
│ │ └── ThinClientUtil.java
│ └── test
│ └── java
│ └── org
│ └── apache
│ └── phoenix
│ ├── DriverCohabitationTest.java
│ └── queryserver
│ ├── server
│ ├── CustomAvaticaServerConfigurationTest.java
│ ├── PhoenixDoAsCallbackTest.java
│ ├── PhoenixRemoteUserExtractorTest.java
│ ├── QueryServerConfigurationTest.java
│ ├── QueryServerTest.java
│ ├── RemoteUserExtractorFactoryTest.java
│ ├── ServerCustomizersTest.java
│ └── customizers
│ │ └── HostedClientJarsServerCustomizerTest.java
│ └── util
│ └── SimpleLRUCacheTest.java
├── pom.xml
└── python-phoenixdb
├── .gitignore
├── .gitlab-ci.yml
├── Dockerfile
├── Dockerfile-pqs
├── LICENSE
├── NEWS.rst
├── NOTICE
├── README.rst
├── RELEASING.rst
├── ci
├── build-env
│ └── Dockerfile
└── phoenix
│ ├── Dockerfile
│ ├── docker-entrypoint.sh
│ └── hbase-site.xml
├── dev-support
├── cache-apache-project-artifact.sh
├── make_rc.sh
├── rat-excludes.txt
└── run-source-ratcheck.sh
├── doc
├── Makefile
├── api.rst
├── conf.py
├── index.rst
└── versions.rst
├── docker-entrypoint.sh
├── examples
└── basic.py
├── gen-protobuf.sh
├── phoenixdb
├── __init__.py
├── avatica
│ ├── __init__.py
│ ├── client.py
│ └── proto
│ │ ├── __init__.py
│ │ ├── common_pb2.py
│ │ ├── requests_pb2.py
│ │ └── responses_pb2.py
├── connection.py
├── cursor.py
├── errors.py
├── meta.py
├── sqlalchemy_phoenix.py
├── tests
│ ├── __init__.py
│ ├── dbapi20.py
│ ├── test_avatica.py
│ ├── test_db.py
│ ├── test_dbapi20.py
│ ├── test_errors.py
│ ├── test_sqlalchemy.py
│ └── test_types.py
└── types.py
├── requirements.txt
├── setup.cfg
├── setup.py
└── tox.ini
/.asf.yaml:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one
2 | # or more contributor license agreements. See the NOTICE file
3 | # distributed with this work for additional information
4 | # regarding copyright ownership. The ASF licenses this file
5 | # to you under the Apache License, Version 2.0 (the
6 | # "License"); you may not use this file except in compliance
7 | # with the License. You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | # This file controls the integration of the Phoenix Queryserver repo with ASF
18 | # infrastructure. Refer to
19 | # https://cwiki.apache.org/confluence/display/INFRA/git+-+.asf.yaml+features
20 | # for details. Be careful when changing the contents of this file since it
21 | # may affect many developers of the project and make sure to discuss the
22 | # changes with dev@ before committing.
23 |
24 | notifications:
25 | commits: commits@phoenix.apache.org
26 | issues: issues@phoenix.apache.org
27 | pullrequests: issues@phoenix.apache.org
28 | jira_options: link label comment
29 |
30 | github:
31 | enabled_merge_buttons:
32 | squash: true
33 | merge: false
34 | rebase: false
35 |
--------------------------------------------------------------------------------
/.github/workflows/maven.yml:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one or more
2 | # contributor license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright ownership.
4 | # The ASF licenses this file to You under the Apache License, Version 2.0
5 | # (the "License"); you may not use this file except in compliance with
6 | # the License. You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 |
16 | name: phoenix-queryserver preCommit Build
17 |
18 | on:
19 | pull_request:
20 |
21 | jobs:
22 | build:
23 | runs-on: ubuntu-latest
24 | steps:
25 | - uses: actions/checkout@v1
26 | - name: Set up JDK 1.8
27 | uses: actions/setup-java@v1
28 | with:
29 | java-version: 1.8
30 | - name: Build with Maven
31 | run: mvn -B clean verify
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #general java
2 | *.class
3 | *.war
4 | *.jar
5 | dependency-reduced-pom.xml
6 |
7 | # python
8 | *.pyc
9 | .checkstyle
10 |
11 | # eclipse stuffs
12 | .settings/*
13 | */.settings/
14 | .classpath
15 | .project
16 | */.externalToolBuilders
17 | */maven-eclipse.xml
18 |
19 | # intellij stuff
20 | .idea/
21 | *.iml
22 | *.ipr
23 | *.iws
24 |
25 | #maven stuffs
26 | target/
27 | release/
28 | RESULTS/
29 | CSV_EXPORT/
30 | .DS_Store
31 |
--------------------------------------------------------------------------------
/BUILDING.md:
--------------------------------------------------------------------------------
1 |
17 |
18 | 
19 |
20 | [Apache Phoenix](http://phoenix.apache.org/) enables OLTP and operational analytics in Hadoop for low latency applications. Visit the Apache Phoenix website [here](http://phoenix.apache.org/). This is the repo for the Phoenix Query Server (PQS).
21 |
22 | Copyright ©2020 [Apache Software Foundation](http://www.apache.org/). All Rights Reserved.
23 |
24 | ## Building
25 |
26 | This repository will build a tarball which is capable of running the Phoenix Query Server.
27 |
28 | By default, this tarball does not contain a Phoenix client jar as it is meant to be agnostic
29 | of Phoenix version (one PQS release should be usable against any Phoenix version).
30 |
31 | However, due to an incompatible change in the relocations used in the phoenix-client JAR, you need to build
32 | Phoenix Query Server with the `shade-javax-servlet` maven profile if you use Phoenix versions
33 | 5.1.1, 5.1.2, 5.1.3 or 4.16.x with it. (See PHOENIX-6861 for more details)
34 | This applies whether you bundle the Phoenix client into the assembly or add it separately.
35 | Phoenix 5.2.0 and later requires that PQS is built WITHOUT the `shade-javax-servlet` maven profile.
36 |
37 | In order to use Phoenix Query Server, you need to copy the phoenix-client-embedded jar appropriate
38 | for your cluster into the Queryserver root directory.
39 |
40 | Note that the resulting Query Server binaries are not tied to any Phoenix, Hbase or Hadoop versions,
41 | apart from the exception above.
42 |
43 |
44 | ```
45 | $ mvn clean package -Pshade-javax-servlet
46 | ```
47 |
48 | For other Phoenix versions build with the default settings
49 |
50 | ```
51 | $ mvn clean package
52 | ```
53 |
54 | ### Bundling a Phoenix Client
55 |
56 | To build a release of PQS which packages a specific version of Phoenix, specify the `package-phoenix-client` system property
57 | and specify the `phoenix.version` system property to indicate a specific Phoenix version, as well as
58 | the `phoenix.client.artifactid` to choose the phoenix-client HBase variant.
59 | You need to bundle the embedded client variant, to avoid conflicts with the logging libraries.
60 |
61 | ```
62 | $ mvn clean package -Dpackage.phoenix.client -Dphoenix.version=5.1.1 -Dphoenix.client.artifactid=phoenix-client-embedded-hbase-2.4 -Pshade-javax-servlet -pl '!phoenix-queryserver-it'
63 | ```
64 |
65 | ### Running integration tests
66 |
67 | `mvn package` will run the unit tests while building, but it will not run the integration test suite.
68 |
69 | The integration tests will run with the default Phoenix and HBase version.
70 | Running the integration tests with non-default Phoenix and HBase versions may or may not work.
71 |
72 | ```
73 | $ mvn clean verify
74 | ```
75 |
76 |
77 | If a different Phoenix version is used for testing, then at least the *hbase.version*
78 | and *hadoop.version* properties must be set to the versions used to build phoenix-client-embdedd,
79 | but other changes may also be needed, or there may be un-resolvable conflicts.
80 |
81 | ```
82 | $ mvn clean verify -Dphoenix.version=5.1.3 -Pshade-javax-servlet -Dphoenix.client.artifactid=phoenix-client-embedded-hbase-2.4 -Dhadoop.version=3.1.3 -Dhbase.version=2.4.15 -DforkCount=6'
83 | ```
84 |
85 | (At the time of writing, the above will run, but fail because 5.1.3 does not have PHOENIX-5066
86 | required by the failing test)
87 |
88 | ### Running project reports
89 |
90 | Phoenix-queryserver currently supports generating the standard set of Maven Project Info Reports,
91 | as well as Spotbugs, Apache Creadur RAT, OWASP Dependency-Check, and Jacoco Code Coverage reports.
92 |
93 | To run all available reports
94 | `$ mvn clean verify site -Dspotbugs.site`
95 |
96 | To run OWASP, RAT and Spotbugs, but not Jacoco
97 | `$ mvn clean compile test-compile site -Dspotbugs.site`
98 |
99 | The reports are accessible via `target/site/index.html`, under the main project,
100 | as well as each of the subprojects. (not every project has all reports)
101 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
17 |
18 | 
19 |
20 | [Apache Phoenix](http://phoenix.apache.org/) enables OLTP and operational analytics in Hadoop for low latency applications. Visit the Apache Phoenix website [here](http://phoenix.apache.org/). This is the repo for the Phoenix Query Server (PQS).
21 |
22 | Copyright ©2020 [Apache Software Foundation](http://www.apache.org/). All Rights Reserved.
23 |
24 | ## Introduction
25 |
26 | The Phoenix Query Server is an JDBC over HTTP abstraction. The Phoenix Query Server proxies the standard
27 | Phoenix JDBC driver and provides a backwards-compatible wire protocol to invoke that JDBC driver. This is
28 | all done via the Apache Avatica project (sub-project of Apache Calcite).
29 |
30 | The reference client implementation for PQS is a "thin" JDBC driver which can communicate with PQS. There
31 | are drivers in other languages which exist in varying levels of maturity including Python, Golang, and .NET.
32 |
33 | The Python driver is maintained by the Phoenix project, and is available in the python-phoenixdb
34 | directory of the phoenix-queryserver repository.
--------------------------------------------------------------------------------
/RELEASENOTES.md:
--------------------------------------------------------------------------------
1 |
2 |
19 | # PHOENIX queryserver-6.0.0 Release Notes
20 |
21 | These release notes cover new developer and user-facing incompatibilities, important issues, features, and major improvements.
22 |
23 |
24 | ---
25 |
26 | * [PHOENIX-6488](https://issues.apache.org/jira/browse/PHOENIX-6488) | *Major* | **Bump Avatica version to 1.18.0 in queryserver**
27 |
28 | Avatica version has been update to 1.18.0
29 |
30 |
31 | ---
32 |
33 | * [PHOENIX-6473](https://issues.apache.org/jira/browse/PHOENIX-6473) | *Major* | **Add Hadoop JMXServlet as /jmx endpoint**
34 |
35 | New HTTP endpoint is available at \/jmx to expose all read-only JMX values in JSON format.
36 |
37 |
38 | ---
39 |
40 | * [PHOENIX-5446](https://issues.apache.org/jira/browse/PHOENIX-5446) | *Major* | **Support Protobuf shaded clients (thin + thick)**
41 |
42 | **WARNING: No release note provided for this change.**
43 |
44 |
45 | ---
46 |
47 | * [PHOENIX-5772](https://issues.apache.org/jira/browse/PHOENIX-5772) | *Major* | **Streamline the kerberos logic in thin client java code**
48 |
49 | The java thin client library has been refactored. It no longer includes Hadoop libraries, and uses the Java SE Kerberos implementation directly.
50 |
51 | The sqlline library has also been removed from the thin client JAR.
52 |
53 | The standalone sqlline JAR is now included in the lib/ directory, and is now added to the classpath by the sqlline-thin.py script.
54 |
55 | Some default parameters that were picked up from hbase-site.xml by the java thin client are now also handled by sqlline-thin.py
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/bin/log4j2.properties:
--------------------------------------------------------------------------------
1 | #/**
2 | # * Licensed to the Apache Software Foundation (ASF) under one
3 | # * or more contributor license agreements. See the NOTICE file
4 | # * distributed with this work for additional information
5 | # * regarding copyright ownership. The ASF licenses this file
6 | # * to you under the Apache License, Version 2.0 (the
7 | # * "License"); you may not use this file except in compliance
8 | # * with the License. You may obtain a copy of the License at
9 | # *
10 | # * http://www.apache.org/licenses/LICENSE-2.0
11 | # *
12 | # * Unless required by applicable law or agreed to in writing, software
13 | # * distributed under the License is distributed on an "AS IS" BASIS,
14 | # * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # * See the License for the specific language governing permissions and
16 | # * limitations under the License.
17 | # */
18 |
19 | # This config is used by sqlline, pherf and psql
20 |
21 | status = warn
22 | dest = err
23 | name = PropertiesConfig
24 |
25 | # Console appender
26 | appender.console.type = Console
27 | appender.console.target = SYSTEM_ERR
28 | appender.console.name = console
29 | appender.console.layout.type = PatternLayout
30 | appender.console.layout.pattern = %d{ISO8601} %-5p [%t] %c{2}: %.1000m%n
31 |
32 | # Not used by default
33 | # Daily Rolling File Appender
34 | appender.DRFA.type = RollingFile
35 | appender.DRFA.name = DRFA
36 | appender.DRFA.fileName = ${sys:psql.log.dir:-.}/${sys:psql.log.file:-psql.log}
37 | appender.DRFA.filePattern = ${sys:psql.log.dir:-.}/${sys:psql.log.file:-psql.log}.%d{yyyy-MM-dd}
38 | appender.DRFA.createOnDemand = true
39 | appender.DRFA.layout.type = PatternLayout
40 | appender.DRFA.layout.pattern = %d{ISO8601} %-5p [%t] %c{2}: %.1000m%n
41 | appender.DRFA.policies.type = Policies
42 | appender.DRFA.policies.time.type = TimeBasedTriggeringPolicy
43 | appender.DRFA.policies.time.interval = 1
44 | appender.DRFA.policies.time.modulate = true
45 | appender.DRFA.policies.size.type = SizeBasedTriggeringPolicy
46 | appender.DRFA.policies.size.size = ${sys:psql.log.maxfilesize:-256MB}
47 | appender.DRFA.strategy.type = DefaultRolloverStrategy
48 | appender.DRFA.strategy.max = ${sys:psql.log.maxbackupindex:-20}
49 |
50 | # Null Appender
51 | appender.NullAppender.type = Null
52 | appender.NullAppender.name = NullAppender
53 |
54 | rootLogger = ${sys:psql.root.logger:-WARN,console}
55 |
56 | # Custom Logging levels
57 | logger.zookeeper.name = org.apache.zookeeper
58 | logger.zookeeper.level = ERROR
59 |
60 | logger.hbase_zk_rzk.name = org.apache.hadoop.hbase.zookeeper.RecoverableZooKeeper
61 | logger.hbase_zk_rzk.level = ERROR
62 |
63 | logger.hbase_zk_zku.name = org.apache.hadoop.hbase.zookeeper.ZKUtil
64 | logger.hbase_zk_zku.level = ERROR
65 |
66 | logger.hbase_conf.name = org.apache.hadoop.hbase.HBaseConfiguration
67 | logger.hbase_conf.level = ERROR
68 |
69 |
70 | # query server custom logging levels
71 | logger.calcite_avatica.name = org.apache.calcite.avatica
72 | logger.calcite_avatica.level = INFO
73 |
74 | logger.phoenix_queryserver_server.name = org.apache.phoenix.queryserver.server
75 | logger.phoenix_queryserver_server.level = INFO
76 |
77 | logger.eclipse_jetty.name = org.eclipse.jetty.server
78 | logger.eclipse_jetty.level = INFO
79 |
--------------------------------------------------------------------------------
/dev/code-coverage/README.md:
--------------------------------------------------------------------------------
1 |
18 |
19 | # Code analysis
20 |
21 | The `run-coverage.sh` script runs maven with the **codecoverage** profile
22 | which generates the test coverage data for the java classes.
23 | If the required parameters are given it also runs the sonar code analysis
24 | and uploads the results to the given SonarQube Server.
25 |
26 | ## Running code analysis
27 |
28 | After running the script the reports generated by the JaCoCo code coverage
29 | library can be found in the modules under the `/target/site/jacoco/` folder.
30 |
31 | Here is how you can generate the code coverage report:
32 |
33 | ```./dev/code-coverage/run-coverage.sh```
34 |
35 | ## Publishing coverage results to SonarQube
36 |
37 | The required parameters for publishing the results to SonarQube are:
38 |
39 | - host URL,
40 | - login credentials,
41 | - project key
42 |
43 | The project name is an optional parameter.
44 |
45 | Here is an example command for running and publishing the coverage data:
46 |
47 | `./dev/code-coverage/run-coverage.sh -l ProjectCredentials
48 | -u https://exampleserver.com -k Project_Key -n Project_Name`
49 |
--------------------------------------------------------------------------------
/dev/code-coverage/run-coverage.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | # Licensed under the Apache License, Version 2.0 (the "License");
3 | # you may not use this file except in compliance with the License.
4 | # You may obtain a copy of the License at
5 | #
6 | # http://www.apache.org/licenses/LICENSE-2.0
7 | #
8 | # Unless required by applicable law or agreed to in writing, software
9 | # distributed under the License is distributed on an "AS IS" BASIS,
10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | # See the License for the specific language governing permissions and
12 | # limitations under the License.
13 |
14 | usage() {
15 | echo
16 | echo "options:"
17 | echo " -h Display help"
18 | echo " -u SonarQube Host URL"
19 | echo " -l SonarQube Login Credentials"
20 | echo " -k SonarQube Project Key"
21 | echo " -n SonarQube Project Name"
22 | echo " -t Number of threads (example: 1 or 2C)."
23 | echo
24 | echo "Important:"
25 | echo " The required parameters for publishing the coverage results to SonarQube:"
26 | echo " - Host URL"
27 | echo " - Login Credentials"
28 | echo " - Project Key"
29 | echo
30 | }
31 |
32 | execute() {
33 | SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" &>/dev/null && pwd)"
34 | MAIN_POM="${SCRIPT_DIR}/../../pom.xml"
35 | # Check the syntax for the THREAD_COUNT variable
36 | if [[ "$THREAD_COUNT" =~ ^[0-9]+([.][0-9]+)?$ ]] || [[ "$THREAD_COUNT" =~ ^[0-9]+([.][0-9]+)+[C]?$ ]]; then
37 | THREADS="${THREAD_COUNT}"
38 | else
39 | THREADS=1
40 | fi
41 |
42 | mvn -B -e -f "$MAIN_POM" clean verify -Pcodecoverage -fn -Dmaven.javadoc.skip=true -DskipShade -T "$THREADS"
43 |
44 | # If the required parameters are given, the code coverage results are uploaded to the SonarQube Server
45 | if [ -n "$SONAR_LOGIN" ] && [ -n "$SONAR_PROJECT_KEY" ] && [ -n "$SONAR_URL" ]; then
46 | mvn -B -e -Pcodecoverage -f "$MAIN_POM" sonar:sonar -Dsonar.projectName="$SONAR_PROJECT_NAME" \
47 | -Dsonar.host.url="$SONAR_URL" -Dsonar.login="$SONAR_LOGIN" -Dsonar.projectKey="$SONAR_PROJECT_KEY" -T "$THREADS"
48 | fi
49 | }
50 |
51 | while getopts ":u:l:k:n:t:h" option; do
52 | case $option in
53 | u) SONAR_URL=${OPTARG:-} ;;
54 | l) SONAR_LOGIN=${OPTARG:-} ;;
55 | k) SONAR_PROJECT_KEY=${OPTARG:-} ;;
56 | n) SONAR_PROJECT_NAME=${OPTARG:-} ;;
57 | t) THREAD_COUNT=${OPTARG:-} ;;
58 | h) # Display usage
59 | usage
60 | exit
61 | ;;
62 | \?) # Invalid option
63 | echo "Error: Invalid option"
64 | exit
65 | ;;
66 | esac
67 | done
68 |
69 | # Start code analysis
70 | execute
71 |
--------------------------------------------------------------------------------
/phoenix-queryserver-assembly/src/assembly/cluster.xml:
--------------------------------------------------------------------------------
1 |
2 |
20 |
22 | cluster
23 | /
24 |
25 | tar.gz
26 |
27 |
28 |
29 | ${project.basedir}/../bin
30 | phoenix-queryserver-${project.parent.version}/bin
31 |
32 | __pycache__
33 | __pycache__/*
34 | *.pyc
35 |
36 |
37 |
38 | ${project.basedir}/../phoenix-queryserver/target
39 | phoenix-queryserver-${project.parent.version}/
40 |
41 | phoenix-queryserver-${project.parent.version}.jar
42 |
43 |
44 |
45 | ${project.basedir}/../phoenix-queryserver-client/target
46 | phoenix-queryserver-${project.parent.version}/
47 |
48 | phoenix-queryserver-client-${project.parent.version}.jar
49 |
50 |
51 |
52 | ${project.build.directory}/maven-repo
53 | phoenix-queryserver-${project.parent.version}/maven
54 |
55 |
56 |
57 |
58 | false
59 | phoenix-queryserver-${project.parent.version}/lib
60 |
61 | sqlline:sqlline:jar:jar-with-dependencies
62 | org.apache.logging.log4j:log4j-slf4j-impl
63 | org.apache.logging.log4j:log4j-api
64 | org.apache.logging.log4j:log4j-core
65 | org.apache.logging.log4j:log4j-1.2-api
66 | org.slf4j:jcl-over-slf4j
67 |
68 |
69 |
70 | false
71 | phoenix-queryserver-${project.parent.version}/
72 |
73 | org.apache.phoenix:${phoenix.client.artifactid}:jar
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/phoenix-queryserver-assembly/src/scripts/replace_jars_with_symlinks.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | ############################################################################
4 | #
5 | # Licensed to the Apache Software Foundation (ASF) under one
6 | # or more contributor license agreements. See the NOTICE file
7 | # distributed with this work for additional information
8 | # regarding copyright ownership. The ASF licenses this file
9 | # to you under the Apache License, Version 2.0 (the
10 | # "License"); you may not use this file except in compliance
11 | # with the License. You may obtain a copy of the License at
12 | #
13 | # http://www.apache.org/licenses/LICENSE-2.0
14 | #
15 | # Unless required by applicable law or agreed to in writing, software
16 | # distributed under the License is distributed on an "AS IS" BASIS,
17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | # See the License for the specific language governing permissions and
19 | # limitations under the License.
20 | #
21 | ############################################################################
22 |
23 | REPO_ROOT=$1
24 | for linksource in $(find $REPO_ROOT -name \*.jar); do
25 | linkfile=$(basename $linksource)
26 | linkdir=$(dirname $linksource)
27 | targetdir=$(realpath $REPO_ROOT/.. --relative-to=$linkdir)
28 | target="$targetdir/$linkfile"
29 | cd $linkdir
30 | #The copy is necessary, as maven won't add dangling symlinks to the assmebly
31 | cp $linkfile $target
32 | ln -sf $target $linkfile
33 | done
--------------------------------------------------------------------------------
/phoenix-queryserver-client/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
26 |
27 | 4.0.0
28 |
29 |
30 | org.apache.phoenix
31 | phoenix-queryserver-parent
32 | 6.0.1-SNAPSHOT
33 |
34 |
35 | phoenix-queryserver-client
36 | Phoenix Query Server Client
37 | A thin JDBC client for interacting with the query server
38 |
39 |
40 |
41 | The Apache Software License, Version 2.0
42 | http://www.apache.org/licenses/LICENSE-2.0.txt
43 | repo
44 |
45 |
46 |
47 |
48 |
49 | Apache Software Foundation
50 | http://www.apache.org
51 |
52 |
53 |
54 | ${project.basedir}/..
55 |
56 |
57 |
58 |
59 |
60 | maven-assembly-plugin
61 |
62 | true
63 |
64 |
65 |
66 | org.apache.maven.plugins
67 | maven-shade-plugin
68 |
69 |
70 | thin-client
71 | package
72 |
73 | shade
74 |
75 |
76 | false
77 |
78 |
80 | README.md
81 | ${project.basedir}/../README.md
82 |
83 |
85 | LICENSE.txt
86 | ${project.basedir}/../LICENSE
87 |
88 |
90 | NOTICE
91 | ${project.basedir}/../NOTICE
92 |
93 |
94 |
95 |
96 |
97 | *:*
98 |
99 | META-INF/*.SF
100 | META-INF/*.DSA
101 | META-INF/*.RSA
102 | META-INF/license/*
103 | LICENSE.*
104 | NOTICE.*
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 | org.apache.rat
114 | apache-rat-plugin
115 |
116 |
117 | src/main/resources/META-INF/services/java.sql.Driver
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 | org.apache.calcite.avatica
127 | avatica
128 |
129 |
130 | sqlline
131 | sqlline
132 | provided
133 | jar-with-dependencies
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/phoenix-queryserver-client/src/main/java/org/apache/phoenix/queryserver/client/Driver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | package org.apache.phoenix.queryserver.client;
19 |
20 | import org.apache.calcite.avatica.DriverVersion;
21 |
22 | public class Driver extends org.apache.calcite.avatica.remote.Driver {
23 |
24 | public static final String CONNECT_STRING_PREFIX = "jdbc:phoenix:thin:";
25 |
26 | static {
27 | new Driver().register();
28 | }
29 |
30 | public Driver() {
31 | super();
32 | }
33 |
34 | @Override
35 | protected DriverVersion createDriverVersion() {
36 | return DriverVersion.load(
37 | Driver.class,
38 | "org-apache-phoenix-remote-jdbc.properties",
39 | "Phoenix Remote JDBC Driver",
40 | "unknown version",
41 | "Phoenix",
42 | "unknown version");
43 | }
44 |
45 | @Override
46 | protected String getConnectStringPrefix() {
47 | return CONNECT_STRING_PREFIX;
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/phoenix-queryserver-client/src/main/java/org/apache/phoenix/queryserver/client/KerberosLoginFromTicketCache.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | package org.apache.phoenix.queryserver.client;
19 |
20 | import java.io.IOException;
21 | import java.util.HashMap;
22 |
23 | import javax.security.auth.Subject;
24 | import javax.security.auth.callback.Callback;
25 | import javax.security.auth.callback.CallbackHandler;
26 | import javax.security.auth.callback.UnsupportedCallbackException;
27 | import javax.security.auth.login.AppConfigurationEntry;
28 | import javax.security.auth.login.Configuration;
29 | import javax.security.auth.login.LoginContext;
30 | import javax.security.auth.login.LoginException;
31 |
32 | public class KerberosLoginFromTicketCache {
33 |
34 | public static Subject login() throws LoginException {
35 |
36 | Configuration kerberosConfig = new KerberosConfiguration();
37 | Subject subject = new Subject();
38 |
39 | LoginContext lc = new LoginContext("PhoenixThinClient", subject, new CallbackHandler() {
40 | @Override
41 | public void handle(Callback[] callbacks)
42 | throws IOException, UnsupportedCallbackException {
43 | throw new UnsupportedCallbackException(callbacks[0],
44 | "Only ticket cache is supported");
45 | }
46 | }, kerberosConfig);
47 |
48 | lc.login();
49 | return subject;
50 | }
51 |
52 | private static class KerberosConfiguration extends Configuration {
53 | private static final String IBM_KRB5_LOGIN_MODULE =
54 | "com.ibm.security.auth.module.Krb5LoginModule";
55 | private static final String SUN_KRB5_LOGIN_MODULE =
56 | "com.sun.security.auth.module.Krb5LoginModule";
57 |
58 | private static final String JAVA_VENDOR_NAME = System.getProperty("java.vendor");
59 | private static final boolean IS_IBM_JAVA = JAVA_VENDOR_NAME.contains("IBM");
60 |
61 | @Override
62 | public AppConfigurationEntry[] getAppConfigurationEntry(String name) {
63 | HashMap options = new HashMap<>();
64 |
65 | if(IS_IBM_JAVA) {
66 | //Also see https://www.ibm.com/support/pages/how-enable-strong-encryption-128-bit
67 |
68 | // This is inferior to the sun class, as it won't work if the kerberos and unix
69 | // users don't match, while that one take any principal from the cache
70 | options.put("principal", System.getProperty("user.name"));
71 | options.put("useDefaultCcache", "true");
72 | return new AppConfigurationEntry[] { new AppConfigurationEntry(
73 | IBM_KRB5_LOGIN_MODULE, AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
74 | options) };
75 | } else {
76 | options.put("useTicketCache", "true");
77 | options.put("doNotPrompt", "true");
78 | return new AppConfigurationEntry[] { new AppConfigurationEntry(
79 | SUN_KRB5_LOGIN_MODULE, AppConfigurationEntry.LoginModuleControlFlag.REQUIRED,
80 | options) };
81 | }
82 | }
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/phoenix-queryserver-client/src/main/java/org/apache/phoenix/queryserver/client/SqllineWrapper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to you under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package org.apache.phoenix.queryserver.client;
18 |
19 | import java.security.PrivilegedExceptionAction;
20 |
21 | import javax.security.auth.Subject;
22 | import javax.security.auth.login.LoginException;
23 |
24 | import sqlline.SqlLine;
25 |
26 | /**
27 | * Utility class which automatically performs a Kerberos login and then launches sqlline. Tries to
28 | * make a pre-populated ticket cache (via kinit before launching) transparently work.
29 | */
30 | public class SqllineWrapper {
31 |
32 | public static String getUrl(String[] args) {
33 | for (int i = 0; i < args.length; i++) {
34 | String arg = args[i];
35 | args[i] = arg;
36 | if (arg.equals("-u") && args.length > i+1) {
37 | return args[i+1];
38 | }
39 | }
40 | return null;
41 | }
42 |
43 | public static void main(String[] args) throws Exception {
44 | String url = getUrl(args);
45 |
46 | if(url.contains(";authentication=SPNEGO") && !url.contains(";principal=")) {
47 | try {
48 | Subject subject = KerberosLoginFromTicketCache.login();
49 | System.out.println("Kerberos login from ticket cache successful");
50 | Subject.doAs(subject, new PrivilegedExceptionAction() {
51 | @Override
52 | public Void run() throws Exception {
53 | SqlLine.main(args);
54 | return null;
55 | }
56 | });
57 | return;
58 | } catch (LoginException e) {
59 | System.out.print("Kerberos login from ticket cache not successful");
60 | e.printStackTrace();
61 | }
62 | }
63 |
64 | SqlLine.main(args);
65 | }
66 |
67 | }
68 |
--------------------------------------------------------------------------------
/phoenix-queryserver-client/src/main/resources/META-INF/services/java.sql.Driver:
--------------------------------------------------------------------------------
1 | org.apache.phoenix.queryserver.client.Driver
2 |
--------------------------------------------------------------------------------
/phoenix-queryserver-client/src/main/resources/version/org-apache-phoenix-remote-jdbc.properties:
--------------------------------------------------------------------------------
1 | # Licensed to the Apache Software Foundation (ASF) under one or more
2 | # contributor license agreements. See the NOTICE file distributed with
3 | # this work for additional information regarding copyright ownership.
4 | # The ASF licenses this file to you under the Apache License, Version 2.0
5 | # (the "License"); you may not use this file except in compliance with
6 | # the License. You may obtain a copy of the License at
7 | #
8 | # http://www.apache.org/licenses/LICENSE-2.0
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | driver.name=Apache Phoenix Remote JDBC Driver
17 | driver.version=${pom.version}
18 | product.name=Apache Phoenix
19 | product.version=${pom.version}
20 | jdbc.compliant=true
21 | driver.version.major=${version.major}
22 | driver.version.minor=${version.minor}
23 | database.version.major=${version.major}
24 | database.version.minor=${version.minor}
25 | build.timestamp=${build.timestamp}
26 |
--------------------------------------------------------------------------------
/phoenix-queryserver-it/src/it/bin/test_phoenixdb.py:
--------------------------------------------------------------------------------
1 | ############################################################################
2 | #
3 | # Licensed to the Apache Software Foundation (ASF) under one
4 | # or more contributor license agreements. See the NOTICE file
5 | # distributed with this work for additional information
6 | # regarding copyright ownership. The ASF licenses this file
7 | # to you under the Apache License, Version 2.0 (the
8 | # "License"); you may not use this file except in compliance
9 | # with the License. You may obtain a copy of the License at
10 | #
11 | # http://www.apache.org/licenses/LICENSE-2.0
12 | #
13 | # Unless required by applicable law or agreed to in writing, software
14 | # distributed under the License is distributed on an "AS IS" BASIS,
15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | # See the License for the specific language governing permissions and
17 | # limitations under the License.
18 | #
19 | ############################################################################
20 |
21 | import phoenixdb
22 | import phoenixdb.cursor
23 | import sys
24 | import os
25 |
26 |
27 | if __name__ == '__main__':
28 | database_url = os.environ.get('PHOENIXDB_TEST_DB_URL')
29 |
30 | print("CREATING PQS CONNECTION")
31 | conn = phoenixdb.connect(database_url, autocommit=True, auth="SPNEGO")
32 | cursor = conn.cursor()
33 |
34 | cursor.execute("CREATE TABLE users (id INTEGER PRIMARY KEY, username VARCHAR)")
35 | cursor.execute("UPSERT INTO users VALUES (?, ?)", (1, 'admin'))
36 | cursor.execute("UPSERT INTO users VALUES (?, ?)", (2, 'user'))
37 | cursor.execute("SELECT * FROM users")
38 | print("RESULTS")
39 | print(cursor.fetchall())
40 |
--------------------------------------------------------------------------------
/phoenix-queryserver-it/src/it/bin/test_phoenixdb.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 | #
3 | ############################################################################
4 | #
5 | # Licensed to the Apache Software Foundation (ASF) under one
6 | # or more contributor license agreements. See the NOTICE file
7 | # distributed with this work for additional information
8 | # regarding copyright ownership. The ASF licenses this file
9 | # to you under the Apache License, Version 2.0 (the
10 | # "License"); you may not use this file except in compliance
11 | # with the License. You may obtain a copy of the License at
12 | #
13 | # http://www.apache.org/licenses/LICENSE-2.0
14 | #
15 | # Unless required by applicable law or agreed to in writing, software
16 | # distributed under the License is distributed on an "AS IS" BASIS,
17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 | # See the License for the specific language governing permissions and
19 | # limitations under the License.
20 | #
21 | ############################################################################
22 |
23 | set -u
24 | set -x
25 | set -e
26 |
27 | function cleanup {
28 | # Capture last command status
29 | RCODE=$?
30 | set +e
31 | set +u
32 | kdestroy
33 | rm -rf $PY_ENV_PATH
34 | exit $RCODE
35 | }
36 |
37 | trap cleanup EXIT
38 |
39 | echo "LAUNCHING SCRIPT"
40 |
41 | LOCAL_PY=$1
42 | PRINC=$2
43 | KEYTAB_LOC=$3
44 | KRB5_CFG_FILE=$4
45 | PQS_PORT=$5
46 |
47 | shift 5
48 |
49 | PY_ENV_PATH=$( mktemp -d )
50 |
51 | virtualenv $PY_ENV_PATH
52 |
53 | pushd ${PY_ENV_PATH}/bin
54 |
55 | # conda activate does stuff with unbound variables :(
56 | set +u
57 | . ./activate ""
58 |
59 | popd
60 |
61 | set -u
62 | echo "INSTALLING COMPONENTS"
63 | pip install -e file:///${LOCAL_PY}/
64 |
65 | export KRB5_CONFIG=$KRB5_CFG_FILE
66 | cat $KRB5_CONFIG
67 | export KRB5_TRACE=/dev/stdout
68 |
69 | echo "RUNNING KINIT"
70 | kinit -kt $KEYTAB_LOC $PRINC
71 | klist
72 |
73 | unset http_proxy
74 | unset https_proxy
75 |
76 | echo "Working Directory is ${PWD}"
77 |
78 | cat > target/krb_setup.sh << EOF
79 | #!/bin/sh
80 | export KRB5_CONFIG=$KRB5_CFG_FILE
81 | export KRB5_TRACE=/dev/stdout
82 | kinit -kt $KEYTAB_LOC $PRINC
83 | klist
84 |
85 | export PHOENIXDB_TEST_DB_URL="http://localhost:$PQS_PORT"
86 | export PHOENIXDB_TEST_DB_AUTHENTICATION="SPNEGO"
87 |
88 | EOF
89 |
90 |
91 | export PHOENIXDB_TEST_DB_URL="http://localhost:$PQS_PORT"
92 | export PHOENIXDB_TEST_DB_AUTHENTICATION="SPNEGO"
93 |
94 | echo "RUN test: $@"
95 | "$@" > >(tee -a target/python-stdout.log) 2> >(tee -a target/python-stderr.log >&2)
96 |
97 |
--------------------------------------------------------------------------------
/phoenix-queryserver-it/src/it/java/org/apache/phoenix/end2end/QueryServerThread.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | package org.apache.phoenix.end2end;
19 |
20 | import org.apache.hadoop.conf.Configuration;
21 | import org.apache.phoenix.queryserver.server.QueryServer;
22 |
23 | /** Wraps up the query server for tests. */
24 | public class QueryServerThread extends Thread {
25 |
26 | private final QueryServer main;
27 |
28 | public QueryServerThread(String[] argv, Configuration conf) {
29 | this(argv, conf, null);
30 | }
31 |
32 | public QueryServerThread(String[] argv, Configuration conf, String name) {
33 | this(new QueryServer(argv, conf), name);
34 | }
35 |
36 | private QueryServerThread(QueryServer m, String name) {
37 | super(m, "query server" + (name == null ? "" : (" - " + name)));
38 | this.main = m;
39 | setDaemon(true);
40 | }
41 |
42 | public QueryServer getQueryServer() {
43 | return main;
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/phoenix-queryserver-it/src/it/java/org/apache/phoenix/end2end/SecureQueryServerIT.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to you under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package org.apache.phoenix.end2end;
18 |
19 | import static org.junit.Assert.assertEquals;
20 | import static org.junit.Assert.assertFalse;
21 | import static org.junit.Assert.assertTrue;
22 |
23 | import java.io.File;
24 | import java.security.PrivilegedExceptionAction;
25 | import java.sql.DriverManager;
26 | import java.sql.ResultSet;
27 | import java.sql.Statement;
28 | import java.util.Arrays;
29 | import java.util.Map.Entry;
30 |
31 | import org.apache.hadoop.conf.Configuration;
32 | import org.apache.hadoop.hbase.coprocessor.CoprocessorHost;
33 | import org.apache.hadoop.hbase.security.token.TokenProvider;
34 | import org.apache.hadoop.security.UserGroupInformation;
35 | import org.junit.AfterClass;
36 | import org.junit.Test;
37 | import org.junit.experimental.categories.Category;
38 | import org.junit.runner.RunWith;
39 | import org.junit.runners.Parameterized;
40 | import org.junit.runners.Parameterized.Parameters;
41 | import org.slf4j.Logger;
42 | import org.slf4j.LoggerFactory;
43 |
44 | @RunWith(Parameterized.class)
45 | @Category(NeedsOwnMiniClusterTest.class)
46 | public class SecureQueryServerIT {
47 | private static final Logger LOG = LoggerFactory.getLogger(SecureQueryServerIT.class);
48 | private static QueryServerEnvironment environment;
49 |
50 | @Parameters(name = "tls = {0}")
51 | public static synchronized Iterable data() {
52 | return Arrays.asList(new Boolean[] {false, true});
53 | }
54 |
55 | public SecureQueryServerIT(Boolean tls) throws Exception {
56 | //Clean up previous environment if any (Junit 4.13 @BeforeParam / @AfterParam would be an alternative)
57 | if(environment != null) {
58 | stopEnvironment();
59 | }
60 |
61 | final Configuration conf = new Configuration();
62 | conf.setStrings(CoprocessorHost.REGION_COPROCESSOR_CONF_KEY,
63 | TokenProvider.class.getName());
64 | environment = new QueryServerEnvironment(conf, 3, tls);
65 | }
66 |
67 |
68 | @AfterClass
69 | public static synchronized void stopEnvironment() throws Exception {
70 | environment.stop();
71 | }
72 |
73 | @Test
74 | public void testBasicReadWrite() throws Exception {
75 | final Entry user1 = environment.getUser(1);
76 | UserGroupInformation user1Ugi = UserGroupInformation.loginUserFromKeytabAndReturnUGI(user1.getKey(), user1.getValue().getAbsolutePath());
77 | user1Ugi.doAs(new PrivilegedExceptionAction() {
78 | @Override public Void run() throws Exception {
79 | // Phoenix
80 | final String tableName = "phx_table1";
81 | try (java.sql.Connection conn = DriverManager.getConnection(environment.getPqsUrl());
82 | Statement stmt = conn.createStatement()) {
83 | conn.setAutoCommit(true);
84 | assertFalse(stmt.execute("CREATE TABLE " + tableName + "(pk integer not null primary key)"));
85 | final int numRows = 5;
86 | for (int i = 0; i < numRows; i++) {
87 | assertEquals(1, stmt.executeUpdate("UPSERT INTO " + tableName + " values(" + i + ")"));
88 | }
89 |
90 | try (ResultSet rs = stmt.executeQuery("SELECT * FROM " + tableName)) {
91 | for (int i = 0; i < numRows; i++) {
92 | assertTrue(rs.next());
93 | assertEquals(i, rs.getInt(1));
94 | }
95 | assertFalse(rs.next());
96 | }
97 | }
98 | return null;
99 | }
100 | });
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/phoenix-queryserver-it/src/it/java/org/apache/phoenix/end2end/ServerCustomizersIT.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to you under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package org.apache.phoenix.end2end;
18 |
19 | import java.sql.Connection;
20 | import java.sql.DriverManager;
21 | import java.sql.Statement;
22 | import java.util.HashMap;
23 | import java.util.Map;
24 |
25 | import org.apache.hadoop.conf.Configuration;
26 | import org.apache.phoenix.query.BaseTest;
27 | import org.apache.phoenix.queryserver.QueryServerProperties;
28 | import org.apache.phoenix.queryserver.server.ServerCustomizersFactory;
29 | import org.apache.phoenix.queryserver.server.customizers.BasicAuthenticationServerCustomizer;
30 | import org.apache.phoenix.queryserver.server.customizers.BasicAuthenticationServerCustomizer.BasicAuthServerCustomizerFactory;
31 | import org.apache.phoenix.util.InstanceResolver;
32 | import org.apache.phoenix.util.ReadOnlyProps;
33 | import org.junit.AfterClass;
34 | import org.junit.Assert;
35 | import org.junit.BeforeClass;
36 | import org.junit.Rule;
37 | import org.junit.Test;
38 | import org.junit.rules.ExpectedException;
39 | import org.slf4j.Logger;
40 | import org.slf4j.LoggerFactory;
41 |
42 | public class ServerCustomizersIT extends BaseTest {
43 | private static final Logger LOG = LoggerFactory.getLogger(ServerCustomizersIT.class);
44 | private static final String USER_NOT_AUTHORIZED = "user1";
45 |
46 | private static QueryServerTestUtil PQS_UTIL;
47 |
48 | @Rule
49 | public ExpectedException expected = ExpectedException.none();
50 |
51 | @BeforeClass
52 | public static synchronized void setup() throws Exception {
53 | setUpTestDriver(ReadOnlyProps.EMPTY_PROPS);
54 |
55 | Configuration conf = config;
56 | if(System.getProperty("do.not.randomize.pqs.port") == null) {
57 | conf.setInt(QueryServerProperties.QUERY_SERVER_HTTP_PORT_ATTRIB, 0);
58 | }
59 | PQS_UTIL = new QueryServerTestUtil(conf);
60 | PQS_UTIL.startLocalHBaseCluster(ServerCustomizersIT.class);
61 | // Register a test jetty server customizer
62 | InstanceResolver.clearSingletons();
63 | InstanceResolver.getSingleton(ServerCustomizersFactory.class, new BasicAuthServerCustomizerFactory());
64 | PQS_UTIL.startQueryServer();
65 | }
66 |
67 | @AfterClass
68 | public static synchronized void teardown() throws Exception {
69 | // Remove custom singletons for future tests
70 | InstanceResolver.clearSingletons();
71 | if (PQS_UTIL != null) {
72 | PQS_UTIL.stopQueryServer();
73 | PQS_UTIL.stopLocalHBaseCluster();
74 | }
75 | }
76 |
77 | @Test
78 | public void testUserAuthorized() throws Exception {
79 | try (Connection conn = DriverManager.getConnection(PQS_UTIL.getUrl(
80 | getBasicAuthParams(BasicAuthenticationServerCustomizer.USER_AUTHORIZED)));
81 | Statement stmt = conn.createStatement()) {
82 | Assert.assertFalse("user3 should have access", stmt.execute(
83 | "create table "+ServerCustomizersIT.class.getSimpleName()+" (pk integer not null primary key)"));
84 | }
85 | }
86 |
87 | @Test
88 | public void testUserNotAuthorized() throws Exception {
89 | expected.expect(RuntimeException.class);
90 | expected.expectMessage("HTTP/401");
91 | try (Connection conn = DriverManager.getConnection(PQS_UTIL.getUrl(
92 | getBasicAuthParams(USER_NOT_AUTHORIZED)));
93 | Statement stmt = conn.createStatement()) {
94 | Assert.assertFalse(stmt.execute(
95 | "select access from database"));
96 | }
97 | }
98 |
99 | private Map getBasicAuthParams(String user) {
100 | Map params = new HashMap<>();
101 | params.put("authentication", "BASIC");
102 | params.put("avatica_user", user);
103 | params.put("avatica_password", BasicAuthenticationServerCustomizer.USER_PW);
104 | return params;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/phoenix-queryserver-it/src/it/resources/hbase-site.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
22 |
23 |
24 | hbase.regionserver.wal.codec
25 | org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec
26 |
27 |
28 | phoenix.query.applyTimeZoneDisplacement
29 | true
30 |
31 |
32 |
--------------------------------------------------------------------------------
/phoenix-queryserver-load-balancer/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
26 | 4.0.0
27 |
28 | org.apache.phoenix
29 | phoenix-queryserver-parent
30 | 6.0.1-SNAPSHOT
31 |
32 | phoenix-queryserver-load-balancer
33 | Phoenix Query Server Load Balancer
34 | A Load balancer which routes calls to Phoenix Query Server
35 |
36 |
37 |
38 |
39 | org.apache.maven.plugins
40 | maven-jar-plugin
41 |
42 |
43 | prepare-package
44 |
45 | test-jar
46 |
47 |
48 |
49 |
50 | true
51 |
52 |
53 |
54 | maven-source-plugin
55 |
56 |
57 | attach-test-sources
58 | prepare-package
59 |
60 | test-jar-no-fork
61 |
62 |
63 |
64 |
65 |
66 | org.apache.maven.plugins
67 | maven-dependency-plugin
68 |
69 |
70 |
71 |
72 | org.slf4j:slf4j-api
73 |
74 |
75 |
76 |
77 |
78 | org.apache.rat
79 | apache-rat-plugin
80 |
81 |
82 | src/main/resources/META-INF/services/org.apache.phoenix.loadbalancer.service.LoadBalanceZookeeperConf
83 | src/main/resources/META-INF/services/org.apache.phoenix.queryserver.register.Registry
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 | org.apache.phoenix
93 | phoenix-queryserver
94 |
95 |
96 | org.apache.hbase
97 | hbase-common
98 |
99 |
100 | org.apache.hadoop
101 | hadoop-common
102 |
103 |
104 | org.apache.zookeeper
105 | zookeeper
106 |
107 |
108 | org.apache.zookeeper
109 | zookeeper-jute
110 |
111 |
112 | org.apache.curator
113 | curator-client
114 |
115 |
116 | org.apache.curator
117 | curator-recipes
118 |
119 |
120 | org.apache.curator
121 | curator-framework
122 |
123 |
124 | org.slf4j
125 | slf4j-api
126 |
127 |
128 |
129 |
130 | junit
131 | junit
132 | test
133 |
134 |
135 | org.apache.curator
136 | curator-test
137 | test
138 |
139 |
140 |
141 |
142 |
--------------------------------------------------------------------------------
/phoenix-queryserver-load-balancer/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalanceZookeeperConfImpl.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 |
20 | package org.apache.phoenix.loadbalancer.service;
21 |
22 | import org.apache.hadoop.conf.Configuration;
23 | import org.apache.hadoop.hbase.HBaseConfiguration;
24 | import org.apache.hadoop.hbase.zookeeper.ZKConfig;
25 | import org.apache.phoenix.queryserver.QueryServerOptions;
26 | import org.apache.phoenix.queryserver.QueryServerProperties;
27 | import org.apache.phoenix.util.HostAndPort;
28 | import org.apache.zookeeper.ZooDefs;
29 | import org.apache.zookeeper.data.ACL;
30 | import org.apache.zookeeper.data.Id;
31 |
32 | import java.util.Arrays;
33 | import java.util.List;
34 |
35 |
36 |
37 | public class LoadBalanceZookeeperConfImpl implements LoadBalanceZookeeperConf {
38 |
39 | private Configuration configuration;
40 |
41 | public LoadBalanceZookeeperConfImpl() {
42 | this.configuration = HBaseConfiguration.create();
43 | }
44 |
45 | public LoadBalanceZookeeperConfImpl(Configuration configuration) {
46 | this.configuration = configuration;
47 | }
48 |
49 | //@VisibleForTesting
50 | public void setConfiguration(Configuration configuration) {
51 | this.configuration = configuration;
52 | }
53 |
54 | @Override
55 | public String getQueryServerBasePath(){
56 | return configuration.get(QueryServerProperties.PHOENIX_QUERY_SERVER_CLUSTER_BASE_PATH,
57 | QueryServerOptions.DEFAULT_PHOENIX_QUERY_SERVER_CLUSTER_BASE_PATH);
58 | }
59 |
60 | @Override
61 | public String getServiceName(){
62 | return configuration.get(QueryServerProperties.PHOENIX_QUERY_SERVER_SERVICE_NAME,
63 | QueryServerOptions.DEFAULT_PHOENIX_QUERY_SERVER_SERVICE_NAME);
64 | }
65 |
66 | @Override
67 | public String getZkConnectString(){
68 | return ZKConfig.standardizeZKQuorumServerString(configuration.get(QueryServerProperties.ZOOKEEPER_QUORUM_ATTRIB,
69 | "localhost"), configuration.get(QueryServerProperties.ZOOKEEPER_PORT_ATTRIB, "2181"));
70 | }
71 |
72 | private String getZkLbUserName(){
73 | return configuration.get(QueryServerProperties.PHOENIX_QUERY_SERVER_ZK_ACL_USERNAME,
74 | QueryServerOptions.DEFAULT_PHOENIX_QUERY_SERVER_ZK_ACL_USERNAME);
75 | }
76 |
77 | private String getZkLbPassword(){
78 | return configuration.get(QueryServerProperties.PHOENIX_QUERY_SERVER_ZK_ACL_PASSWORD,
79 | QueryServerOptions.DEFAULT_PHOENIX_QUERY_SERVER_ZK_ACL_PASSWORD);
80 | }
81 |
82 | @Override
83 | public List getAcls() {
84 | ACL acl = new ACL();
85 | acl.setId(new Id("digest",getZkLbUserName()+":"+getZkLbPassword()));
86 | acl.setPerms(ZooDefs.Perms.READ);
87 | return Arrays.asList(acl);
88 | }
89 |
90 | @Override
91 | public String getParentPath() {
92 | String path = String.format("%s/%s",getQueryServerBasePath(),getServiceName());
93 | return path;
94 | }
95 |
96 | @Override
97 | public String getFullPathToNode(HostAndPort hostAndPort) {
98 | String path = String.format("%s/%s",getParentPath()
99 | ,hostAndPort.toString());
100 | return path;
101 | }
102 | }
103 |
104 |
--------------------------------------------------------------------------------
/phoenix-queryserver-load-balancer/src/main/java/org/apache/phoenix/queryserver/register/ZookeeperRegistry.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 | package org.apache.phoenix.queryserver.register;
20 |
21 |
22 | import org.apache.curator.framework.CuratorFramework;
23 | import org.apache.curator.framework.CuratorFrameworkFactory;
24 | import org.apache.curator.retry.ExponentialBackoffRetry;
25 | import org.apache.curator.utils.CloseableUtils;
26 | import org.apache.phoenix.loadbalancer.service.LoadBalanceZookeeperConf;
27 | import org.apache.phoenix.util.HostAndPort;
28 | import org.apache.zookeeper.CreateMode;
29 | import org.apache.zookeeper.data.Stat;
30 | import org.slf4j.Logger;
31 | import org.slf4j.LoggerFactory;
32 |
33 | import java.nio.charset.StandardCharsets;
34 |
35 |
36 | public class ZookeeperRegistry implements Registry {
37 |
38 | private static final Logger LOG = LoggerFactory.getLogger(ZookeeperRegistry.class);
39 | private CuratorFramework client;
40 |
41 | public ZookeeperRegistry(){}
42 |
43 | @Override
44 | public void registerServer(LoadBalanceZookeeperConf configuration, int pqsPort,
45 | String zookeeperConnectString, String pqsHost)
46 | throws Exception {
47 |
48 | this.client = CuratorFrameworkFactory.newClient(zookeeperConnectString,
49 | new ExponentialBackoffRetry(1000,10));
50 | this.client.start();
51 | HostAndPort hostAndPort = HostAndPort.fromParts(pqsHost,pqsPort);
52 | String path = configuration.getFullPathToNode(hostAndPort);
53 | String node = hostAndPort.toString();
54 | this.client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(path
55 | ,node.getBytes(StandardCharsets.UTF_8));
56 | Stat stat = this.client.setACL().withACL(configuration.getAcls()).forPath(path);
57 | if (stat != null) {
58 | LOG.info(" node created with right ACL");
59 | }
60 | else {
61 | LOG.error("could not create node with right ACL. So, system would exit now.");
62 | throw new RuntimeException(" Unable to connect to Zookeeper");
63 | }
64 |
65 | }
66 |
67 | @Override
68 | public void unRegisterServer() throws Exception {
69 | CloseableUtils.closeQuietly(this.client);
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/phoenix-queryserver-load-balancer/src/main/resources/META-INF/services/org.apache.phoenix.loadbalancer.service.LoadBalanceZookeeperConf:
--------------------------------------------------------------------------------
1 | org.apache.phoenix.loadbalancer.service.LoadBalanceZookeeperConfImpl
--------------------------------------------------------------------------------
/phoenix-queryserver-load-balancer/src/main/resources/META-INF/services/org.apache.phoenix.queryserver.register.Registry:
--------------------------------------------------------------------------------
1 | org.apache.phoenix.queryserver.register.ZookeeperRegistry
--------------------------------------------------------------------------------
/phoenix-queryserver-load-balancer/src/test/java/org/apache/phoenix/loadbalancer/service/LoadBalanceZookeeperConfImplTest.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 | package org.apache.phoenix.loadbalancer.service;
20 |
21 | import org.apache.hadoop.conf.Configuration;
22 | import org.apache.hadoop.hbase.HBaseConfiguration;
23 | import org.apache.phoenix.queryserver.QueryServerProperties;
24 | import org.junit.Assert;
25 | import org.junit.Test;
26 |
27 | public class LoadBalanceZookeeperConfImplTest {
28 | @Test
29 | public void testZkConnectString() {
30 | // server port is different from the port which is set by user
31 | testZKClusterKey("server:2183", "2182");
32 | // multiple servers have their own port
33 | testZKClusterKey("server1:2182,server2:2183,server3:2184", "2181");
34 | // some servers no specified port
35 | testZKClusterKey("server1,server2:2181,server3:2182", "2181");
36 | testZKClusterKey("server1:2182,server2,server3:2183", "2181");
37 | testZKClusterKey("server1:2182,server2:2183,server3", "2181");
38 | testZKClusterKey("server1:2182,server2,server3:2183", "2184");
39 | // no port set
40 | testZKClusterKey("server1,server2,server3", "");
41 | testZKClusterKey("server1:2182,server2,server3:2183", "");
42 | }
43 |
44 | private void testZKClusterKey(String quorum, String port) {
45 | final Configuration conf = HBaseConfiguration.create();
46 | conf.set(QueryServerProperties.ZOOKEEPER_QUORUM_ATTRIB, quorum);
47 | conf.set(QueryServerProperties.ZOOKEEPER_PORT_ATTRIB, port);
48 | final LoadBalanceZookeeperConfImpl loadBalanceZookeeperConf = new LoadBalanceZookeeperConfImpl(conf);
49 | String[] connectStrings = loadBalanceZookeeperConf.getZkConnectString().split(",");
50 | String[] quorums = quorum.split(",");
51 | Assert.assertTrue( connectStrings.length == quorums.length);
52 | for (int i = 0; i< connectStrings.length; ++i) {
53 | if (quorums[i].contains(":")) {
54 | Assert.assertEquals(quorums[i], connectStrings[i]);
55 | } else {
56 | Assert.assertEquals(quorums[i] + ":" + port, connectStrings[i]);
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/phoenix-queryserver-orchestrator/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
22 |
25 |
26 | 4.0.0
27 |
28 |
29 | phoenix-queryserver-parent
30 | org.apache.phoenix
31 | 6.0.1-SNAPSHOT
32 |
33 |
34 | phoenix-queryserver-orchestrator
35 | Phoenix Query Server Orchestrator
36 |
37 |
38 |
39 |
40 | org.apache.maven.plugins
41 | maven-dependency-plugin
42 |
43 |
44 |
45 |
46 | org.apache.hbase:hbase-testing-util
47 |
48 |
49 | org.apache.hbase:hbase-it
50 |
51 |
52 |
53 | true
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | org.slf4j
62 | slf4j-api
63 |
64 |
65 | org.slf4j
66 | jcl-over-slf4j
67 | test
68 |
69 |
70 | net.sourceforge.argparse4j
71 | argparse4j
72 |
73 |
74 | org.apache.curator
75 | curator-client
76 |
77 |
78 | org.apache.curator
79 | curator-framework
80 |
81 |
82 | org.apache.curator
83 | curator-recipes
84 |
85 |
86 | org.apache.hbase
87 | hbase-common
88 |
89 |
90 | org.apache.hadoop
91 | hadoop-common
92 |
93 |
94 | com.google.code.gson
95 | gson
96 |
97 |
98 |
99 | junit
100 | junit
101 | test
102 |
103 |
104 | org.mockito
105 | mockito-core
106 | test
107 |
108 |
109 | org.apache.hbase
110 | hbase-it
111 | test-jar
112 | test
113 |
114 |
115 | org.apache.hbase
116 | hbase-testing-util
117 | test
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/phoenix-queryserver-orchestrator/src/main/java/org/apache/phoenix/queryserver/orchestrator/ToolWrapper.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 | package org.apache.phoenix.queryserver.orchestrator;
20 |
21 | import org.apache.phoenix.tool.PhoenixCanaryTool;
22 | import org.slf4j.Logger;
23 | import org.slf4j.LoggerFactory;
24 |
25 | import java.util.Arrays;
26 |
27 | /*
28 | This is a wrapper class runs the PhoenixCanaryTool.
29 | */
30 | public class ToolWrapper {
31 |
32 | private static final Logger LOGGER = LoggerFactory.getLogger(ToolWrapper.class);
33 |
34 | public void executeMain(String [] args){
35 | if(Arrays.asList(args).contains(null)){
36 | LOGGER.error("Bad argument list passed to executeMain. Skipping QueryServerCanaryTool.");
37 | return;
38 | }
39 | LOGGER.info("Passing args to QueryServerCanaryTool: " + String.join(",",args));
40 | PhoenixCanaryTool.main(args);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/phoenix-queryserver-orchestrator/src/main/java/org/apache/phoenix/tool/CanaryTestResult.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | package org.apache.phoenix.tool;
19 |
20 | public class CanaryTestResult {
21 |
22 | private boolean isSuccessful;
23 | private long startTime;
24 | private long executionTime;
25 | private String message;
26 | private String testName;
27 | private String timestamp;
28 | private Object miscellaneous;
29 |
30 | public Object getMiscellaneous() {
31 | return miscellaneous;
32 | }
33 |
34 | public void setMiscellaneous(Object miscellaneous) {
35 | this.miscellaneous = miscellaneous;
36 | }
37 |
38 | public long getStartTime() {
39 | return startTime;
40 | }
41 |
42 | public void setStartTime(long startTime) {
43 | this.startTime = startTime;
44 | }
45 |
46 | public String getTimestamp() {
47 | return timestamp;
48 | }
49 |
50 | public void setTimestamp(String timestamp) {
51 | this.timestamp = timestamp;
52 | }
53 |
54 | public boolean isSuccessful() {
55 | return isSuccessful;
56 | }
57 |
58 | public void setSuccessful(boolean successful) {
59 | isSuccessful = successful;
60 | }
61 |
62 | public long getExecutionTime() {
63 | return executionTime;
64 | }
65 |
66 | public void setExecutionTime(long executionTime) {
67 | this.executionTime = executionTime;
68 | }
69 |
70 | public String getMessage() {
71 | return message;
72 | }
73 |
74 | public void setMessage(String message) {
75 | this.message = message;
76 | }
77 |
78 | public String getTestName() {
79 | return testName;
80 | }
81 |
82 | public void setTestName(String testName) {
83 | this.testName = testName;
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/phoenix-queryserver-orchestrator/src/test/java/org/apache/phoenix/tool/PhoenixCanaryToolTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | package org.apache.phoenix.tool;
19 |
20 | import static org.junit.Assert.assertEquals;
21 |
22 | import org.junit.Before;
23 | import org.junit.Test;
24 | import org.mockito.Mock;
25 | import org.mockito.Mockito;
26 | import static org.mockito.Mockito.when;
27 | import org.mockito.MockitoAnnotations;
28 | import java.sql.Connection;
29 | import java.sql.DatabaseMetaData;
30 | import java.sql.PreparedStatement;
31 | import java.sql.ResultSet;
32 | import java.sql.Statement;
33 |
34 | public class PhoenixCanaryToolTest {
35 |
36 | @Mock
37 | private Connection connection;
38 |
39 | @Mock
40 | private Statement statement;
41 |
42 | @Mock
43 | private PreparedStatement ps;
44 |
45 | @Mock
46 | private ResultSet rs;
47 |
48 | @Mock
49 | private DatabaseMetaData dbm;
50 |
51 | @Before
52 | public void setUp() {
53 | MockitoAnnotations.initMocks(this);
54 | }
55 |
56 | @Test
57 | public void upsertTableTest() throws Exception {
58 | when(connection.createStatement()).thenReturn(statement);
59 | when(connection.prepareStatement(Mockito.anyString())).thenReturn(ps);
60 | when(statement.executeUpdate(Mockito.anyString())).thenReturn(1);
61 | CanaryTestResult result = new PhoenixCanaryTool.UpsertTableTest().runTest(connection);
62 | assertEquals(true, result.isSuccessful());
63 | assertEquals("Test upsertTable successful", result.getMessage());
64 | }
65 |
66 | @Test
67 | public void readTableTest() throws Exception {
68 | when(connection.prepareStatement(Mockito.anyString())).thenReturn(ps);
69 | when(ps.executeQuery()).thenReturn(rs);
70 | when(rs.next()).thenReturn(true).thenReturn(false);
71 | when(rs.getInt(1)).thenReturn(1);
72 | when(rs.getString(2)).thenReturn("Hello World");
73 | CanaryTestResult result = new PhoenixCanaryTool.ReadTableTest().runTest(connection);
74 | assertEquals(true, result.isSuccessful());
75 | assertEquals("Test readTable successful", result.getMessage());
76 | }
77 |
78 | @Test
79 | public void failTest() throws Exception {
80 | when(connection.prepareStatement(Mockito.anyString())).thenReturn(ps);
81 | when(ps.executeQuery()).thenReturn(rs);
82 | when(rs.getInt(1)).thenReturn(3);
83 | when(rs.getString(2)).thenReturn("Incorrect data");
84 | when(rs.next()).thenReturn(true).thenReturn(false);
85 | CanaryTestResult result = new PhoenixCanaryTool.ReadTableTest().runTest(connection);
86 | assertEquals(false, result.isSuccessful());
87 | assert (result.getMessage().contains("Retrieved values do not match the inserted values"));
88 | }
89 | }
--------------------------------------------------------------------------------
/phoenix-queryserver/src/build/query-server-runnable.xml:
--------------------------------------------------------------------------------
1 |
2 |
22 |
23 |
26 | runnable
27 |
28 | jar
29 |
30 | false
31 |
32 |
33 |
37 | metaInf-services
38 |
39 |
40 |
41 |
42 | true
43 | runtime
44 | /
45 |
46 | org.apache.phoenix:phoenix-queryserver
47 | org.apache.phoenix:phoenix-queryserver-client
48 | org.apache.calcite.avatica:*
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/phoenix-queryserver/src/main/java/org/apache/phoenix/loadbalancer/service/LoadBalanceZookeeperConf.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 | package org.apache.phoenix.loadbalancer.service;
20 |
21 | import org.apache.phoenix.util.HostAndPort;
22 | import org.apache.zookeeper.data.ACL;
23 |
24 | import java.util.List;
25 |
26 |
27 | public interface LoadBalanceZookeeperConf {
28 |
29 | String getQueryServerBasePath();
30 |
31 | String getServiceName();
32 |
33 | String getZkConnectString();
34 |
35 | List getAcls();
36 |
37 | String getParentPath();
38 |
39 | String getFullPathToNode(HostAndPort hostAndPort);
40 |
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/register/Registry.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * Licensed to the Apache Software Foundation (ASF) under one
4 | * or more contributor license agreements. See the NOTICE file
5 | * distributed with this work for additional information
6 | * regarding copyright ownership. The ASF licenses this file
7 | * to you under the Apache License, Version 2.0 (the
8 | * "License"); you may not use this file except in compliance
9 | * with the License. You may obtain a copy of the License at
10 | *
11 | * http://www.apache.org/licenses/LICENSE-2.0
12 | *
13 | * Unless required by applicable law or agreed to in writing, software
14 | * distributed under the License is distributed on an "AS IS" BASIS,
15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 | * See the License for the specific language governing permissions and
17 | * limitations under the License.
18 | */
19 | package org.apache.phoenix.queryserver.register;
20 |
21 |
22 | import org.apache.phoenix.loadbalancer.service.LoadBalanceZookeeperConf;
23 |
24 | /**
25 | * Registry interface for implementing registering
26 | * and un-registering to service locator.
27 | */
28 | public interface Registry {
29 |
30 | /**
31 | * Unreqister the server with zookeeper. All Cleanup
32 | * is done in this method.
33 | * @throws Exception
34 | */
35 | void unRegisterServer() throws Exception;
36 |
37 | /**
38 | * Registers the server with the service locator ( zookeeper).
39 | * @param configuration - Hbase Configuration
40 | * @param port - port for PQS server
41 | * @param connectString - zookeeper connect string
42 | * @param pqsHost - host for PQS server.
43 | * @throws Exception
44 | */
45 | void registerServer(LoadBalanceZookeeperConf configuration, int port
46 | , String connectString, String pqsHost) throws Exception ;
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/AvaticaServerConfigurationFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | package org.apache.phoenix.queryserver.server;
19 |
20 | import org.apache.calcite.avatica.server.AvaticaServerConfiguration;
21 | import org.apache.hadoop.conf.Configuration;
22 | import org.apache.hadoop.security.UserGroupInformation;
23 |
24 |
25 | public interface AvaticaServerConfigurationFactory {
26 |
27 | AvaticaServerConfiguration getAvaticaServerConfiguration(Configuration conf, UserGroupInformation ugi);
28 |
29 | class AvaticaServerConfigurationFactoryImpl implements AvaticaServerConfigurationFactory {
30 |
31 | @Override
32 | public AvaticaServerConfiguration getAvaticaServerConfiguration(Configuration conf, UserGroupInformation ugi) {
33 | return null;
34 | }
35 | }
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/PhoenixMetaFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | package org.apache.phoenix.queryserver.server;
19 |
20 | import org.apache.calcite.avatica.Meta;
21 | import org.apache.hadoop.conf.Configurable;
22 |
23 | /**
24 | * A @{link Meta.Factory} that can also respect Hadoop
25 | * {@link org.apache.hadoop.conf.Configuration} objects.
26 | */
27 | public interface PhoenixMetaFactory extends Meta.Factory, Configurable {
28 | }
29 |
--------------------------------------------------------------------------------
/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/RemoteUserExtractorFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | package org.apache.phoenix.queryserver.server;
19 |
20 | import org.apache.calcite.avatica.server.RemoteUserExtractor;
21 | import org.apache.hadoop.conf.Configuration;
22 |
23 | /**
24 | * Creates remote user extractors.
25 | */
26 | public interface RemoteUserExtractorFactory {
27 |
28 | RemoteUserExtractor createRemoteUserExtractor(Configuration conf);
29 |
30 | class RemoteUserExtractorFactoryImpl implements RemoteUserExtractorFactory {
31 | @Override
32 | public RemoteUserExtractor createRemoteUserExtractor(Configuration conf) {
33 | return new QueryServer.PhoenixRemoteUserExtractor(conf);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/ServerCustomizersFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | package org.apache.phoenix.queryserver.server;
19 |
20 | import java.io.File;
21 | import java.util.ArrayList;
22 | import java.util.Collections;
23 | import java.util.List;
24 |
25 | import org.apache.calcite.avatica.server.AvaticaServerConfiguration;
26 | import org.apache.calcite.avatica.server.ServerCustomizer;
27 | import org.apache.hadoop.conf.Configuration;
28 | import org.apache.phoenix.queryserver.QueryServerOptions;
29 | import org.apache.phoenix.queryserver.QueryServerProperties;
30 | import org.apache.phoenix.queryserver.server.customizers.HostedClientJarsServerCustomizer;
31 | import org.apache.phoenix.queryserver.server.customizers.JMXJsonEndpointServerCustomizer;
32 | import org.eclipse.jetty.server.Server;
33 | import org.slf4j.Logger;
34 | import org.slf4j.LoggerFactory;
35 |
36 | /**
37 | * Creates customizers for the underlying Avatica HTTP server.
38 | * Allows for fine grained control of authentication, etc.
39 | */
40 | public interface ServerCustomizersFactory {
41 | /**
42 | * Creates a list of customizers that will customize the server.
43 | * @param conf Configuration to use
44 | * @param avaticaServerConfiguration to use in case custom-auth is enabled
45 | * @return List of server suctomizers
46 | */
47 | List> createServerCustomizers(Configuration conf, AvaticaServerConfiguration avaticaServerConfiguration);
48 |
49 | /**
50 | * Factory that creates an empty list of customizers.
51 | */
52 | class ServerCustomizersFactoryImpl implements ServerCustomizersFactory {
53 | private static final Logger LOG = LoggerFactory.getLogger(ServerCustomizersFactoryImpl.class);
54 | @Override
55 | public List> createServerCustomizers(Configuration conf,
56 | AvaticaServerConfiguration avaticaServerConfiguration) {
57 | List> customizers = new ArrayList<>();
58 | if (conf.getBoolean(QueryServerProperties.CLIENT_JARS_ENABLED_ATTRIB, QueryServerOptions.DEFAULT_CLIENT_JARS_ENABLED)) {
59 | String repoLocation = conf.get(QueryServerProperties.CLIENT_JARS_REPO_ATTRIB,
60 | QueryServerOptions.DEFAULT_CLIENT_JARS_REPO);
61 | if (repoLocation != null && !repoLocation.isEmpty()) {
62 | File repo = new File(repoLocation);
63 | if (!repo.isDirectory()) {
64 | throw new IllegalArgumentException("Provided maven repository is not a directory. " + repo);
65 | }
66 | String contextPath = conf.get(QueryServerProperties.CLIENT_JARS_CONTEXT_ATTRIB,
67 | QueryServerOptions.DEFAULT_CLIENT_JARS_CONTEXT);
68 | LOG.info("Creating ServerCustomizer to host client jars from {} at HTTP endpoint {}", repo, contextPath);
69 | HostedClientJarsServerCustomizer customizer = new HostedClientJarsServerCustomizer(repo, contextPath);
70 | customizers.add(customizer);
71 | } else {
72 | LOG.warn("Empty value provided for {}, ignoring", QueryServerProperties.CLIENT_JARS_REPO_ATTRIB);
73 | }
74 | }
75 | if (!conf.getBoolean(QueryServerProperties.QUERY_SERVER_JMX_JSON_ENDPOINT_DISABLED,
76 | QueryServerOptions.DEFAULT_QUERY_SERVER_JMXJSONENDPOINT_DISABLED)) {
77 | customizers.add(new JMXJsonEndpointServerCustomizer());
78 | }
79 | return Collections.unmodifiableList(customizers);
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/customizers/BasicAuthenticationServerCustomizer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | package org.apache.phoenix.queryserver.server.customizers;
19 |
20 | import java.util.Collections;
21 | import java.util.List;
22 |
23 | import org.apache.calcite.avatica.server.AvaticaServerConfiguration;
24 | import org.apache.calcite.avatica.server.ServerCustomizer;
25 | import org.apache.hadoop.conf.Configuration;
26 | import org.apache.phoenix.queryserver.server.ServerCustomizersFactory;
27 | import org.eclipse.jetty.security.ConstraintMapping;
28 | import org.eclipse.jetty.security.ConstraintSecurityHandler;
29 | import org.eclipse.jetty.security.HashLoginService;
30 | import org.eclipse.jetty.security.UserStore;
31 | import org.eclipse.jetty.security.authentication.BasicAuthenticator;
32 | import org.eclipse.jetty.server.Server;
33 | import org.eclipse.jetty.util.security.Constraint;
34 | import org.eclipse.jetty.util.security.Credential;
35 | import org.slf4j.Logger;
36 | import org.slf4j.LoggerFactory;
37 |
38 | /**
39 | * Avatica ServerCustomizer which performs HTTP Basic authentication against a static user database.
40 | *
41 | * For testing ONLY.
42 | */
43 | public class BasicAuthenticationServerCustomizer implements ServerCustomizer {
44 | private static final Logger LOG = LoggerFactory.getLogger(BasicAuthenticationServerCustomizer.class);
45 |
46 | public static final String USER_AUTHORIZED = "user3";
47 | public static final String USER_PW = "s3cr3t";
48 |
49 | public static class BasicAuthServerCustomizerFactory implements ServerCustomizersFactory {
50 | @Override
51 | public List> createServerCustomizers(
52 | Configuration conf, AvaticaServerConfiguration avaticaServerConfiguration) {
53 | return Collections.>singletonList(new BasicAuthenticationServerCustomizer());
54 | }
55 | }
56 |
57 | @Override
58 | public void customize(Server server) {
59 | LOG.debug("Customizing server to allow requests for {}", USER_AUTHORIZED);
60 |
61 | UserStore store = new UserStore();
62 | store.addUser(USER_AUTHORIZED, Credential.getCredential(USER_PW), new String[] {"users"});
63 | HashLoginService login = new HashLoginService();
64 | login.setName("users");
65 | login.setUserStore(store);
66 |
67 | Constraint constraint = new Constraint();
68 | constraint.setName(Constraint.__BASIC_AUTH);
69 | constraint.setRoles(new String[]{"users"});
70 | constraint.setAuthenticate(true);
71 |
72 | ConstraintMapping cm = new ConstraintMapping();
73 | cm.setConstraint(constraint);
74 | cm.setPathSpec("/*");
75 |
76 | ConstraintSecurityHandler security = new ConstraintSecurityHandler();
77 | security.setAuthenticator(new BasicAuthenticator());
78 | security.setRealmName("users");
79 | security.addConstraintMapping(cm);
80 | security.setLoginService(login);
81 |
82 | // chain the PQS handler to security
83 | security.setHandler(server.getHandlers()[0]);
84 | server.setHandler(security);
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/customizers/HostedClientJarsServerCustomizer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | package org.apache.phoenix.queryserver.server.customizers;
19 |
20 | import java.io.File;
21 | import java.util.Arrays;
22 |
23 | import org.apache.calcite.avatica.server.ServerCustomizer;
24 | import org.eclipse.jetty.server.Handler;
25 | import org.eclipse.jetty.server.Server;
26 | import org.eclipse.jetty.server.handler.ContextHandler;
27 | import org.eclipse.jetty.server.handler.HandlerList;
28 | import org.eclipse.jetty.server.handler.ResourceHandler;
29 | import org.slf4j.Logger;
30 | import org.slf4j.LoggerFactory;
31 |
32 | /**
33 | * Hosts a Maven repository from local filesystem over HTTP from within PQS.
34 | */
35 | public class HostedClientJarsServerCustomizer implements ServerCustomizer {
36 | private static final Logger LOG = LoggerFactory.getLogger(HostedClientJarsServerCustomizer.class);
37 |
38 | private final File repoRoot;
39 | private final String contextPath;
40 |
41 | /**
42 | * @param localMavenRepoRoot The path to the Phoenix-built maven repository on the local filesystem
43 | * @param contextPath The HTTP path which the repository will be hosted at
44 | */
45 | public HostedClientJarsServerCustomizer(File localMavenRepoRoot, String contextPath) {
46 | this.repoRoot = localMavenRepoRoot;
47 | this.contextPath = contextPath;
48 | }
49 |
50 | @Override
51 | public void customize(Server server) {
52 | Handler[] handlers = server.getHandlers();
53 | if (handlers.length != 1) {
54 | LOG.warn("Observed handlers on server {}", Arrays.toString(handlers));
55 | throw new IllegalStateException("Expected to find one handler");
56 | }
57 | HandlerList list = (HandlerList) handlers[0];
58 |
59 | ContextHandler ctx = new ContextHandler(contextPath);
60 | ResourceHandler resource = new ResourceHandler();
61 | resource.setDirAllowed(true);
62 | resource.setDirectoriesListed(false);
63 | resource.setResourceBase(repoRoot.getAbsolutePath());
64 | ctx.setHandler(resource);
65 |
66 | Handler[] realHandlers = list.getChildHandlers();
67 |
68 | Handler[] newHandlers = new Handler[realHandlers.length + 1];
69 | newHandlers[0] = ctx;
70 | System.arraycopy(realHandlers, 0, newHandlers, 1, realHandlers.length);
71 | server.setHandler(new HandlerList(newHandlers));
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/phoenix-queryserver/src/main/java/org/apache/phoenix/queryserver/server/customizers/JMXJsonEndpointServerCustomizer.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one or more
3 | * contributor license agreements. See the NOTICE file distributed with
4 | * this work for additional information regarding copyright ownership.
5 | * The ASF licenses this file to you under the Apache License, Version 2.0
6 | * (the "License"); you may not use this file except in compliance with
7 | * the License. You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package org.apache.phoenix.queryserver.server.customizers;
18 |
19 | import static org.apache.hadoop.http.HttpServer2.CONF_CONTEXT_ATTRIBUTE;
20 |
21 | import org.apache.calcite.avatica.server.ServerCustomizer;
22 | import org.apache.hadoop.hbase.HBaseConfiguration;
23 | import org.apache.hadoop.jmx.JMXJsonServlet;
24 | import org.eclipse.jetty.server.Handler;
25 | import org.eclipse.jetty.server.Server;
26 | import org.eclipse.jetty.server.handler.HandlerList;
27 | import org.eclipse.jetty.servlet.ServletContextHandler;
28 | import org.eclipse.jetty.servlet.ServletHolder;
29 | import org.slf4j.Logger;
30 | import org.slf4j.LoggerFactory;
31 |
32 | import java.util.Arrays;
33 |
34 | import javax.servlet.Servlet;
35 |
36 | public class JMXJsonEndpointServerCustomizer implements ServerCustomizer {
37 | private static final Logger LOG = LoggerFactory.getLogger(JMXJsonEndpointServerCustomizer.class);
38 |
39 | @Override
40 | public void customize(Server server) {
41 | Handler[] handlers = server.getHandlers();
42 | if (handlers.length != 1) {
43 | LOG.warn("Observed handlers on server {}", Arrays.toString(handlers));
44 | throw new IllegalStateException("Expected to find one handler");
45 | }
46 | HandlerList list = (HandlerList) handlers[0];
47 |
48 | ServletContextHandler ctx = new ServletContextHandler();
49 | ctx.setContextPath("/jmx");
50 | ctx.getServletContext().setAttribute(CONF_CONTEXT_ATTRIBUTE, HBaseConfiguration.create());
51 |
52 | Servlet servlet = new JMXJsonServlet();
53 | ServletHolder holder = new ServletHolder(servlet);
54 | ctx.addServlet(holder, "/");
55 |
56 | Handler[] realHandlers = list.getChildHandlers();
57 | Handler[] newHandlers = new Handler[realHandlers.length + 1];
58 | newHandlers[0] = ctx;
59 | System.arraycopy(realHandlers, 0, newHandlers, 1, realHandlers.length);
60 | server.setHandler(new HandlerList(newHandlers));
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/phoenix-queryserver/src/main/java/org/apache/phoenix/util/InstanceResolver.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | package org.apache.phoenix.util;
19 |
20 | import java.util.ArrayList;
21 | import java.util.Iterator;
22 | import java.util.List;
23 | import java.util.ServiceLoader;
24 | import java.util.concurrent.ConcurrentHashMap;
25 |
26 | /**
27 | * Resolves object instances registered using the JDK 6+ {@link java.util.ServiceLoader}.
28 | *
29 | *
30 | * @since 2.0
31 | */
32 | public class InstanceResolver {
33 | private static final ConcurrentHashMap RESOLVED_SINGLETONS = new ConcurrentHashMap();
34 |
35 | private InstanceResolver() {/* not allowed */}
36 |
37 | /**
38 | * Resolves an instance of the specified class if it has not already been resolved.
39 | * @param clazz The type of instance to resolve
40 | * @param defaultInstance The instance to use if a custom instance has not been registered
41 | * @return The resolved instance or the default instance provided.
42 | * {@code null} if an instance is not registered and a default is not provided.
43 | */
44 | @SuppressWarnings("unchecked")
45 | public static T getSingleton(Class clazz, T defaultInstance) {
46 | Object obj = RESOLVED_SINGLETONS.get(clazz);
47 | if(obj != null) {
48 | return (T)obj;
49 | }
50 | if (defaultInstance != null && !clazz.isInstance(defaultInstance)) throw new IllegalArgumentException("defaultInstance is not of type " + clazz.getName());
51 | final Object o = resolveSingleton(clazz, defaultInstance);
52 | obj = RESOLVED_SINGLETONS.putIfAbsent(clazz, o);
53 | if(obj == null) {
54 | obj = o;
55 | }
56 | return (T)obj;
57 | }
58 |
59 | /**
60 | * Resolves all instances of a specified class and add it to the list of default implementations
61 | * @param clazz Type of the instance to resolve
62 | * @param defaultInstances {@link List} of instances that match the type clazz
63 | * @param Type of class passed
64 | * @return {@link List} of instance of the specified class. Newly found instances will be added
65 | * to the existing contents of defaultInstances
66 | */
67 | @SuppressWarnings("unchecked")
68 | public static List get(Class clazz, List defaultInstances) {
69 | Iterator iterator = ServiceLoader.load(clazz).iterator();
70 | List instances = new ArrayList<>();
71 | iterator.forEachRemaining(instances::add);
72 |
73 | if (defaultInstances != null) {
74 | defaultInstances.addAll(instances);
75 | } else {
76 | defaultInstances = instances;
77 | }
78 |
79 | return defaultInstances;
80 | }
81 |
82 | private synchronized static T resolveSingleton(Class clazz, T defaultInstance) {
83 | ServiceLoader loader = ServiceLoader.load(clazz);
84 | // returns the first registered instance found
85 | for (T singleton : loader) {
86 | return singleton;
87 | }
88 | return defaultInstance;
89 | }
90 |
91 | //@VisibleForTesting
92 | public static void clearSingletons() {
93 | RESOLVED_SINGLETONS.clear();
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/phoenix-queryserver/src/main/java/org/apache/phoenix/util/SimpleLRUCache.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed to the Apache Software Foundation (ASF) under one
3 | * or more contributor license agreements. See the NOTICE file
4 | * distributed with this work for additional information
5 | * regarding copyright ownership. The ASF licenses this file
6 | * to you under the Apache License, Version 2.0 (the
7 | * "License"); you may not use this file except in compliance
8 | * with the License. You may obtain a copy of the License at
9 | *
10 | * http://www.apache.org/licenses/LICENSE-2.0
11 | *
12 | * Unless required by applicable law or agreed to in writing, software
13 | * distributed under the License is distributed on an "AS IS" BASIS,
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | * See the License for the specific language governing permissions and
16 | * limitations under the License.
17 | */
18 | package org.apache.phoenix.util;
19 |
20 | import java.util.Arrays;
21 | import java.util.Comparator;
22 | import java.util.TreeSet;
23 | import java.util.concurrent.ConcurrentHashMap;
24 | import java.util.concurrent.atomic.AtomicLong;
25 | import java.util.function.Function;
26 | import java.util.stream.Collectors;
27 |
28 | import org.slf4j.Logger;
29 | import org.slf4j.LoggerFactory;
30 |
31 |
32 | /**
33 | * Minimal Cache implementation based on ConcurrentHashMap.
34 | *
35 | * The maxSize logic will only work if all access is via the the computeIfAbsent() method.
36 | *
37 | */
38 | public class SimpleLRUCache extends ConcurrentHashMap {
39 |
40 | protected static final Logger LOG = LoggerFactory.getLogger(SimpleLRUCache.class);
41 |
42 | int maxSize;
43 | int triggerSize;
44 |
45 | private ConcurrentHashMap accessed =
46 | new ConcurrentHashMap<>();
47 |
48 | public SimpleLRUCache (long maxSize, int concurrencyLevel) {
49 | super((int)(maxSize * 1.1), (float)0.75, concurrencyLevel);
50 | this.maxSize = (int)maxSize;
51 | this.triggerSize = (int)(maxSize * 1.1)+1 ;
52 | }
53 |
54 | @Override
55 | public V computeIfAbsent(K key, Function super K,? extends V> mappingFunction) {
56 | V value = super.computeIfAbsent(key, mappingFunction);
57 | if (value != null) {
58 | accessed.put(key, new AtomicLong(System.currentTimeMillis()));
59 | if (this.size() > triggerSize) {
60 | evict();
61 | }
62 | }
63 | return value;
64 | }
65 |
66 | private void evict() {
67 | synchronized(this) {
68 | int currentSize = this.size();
69 | if (currentSize <= triggerSize) {
70 | return;
71 | }
72 | LOG.warn("UGI Cache capacity exceeded, you may want to increase its size");
73 | TreeSet> sortedByLRU = new TreeSet<>(
74 | new Comparator>() {
75 | @Override
76 | public int compare(Entry o1, Entry o2) {
77 | int keyResult =
78 | Long.compare(o2.getValue().get(), o1.getValue().get());
79 | if(keyResult == 0) {
80 | return o2.getKey().compareTo(o1.getKey());
81 | } else {
82 | return keyResult;
83 | }
84 | }
85 | });
86 | sortedByLRU.addAll(accessed.entrySet());
87 | Entry