-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[AppConfig] appconfig feature list/show and appconfig kv import/export
: Support microsoft feature management schema
#30376
[AppConfig] appconfig feature list/show and appconfig kv import/export
: Support microsoft feature management schema
#30376
Conversation
…ineWanjau/azure-cli into cwanjau/supportFFV2Schema
…ineWanjau/azure-cli into cwanjau/supportFFV2Schema
️✔️AzureCLI-FullTest
|
️✔️AzureCLI-BreakingChangeTest
|
AppConfig |
elif feature_flag_version == FeatureFlagVersion.V1: | ||
feature_flag_dict[FeatureFlagConstants.CONDITIONS] = default_conditions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this looks odd. which if
statement is this elif
corresponding to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It corresponds to the first if checking if conditions are None. If None and Feature Flag is version 1, we set the conditions to the default conditions.
|
||
# Backend returns conditions: {client_filters: None} for flags with no conditions. | ||
# No need to write empty conditions to key-values. | ||
if conditions.get(FeatureFlagConstants.CLIENT_FILTERS, None) is None and conditions.get(FeatureFlagConstants.REQUIREMENT_TYPE, None) is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you could simplify this:
if client_filters or requirement_type:
feature_flag_dict[FeatureFlagConstants.CONDITIONS] = conditions
elif feature_flag_version == FeatureFlagVersion.V1:
feature_flag_dict[FeatureFlagConstants.CONDITIONS] = default_conditions
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Updated
@@ -939,6 +989,25 @@ def is_feature_flag(kv): | |||
return False | |||
|
|||
|
|||
def convert_boolean_value(enabled, feature_name): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can make this method generic for converting any boolean to string.
def convert_string_to_bool(value, feature_name)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, this has been updated
""" | ||
enabled = None | ||
telemetry_enabled = feature_telemetry_dict.get(FeatureFlagConstants.ENABLED, None) | ||
if telemetry_enabled is not None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if telemetry_enabled is not None: | |
if telemetry_enabled: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
telemetry_enabled
could be false
and we don't want to remove it if its explictly defined as False
FeatureFlagConstants.TELEMETRY, | ||
FeatureFlagConstants.DISPLAY_NAME | ||
} | ||
if valid_fields.union(feature_flag_dict.keys()) == valid_fields: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be !=
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, nice catch! Updated
featurefilterdict = {} | ||
|
||
for key, value in conditions_dict.items(): | ||
if key == FeatureFlagConstants.CLIENT_FILTERS: | ||
featurefilterdict[key] = [feature_filter.__dict__ for feature_filter in value] | ||
if value is not None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if value is not None: | |
if value: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering a case where we have conditions: {client_filters: [] }
I was thinking we would want to retain this, if we just check it as suggested it might be removed.
description = feature_flag_dict.get(FeatureFlagConstants.DESCRIPTION, "") # assign empty string as default | ||
feature_flag_dict[FeatureFlagConstants.DESCRIPTION] = description |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
description = feature_flag_dict.get(FeatureFlagConstants.DESCRIPTION, "") # assign empty string as default | |
feature_flag_dict[FeatureFlagConstants.DESCRIPTION] = description | |
feature_flag_dict[FeatureFlagConstants.DESCRIPTION] = feature_flag_dict.get(FeatureFlagConstants.DESCRIPTION, "") # assign empty string as default |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
variant_list = [] | ||
if variants: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
variant_list = [] | |
if variants: | |
if variants: | |
variant_list = [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated
if variants: | ||
for variant in variants: | ||
feature_variant = FeatureVariant.convert_from_dict(variant) | ||
if feature_variant: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a condition under which convert_from_dict
can retun None
?
Should we rather check if variant
is not None
first before trying to convert?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we should. This has been updated
for keywordset in FeatureManagementReservedKeywords.ALL: | ||
if keywordset.feature_management == dotnet_schema_keyword: | ||
feature_management_keywords = keywordset | ||
break |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think there is a need to do that since the keywords are already defined in the keywordset.
Hello @zhoxing-ms this PR is ready to be merged. |
appconfig feature list/show and appconfig kv import/export
: Support new microsoft feature management schemaappconfig feature list/show and appconfig kv import/export
: Support microsoft feature management schema
Since there are multiple changes in this PR, it is better to seperate the changelog into small ones and list in the History Notes section, e.g., |
/azp run |
Azure Pipelines successfully started running 3 pipeline(s). |
/azp run |
Azure Pipelines successfully started running 3 pipeline(s). |
Related command
Description
This PR updates the import and export of features to support new feature management schema.
The currently supported schema is the Feature Managment Dotnet Schema.
This PR also adds the use of a new environment variable called [AZURE_APPCONFIG_FM_COMPATIBILE] when exporting to a file for backward compatibility for users. This ensures our systems can process data in both old and new formats, avoiding disruptions for users of the previous version and maintaining functionality during the transition.
Default compatibility mode to true.
If compatibility mode true:
Example,
{
"FeatureManagement":{
// old schema
}
"feature_management":{
"feature_flags": [
// new schema
]
}
}
If compatibility mode is false:
"feature_management":{
"feature_flags": [
// new schema
]
}
Link to design doc
Testing Guide
History Notes
[App Config]
az appconfig kv import
: Support microsoft feature management schema[App Config]
az appconfig kv export
: Support microsoft feature management schema[App Config]
az appconfig kv export
: Introduce a new environment variable calledAZURE_APPCONFIG_FM_COMPATIBILE
when exporting to a file for backward compatibility for users[App Config]
az appconfig feature show
: Support microsoft feature management schema[App Config]
az appconfig feature list
: Support microsoft feature management schemaThis checklist is used to make sure that common guidelines for a pull request are followed.
The PR title and description has followed the guideline in Submitting Pull Requests.
I adhere to the Command Guidelines.
I adhere to the Error Handling Guidelines.