Skip to content
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

Add FeatureFlagConfigurationSetting, SecretReferenceConfigurationSetting #16771

Merged
merged 65 commits into from
Apr 5, 2021

Conversation

seankane-msft
Copy link
Member

No description provided.

@seankane-msft seankane-msft added the App Configuration Azure.ApplicationModel.Configuration label Feb 16, 2021
@seankane-msft seankane-msft self-assigned this Feb 16, 2021
@Azure Azure deleted a comment from check-enforcer bot Mar 8, 2021
self.last_modified = kwargs.get("last_modified", None)
self.read_only = kwargs.get("read_only", None)
self.tags = kwargs.get("tags", None)
self.tags = kwargs.get("tags", {})
Copy link
Member

@xiangyan99 xiangyan99 Mar 31, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we give default value {}?

Given the case user creates a ConfigSetting w/o tags, reads it and sends it back, will this change the value of tag?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No this will not.

super(FeatureFlagConfigurationSetting, self).__init__(**kwargs)
self.key = key
if not key.startswith(self.key_prefix):
self.key = self.key_prefix + key
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is interesting. What's the behavior of other languages?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only happens when a user creates one in a Python program. On deserialization we only deserialize into FeatureFlagConfigurationSetting if the prefix and content_type are the correct value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean if user creates a FeatureFlagConfigurationSetting with key ".appconfig.featureflag/abc"

How can we know he/she wants ".appconfig.featureflag/abc" or ".appconfig.featureflag/.appconfig.featureflag/abc"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the other hand do we want a user to have to create a feature flag by doing:

my_flag = FeatureFlagConfigurationSetting(".appconfig.featureflag/my_flag", enabled=True)

or

my_flag = FeatureFlagConfigurationSetting("my_flag", enabled=True)

@xiangyan99

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't have a strong opinion on this. Let's align the behavior with other languages. :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talked with other languages. I will make the key prefix a constant and export it.

if not new_value:
new_value = {}
self._enabled = new_value.get("enabled") or self._enabled
self._value = new_value
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like if we set value=None then get enabled, the value will be changed to {"enabled": self._enabled}?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if new_value = None this will raise an AttributeError on line 196 (new_value.get("enabled")).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

{}.get('enabled')

returns None. :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, good catch. I will remove the if not new_value lines, then it will throw an AttributeError.

@seankane-msft seankane-msft requested a review from xiangyan99 April 1, 2021 21:15
@@ -147,8 +147,6 @@ def __init__(self, key, enabled, filters=None, **kwargs):
self._enabled = enabled
super(FeatureFlagConfigurationSetting, self).__init__(**kwargs)
self.key = key
if not key.startswith(self.key_prefix):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to check if key.startswith(self.key_prefix)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still want to do this? I removed it to align with java and javascript/typescript.

Copy link
Member

@xiangyan99 xiangyan99 Apr 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if not key.startswith(self.key_prefix):
    raise ValueError. :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was some confusion in our discussion, the standard is to prefix no matter what. That is what Java and C# do, I will add the same to Python

@property
def enabled(self):
# type: () -> bool
if self._value is None:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not raise AttributeError("value parameter is expected to be a dictionary") if value is None?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you suggesting that we raise that error if the user tries to set the value to None?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If _value is not in right schema or key not startswith(self.key_prefix), it is not FeatureFlagConfigurationSetting any longer. Hence enabled & filters properties are invalid.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self._value is the real value we store.

In a GETTER, we cannot change the value.

if self._value is None:
    return None

same in

else:
            self._value["enabled"] = self._enabled

the value can only be changed in a setter method which means user explicitly modify the value.

Copy link
Member

@xiangyan99 xiangyan99 Apr 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I would suggest we have a private method to validate if the value and key are valid. It will be called for multiple times. (any time user reads/write FeatureFlagConfigurationSetting specific properties, we need to validate it first.)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be clear, we will

  1. validate anytime my_key.value = <new_value> and my_key.enabled = <bool> occur, (validating on a set)?
  2. Validate anytime a user tries to read the value or enabled properties as well (validate on a get)?
  3. If they are valid, we update the internal dictionary or enabled value
  4. if they are not valid (ie not a dictionary, not a boolean) we raise an error?

def enabled(self, value):
# type: (bool) -> bool
if self._value is None:
self._value = {"enabled": value}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If self._value is None, it is not a FeatureFlagConfigurationSetting, right? :)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FeatureFlagConfigurationSetting is determined by the key_prefix and content_type, The value can be anything, there is no service side validation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean enabled property is Nullable?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it is nullable

@Azure Azure deleted a comment from check-enforcer bot Apr 1, 2021
@seankane-msft seankane-msft requested a review from xiangyan99 April 2, 2021 20:49
@xiangyan99
Copy link
Member

Btw, don't forget to update changelog. :)

@seankane-msft seankane-msft requested a review from xiangyan99 April 5, 2021 16:59
@seankane-msft seankane-msft merged commit fed3b36 into Azure:master Apr 5, 2021
@seankane-msft seankane-msft deleted the appconfig-addtoken branch April 5, 2021 17:23
openapi-sdkautomation bot pushed a commit to AzureSDKAutomation/azure-sdk-for-python that referenced this pull request Nov 22, 2021
Add 'id' property to ClientEncryptionKeyResource (Azure#16771)

* Add 'id' property to ClientEncryptionKeyResource

* prettier fix

* Mark operation as long running to fix warning.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
App Configuration Azure.ApplicationModel.Configuration
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants