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
6 changes: 5 additions & 1 deletion src/fleet/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -168,4 +168,8 @@ Release History

1.8.2
++++++
* Fix fleet namespace get-credentials command with fleet member parameter.
* Fix fleet namespace get-credentials command with fleet member parameter.

1.8.3
++++++
* Add automatic kubelogin conversion to Azure CLI authentication for fleet get-credentials command.
7 changes: 6 additions & 1 deletion src/fleet/azext_fleet/_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,17 @@
logger = get_logger(__name__)


def is_stdout_path(path):
"""Check if the path represents stdout."""
return path == "-"


def print_or_merge_credentials(path, kubeconfig, overwrite_existing, context_name):
"""Merge an unencrypted kubeconfig into the file at the specified path, or print it to
stdout if the path is "-".
"""
# Special case for printing to stdout
if path == "-":
if is_stdout_path(path):
print(kubeconfig)
return

Expand Down
1 change: 1 addition & 0 deletions src/fleet/azext_fleet/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def load_arguments(self, _):
c.argument('context_name', options_list=['--context'], help='If specified, overwrite the default context name.')
c.argument('path', options_list=['--file', '-f'], type=file_type, completer=FilesCompleter(),
default=os.path.join(os.path.expanduser('~'), '.kube', 'config'))
c.ignore('skip_kubelogin_conversion') # Internal parameter, not exposed to users

with self.argument_context('fleet member') as c:
c.argument('name', options_list=['--name', '-n'], help='Specify the fleet member name.')
Expand Down
56 changes: 53 additions & 3 deletions src/fleet/azext_fleet/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
# --------------------------------------------------------------------------------------------

import os
import yaml
import shutil
import subprocess
import tempfile
import yaml

from knack.log import get_logger
from knack.util import CLIError
Expand All @@ -20,6 +22,7 @@
from azext_fleet._helpers import is_rp_registered, print_or_merge_credentials
from azext_fleet._helpers import assign_network_contributor_role_to_subnet
from azext_fleet._helpers import get_msi_object_id
from azext_fleet._helpers import is_stdout_path
from azext_fleet.constants import UPGRADE_TYPE_CONTROLPLANEONLY
from azext_fleet.constants import UPGRADE_TYPE_FULL
from azext_fleet.constants import UPGRADE_TYPE_NODEIMAGEONLY
Expand Down Expand Up @@ -218,14 +221,52 @@ def delete_fleet(cmd, # pylint: disable=unused-argument
return sdk_no_wait(no_wait, client.begin_delete, resource_group_name, name, polling_interval=5)


def _convert_kubeconfig_to_azurecli(path):
"""
Convert kubeconfig to use Azure CLI authentication if it uses devicecode.

Args:
path: Path to the kubeconfig file to convert
"""
# Skip conversion if path is stdout
if is_stdout_path(path):
return

if shutil.which("kubelogin"):
try:
subprocess.run(
["kubelogin", "convert-kubeconfig", "-l", "azurecli", "--kubeconfig", path],
check=True,
capture_output=True,
text=True,
timeout=60,
)
logger.warning("Converted kubeconfig to use Azure CLI authentication.")
except subprocess.CalledProcessError as e:
logger.warning("Failed to convert kubeconfig with kubelogin: %s", str(e))
except subprocess.TimeoutExpired as e:
logger.warning("kubelogin command timed out: %s", str(e))
except Exception as e: # pylint: disable=broad-except
logger.warning("Error running kubelogin: %s", str(e))
else:
logger.warning(
"The fleet hub cluster kubeconfig requires kubelogin. "
"Please install kubelogin from https://github.com/Azure/kubelogin or run "
"'az aks install-cli' to install both kubectl and kubelogin. "
"After installing kubelogin, rerun 'az fleet get-credentials' and the "
"kubeconfig will be converted automatically."
)


def get_credentials(cmd,
client,
resource_group_name,
name,
path=os.path.join(os.path.expanduser('~'), '.kube', 'config'),
overwrite_existing=False,
context_name=None,
member_name=None):
member_name=None,
skip_kubelogin_conversion=False):

# If a member name is given, we use the cluster resource ID from the fleet member
# to get that member cluster's credentials
Expand Down Expand Up @@ -273,6 +314,11 @@ def get_credentials(cmd,
try:
kubeconfig = credential_results.kubeconfigs[0].value.decode(encoding='UTF-8')
print_or_merge_credentials(path, kubeconfig, overwrite_existing, context_name)
# Fleet hub is always RBAC-enabled and should convert it with kubelogin so that
# user doesn't have to manually run kubelogin convert-kubeconfig -l azurecli
# every time after az fleet get-credentials
if not skip_kubelogin_conversion:
_convert_kubeconfig_to_azurecli(path)
except (IndexError, ValueError) as exc:
raise CLIError("Fail to find kubeconfig file.") from exc

Expand Down Expand Up @@ -985,7 +1031,8 @@ def get_namespace_credentials(cmd,
path=temp_file.name,
overwrite_existing=overwrite_existing,
context_name=context_name,
member_name=member_name
member_name=member_name,
skip_kubelogin_conversion=True # Skip here, we'll convert after namespace modification
)

with open(temp_file.name, 'r', encoding='utf-8') as f:
Expand All @@ -998,3 +1045,6 @@ def get_namespace_credentials(cmd,
modified_kubeconfig = yaml.dump(kubeconfig, default_flow_style=False)
print_or_merge_credentials(path, modified_kubeconfig, overwrite_existing, context_name)
print(f"Default namespace set to '{managed_namespace_name}' for context '{kubeconfig.get('current-context')}'")

# Apply kubelogin conversion to the final file after namespace modification
_convert_kubeconfig_to_azurecli(path)
2,613 changes: 1,202 additions & 1,411 deletions src/fleet/azext_fleet/tests/latest/recordings/test_fleet_hubful.yaml

Large diffs are not rendered by default.

Loading
Loading