Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
27e6843
first draft
Jun 20, 2025
5c706c2
fixed error
Jun 20, 2025
793d69e
lines too long fix
Jun 20, 2025
49af9a4
linting fixes
Jun 20, 2025
33fbffa
release history
Jun 20, 2025
d6c5548
logic fixes
Jun 20, 2025
cc19cbe
pr feedback
Jun 20, 2025
8abdc40
PR comments
Jun 24, 2025
0abae14
linting fixes
Jun 24, 2025
b29f6e6
fixed the linting issue
Jun 25, 2025
bbae6cb
fixes for PR comments
Jun 25, 2025
6fe79dc
minor changes
Jun 25, 2025
087ebce
adding tests and minor fixes
Jun 26, 2025
3dd272f
Update src/aks-preview/azext_aks_preview/tests/latest/test_aks_comman…
anushkasingh16 Jun 26, 2025
e67b2ac
linting + sytax error
Jun 26, 2025
099c683
Merge branch 'anushkasingh/local-dns-cli-extension' of https://github…
Jun 26, 2025
de8a20c
style fixes
Jun 26, 2025
6115a07
linting
Jun 26, 2025
1061995
passing the file name
Jun 26, 2025
1240e1b
header placement fix
Jun 26, 2025
89f9b32
version should be higher than 1.33
Jun 26, 2025
41e28fa
testing fixes
Jun 26, 2025
54e106a
version
Jun 27, 2025
8621d74
json parsing:
Jun 27, 2025
3b52ffb
spacing fix
Jun 27, 2025
8a19986
json parsing
Jun 27, 2025
b61e90a
parsing
Jun 27, 2025
483ecb3
json parsing fixes
Jun 27, 2025
b988309
test changes
Jun 27, 2025
80b8bb4
test data matching
Jun 27, 2025
e4a026c
testing data
Jun 27, 2025
2e2f161
test logic changes
Jun 27, 2025
a73f8b7
Changed serveStale to immediate for ForceTCP
Jun 27, 2025
947a4e0
Merge branch 'main' into anushkasingh/local-dns-cli-extension
Jul 10, 2025
d35c002
history file fix
Jul 10, 2025
e2b87d8
profile name fixes
Jul 10, 2025
8caf2db
Revert "profile name fixes"
Jul 10, 2025
0bbb49e
parsing fix
Jul 11, 2025
dd8ccd1
syntax
Jul 11, 2025
a0ab576
seralization attempt
Jul 11, 2025
cf1b36d
added logging for testing
Jul 11, 2025
62f4742
model initalization fix
Jul 14, 2025
77adc7f
more pasrsing changes +printing
Jul 14, 2025
2393e59
more parsing
Jul 15, 2025
8161ddd
reattempted
Jul 15, 2025
582935c
Revert "reattempted"
Jul 15, 2025
30b12b7
parsing for update localdns profile
Jul 15, 2025
a2e0f91
syntax fix
Jul 15, 2025
6189a28
update function
Jul 15, 2025
72751ff
moved common logic to _apply_localdns_profile
Jul 15, 2025
65db120
Revert "moved common logic to _apply_localdns_profile"
Jul 15, 2025
e7428a9
duplicated parsing
Jul 15, 2025
e6aab99
Merge branch 'main' into anushkasingh/local-dns-cli-extension
Jul 16, 2025
ea29a7f
removed print statements
Jul 16, 2025
197055e
style fixes
Jul 16, 2025
ad45bfc
recordings latest
Jul 16, 2025
4038391
adding mocks for localdns update command
Jul 17, 2025
86ad9f7
Merge branch 'main' into anushkasingh/local-dns-cli-extension
Jul 17, 2025
6747889
PR comments
Jul 17, 2025
a21d7ea
Update src/aks-preview/HISTORY.rst
anushkasingh16 Jul 18, 2025
a7b4c13
Update src/aks-preview/HISTORY.rst
anushkasingh16 Jul 18, 2025
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
7 changes: 6 additions & 1 deletion src/aks-preview/HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ Pending
+++++++
* Add support for `ManagedSystem` Agent Pool Mode.

18.0.0b19
+++++++
- Add `--localdns-config` to `az aks nodepool add` and to `az aks nodepool update` to support configuring a local DNS profile for agent pools.


18.0.0b18
+++++++
* Add validation error when neither --location or --cluster and --resource-group-name are specified for az extension type list or az extension type version list
Expand Down Expand Up @@ -1907,4 +1912,4 @@ Pending
+++++

* new feature `enable-cluster-autoscaler`
* default agentType is VMSS
* default agentType is VMSS
6 changes: 6 additions & 0 deletions src/aks-preview/azext_aks_preview/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -2048,6 +2048,9 @@
- name: --undrainable-node-behavior
type: string
short-summary: Define the behavior for undrainable nodes during upgrade. The value should be "Cordon" or "Schedule". The default value is "Schedule".
- name: --localdns-config
type: string
short-summary: Set the localDNS Profile for a nodepool with a JSON config file.
examples:
- name: Create a nodepool in an existing AKS cluster with ephemeral os enabled.
text: az aks nodepool add -g MyResourceGroup -n nodepool1 --cluster-name MyManagedCluster --node-osdisk-type Ephemeral --node-osdisk-size 48
Expand Down Expand Up @@ -2223,6 +2226,9 @@
- name: --undrainable-node-behavior
type: string
short-summary: Define the behavior for undrainable nodes during upgrade. The value should be "Cordon" or "Schedule". The default value is "Schedule".
- name: --localdns-config
type: string
short-summary: Set the localDNS Profile for a nodepool with a JSON config file.
examples:
- name: Reconcile the nodepool back to its current state.
text: az aks nodepool update -g MyResourceGroup -n nodepool1 --cluster-name MyManagedCluster
Expand Down
10 changes: 10 additions & 0 deletions src/aks-preview/azext_aks_preview/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -1772,6 +1772,11 @@ def load_arguments(self, _):
)
# virtual machines
c.argument("vm_sizes", is_preview=True)
# local DNS
c.argument(
'localdns_config',
help='Path to a JSON file to configure the local DNS profile for a new nodepool.'
)

with self.argument_context("aks nodepool update") as c:
c.argument(
Expand Down Expand Up @@ -1864,6 +1869,11 @@ def load_arguments(self, _):
"disable_fips_image",
action="store_true"
)
# local DNS
c.argument(
'localdns_config',
help='Path to a JSON file to configure the local DNS profile for an existing nodepool.',
)

with self.argument_context("aks nodepool upgrade") as c:
c.argument("max_surge", validator=validate_max_surge)
Expand Down
118 changes: 118 additions & 0 deletions src/aks-preview/azext_aks_preview/agentpool_decorator.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import base64
import os
from azure.cli.core.util import get_file_json
from types import SimpleNamespace
from typing import Dict, TypeVar, Union, List

Expand Down Expand Up @@ -810,6 +811,30 @@ def get_disable_fips_image(self) -> bool:
# read the original value passed by the command
return self.raw_param.get("disable_fips_image")

def get_localdns_config(self):
return self.raw_param.get("localdns_config")

def get_localdns_profile(self):
"""
Returns the local DNS profile dict if set, or None.
Only supports loading from --localdns-config (JSON file).
Assumes the input is always a string filename.
"""
config = self.get_localdns_config()
if config:
if not isinstance(config, str) or not os.path.isfile(config):
raise InvalidArgumentValueError(
f"{config} is not a valid file, or not accessible."
)
profile = get_file_json(config)
if not isinstance(profile, dict):
raise InvalidArgumentValueError(
f"Error reading local DNS config from {config}. "
"Please provide a valid JSON file."
)
return profile
return None


