Skip to content

[BUG] Removing a rule set from a Front Door route doesn't work #56314

@mderriey

Description

@mderriey

Library name and version

Azure.ResourceManager.Cdn 1.5.1

Describe the bug

I have a route with a single rule set that I want to dissociate from the route.

Here's the code I'm using:

FrontDoorRouteResource route = /* get the route */;
ResourceIdentifier ruleSetToDissociate = /* Get the ID */;

if (route.Data.RuleSets.Any(x => x.Id == ruleSetToDissociate))
{
    // 1. Build a PATCH with the exact same configuration as the route
    var routePatch = new FrontDoorRoutePatch
    {
        EnabledState = route.Data.EnabledState,
        ForwardingProtocol = route.Data.ForwardingProtocol,
        HttpsRedirect = route.Data.HttpsRedirect,
        LinkToDefaultDomain = route.Data.LinkToDefaultDomain,
        OriginGroupId = route.Data.OriginGroupId,
        OriginPath = route.Data.OriginPath,
    };

    foreach (var pattern in route.Data.PatternsToMatch)
    {
        routePatch.PatternsToMatch.Add(pattern);
    }

    foreach (var protocol in route.Data.SupportedProtocols)
    {
        routePatch.SupportedProtocols.Add(protocol);
    }

    foreach (var domain in route.Data.CustomDomains)
    {
        routePatch.CustomDomains.Add(domain);
    }

    // 2. EXCEPT for the rule sets where we ignore the one we don't want anymore
    foreach (var existingRuleSet in route.Data.RuleSets)
    {
        if (existingRuleSet.Id != ruleSetResourceId)
        {
            routePatch.RuleSets.Add(existingRuleSet);
        }
    }

    // 3. Issue the PATCH request
    await route.UpdateAsync(WaitUntil.Completed, routePatch, ct);
}

Expected behavior

The rule set is not associated with the route anymore.

Actual behavior

The rule set is still associated with the route.

I looked into this and found the following:

  1. Rule sets will only be serialized if the collection is "defined", see
    if (Optional.IsCollectionDefined(RuleSets))
    {
    writer.WritePropertyName("ruleSets"u8);
    writer.WriteStartArray();
    foreach (var item in RuleSets)
    {
    ((IJsonModel<WritableSubResource>)item).Write(writer, options);
    }
    writer.WriteEndArray();
    }
  2. IsCollectionDefined only returns false if it's a ChangeTrackingList<T> where IsUndefined is true,
    public static bool IsCollectionDefined<T>(IEnumerable<T> collection)
    {
    return !(collection is ChangeTrackingList<T> changeTrackingList && changeTrackingList.IsUndefined);
    }
  3. RuleSets is indeed a ChangeTrackingList<T>,
    RuleSets = new ChangeTrackingList<WritableSubResource>();
  4. ChangeTrackingList<T> is marked as IsUndefined by default until an operation is performed on it, which ensures the backing List<T> is initialized, https://github.com/Azure/azure-sdk-for-net/blob/9b622f049bda3420d2bb4b5c29fe59a89fafa710/sdk/cdn/Azure.ResourceManager.Cdn/src/Generated/Internal/ChangeTrackingList.cs

In other words, not performing any actions on the RuleSets collection prevents it from being serialized, and the service doesn't remove the rule set from the route.

It can be worked around by making sure the ChangeTrackingList<T> is defined:

[...]

// Force it to be defined so it will be serialized to an empty array even if we don't add any rule sets below
routePatch.RuleSets.Clear();

// 2. EXCEPT for the rule sets where we ignore the one we don't want anymore
foreach (var existingRuleSet in route.Data.RuleSets)
{
    if (existingRuleSet.Id != ruleSetResourceId)
    {
        routePatch.RuleSets.Add(existingRuleSet);
    }
}

// 3. Issue the PATCH request
await route.UpdateAsync(WaitUntil.Completed, routePatch, ct);

Reproduction Steps

See code above.

Environment

  • Azure App Service running on Windows.
  • .NET Framework 4.8

Metadata

Metadata

Assignees

Labels

MgmtThis issue is related to a management package.Network - Front DoorService: Azure Front Doorcustomer-reportedIssues that are reported by GitHub users external to the Azure organization.needs-team-attentionWorkflow: This issue needs attention from Azure service team or SDK teamquestionThe issue doesn't require a change to the product in order to be resolved. Most issues start as that

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions