Skip to content
90 changes: 81 additions & 9 deletions src/containerapp/azext_containerapp/_arc_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -548,21 +548,16 @@ def create_openshift_custom_coredns_resources(kube_client, namespace=OPENSHIFT_D
raise CLIError(f"An error occurred while creating custom CoreDNS resources: {str(e)}")


def patch_openshift_dns_operator(kube_client, domain):
def patch_openshift_dns_operator(kube_client, domain, original_folder=None):
try:
logger.info("Patching OpenShift DNS operator to add custom resolver")

# Fetch the existing DNS operator configuration
custom_objects_api = client.CustomObjectsApi(kube_client)

dns_operator_config = custom_objects_api.get_cluster_custom_object(
group="operator.openshift.io",
version="v1",
plural="dnses",
name="default"
)

coredns_service = client.CoreV1Api(kube_client).read_namespaced_service(name=CUSTOM_CORE_DNS, namespace=OPENSHIFT_DNS);
dns_operator_config = get_and_save_openshift_dns_operator_config(kube_client, original_folder)

coredns_service = client.CoreV1Api(kube_client).read_namespaced_service(name=CUSTOM_CORE_DNS, namespace=OPENSHIFT_DNS)

# Add the custom resolver to the DNS operator configuration
servers = dns_operator_config.get("spec", {}).get("servers", [])
Expand Down Expand Up @@ -620,3 +615,80 @@ def extract_domain_from_configmap(kube_client, resource_name=CUSTOM_CORE_DNS, na
except Exception as e:
logger.error(f"Failed to extract domain from configmap: {str(e)}")
return None


def get_and_save_openshift_dns_operator_config(kube_client, folder=None):
try:
custom_objects_api = client.CustomObjectsApi(kube_client)
dns_operator_config = custom_objects_api.get_cluster_custom_object(
group="operator.openshift.io",
version="v1",
plural="dnses",
name="default"
)

if folder is not None:
filepath = os.path.join(folder, "openshift-dns-operator-config.json")
with open(filepath, "w") as f:
f.write(json.dumps(dns_operator_config, indent=2))
logger.info(f"OpenShift DNS operator configuration saved to {filepath}")

return dns_operator_config
except Exception as e:
raise ValidationError(f"Failed to retrieve OpenShift DNS operator configuration: {str(e)}")


def restart_openshift_dns_pods(kube_client):
try:
label_selector = "dns.operator.openshift.io/daemonset-dns=default"

# Get the list of pods first to show what will be deleted
core_v1_api = client.CoreV1Api(kube_client)
pods = core_v1_api.list_namespaced_pod(
namespace=OPENSHIFT_DNS,
label_selector=label_selector
)

if not pods.items:
logger.info(f"No DNS pods found in namespace '{OPENSHIFT_DNS}' with label '{label_selector}'")
return

# Show user what pods will be deleted
pod_names = [pod.metadata.name for pod in pods.items]
logger.info(f"Found {len(pod_names)} DNS pods to restart:")
for pod_name in pod_names:
logger.info(f" - {pod_name}")

try:
response = input(f"The DNS pods in namespace '{OPENSHIFT_DNS}' needs to be restarted. Are you sure you want to proceed? (y/n): ")
confirmed = response.lower() in ['y', 'yes']
except (EOFError, KeyboardInterrupt):
logger.info("Operation cancelled by user")
return

if not confirmed:
logger.info("Operation cancelled by user")
return

# Delete the pods
logger.info(f"Deleting DNS pods in namespace '{OPENSHIFT_DNS}'...")
delete_options = client.V1DeleteOptions(
propagation_policy='Foreground',
grace_period_seconds=30
)

core_v1_api.delete_collection_namespaced_pod(
namespace=OPENSHIFT_DNS,
label_selector=label_selector,
body=delete_options
)

logger.info("Successfully initiated deletion of DNS pods. DaemonSet will recreate them automatically.")

except client.exceptions.ApiException as e:
if e.status == 404:
logger.warning(f"Namespace '{OPENSHIFT_DNS}' or pods with label '{label_selector}' not found")
else:
raise CLIError(f"Failed to restart DNS pods: {str(e)}")
except Exception as e:
raise CLIError(f"An error occurred while restarting DNS pods: {str(e)}")
10 changes: 7 additions & 3 deletions src/containerapp/azext_containerapp/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@
from ._arc_utils import (extract_domain_from_configmap, get_core_dns_deployment, get_core_dns_configmap, backup_custom_core_dns_configmap,
replace_configmap, replace_deployment, delete_configmap, patch_coredns,
create_folder, create_sub_folder,
check_kube_connection, create_kube_client)
check_kube_connection, create_kube_client, restart_openshift_dns_pods)

from ._constants import (AKS_AZURE_LOCAL_DISTRO, CONTAINER_APPS_RP,
NAME_INVALID, NAME_ALREADY_EXISTS, ACR_IMAGE_SUFFIX, DEV_POSTGRES_IMAGE, DEV_POSTGRES_SERVICE_TYPE,
Expand Down Expand Up @@ -2188,7 +2188,7 @@ def setup_core_dns(cmd, distro=None, kube_config=None, kube_context=None, skip_s

kube_client = create_kube_client(kube_config, kube_context, skip_ssl_verification)

if distro == AKS_AZURE_LOCAL_DISTRO or distro is None:
if distro == AKS_AZURE_LOCAL_DISTRO:
# backup original deployment and configmap
logger.info("Backup existing coredns deployment and configmap")
original_coredns_deployment = get_core_dns_deployment(kube_client, original_folder)
Expand Down Expand Up @@ -2276,12 +2276,16 @@ def setup_core_dns(cmd, distro=None, kube_config=None, kube_context=None, skip_s
domain = extract_domain_from_configmap(kube_client)

# Patch the OpenShift DNS operator to use the custom CoreDNS service
patch_openshift_dns_operator(kube_client, domain)
patch_openshift_dns_operator(kube_client, domain, original_folder)

restart_openshift_dns_pods(kube_client)

logger.info("Successfully set up CoreDNS for OpenShift")
except Exception as e:
logger.error(f"Failed to setup CoreDNS for OpenShift. {e}")
raise ValidationError("Failed to setup CoreDNS for OpenShift distro")
else:
raise ValidationError(f"Unsupported distro: {distro}. Supported distros are: {AKS_AZURE_LOCAL_DISTRO}, {OPENSHIFT_DISTRO}.")


def init_dapr_components(cmd, resource_group_name, environment_name, statestore="redis", pubsub="redis"):
Expand Down
Loading