-
Notifications
You must be signed in to change notification settings - Fork 5k
Make Azure.ResourceManager AOT-compatible #50129
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
base: main
Are you sure you want to change the base?
Conversation
Thank you for your contribution @agocke! We will review the pull request and get back to you soon. |
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.
Pull Request Overview
This PR updates Azure.ResourceManager to be AOT-compatible by replacing non-source generated JSON with source-generated contexts and marking incompatible configuration bindings.
- Added attributes in ArmClientBuilderExtensions to flag reflection and dynamic code usage.
- Introduced new JSON context classes and updated serialization/deserialization calls to use them.
- Updated the project file and ArmClientOptions to support AOT compatibility.
Reviewed Changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
File | Description |
---|---|
sdk/resourcemanager/Azure.ResourceManager/src/Extensions/ArmClientBuilderExtensions.cs | Added AOT-related attributes to the AddArmClient method. |
sdk/resourcemanager/Azure.ResourceManager/src/Common/Custom/Models/ManagedServiceIdentityJsonContext.cs | Added a new JSON source generation context. |
sdk/resourcemanager/Azure.ResourceManager/src/Common/Custom/Models/ManagedServiceIdentity.Serialization.cs | Updated JSON serialization/deserialization to use the new context. |
sdk/resourcemanager/Azure.ResourceManager/src/Azure.ResourceManager.csproj | Added AOT compatibility property. |
sdk/resourcemanager/Azure.ResourceManager/src/ArmEnvironmentJsonContext.cs | Introduced a context for ArmEnvironment JSON serialization. |
sdk/resourcemanager/Azure.ResourceManager/src/ArmEnvironment.cs | Updated ToString to utilize the source-generated context. |
sdk/resourcemanager/Azure.ResourceManager/src/ArmClientOptionsJsonContext.cs | Added a JSON context for ArmClientOptions. |
sdk/resourcemanager/Azure.ResourceManager/src/ArmClientOptions.cs | Migrated deserialization to use the new JSON context. |
@m-nash: Could you give this another pair of eyes from the management + MRW perspective? |
FYI, still trying to repro those code generation failures locally. For some reason restore is taking forever |
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.
LGTM, though I lack in-depth knowledge of the management packages. I've pulled a couple of others in for additional perspectives.
@agocke: The failures are:
|
I've fixed up all the formatting and added the attribute, so I think this is ready to go. |
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 LGTM from my perspective although I also don't have much knowledge on the mgmt packages
@@ -23,6 +24,8 @@ public static IAzureClientBuilder<ArmClient, ArmClientOptions> AddArmClient<TBui | |||
/// <summary> | |||
/// Registers an <see cref="ArmClient"/> instance with connection options loaded from the provided <paramref name="configuration"/> instance. | |||
/// </summary> | |||
[RequiresUnreferencedCode("Uses reflection for registration")] | |||
[RequiresDynamicCode("Uses code generation for registration")] |
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.
nit - The message could be more descriptive like what I have in this one here"This utilizes reflection-based JSON serialization and deserialization which is not compatible with trimming."
idk if there's an AOT safe alternative path here but if there is adding that would also be a plus
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.
@ArthurMa1978, @ArcturusZhang, @live1206, @m-nash: Folks, can you please give this a quick look from the management ownership perspective? Since everything is green, I'm going to move forward with the merge tomorrow EOD if nobody registers any objections or questions. |
I think we want to switch this to SCM SG to stay in line with the other core libraries. Spoke with @agocke today offline and we will come up with a overarching plan to fix the cross library JsonSerializer calls |
@@ -23,6 +24,8 @@ public static IAzureClientBuilder<ArmClient, ArmClientOptions> AddArmClient<TBui | |||
/// <summary> | |||
/// Registers an <see cref="ArmClient"/> instance with connection options loaded from the provided <paramref name="configuration"/> instance. | |||
/// </summary> | |||
[RequiresUnreferencedCode("Uses reflection for registration")] | |||
[RequiresDynamicCode("Uses code generation for registration")] |
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.
[JsonSerializable(typeof(ManagedServiceIdentity))] | ||
[JsonSerializable(typeof(ManagedServiceIdentityType))] | ||
[JsonSerializable(typeof(UserAssignedIdentity))] | ||
internal partial class ManagedServiceIdentityJsonContext : JsonSerializerContext |
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.
Lets drop this context file and use MRWContext instead which is already created https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/resourcemanager/Azure.ResourceManager/src/Common/Generated/Models/AzureResourceManagerContext.cs.
I think the other JsonSerializerContext files you created above (https://github.com/Azure/azure-sdk-for-net/pull/50129/files#diff-db2b8de102500dff3ce1b4cca617984a46fc86d3b50072de5dd2982af021a09a, https://github.com/Azure/azure-sdk-for-net/pull/50129/files#diff-ac7d79bf6d6b455a3e36744cfa1bc766421ac11e520f80cd6b667c53625764a3) are fine since those are not IJsonModel's and aren't intended to be used in service communication. The serialization there is for utility only.
@@ -45,7 +50,7 @@ internal void Write(Utf8JsonWriter writer, ModelReaderWriterOptions options, Jso | |||
foreach (var item in UserAssignedIdentities) | |||
{ | |||
writer.WritePropertyName(item.Key); | |||
JsonSerializer.Serialize(writer, item.Value); | |||
JsonSerializer.Serialize(writer, item.Value, jsonContext.UserAssignedIdentity); |
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.
Lets swap the serialize calls to a cast to IJsonModel and call the write method on there passing in the MRWOptions and MRWContext
@@ -202,7 +211,7 @@ internal static ManagedServiceIdentity DeserializeManagedServiceIdentity(JsonEle | |||
} | |||
if (property.NameEquals("type"u8)) | |||
{ | |||
type = JsonSerializer.Deserialize<ManagedServiceIdentityType>($"{{{property}}}", jOptions); | |||
type = JsonSerializer.Deserialize<ManagedServiceIdentityType>($"{{{property}}}", jsonContext.ManagedServiceIdentityType); |
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.
The deserialize here I believe is an internal static we should have access to.
@@ -214,7 +223,7 @@ internal static ManagedServiceIdentity DeserializeManagedServiceIdentity(JsonEle | |||
Dictionary<ResourceIdentifier, UserAssignedIdentity> dictionary = new Dictionary<ResourceIdentifier, UserAssignedIdentity>(); | |||
foreach (var property0 in property.Value.EnumerateObject()) | |||
{ | |||
dictionary.Add(new ResourceIdentifier(property0.Name), JsonSerializer.Deserialize<UserAssignedIdentity>(property0.Value.GetRawText())); | |||
dictionary.Add(new ResourceIdentifier(property0.Name), JsonSerializer.Deserialize<UserAssignedIdentity>(property0.Value.GetRawText(), ManagedServiceIdentityJsonContext.Default.UserAssignedIdentity)); |
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.
The deserialize here I believe is an internal static we should have access to.
@@ -27,7 +28,7 @@ internal void Write(Utf8JsonWriter writer, ModelReaderWriterOptions options, Jso | |||
} | |||
|
|||
writer.WriteStartObject(); | |||
JsonSerializer.Serialize(writer, ManagedServiceIdentityType, jOptions); |
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.
@m-nash the problem here is that ManagedServiceIdentityType doesn’t implement IJsonModel. What’s the appropriate fix? Implement manually?
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.
ManagedServiceIdentityType doesn't need to because its an extensible enum. ToString() is the "serialization" and ctor(string) is the "deserialization".
There were only two places which were not AOT compatible:
Note: almost all of this code was generated by VS Code CoPilot w/ Agent Mode. If you're interested in the prompts I used and the chat session, contact me privately and I'd be happy to share the whole session.