Skip to content
Merged
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 @@ -10,6 +10,8 @@

- Fixed `GetConfigurationSettings(SettingSelector)` not setting `ContentType` and `LastModified` properties [(#38524)](https://github.com/Azure/azure-sdk-for-net/issues/38524).

- `FeatureFlagConfigurationSetting` will now allow custom attributes under the `conditions` element in the setting value. Previously, only `client_filters` was recognized and other data would be discarded.

### Other Changes

## 1.2.1 (2023-09-13)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ internal override string GetValue()
{
var (name, jsonValue) = _parsedProperties[index];

if (TryWriteKnownProperty(name, writer, includeOptionalWhenNull: true))
if (TryWriteKnownProperty(name, writer, jsonValue, includeOptionalWhenNull: true))
{
knownProperties.Remove(name);
}
Expand All @@ -218,7 +218,7 @@ internal override string GetValue()

foreach (var name in knownProperties)
{
TryWriteKnownProperty(name, writer);
TryWriteKnownProperty(name, writer, default);
}

writer.WriteEndObject();
Expand All @@ -244,39 +244,46 @@ private bool TryParseValue()
case "id":
_featureId = item.Value.GetString();
_parsedProperties.Add((item.Name, default));
requiredProperties.Remove(item.Name);
break;

case "description":
_description = item.Value.GetString();
_parsedProperties.Add((item.Name, default));
requiredProperties.Remove(item.Name);
Comment thread
ShivangiReja marked this conversation as resolved.
break;

case "display_name":
_displayName = item.Value.GetString();
_parsedProperties.Add((item.Name, default));
requiredProperties.Remove(item.Name);
break;

case "enabled":
_isEnabled = item.Value.GetBoolean();
_parsedProperties.Add((item.Name, default));
requiredProperties.Remove(item.Name);
break;

case "conditions":
_parsedProperties.Add((item.Name, default));
_parsedProperties.Add((item.Name, item.Value.Clone()));

if (item.Value.TryGetProperty("client_filters", out var clientFiltersProperty)
&& clientFiltersProperty.ValueKind == JsonValueKind.Array)
{
_clientFilters = ParseFilters(clientFiltersProperty);
}

if (item.Value.ValueKind == JsonValueKind.Object)
{
requiredProperties.Remove(item.Name);
}
break;

default:
_parsedProperties.Add((item.Name, item.Value.Clone()));
break;
}

requiredProperties.Remove(item.Name);
}

return requiredProperties.Count == 0;
Expand All @@ -287,7 +294,7 @@ private bool TryParseValue()
}
}

private bool TryWriteKnownProperty(string propertyName, Utf8JsonWriter writer, bool includeOptionalWhenNull = false)
private bool TryWriteKnownProperty(string propertyName, Utf8JsonWriter writer, JsonElement sourceElement, bool includeOptionalWhenNull = false)
{
switch (propertyName)
{
Expand Down Expand Up @@ -324,6 +331,17 @@ private bool TryWriteKnownProperty(string propertyName, Utf8JsonWriter writer, b
writer.WriteEndArray();
}

if (sourceElement.ValueKind != JsonValueKind.Undefined)
{
foreach (var item in sourceElement.EnumerateObject())
{
if (item.Name != "client_filters")
{
item.WriteTo(writer);
}
}
}

writer.WriteEndObject();
break;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
using System.Collections.Generic;
using System.Text.Json;
using Newtonsoft.Json.Linq;
using NUnit.Framework;

namespace Azure.Data.AppConfiguration.Tests
Expand Down Expand Up @@ -49,6 +51,7 @@ public class FeatureFlagConfigurationSettingTests
""enabled"": false,
""custom_stuff"": { ""id"":""dummy"", ""description"":""dummy"", ""enabled"":false },
""conditions"": {
""custom_condition"": { ""id"":""custcond"", ""description"":""a thing"" },
""client_filters"": [
{
""name"": ""Flag1"",
Expand Down Expand Up @@ -78,7 +81,8 @@ public class FeatureFlagConfigurationSettingTests
]
}
}
]
],
""condition_val"":1
}
}";

Expand All @@ -90,6 +94,7 @@ public class FeatureFlagConfigurationSettingTests
}";

private const string MinimalFeatureValueWithFormatting = "{ \"id\" : \"my feature\" , \"enabled\":false,\"conditions\":{}}";
private const string MinimalFeatureValueWithInvalidConditions = "{\"id\":\"my feature\",\"enabled\":false,\"conditions\": \"broken\"}";
private readonly JsonElementEqualityComparer _jsonComparer = new();

[Test]
Expand All @@ -105,6 +110,7 @@ public void CreatingSetsContentTypeAndPrefix()

[TestCase("INVALID")]
[TestCase(MinimalFeatureValue)]
[TestCase(MinimalFeatureValueWithInvalidConditions)]
[TestCase("")]
public void CanRountripValue(string value)
{
Expand Down Expand Up @@ -374,5 +380,25 @@ public void UnknownAttributesArePreservedAndNullOptionalMembersAreNotAdded()

Assert.IsTrue(_jsonComparer.Equals(expected.RootElement, actual.RootElement));
}

[Test]
public void InvalidConditionTypeIsTreatedAsInvalid()
{
var featureFlag = new FeatureFlagConfigurationSetting();
featureFlag.Value = MinimalFeatureValueWithInvalidConditions;

Assert.Throws<InvalidOperationException>(() =>
featureFlag.ClientFilters.Add(new FeatureFlagFilter(
"file",
new Dictionary<string, object>()
{
{"p1", 1}
})));

using var expected = JsonDocument.Parse(MinimalFeatureValueWithInvalidConditions);
using var actual = JsonDocument.Parse(featureFlag.Value);

Assert.IsTrue(_jsonComparer.Equals(expected.RootElement, actual.RootElement));
}
}
}