Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
75b1ffd
initial changes
hmtosi Mar 16, 2026
dea5ae8
update to include all Client parameters
hmtosi Mar 17, 2026
98b09be
remove UI components
hmtosi Mar 17, 2026
3181b0b
remove ui components
hmtosi Mar 17, 2026
0a7b6ce
remove test until functionality is confirmed
hmtosi Mar 17, 2026
64f7682
Merge branch 'main' into issue-680-configure-server
hmtosi Mar 17, 2026
2f35252
Merge branch 'main' into issue-680-configure-server
hmtosi Mar 18, 2026
ce8b94e
finish removing ui functionality
hmtosi Mar 18, 2026
2a5525e
add unit test for kfp server config
hmtosi Mar 18, 2026
a99999d
update paramter descriptions
hmtosi Mar 18, 2026
a406305
Merge branch 'main' into issue-680-configure-server
hmtosi Mar 20, 2026
9b77459
fix linting
hmtosi Mar 20, 2026
0ea0c75
change to factory architecture
hmtosi Mar 20, 2026
469368b
add factory to git tracking
hmtosi Mar 20, 2026
3633771
update documentation
hmtosi Mar 20, 2026
4a1370b
update so e2e passes
hmtosi Mar 20, 2026
808c32f
Merge branch 'main' into issue-680-configure-server
hmtosi Mar 20, 2026
92b7567
Merge branch 'kubeflow:main' into issue-680-configure-server
hmtosi Mar 24, 2026
136e2dd
update default config path
hmtosi Mar 24, 2026
0500397
update kfp authentication to allow credentials
hmtosi Mar 24, 2026
57e7e12
add authenticator file
hmtosi Mar 24, 2026
33cd1e3
Merge branch 'kubeflow:main' into issue-680-configure-server
hmtosi Mar 25, 2026
5d3ac89
Fix circular import
jesuino Mar 25, 2026
351638b
Merge pull request #2 from jesuino/credentials_circular_import
hmtosi Mar 25, 2026
f41d494
Apply suggestion from @Copilot
hmtosi Mar 25, 2026
192cded
add config env var so it can be explicitly set
hmtosi Mar 25, 2026
1a80fe5
add atomic rename suggested by copilot
hmtosi Mar 26, 2026
59703ae
update documentation
hmtosi Mar 26, 2026
3ba3ece
Merge branch 'kubeflow:main' into issue-680-configure-server
hmtosi Apr 1, 2026
481266c
separate configuration (persisted) from credentials (resolved at runt…
hmtosi Apr 1, 2026
bec5c32
prevent tokens from being saved to disk
hmtosi Apr 2, 2026
bd43a9b
Merge branch 'kubeflow:main' into issue-680-configure-server
hmtosi Apr 3, 2026
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
52 changes: 50 additions & 2 deletions kale/common/kfputils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import kfp

from kale.common import podutils, utils, workflowutils
from kale.config import kfp_server_config

KFP_RUN_ID_LABEL_KEY = "pipeline/runid"
KFP_RUN_NAME_ANNOTATION_KEY = "pipelines.kubeflow.org/run_name"
Expand All @@ -40,8 +41,55 @@
log = logging.getLogger(__name__)


def _get_kfp_client(host=None, namespace: str = "kubeflow"):
return kfp.Client(host=host, namespace=namespace)
def _get_kfp_client(
host=None,
cookies: str = None,
credentials=None,
existing_token: str = None,
namespace: str = None,
ssl_ca_cert: str = None,
):
"""Get a KFP client with configuration.

Loads saved configuration and allows parameter overrides.
Explicit parameters take precedence over saved config.

Args:
host: KFP API server host
cookies: Authentication cookies
credentials: Service account credentials for authentication
existing_token: Bearer token for authentication
namespace: Kubernetes namespace
ssl_ca_cert: Path to CA certificate file for SSL verification

Returns:
kfp.Client instance
"""
# Load saved configuration
config = kfp_server_config.load_config()

# Use parameter if provided, otherwise fall back to config
if host is None:
host = config.host
if cookies is None:
cookies = config.cookies
if credentials is None:
credentials = config.credentials
if existing_token is None:
existing_token = config.existing_token
if namespace is None:
namespace = config.namespace or "kubeflow"
if ssl_ca_cert is None:
ssl_ca_cert = config.ssl_ca_cert

return kfp.Client(
host=host,
cookies=cookies,
credentials=credentials,
existing_token=existing_token,
namespace=namespace,
ssl_ca_cert=ssl_ca_cert,
)


def get_pipeline_id(pipeline_name: str, host: str = None) -> str:
Expand Down
84 changes: 84 additions & 0 deletions kale/config/kfp_server_config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Copyright 2026 The Kubeflow Authors.
#
# Licensed 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 json
import logging
import os
from typing import Any

from kale.config.config import Config, Field

log = logging.getLogger(__name__)


class KFPServerConfig(Config):
"""Configuration for KFP server connection."""

host = Field(type=str, default=None)
cookies = Field(type=str, default=None)
credentials = Field(type=str, default=None)
existing_token = Field(type=str, default=None)
namespace = Field(type=str, default="kubeflow")
ssl_ca_cert = Field(type=str, default=None)


def get_config_path() -> str:
"""Get the path to the KFP server configuration file."""
kale_dir = os.path.join(os.path.expanduser("~"), ".kale")
return os.path.join(kale_dir, "kfp_server_config.json")


def load_config() -> KFPServerConfig:
"""Load KFP server configuration from disk.

Returns:
KFPServerConfig instance. If no config file exists, returns default config.
"""
config_path = get_config_path()
if not os.path.exists(config_path):
log.debug("No KFP server config found at %s, using defaults", config_path)
return KFPServerConfig()

try:
with open(config_path) as f:
config_dict = json.load(f)
log.info("Loaded KFP server config from %s", config_path)
return KFPServerConfig(**config_dict)
except (json.JSONDecodeError, OSError) as e:
log.warning("Failed to load KFP server config from %s: %s. Using defaults.", config_path, e)
return KFPServerConfig()


def save_config(config: KFPServerConfig | dict[str, Any]) -> None:
"""Save KFP server configuration to disk.

Args:
config: KFPServerConfig instance or dict with config values
"""
if isinstance(config, dict):
config = KFPServerConfig(**config)

config_path = get_config_path()
kale_dir = os.path.dirname(config_path)

# Create .kale directory if it doesn't exist
os.makedirs(kale_dir, exist_ok=True)

config_dict = config.to_dict()
with open(config_path, "w") as f:
json.dump(config_dict, f, indent=2)

# Set restrictive permissions for security (only owner can read/write)
os.chmod(config_path, 0o600)
log.info("Saved KFP server config to %s", config_path)
4 changes: 2 additions & 2 deletions kale/rpc/kfp.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import kfp

from kale.common import kfputils


def _get_client(host=None):
return kfp.Client()
"""Get a KFP client using saved configuration."""
return kfputils._get_kfp_client(host=host)


def ping(request):
Expand Down
Loading
Loading