Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ client-setup-env: $(VENV_DIR) client-install-dependencies
.PHONY: client-lint
client-lint: client-setup-env ## Run linting checks for Polaris client
@echo "--- Running client linting checks ---"
@$(ACTIVATE_AND_CD) && poetry run pre-commit run --files integration_tests/* python/cli/*
@$(ACTIVATE_AND_CD) && poetry run pre-commit run --files integration_tests/* generate_clients.py apache_polaris/cli/* apache_polaris/cli/command/* apache_polaris/cli/options/* test/*
@echo "--- Client linting checks complete ---"

.PHONY: client-regenerate
Expand Down
4 changes: 2 additions & 2 deletions client/python/.pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ repos:
hooks:
- id: mypy
args:
[--disallow-untyped-defs, --ignore-missing-imports, --install-types, --non-interactive]
files: 'integration_tests/.*\.py'
[--disallow-untyped-defs, --ignore-missing-imports, --install-types, --non-interactive, --follow-imports=skip]
files: '(integration_tests/.*\.py)|(test/.*\.py)|(apache_polaris/cli/.*\.py)|generate_clients.py'
61 changes: 32 additions & 29 deletions client/python/apache_polaris/cli/api_client_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,24 @@
import os
from argparse import Namespace
from functools import cached_property
from typing import Optional, Dict
from typing import Optional, Dict, Any

from apache_polaris.cli.constants import (
CONFIG_FILE,
CLIENT_PROFILE_ENV,
CLIENT_ID_ENV,
CLIENT_SECRET_ENV,
REALM_ENV,
HEADER_ENV,
Arguments,
DEFAULT_HOSTNAME,
DEFAULT_PORT
CONFIG_FILE,
CLIENT_PROFILE_ENV,
CLIENT_ID_ENV,
CLIENT_SECRET_ENV,
REALM_ENV,
HEADER_ENV,
Arguments,
DEFAULT_HOSTNAME,
DEFAULT_PORT,
)
from apache_polaris.cli.options.option_tree import Argument
from apache_polaris.sdk.management import ApiClient, Configuration


def _load_profiles() -> Dict[str, str]:
def _load_profiles() -> Dict[str, Dict[str, Any]]:
if not os.path.exists(CONFIG_FILE):
return {}
with open(CONFIG_FILE, "r") as f:
Expand All @@ -51,14 +51,15 @@ def __init__(self, options: Namespace):
self.access_token = options.access_token

@cached_property
def profile(self) -> Dict[str, str]:
profile = {}
def profile(self) -> Dict[str, Any]:
profile: Dict[str, Any] = {}
client_profile = self.options.profile or os.getenv(CLIENT_PROFILE_ENV)
if client_profile:
profiles = _load_profiles()
profile = profiles.get(client_profile)
if not profile:
loaded_profile = profiles.get(client_profile)
if loaded_profile is None:
raise Exception(f"Polaris profile {client_profile} not found")
profile = loaded_profile
return profile

@cached_property
Expand Down Expand Up @@ -87,34 +88,34 @@ def catalog_url(self) -> str:
@cached_property
def client_id(self) -> Optional[str]:
return (
self.options.client_id
or os.getenv(CLIENT_ID_ENV)
or self.profile.get(Arguments.CLIENT_ID)
self.options.client_id
or os.getenv(CLIENT_ID_ENV)
or self.profile.get(Arguments.CLIENT_ID)
)

@cached_property
def client_secret(self) -> Optional[str]:
return (
self.options.client_secret
or os.getenv(CLIENT_SECRET_ENV)
or self.profile.get(Arguments.CLIENT_SECRET)
self.options.client_secret
or os.getenv(CLIENT_SECRET_ENV)
or self.profile.get(Arguments.CLIENT_SECRET)
)

@cached_property
def realm(self) -> Optional[str]:
realms = (
self.options.realm
or os.getenv(REALM_ENV)
or self.profile.get(Arguments.REALM)
self.options.realm
or os.getenv(REALM_ENV)
or self.profile.get(Arguments.REALM)
)
return realms

@cached_property
def header(self) -> Optional[str]:
return (
self.options.header
or os.getenv(HEADER_ENV)
or self.profile.get(Arguments.HEADER)
self.options.header
or os.getenv(HEADER_ENV)
or self.profile.get(Arguments.HEADER)
)


Expand All @@ -123,7 +124,7 @@ def __init__(self, options: Namespace, *, direct_authentication: bool = False):
self.conf = BuilderConfig(options)
self.direct_auth_enabled = direct_authentication

def _get_token(self):
def _get_token(self) -> str:
header_params = {"Content-Type": "application/x-www-form-urlencoded"}
if self.conf.header and self.conf.realm:
header_params[self.conf.header] = self.conf.realm
Expand All @@ -148,7 +149,9 @@ def _get_token(self):

def _build(self) -> ApiClient:
has_access_token = self.conf.access_token is not None
has_client_secret = self.conf.client_id is not None and self.conf.client_secret is not None
has_client_secret = (
self.conf.client_id is not None and self.conf.client_secret is not None
)
if has_access_token and (self.conf.client_id or self.conf.client_secret):
raise Exception(
f"Please provide credentials via either {Argument.to_flag_name(Arguments.CLIENT_ID)} &"
Expand Down
35 changes: 25 additions & 10 deletions client/python/apache_polaris/cli/command/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#
import argparse
from abc import ABC
from typing import Callable, Optional, Any

from apache_polaris.cli.constants import Commands, Arguments
from apache_polaris.cli.options.parser import Parser
Expand All @@ -33,7 +34,7 @@ class Command(ABC):

@staticmethod
def from_options(options: argparse.Namespace) -> "Command":
def options_get(key, f=lambda x: x):
def options_get(key: str, f: Callable[[Any], Any] = lambda x: x) -> Any:
return f(getattr(options, key)) if hasattr(options, key) else None

properties = Parser.parse_properties(options_get(Arguments.PROPERTY))
Expand All @@ -42,7 +43,7 @@ def options_get(key, f=lambda x: x):
catalog_client_scopes = options_get(Arguments.CATALOG_CLIENT_SCOPE)
parameters = Parser.parse_properties(options_get(Arguments.PARAMETERS))

command = None
command: Optional[Command] = None
if options.command == Commands.CATALOGS:
from apache_polaris.cli.command.catalogs import CatalogsCommand

Expand All @@ -65,8 +66,12 @@ def options_get(key, f=lambda x: x):
set_properties={} if set_properties is None else set_properties,
hadoop_warehouse=options_get(Arguments.HADOOP_WAREHOUSE),
hive_warehouse=options_get(Arguments.HIVE_WAREHOUSE),
iceberg_remote_catalog_name=options_get(Arguments.ICEBERG_REMOTE_CATALOG_NAME),
remove_properties=[] if remove_properties is None else remove_properties,
iceberg_remote_catalog_name=options_get(
Arguments.ICEBERG_REMOTE_CATALOG_NAME
),
remove_properties=[]
if remove_properties is None
else remove_properties,
endpoint=options_get(Arguments.ENDPOINT),
endpoint_internal=options_get(Arguments.ENDPOINT_INTERNAL),
sts_endpoint=options_get(Arguments.STS_ENDPOINT),
Expand All @@ -75,20 +80,30 @@ def options_get(key, f=lambda x: x):
current_kms_key=options_get(Arguments.KMS_KEY_CURRENT),
allowed_kms_keys=options_get(Arguments.KMS_KEY_ALLOWED),
catalog_connection_type=options_get(Arguments.CATALOG_CONNECTION_TYPE),
catalog_authentication_type=options_get(Arguments.CATALOG_AUTHENTICATION_TYPE),
catalog_service_identity_type=options_get(Arguments.CATALOG_SERVICE_IDENTITY_TYPE),
catalog_service_identity_iam_arn=options_get(Arguments.CATALOG_SERVICE_IDENTITY_IAM_ARN),
catalog_authentication_type=options_get(
Arguments.CATALOG_AUTHENTICATION_TYPE
),
catalog_service_identity_type=options_get(
Arguments.CATALOG_SERVICE_IDENTITY_TYPE
),
catalog_service_identity_iam_arn=options_get(
Arguments.CATALOG_SERVICE_IDENTITY_IAM_ARN
),
catalog_uri=options_get(Arguments.CATALOG_URI),
catalog_token_uri=options_get(Arguments.CATALOG_TOKEN_URI),
catalog_client_id=options_get(Arguments.CATALOG_CLIENT_ID),
catalog_client_secret=options_get(Arguments.CATALOG_CLIENT_SECRET),
catalog_client_scopes=[] if catalog_client_scopes is None else catalog_client_scopes,
catalog_client_scopes=[]
if catalog_client_scopes is None
else catalog_client_scopes,
catalog_bearer_token=options_get(Arguments.CATALOG_BEARER_TOKEN),
catalog_role_arn=options_get(Arguments.CATALOG_ROLE_ARN),
catalog_role_session_name=options_get(Arguments.CATALOG_ROLE_SESSION_NAME),
catalog_role_session_name=options_get(
Arguments.CATALOG_ROLE_SESSION_NAME
),
catalog_external_id=options_get(Arguments.CATALOG_EXTERNAL_ID),
catalog_signing_region=options_get(Arguments.CATALOG_SIGNING_REGION),
catalog_signing_name=options_get(Arguments.CATALOG_SIGNING_NAME)
catalog_signing_name=options_get(Arguments.CATALOG_SIGNING_NAME),
)
elif options.command == Commands.PRINCIPALS:
from apache_polaris.cli.command.principals import PrincipalsCommand
Expand Down
2 changes: 1 addition & 1 deletion client/python/apache_polaris/cli/command/catalog_roles.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class CatalogRolesCommand(Command):
set_properties: Dict[str, StrictStr]
remove_properties: List[str]

def validate(self):
def validate(self) -> None:
if not self.catalog_name:
raise Exception(
f"Missing required argument: {Argument.to_flag_name(Arguments.CATALOG)}"
Expand Down
Loading