class AKSPreviewAgentPoolAddDecorator(AKSAgentPoolAddDecorator):
def __init__(
Expand Down Expand Up @@ -1099,6 +1124,50 @@ def set_up_managed_system_mode(self, agentpool: AgentPool) -> AgentPool:

return agentpool

def set_up_localdns_profile(self, agentpool: AgentPool) -> AgentPool:
"""Set up local DNS profile for the AgentPool object if provided via --localdns-config."""
self._ensure_agentpool(agentpool)
localdns_profile = self.context.get_localdns_profile()
if localdns_profile is not None:
kube_dns_overrides = {}
vnet_dns_overrides = {}

def build_override(override_dict):
camel_to_snake_case = {
"queryLogging": "query_logging",
"protocol": "protocol",
"forwardDestination": "forward_destination",
"forwardPolicy": "forward_policy",
"maxConcurrent": "max_concurrent",
"cacheDurationInSeconds": "cache_duration_in_seconds",
"serveStaleDurationInSeconds": "serve_stale_duration_in_seconds",
"serveStale": "serve_stale",
}
valid_keys = set(camel_to_snake_case.values())
filtered = {}
for k, v in override_dict.items():
if k in camel_to_snake_case:
filtered[camel_to_snake_case[k]] = v
elif k in valid_keys:
filtered[k] = v
return self.models.LocalDNSOverride(**filtered)

# Build kubeDNSOverrides and vnetDNSOverrides from the localdns_profile
kube_overrides = localdns_profile.get("kubeDNSOverrides")
for key, value in kube_overrides.items():
kube_dns_overrides[key] = build_override(value)

vnet_overrides = localdns_profile.get("vnetDNSOverrides")
for key, value in vnet_overrides.items():
vnet_dns_overrides[key] = build_override(value)

agentpool.local_dns_profile = self.models.LocalDNSProfile(
mode=localdns_profile.get("mode"),
kube_dns_overrides=kube_dns_overrides,
vnet_dns_overrides=vnet_dns_overrides,
)
return agentpool

def construct_agentpool_profile_preview(self) -> AgentPool:
"""The overall controller used to construct the preview AgentPool profile.

Expand Down Expand Up @@ -1151,6 +1220,8 @@ def construct_agentpool_profile_preview(self) -> AgentPool:
agentpool = self.set_up_agentpool_gateway_profile(agentpool)
# set up virtual machines profile
agentpool = self.set_up_virtual_machines_profile(agentpool)
# set up local DNS profile
agentpool = self.set_up_localdns_profile(agentpool)
# DO NOT MOVE: keep this at the bottom, restore defaults
agentpool = self._restore_defaults_in_agentpool(agentpool)
return agentpool
Expand Down Expand Up @@ -1343,6 +1414,50 @@ def update_fips_image(self, agentpool: AgentPool) -> AgentPool:

return agentpool

def update_localdns_profile(self, agentpool: AgentPool) -> AgentPool:
"""Update local DNS profile for the AgentPool object if provided via --localdns-config."""
self._ensure_agentpool(agentpool)
localdns_profile = self.context.get_localdns_profile()
if localdns_profile is not None:
kube_dns_overrides = {}
vnet_dns_overrides = {}

def build_override(override_dict):
camel_to_snake_case = {
"queryLogging": "query_logging",
"protocol": "protocol",
"forwardDestination": "forward_destination",
"forwardPolicy": "forward_policy",
"maxConcurrent": "max_concurrent",
"cacheDurationInSeconds": "cache_duration_in_seconds",
"serveStaleDurationInSeconds": "serve_stale_duration_in_seconds",
"serveStale": "serve_stale",
}
valid_keys = set(camel_to_snake_case.values())
filtered = {}
for k, v in override_dict.items():
if k in camel_to_snake_case:
filtered[camel_to_snake_case[k]] = v
elif k in valid_keys:
filtered[k] = v
return self.models.LocalDNSOverride(**filtered)

# Build kubeDNSOverrides and vnetDNSOverrides from the localdns_profile
kube_overrides = localdns_profile.get("kubeDNSOverrides")
for key, value in kube_overrides.items():
kube_dns_overrides[key] = build_override(value)

vnet_overrides = localdns_profile.get("vnetDNSOverrides")
for key, value in vnet_overrides.items():
vnet_dns_overrides[key] = build_override(value)

agentpool.local_dns_profile = self.models.LocalDNSProfile(
mode=localdns_profile.get("mode"),
kube_dns_overrides=kube_dns_overrides,
vnet_dns_overrides=vnet_dns_overrides,
)
return agentpool

def update_agentpool_profile_preview(self, agentpools: List[AgentPool] = None) -> AgentPool:
"""The overall controller used to update the preview AgentPool profile.

Expand Down Expand Up @@ -1387,6 +1502,9 @@ def update_agentpool_profile_preview(self, agentpools: List[AgentPool] = None) -
# update ssh access
agentpool = self.update_ssh_access(agentpool)

# update local DNS profile
agentpool = self.update_localdns_profile(agentpool)

return agentpool

def update_upgrade_settings(self, agentpool: AgentPool) -> AgentPool:
Expand Down
4 changes: 4 additions & 0 deletions src/aks-preview/azext_aks_preview/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -1419,6 +1419,8 @@ def aks_agentpool_add(
gateway_prefix_size=None,
# virtualmachines
vm_sizes=None,
# local DNS
localdns_config=None,
):
# DO NOT MOVE: get all the original parameters and save them as a dictionary
raw_parameters = locals()
Expand Down Expand Up @@ -1486,6 +1488,8 @@ def aks_agentpool_update(
if_none_match=None,
enable_fips_image=False,
disable_fips_image=False,
# local DNS
localdns_config=None,
):
# DO NOT MOVE: get all the original parameters and save them as a dictionary
raw_parameters = locals()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"mode": "Required",
"kubeDNSOverrides": {
".": {
"cacheDurationInSeconds": 3600,
"forwardDestination": "ClusterCoreDNS",
"forwardPolicy": "Sequential",
"maxConcurrent": 1000,
"protocol": "PreferUDP",
"queryLogging": "Error",
"serveStale": "Verify",
"serveStaleDurationInSeconds": 3600
},
"cluster.local": {
"cacheDurationInSeconds": 3600,
"forwardDestination": "ClusterCoreDNS",
"forwardPolicy": "Sequential",
"maxConcurrent": 1000,
"protocol": "ForceTCP",
"queryLogging": "Error",
"serveStale": "Immediate",
"serveStaleDurationInSeconds": 3600
}
},
"vnetDNSOverrides": {
".": {
"cacheDurationInSeconds": 3600,
"forwardDestination": "VnetDNS",
"forwardPolicy": "Sequential",
"maxConcurrent": 1000,
"protocol": "PreferUDP",
"queryLogging": "Error",
"serveStale": "Verify",
"serveStaleDurationInSeconds": 3600
},
"cluster.local": {
"cacheDurationInSeconds": 3600,
"forwardDestination": "ClusterCoreDNS",
"forwardPolicy": "Sequential",
"maxConcurrent": 1000,
"protocol": "ForceTCP",
"queryLogging": "Error",
"serveStale": "Immediate",
"serveStaleDurationInSeconds": 3600
}
}
}
Loading
Loading