Skip to content

[AKS] az aks update --enable-azure-container-storage: ACStor configuration is silently misdetected because configurationSettings booleans are compared case-sensitively against "True" #33937

Description

@DanteMustCode

Describe the bug

az aks create/update's Azure Container Storage (ACStor) support reads the installed
extension's configurationSettings and compares boolean values case-sensitively
against the string "True".

Since k8s-extension 1.8.0 (released 2026-07-17, migrated to api-version 2025-03-01),
these values are persisted as lowercase true/false instead of "True"/"False".
Every one of those comparisons now silently evaluates to False.

The most damaging one is the gate at the top:

https://github.com/Azure/azure-cli/blob/dev/src/azure-cli/azure/cli/command_modules/acs/azurecontainerstorage/_helpers.py#L183

is_cli_operation_active = config_settings.get("global.cli.activeControl", "False") == "True"
if is_cli_operation_active:
    ...  # read real cluster config
else:
    # legacy fallback: assume all storage pool types active, defaults everywhere

global.cli.activeControl is now true, so is_cli_operation_active is always False
and the CLI unconditionally takes the legacy fallback branch. The returned
ephemeral_disk_volume_type stays at its default EphemeralVolumeOnly regardless of
what is actually installed on the cluster.

Note this fails silently — the vendored SDK keeps attribute-level backwards
compatibility via flattened properties, so extension.configuration_settings still
resolves; only the values changed shape.

Affected lines

All in src/azure-cli/azure/cli/command_modules/acs/azurecontainerstorage/:

File Lines
_helpers.py 183, 186, 189, 192, 195, 201, 277, 280

Affected settings: global.cli.activeControl, global.cli.storagePool.azureDisk.enabled,
global.cli.storagePool.elasticSan.enabled,
global.cli.storagePool.ephemeralDisk.nvme.enabled,
global.cli.storagePool.ephemeralDisk.temp.enabled,
global.cli.storagePool.ephemeralDisk.enableEphemeralBypassAnnotation,
csiDriverConfigs.local-csi-driver.enabled, csiDriverConfigs.azuresan-csi-driver.enabled.

Root cause of the value change

acstor_ops.py writes these settings as Python bool, not as strings:

https://github.com/Azure/azure-cli/blob/dev/src/azure-cli/azure/cli/command_modules/acs/azurecontainerstorage/acstor_ops.py#L155

config_settings.extend([
    {"global.cli.activeControl": True},
    {"global.cli.storagePool.azureDisk.enabled": azure_disk_enabled},
    ...
])

Under the old 2023-05-01 msrest model, configuration_settings was typed {str}, so
msrest coerced each value with str()"True". The new 2025-03-01 TypeSpec model
serializes the dict as-is → JSON true.

Reproduced with the two vendored SDKs directly:

# k8s-extension 1.7.0 (api-version 2023-05-01, msrest)
Serializer().serialize_data({"nvme.enabled": True}, "{str}")
# -> {'nvme.enabled': 'True'}

# k8s-extension 1.8.0 (api-version 2025-03-01, TypeSpec model_base)
json.dumps(dict(ExtensionProperties(configuration_settings={"nvme.enabled": True})))
# -> {"configurationSettings": {"nvme.enabled": true}}

So the write path and the read path have always been asymmetric (writes bool, reads
str); the SDK migration is what made them disagree.

Related command

az aks update

Errors

ERROR: Azure Container Storage is already configured with --ephemeral-disk-volume-type
value set to EphemeralVolumeOnly.

Issue script & Debug output

az extension add --upgrade --name k8s-extension     # picks up >= 1.8.0

az aks create -g <rg> -n <cluster> \
    --node-vm-size Standard_L8s_v3 --node-count 3 \
    --enable-azure-container-storage ephemeralDisk --storage-pool-option NVMe

# switch away from the default, succeeds
az aks update -g <rg> -n <cluster> \
    --enable-azure-container-storage ephemeralDisk --storage-pool-option NVMe \
    --ephemeral-disk-volume-type PersistentVolumeWithAnnotation

# switch back -- fails
az aks update -g <rg> -n <cluster> \
    --enable-azure-container-storage ephemeralDisk --storage-pool-option NVMe \
    --ephemeral-disk-volume-type EphemeralVolumeOnly

Inspecting the cluster confirms the value really is PersistentVolumeWithAnnotation:

az k8s-extension show -g <rg> --cluster-name <cluster> \
    --cluster-type managedClusters --name azurecontainerstorage \
    --query "properties.configurationSettings"
# {
#   "global.cli.activeControl": "true",
#   "global.cli.storagePool.ephemeralDisk.enableEphemeralBypassAnnotation": "true",
#   ...
# }

Expected behavior

The CLI reads the cluster's actual ACStor configuration and performs the update.

Actual behavior

The CLI believes activeControl is off, falls back to legacy defaults, concludes the
current volume type is EphemeralVolumeOnly, and rejects the command. Users cannot
switch --ephemeral-disk-volume-type back, and the same misdetection affects which
storage pool types the CLI thinks are enabled.

Suggested fix

Compare case-insensitively, e.g. a small helper:

def _is_enabled(config_settings, key, default=False):
    value = config_settings.get(key)
    if value is None:
        return default
    if isinstance(value, bool):
        return value
    return str(value).strip().lower() == "true"

and use it for all 8 sites. Optionally also make acstor_ops.py write explicit
"True"/"False" strings so old and new CLI versions interoperate — but the
case-insensitive read is the part that must ship, since clusters configured by
k8s-extension >= 1.8.0 already contain lowercase values.

Environment Summary

azure-cli                        2.74.0 and 2.86.0 (both affected)
k8s-extension                    1.8.0

Additional context

Not a regression in azure-cli itself — it is triggered by k8s-extension 1.8.0, but the
defect is in this comparison logic. Filed separately against azure-cli-extensions for
the undocumented breaking change
.

Metadata

Metadata

Labels

AKSaz aks/acs/openshiftAuto-AssignAuto assign by botAuto-ResolveAuto resolve by botService AttentionThis issue is responsible by Azure service team.act-observability-squadbugThis issue requires a change to an existing behavior in the product in order to be resolved.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions