Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ class FeatureFlagConstants:
REQUIREMENT_TYPE = "requirement_type"
DISPLAY_NAME = "display_name"
NAME = "name"
LABEL = "label"
TAGS = "tags"
LAST_MODIFIED = "last_modified"
FILTER_PARAMETERS = "parameters"
ALLOCATION = "allocation"
TELEMETRY = "telemetry"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,23 @@

logger = get_logger(__name__)


def parse_feature_flag_input(value):
"""Parse the --flag value as AAZ shorthand syntax, falling back to JSON.

Mirrors AAZAnyTypeArgAction.decode_str: shorthand is tried first and, because the shorthand
parser rejects double-quoted JSON, valid JSON falls through to shell_safe_json_parse. The
@file/@- convention is expanded to file content by the CLI core before this runs.
"""
from azure.cli.core.aaz._utils import AAZShortHandSyntaxParser
from azure.cli.core.aaz.exceptions import AAZInvalidShorthandSyntaxError

try:
return AAZShortHandSyntaxParser()(value)
except AAZInvalidShorthandSyntaxError:
return shell_safe_json_parse(value, preserve_order=True)


# Feature Flag Models #


Expand Down
20 changes: 20 additions & 0 deletions src/azure-cli/azure/cli/command_modules/appconfig/_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ def featureflag_entry_format(result):
return _output_format(result, _featureflag_entry_format_group)


def enhanced_featureflag_entry_format(result):
return _output_format(result, _enhanced_featureflag_entry_format_group)


def featurefilter_entry_format(result):
return _output_format(result, _featurefilter_entry_format_group)

Expand Down Expand Up @@ -146,6 +150,22 @@ def _featureflag_entry_format_group(item):
])


def _enhanced_featureflag_entry_format_group(item):

return OrderedDict([
('NAME', _get_value(item, 'name')),
('ENABLED', _get_value(item, 'enabled')),
('LABEL', _get_value(item, 'label')),
('DESCRIPTION', _get_value(item, 'description')),
('LAST MODIFIED', _format_datetime(_get_value_by_names(item, ['lastModified', 'last_modified']))),
('TAGS', _get_value(item, 'tags')),
('CONDITIONS', _get_value(item, 'conditions')),
('VARIANTS', _get_value(item, 'variants')),
('ALLOCATION', _get_value(item, 'allocation')),
('TELEMETRY', _get_value(item, 'telemetry'))
])


def _snapshot_output_format_group(item):

return OrderedDict([
Expand Down
122 changes: 122 additions & 0 deletions src/azure-cli/azure/cli/command_modules/appconfig/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,128 @@
az appconfig feature disable -n MyAppConfiguration --key .appconfig.featureflag/MyApp1:Beta
"""

helps['appconfig enhanced-feature-flag'] = """
type: group
short-summary: Manage enhanced feature flags stored in an App Configuration store.
"""

helps['appconfig enhanced-feature-flag set'] = """
type: command
short-summary: Set an enhanced feature flag.
examples:
- name: Set an enhanced feature flag with label MyLabel.
text:
az appconfig enhanced-feature-flag set -n MyAppConfiguration --feature color --label MyLabel
- name: Set an enhanced feature flag with null label using connection string and set a description.
text:
az appconfig enhanced-feature-flag set --connection-string Endpoint=https://contoso.azconfig.io;Id=xxx;Secret=xxx --feature color --description "This is a colorful feature"
- name: Enable an enhanced feature flag while setting it.
text:
az appconfig enhanced-feature-flag set -n MyAppConfiguration --feature color --enable
- name: Disable an enhanced feature flag while setting it.
text:
az appconfig enhanced-feature-flag set -n MyAppConfiguration --feature color --enable false
- name: Set an enhanced feature flag using your 'az login' credentials.
text:
az appconfig enhanced-feature-flag set --endpoint https://myappconfiguration.azconfig.io --feature color --label MyLabel --auth-mode login
- name: Set an enhanced feature flag with tags "tag1=value1" and "tag2=value2".
text:
az appconfig enhanced-feature-flag set -n MyAppConfiguration --feature color --tags tag1=value1 tag2=value2
- name: Set an enhanced feature flag with telemetry enabled.
text:
az appconfig enhanced-feature-flag set -n MyAppConfiguration --feature color --telemetry-enabled
- name: Disable telemetry on an enhanced feature flag.
text:
az appconfig enhanced-feature-flag set -n MyAppConfiguration --feature color --telemetry-enabled false
- name: Set the entire enhanced feature flag from an inline JSON object.
text:
az appconfig enhanced-feature-flag set -n MyAppConfiguration --flag '{"name":"Beta","enabled":true,"conditions":{"requirement_type":"Any","filters":[{"name":"Microsoft.TimeWindow","parameters":{"Start":"Wed, 01 Jan 2025 00:00:00 GMT"}}]}}'
- name: Set the entire enhanced feature flag using shorthand syntax.
text:
az appconfig enhanced-feature-flag set -n MyAppConfiguration --flag "{name:Beta,enabled:true,conditions:{requirement_type:Any,filters:[{name:Microsoft.TimeWindow,parameters:{Start:'Wed, 01 Jan 2025 00:00:00 GMT'}}]}}"
- name: Set the entire enhanced feature flag from a JSON file.
text:
az appconfig enhanced-feature-flag set -n MyAppConfiguration --flag @flag.json
- name: Set the entire enhanced feature flag by reading the JSON from stdin.
text:
cat flag.json | az appconfig enhanced-feature-flag set -n MyAppConfiguration --flag @-
"""

helps['appconfig enhanced-feature-flag delete'] = """
type: command
short-summary: Delete an enhanced feature flag.
examples:
- name: Delete an enhanced feature flag using App Configuration store name without confirmation.
text:
az appconfig enhanced-feature-flag delete -n MyAppConfiguration --feature color --label MyLabel --yes
- name: Delete an enhanced feature flag using connection string.
text:
az appconfig enhanced-feature-flag delete --connection-string Endpoint=https://contoso.azconfig.io;Id=xxx;Secret=xxx --feature color --label MyLabel
- name: Delete an enhanced feature flag using App Configuration store endpoint and your 'az login' credentials.
text:
az appconfig enhanced-feature-flag delete --endpoint https://myappconfiguration.azconfig.io --feature color --auth-mode login
"""

helps['appconfig enhanced-feature-flag show'] = """
type: command
short-summary: Show all attributes of an enhanced feature flag.
examples:
- name: Show an enhanced feature flag using App Configuration store name with a specific label.
text:
az appconfig enhanced-feature-flag show -n MyAppConfiguration --feature color --label MyLabel
- name: Show an enhanced feature flag using connection string and field filters.
text:
az appconfig enhanced-feature-flag show --connection-string Endpoint=https://contoso.azconfig.io;Id=xxx;Secret=xxx --feature color --fields name enabled conditions
- name: Show an enhanced feature flag using App Configuration store endpoint and your 'az login' credentials.
text:
az appconfig enhanced-feature-flag show --endpoint https://myappconfiguration.azconfig.io --feature color --auth-mode login
"""

helps['appconfig enhanced-feature-flag list'] = """
type: command
short-summary: List enhanced feature flags.
examples:
- name: List all enhanced feature flags.
text:
az appconfig enhanced-feature-flag list -n MyAppConfiguration
- name: List a specific feature for any label starting with v1. using connection string.
text:
az appconfig enhanced-feature-flag list --feature color --connection-string Endpoint=https://contoso.azconfig.io;Id=xxx;Secret=xxx --label v1.*
- name: List all features with any labels and query only name, enabled and conditions.
text:
az appconfig enhanced-feature-flag list --connection-string Endpoint=https://contoso.azconfig.io;Id=xxx;Secret=xxx --fields name enabled conditions
- name: List 150 enhanced feature flags with any labels.
text:
az appconfig enhanced-feature-flag list --connection-string Endpoint=https://contoso.azconfig.io;Id=xxx;Secret=xxx --top 150
- name: List all enhanced feature flags with specific tags.
text:
az appconfig enhanced-feature-flag list -n MyAppConfiguration --tags tag1=value1 tag2=value2
"""

helps['appconfig enhanced-feature-flag enable'] = """
type: command
short-summary: Enable an enhanced feature flag to turn it ON for use.
examples:
- name: Enable an enhanced feature flag using App Configuration store name.
text:
az appconfig enhanced-feature-flag enable -n MyAppConfiguration --feature color --label test
- name: Force enabling an enhanced feature flag using connection string.
text:
az appconfig enhanced-feature-flag enable --connection-string Endpoint=https://contoso.azconfig.io;Id=xxx;Secret=xxx --feature color --label test --yes
"""

helps['appconfig enhanced-feature-flag disable'] = """
type: command
short-summary: Disable an enhanced feature flag to turn it OFF for use.
examples:
- name: Disable an enhanced feature flag using App Configuration store name.
text:
az appconfig enhanced-feature-flag disable -n MyAppConfiguration --feature color --label test
- name: Force disabling an enhanced feature flag using connection string.
text:
az appconfig enhanced-feature-flag disable --connection-string Endpoint=https://contoso.azconfig.io;Id=xxx;Secret=xxx --feature color --label test --yes
"""

helps['appconfig feature filter'] = """
type: group
short-summary: Manage filters associated with feature flags stored in an App Configuration store.
Expand Down
43 changes: 41 additions & 2 deletions src/azure-cli/azure/cli/command_modules/appconfig/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,24 @@
resource_group_name_type)
from azure.cli.core.commands.validators import \
get_default_location_from_resource_group
from argcomplete.completers import FilesCompleter
from ._constants import ImportExportProfiles, ImportMode, FeatureFlagConstants, ARMAuthenticationMode
from ._featuremodels import parse_feature_flag_input

from ._validators import (validate_appservice_name_or_id, validate_aks_cluster_name_or_id,
validate_sku, validate_snapshot_query_fields,
validate_connection_string, validate_datetime,
validate_export, validate_import,
validate_import_depth, validate_query_fields,
validate_feature_query_fields, validate_filter_parameters,
validate_feature_query_fields, validate_enhanced_feature_query_fields, validate_filter_parameters,
validate_separator, validate_secret_identifier,
validate_key, validate_feature, validate_feature_key,
validate_identity, validate_auth_mode, validate_snapshot_reference,
validate_resolve_keyvault, validate_export_profile, validate_import_profile,
validate_strict_import, validate_export_as_reference, validate_snapshot_filters,
validate_snapshot_export, validate_snapshot_import, validate_tag_filters,
validate_import_tag_filters, validate_dry_run, validate_kv_revision_retention_period,
validate_public_network_args)
validate_public_network_args, validate_feature_flag)


