-
Notifications
You must be signed in to change notification settings - Fork 1k
Ranger-5081: CI: Add check to verify plugin installation in ranger-service containers #583
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
d75acb7
c1fce72
3a1b6a2
b05585d
3feda2b
b72acf1
b16078e
1a688fa
8c962e1
1fcf355
4e3eaee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
#!/usr/bin/env python3 | ||
|
||
# Licensed to the Apache Software Foundation (ASF) under one | ||
# or more contributor license agreements. See the NOTICE file | ||
# distributed with this work for additional information | ||
# regarding copyright ownership. The ASF licenses this file | ||
# to you under the Apache License, Version 2.0 (the | ||
# "License"); you may not use this file except in compliance | ||
# with the License. You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
import os | ||
import time | ||
from dotenv import load_dotenv | ||
from apache_ranger.client.ranger_client import RangerClient | ||
|
||
# Load environment variables from .env | ||
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) | ||
|
||
# Path to the .env file in the parent directory | ||
ENV_PATH = os.path.join(SCRIPT_DIR, "..", ".env") | ||
|
||
# Load it | ||
load_dotenv(dotenv_path=ENV_PATH) | ||
|
||
RANGER_ADMIN_USER = os.getenv("RANGER_ADMIN_USER") | ||
RANGER_ADMIN_PASS = os.getenv("RANGER_ADMIN_PASS") | ||
KNOX_USER = os.getenv("KNOX_USER") | ||
KNOX_PASS = os.getenv("KNOX_PASS") | ||
|
||
# Ranger Admin URL and credentials | ||
ranger_url = "http://localhost:6080" | ||
credentials = (RANGER_ADMIN_USER, RANGER_ADMIN_PASS) | ||
|
||
# Initialize the Ranger client | ||
ranger = RangerClient(ranger_url, credentials) | ||
|
||
PLUGIN_INFO_ENDPOINT = "/service/public/v2/api/plugins/info" | ||
KNOX_ENDPOINT = "https://localhost:8443/gateway/sandbox/webhdfs/v1/?op=LISTSTATUS" | ||
|
||
RETRY_COUNT = int(os.getenv("PLUGIN_RETRY_COUNT", 4)) | ||
RETRY_INTERVAL = int(os.getenv("PLUGIN_RETRY_INTERVAL", 30)) | ||
|
||
expected_services = ["hdfs", "hbase", "kms", "yarn", "kafka", "ozone", "knox", "hive"] | ||
|
||
|
||
def init_knox_plugin(): | ||
print("\nTriggering Knox activity to ensure plugin status is updated...") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. change log to |
||
try: | ||
response = ranger.session.get( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. use a single line instead |
||
KNOX_ENDPOINT, | ||
auth=(KNOX_USER,KNOX_PASS), | ||
verify=False, | ||
timeout=10 | ||
) | ||
print("Knox activity triggered.") | ||
except Exception as e: | ||
print(f"Failed to trigger Knox activity: {e}") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update: |
||
|
||
def fetch_plugin_info(): | ||
print(f"\nFetching plugin info from {PLUGIN_INFO_ENDPOINT} ...") | ||
try: | ||
response = ranger.session.get(ranger_url + PLUGIN_INFO_ENDPOINT) | ||
response.raise_for_status() | ||
return response.json() | ||
except Exception as e: | ||
print(f"Error fetching plugin info: {e}") | ||
exit(1) | ||
|
||
def check_plugins(plugin_data): | ||
|
||
failed_services = [] | ||
print("\n<--------- Plugin Status ---------->") | ||
for svc in expected_services: | ||
print(f"\nChecking service type: {svc}") | ||
entries = [entry for entry in plugin_data if entry.get("serviceType") == svc] | ||
|
||
if not entries: | ||
print(f"MISSING: No plugins found for service type '{svc}'.") | ||
failed_services.append(svc) | ||
continue | ||
|
||
active_plugins = [ | ||
entry for entry in entries | ||
if entry.get("info", {}).get("policyActiveVersion") | ||
] | ||
print(f"🟢 Active plugins: {len(active_plugins)} / {len(entries)} total plugins found.") | ||
|
||
if not active_plugins: | ||
print(f"WARNING: Plugins present but NONE are active for '{svc}'.") | ||
failed_services.append(svc) | ||
|
||
print("Details:") | ||
for entry in entries: | ||
host = entry.get("hostName", "unknown") | ||
app_type = entry.get("appType", "unknown") | ||
version = entry.get("info", {}).get("policyActiveVersion", "null") | ||
print(f"- Host: {host}, AppType: {app_type}, PolicyActiveVersion: {version}") | ||
return failed_services | ||
|
||
|
||
def main(): | ||
|
||
print("Checking Ranger plugin status via Ranger Admin API") | ||
|
||
# Trigger knox activity | ||
init_knox_plugin() | ||
|
||
# wait for status update | ||
for i in range(RETRY_COUNT): #retrying upto RETRY_COUNT * RETRY_INTERVAL seconds | ||
plugin_data = fetch_plugin_info() | ||
if all(any(entry.get("info", {}).get("policyActiveVersion") for entry in plugin_data if entry["serviceType"] == svc) for svc in expected_services): | ||
break | ||
print(f"Some plugins not active yet, retrying in {RETRY_INTERVAL}s...") | ||
time.sleep(RETRY_INTERVAL) | ||
|
||
else: | ||
print("Timed out waiting for plugins to become active.") | ||
|
||
# fetch plugin info through admin API | ||
plugin_data = fetch_plugin_info() | ||
|
||
if not plugin_data: | ||
print("No plugin info returned from API.") | ||
exit(1) | ||
|
||
# get plugin details | ||
failed_services = check_plugins(plugin_data) | ||
|
||
print() | ||
if failed_services: | ||
print(f"❌ The following plugins are missing or inactive: {', '.join(failed_services)}") | ||
exit(1) | ||
else: | ||
print("✅ All expected plugins are present and active.") | ||
|
||
if __name__ == "__main__": | ||
main() | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
#!/bin/bash | ||
|
||
# Licensed to the Apache Software Foundation (ASF) under one | ||
# or more contributor license agreements. See the NOTICE file | ||
# distributed with this work for additional information | ||
# regarding copyright ownership. The ASF licenses this file | ||
# to you under the Apache License, Version 2.0 (the | ||
# "License"); you may not use this file except in compliance | ||
# with the License. You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
set -e | ||
|
||
echo "Checking Ranger plugin status via Ranger Admin API" | ||
|
||
# Load environment variables from .env file | ||
SCRIPT_DIR=$(dirname "$0") | ||
source "$SCRIPT_DIR/../.env" | ||
|
||
RANGER_HOST="http://localhost:6080" | ||
ENDPOINT="$RANGER_HOST/service/public/v2/api/plugins/info" | ||
|
||
# Trigger activity for KNOX to make plugin active | ||
echo | ||
echo "Triggering Knox activity to ensure plugin status is updated..." | ||
KNOX_ENDPOINT="https://localhost:8443/gateway/sandbox/webhdfs/v1/?op=LISTSTATUS" | ||
|
||
curl -k -u "$KNOX_USER:$KNOX_PASS" "$KNOX_ENDPOINT" > /dev/null 2>&1 | ||
echo "Knox activity triggered." | ||
|
||
sleep 60 | ||
|
||
echo "Fetching plugin info from $ENDPOINT ..." | ||
response=$(curl -s -u "$RANGER_ADMIN_USER:$RANGER_ADMIN_PASS" "$ENDPOINT") | ||
|
||
if [[ -z "$response" || "$response" == "[]" ]]; then | ||
echo "No plugin info returned from API." | ||
exit 1 | ||
fi | ||
|
||
expected_services=("hdfs" "hbase" "kms" "yarn" "kafka" "ozone" "knox" "hive") | ||
failed=false | ||
|
||
echo | ||
echo "<--------- Plugin Status ----------> " | ||
for svc in "${expected_services[@]}"; do | ||
echo | ||
echo "Checking service type: $svc" | ||
|
||
entries=$(echo "$response" | jq --arg svc "$svc" '[.[] | select(.serviceType == $svc)]') | ||
count=$(echo "$entries" | jq 'length') | ||
|
||
if (( count == 0 )); then | ||
echo "MISSING: No plugins found for service type '$svc'." | ||
failed=true | ||
continue | ||
fi | ||
|
||
active_count=$(echo "$entries" | jq '[.[] | select(.info.policyActiveVersion != null and .info.policyActiveVersion != "")] | length') | ||
|
||
echo "🟢 Active plugins: $active_count / $count total plugins found." | ||
|
||
if (( active_count == 0 )); then | ||
echo "WARNING: Plugins present but NONE are active for '$svc'." | ||
failed=true | ||
fi | ||
|
||
# List hostnames and plugin statuses for this service type | ||
echo "Details:" | ||
echo "$entries" | jq -r '.[] | "- Host: \(.hostName), AppType: \(.appType), PolicyActiveVersion: \(.info.policyActiveVersion // "null")"' | ||
done | ||
|
||
echo | ||
if $failed; then | ||
echo "❌ One or more plugins are missing or inactive." | ||
exit 1 | ||
else | ||
echo "✅ All expected plugins are present and active." | ||
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are defined as env variables in
maven.yml
so this is unncesssary.