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.
Describe the bug
az aks create/update's Azure Container Storage (ACStor) support reads the installedextension's
configurationSettingsand compares boolean values case-sensitivelyagainst 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/falseinstead 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
global.cli.activeControlis nowtrue, sois_cli_operation_activeis alwaysFalseand the CLI unconditionally takes the legacy fallback branch. The returned
ephemeral_disk_volume_typestays at its defaultEphemeralVolumeOnlyregardless ofwhat is actually installed on the cluster.
Note this fails silently — the vendored SDK keeps attribute-level backwards
compatibility via flattened properties, so
extension.configuration_settingsstillresolves; only the values changed shape.
Affected lines
All in
src/azure-cli/azure/cli/command_modules/acs/azurecontainerstorage/:_helpers.pyAffected 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.pywrites these settings as Pythonbool, not as strings:https://github.com/Azure/azure-cli/blob/dev/src/azure-cli/azure/cli/command_modules/acs/azurecontainerstorage/acstor_ops.py#L155
Under the old
2023-05-01msrest model,configuration_settingswas typed{str}, somsrest coerced each value with
str()→"True". The new2025-03-01TypeSpec modelserializes the dict as-is → JSON
true.Reproduced with the two vendored SDKs directly:
So the write path and the read path have always been asymmetric (writes
bool, readsstr); the SDK migration is what made them disagree.Related command
az aks updateErrors
Issue script & Debug output
Inspecting the cluster confirms the value really is
PersistentVolumeWithAnnotation:Expected behavior
The CLI reads the cluster's actual ACStor configuration and performs the update.
Actual behavior
The CLI believes
activeControlis off, falls back to legacy defaults, concludes thecurrent volume type is
EphemeralVolumeOnly, and rejects the command. Users cannotswitch
--ephemeral-disk-volume-typeback, and the same misdetection affects whichstorage pool types the CLI thinks are enabled.
Suggested fix
Compare case-insensitively, e.g. a small helper:
and use it for all 8 sites. Optionally also make
acstor_ops.pywrite explicit"True"/"False"strings so old and new CLI versions interoperate — but thecase-insensitive read is the part that must ship, since clusters configured by
k8s-extension >= 1.8.0 already contain lowercase values.
Environment Summary
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-extensionsforthe undocumented breaking change.