def load_arguments(self, _):
Expand All @@ -47,6 +49,12 @@ def load_arguments(self, _):
validator=validate_feature_query_fields,
arg_type=get_enum_type(['name', 'key', 'label', 'locked', 'last_modified', 'state', 'description', 'conditions'])
)
enhanced_feature_fields_arg_type = CLIArgumentType(
nargs='+',
help='Customize output fields for Enhanced Feature Flags.',
validator=validate_enhanced_feature_query_fields,
arg_type=get_enum_type(['name', 'enabled', 'label', 'description', 'conditions', 'variants', 'allocation', 'tags', 'last_modified'])
)
snapshot_fields_arg_type = CLIArgumentType(
nargs='+',
help='Customize output fields for Snapshots',
Expand Down Expand Up @@ -464,6 +472,37 @@ def load_arguments(self, _):
c.argument('label', help="If no label specified, display filters from the feature flag with null label by default.")
c.argument('all_', help="List all filters associated with a feature flag.")

with self.argument_context('appconfig enhanced-feature-flag') as c:
c.argument('name', arg_type=data_plane_name_arg_type)
c.argument('feature', options_list=['--feature-name', '--feature'], validator=validate_feature, help="Name of the enhanced feature flag. Enhanced feature flag name cannot contain the '%' or ':' characters.")
c.argument('label', help="If no label specified, uses the null label.")

with self.argument_context('appconfig enhanced-feature-flag set') as c:
c.argument('enable', arg_type=get_three_state_flag(), help='Enable or disable the enhanced feature flag.')
c.argument('description', help='Description of the enhanced feature flag to be set.')
c.argument('requirement_type', arg_type=get_enum_type([FeatureFlagConstants.REQUIREMENT_TYPE_ALL, FeatureFlagConstants.REQUIREMENT_TYPE_ANY]),
help='Requirement type determines if filters should use "Any" or "All" logic when evaluating the state of an enhanced feature flag.')
c.argument('telemetry_enabled', arg_type=get_three_state_flag(), help='Enable or disable telemetry for the enhanced feature flag.')
c.argument('tags', arg_type=tags_type)
c.argument('flag', options_list=['--flag'], type=parse_feature_flag_input,
completer=FilesCompleter(), validator=validate_feature_flag,
help="The entire enhanced feature flag, using the same property names, casing and types as the "
"data-plane API and 'az appconfig enhanced-feature-flag show' (name, enabled, description, "
"conditions, allocation, variants, telemetry, tags). Accepts a JSON object, a shorthand-syntax "
"object, a file path with @ prefix (e.g. @flag.json), or @- to read from stdin. Providing --flag "
"replaces the entire feature flag and cannot be combined with --enable, --description, "
"--requirement-type or --telemetry-enabled.")

with self.argument_context('appconfig enhanced-feature-flag show') as c:
c.argument('fields', arg_type=enhanced_feature_fields_arg_type)

with self.argument_context('appconfig enhanced-feature-flag list') as c:
c.argument('feature', validator=validate_feature, help='Name of the enhanced feature flag to be listed. Support star sign as filters, for instance * means all enhanced feature flags and abc* means enhanced feature flags with abc as prefix.')
c.argument('label', help="If no label specified, list all labels. Support star sign as filters, for instance * means all labels and abc* means labels with abc as prefix.")
c.argument('fields', arg_type=enhanced_feature_fields_arg_type)
c.argument('all_', help="List all enhanced feature flags.")
c.argument('tags', arg_type=tags_arg_type, help="If no tags are specified, list all enhanced feature flags with any tags. Support space-separated tags: key[=value] [key[=value] ...].")

with self.argument_context('appconfig replica') as c:
c.argument('store_name', arg_type=store_name_arg_type)
c.argument('name', arg_type=replica_name_arg_type)
Expand Down
Loading
Loading