profile_manager.py•3.41 kB
"""
Profile management for OCI configuration.
Handles reading available profiles from ~/.oci/config and managing
the currently active profile for dynamic profile switching.
"""
import os
from typing import Dict, List, Optional
from pathlib import Path
import configparser
import logging
logger = logging.getLogger(__name__)
# Default OCI config location
DEFAULT_OCI_CONFIG_PATH = os.path.expanduser("~/.oci/config")
def get_oci_config_path() -> str:
    """
    Get the path to the OCI config file.
    Returns:
        Path to the OCI config file (defaults to ~/.oci/config)
    """
    return os.environ.get("OCI_CONFIG_FILE", DEFAULT_OCI_CONFIG_PATH)
def list_available_profiles() -> List[Dict[str, str]]:
    """
    List all available profiles from the OCI config file.
    Returns:
        List of dictionaries containing profile information:
        [
            {
                "name": "DEFAULT",
                "user": "ocid1.user...",
                "tenancy": "ocid1.tenancy...",
                "region": "us-ashburn-1",
                "fingerprint": "aa:bb:cc:..."
            },
            ...
        ]
    Raises:
        FileNotFoundError: If OCI config file doesn't exist
        Exception: If config file cannot be parsed
    """
    config_path = get_oci_config_path()
    if not os.path.exists(config_path):
        raise FileNotFoundError(
            f"OCI config file not found at {config_path}. "
            f"Please create it or set OCI_CONFIG_FILE environment variable."
        )
    try:
        config = configparser.ConfigParser()
        config.read(config_path)
        profiles = []
        for section in config.sections():
            profile_info = {
                "name": section,
                "user": config.get(section, "user", fallback="N/A"),
                "tenancy": config.get(section, "tenancy", fallback="N/A"),
                "region": config.get(section, "region", fallback="N/A"),
                "fingerprint": config.get(section, "fingerprint", fallback="N/A"),
            }
            profiles.append(profile_info)
        logger.info(f"Found {len(profiles)} profiles in {config_path}")
        return profiles
    except Exception as e:
        logger.exception(f"Error parsing OCI config file: {e}")
        raise Exception(f"Failed to parse OCI config file at {config_path}: {str(e)}")
def validate_profile_exists(profile_name: str) -> bool:
    """
    Check if a profile exists in the OCI config file.
    Args:
        profile_name: Name of the profile to check
    Returns:
        True if profile exists, False otherwise
    """
    try:
        profiles = list_available_profiles()
        return any(p["name"] == profile_name for p in profiles)
    except Exception as e:
        logger.error(f"Error validating profile: {e}")
        return False
def get_profile_info(profile_name: str) -> Optional[Dict[str, str]]:
    """
    Get detailed information about a specific profile.
    Args:
        profile_name: Name of the profile
    Returns:
        Dictionary with profile information, or None if not found
    """
    try:
        profiles = list_available_profiles()
        for profile in profiles:
            if profile["name"] == profile_name:
                return profile
        return None
    except Exception as e:
        logger.error(f"Error getting profile info: {e}")
        return None