diff --git a/common/Perf/Azure.Test.Perf/Azure.Test.Perf.csproj b/common/Perf/Azure.Test.Perf/Azure.Test.Perf.csproj index 0287d57dcd06..b8bc428847ea 100644 --- a/common/Perf/Azure.Test.Perf/Azure.Test.Perf.csproj +++ b/common/Perf/Azure.Test.Perf/Azure.Test.Perf.csproj @@ -12,6 +12,7 @@ + diff --git a/eng/Packages.Data.props b/eng/Packages.Data.props index 7fdbc92d1383..8f36fc86f2cc 100644 --- a/eng/Packages.Data.props +++ b/eng/Packages.Data.props @@ -213,6 +213,7 @@ + diff --git a/eng/scripts/splittestdependencies/tests/inputs/projects.txt b/eng/scripts/splittestdependencies/tests/inputs/projects.txt index 9d6515197741..2a6bbe06b9fc 100644 --- a/eng/scripts/splittestdependencies/tests/inputs/projects.txt +++ b/eng/scripts/splittestdependencies/tests/inputs/projects.txt @@ -40,6 +40,7 @@ $(RepoRoot)sdk\core\Azure.Core.Experimental\tests\Azure.Core.Experimental.Tests. $(RepoRoot)sdk\core\Azure.Core.Experimental\tests\perf\Azure.Core.Experimental.Performance.csproj $(RepoRoot)sdk\core\Azure.Core.TestFramework\tests\Azure.Core.TestFramework.Tests.csproj $(RepoRoot)sdk\core\Azure.Core\tests\Azure.Core.Tests.csproj +$(RepoRoot)sdk\core\Azure.Core\tests\public\Azure.Core.Tests.Public.csproj $(RepoRoot)sdk\core\Microsoft.Azure.Core.NewtonsoftJson\tests\Microsoft.Azure.Core.NewtonsoftJson.Tests.csproj $(RepoRoot)sdk\core\Microsoft.Azure.Core.Spatial.NewtonsoftJson\tests\Microsoft.Azure.Core.Spatial.NewtonsoftJson.Tests.csproj $(RepoRoot)sdk\core\Microsoft.Azure.Core.Spatial\tests\Microsoft.Azure.Core.Spatial.Tests.csproj diff --git a/sdk/core/Azure.Core/Azure.Core.sln b/sdk/core/Azure.Core/Azure.Core.sln index 23ac37baec81..6cdf7559841e 100644 --- a/sdk/core/Azure.Core/Azure.Core.sln +++ b/sdk/core/Azure.Core/Azure.Core.sln @@ -53,6 +53,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.Expressions.Data EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.Tests.Public", "tests\public\Azure.Core.Tests.Public.csproj", "{BFBF8EF7-61D8-40E7-9E98-468A0427761E}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Azure.Core.Tests.Common", "tests\common\Azure.Core.Tests.Common.csproj", "{0EEDF53F-120A-45B1-8468-A97A0D46DBAC}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -131,6 +133,10 @@ Global {BFBF8EF7-61D8-40E7-9E98-468A0427761E}.Debug|Any CPU.Build.0 = Debug|Any CPU {BFBF8EF7-61D8-40E7-9E98-468A0427761E}.Release|Any CPU.ActiveCfg = Release|Any CPU {BFBF8EF7-61D8-40E7-9E98-468A0427761E}.Release|Any CPU.Build.0 = Release|Any CPU + {0EEDF53F-120A-45B1-8468-A97A0D46DBAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0EEDF53F-120A-45B1-8468-A97A0D46DBAC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0EEDF53F-120A-45B1-8468-A97A0D46DBAC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0EEDF53F-120A-45B1-8468-A97A0D46DBAC}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/sdk/core/Azure.Core/CHANGELOG.md b/sdk/core/Azure.Core/CHANGELOG.md index a2318c735a21..5a90f4b360ed 100644 --- a/sdk/core/Azure.Core/CHANGELOG.md +++ b/sdk/core/Azure.Core/CHANGELOG.md @@ -4,6 +4,8 @@ ### Features Added +-Added `ModelSerializer` which provides a public API to serialize and deserialize models. The new API works with any classes that implement `IModelSerializeable`. + ### Breaking Changes ### Bugs Fixed diff --git a/sdk/core/Azure.Core/api/Azure.Core.net461.cs b/sdk/core/Azure.Core/api/Azure.Core.net461.cs index 3f774979daad..9aaf09bb355c 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.net461.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.net461.cs @@ -539,6 +539,8 @@ public abstract partial class RequestContent : System.IDisposable { protected RequestContent() { } public static Azure.Core.RequestContent Create(Azure.Core.Serialization.DynamicData content) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } public static Azure.Core.RequestContent Create(System.BinaryData content) { throw null; } public static Azure.Core.RequestContent Create(System.Buffers.ReadOnlySequence bytes) { throw null; } public static Azure.Core.RequestContent Create(byte[] bytes) { throw null; } @@ -1075,6 +1077,12 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce } namespace Azure.Core.Serialization { + [System.AttributeUsageAttribute(System.AttributeTargets.Class)] + public sealed partial class AbstractHierarchyDeserializerAttribute : System.Attribute + { + public AbstractHierarchyDeserializerAttribute(System.Type typeToActivate) { } + public System.Type TypeToActivate { get { throw null; } } + } [System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")] public sealed partial class DynamicData : System.Dynamic.IDynamicMetaObjectProvider, System.IDisposable { @@ -1109,6 +1117,16 @@ public partial interface IMemberNameConverter { string? ConvertMemberName(System.Reflection.MemberInfo member); } + public partial interface IModelJsonSerializable : Azure.Core.Serialization.IModelSerializable + { + T Deserialize(ref System.Text.Json.Utf8JsonReader reader, Azure.Core.Serialization.ModelSerializerOptions options); + void Serialize(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.ModelSerializerOptions options); + } + public partial interface IModelSerializable + { + T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions options); + System.BinaryData Serialize(Azure.Core.Serialization.ModelSerializerOptions options); + } public partial class JsonObjectSerializer : Azure.Core.Serialization.ObjectSerializer, Azure.Core.Serialization.IMemberNameConverter { public JsonObjectSerializer() { } @@ -1127,6 +1145,54 @@ public enum JsonPropertyNames UseExact = 0, CamelCase = 1, } + public partial class ModelJsonConverter : System.Text.Json.Serialization.JsonConverter> + { + public ModelJsonConverter() { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerFormat format) { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerOptions options) { } + public Azure.Core.Serialization.ModelSerializerOptions ModelSerializerOptions { get { throw null; } } + public override bool CanConvert(System.Type typeToConvert) { throw null; } + public override Azure.Core.Serialization.IModelJsonSerializable Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } + public override void Write(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.IModelJsonSerializable value, System.Text.Json.JsonSerializerOptions options) { } + } + public static partial class ModelSerializer + { + public static object Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static object Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static System.BinaryData SerializeCore(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions options) { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct ModelSerializerFormat : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Json; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Wire; + public ModelSerializerFormat(string value) { throw null; } + public bool Equals(Azure.Core.Serialization.ModelSerializerFormat other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public static implicit operator Azure.Core.Serialization.ModelSerializerFormat (string value) { throw null; } + public static bool operator !=(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public override string ToString() { throw null; } + } + public partial class ModelSerializerOptions + { + public static readonly Azure.Core.Serialization.ModelSerializerOptions DefaultWireOptions; + public ModelSerializerOptions() { } + public ModelSerializerOptions(Azure.Core.Serialization.ModelSerializerFormat format) { } + public Azure.Core.Serialization.ModelSerializerFormat Format { get { throw null; } } + public System.Func? GenericTypeSerializerCreator { get { throw null; } set { } } + } public abstract partial class ObjectSerializer { protected ObjectSerializer() { } diff --git a/sdk/core/Azure.Core/api/Azure.Core.net5.0.cs b/sdk/core/Azure.Core/api/Azure.Core.net5.0.cs index c10168bea2ae..87a66a878b2f 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.net5.0.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.net5.0.cs @@ -539,6 +539,8 @@ public abstract partial class RequestContent : System.IDisposable { protected RequestContent() { } public static Azure.Core.RequestContent Create(Azure.Core.Serialization.DynamicData content) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } public static Azure.Core.RequestContent Create(System.BinaryData content) { throw null; } public static Azure.Core.RequestContent Create(System.Buffers.ReadOnlySequence bytes) { throw null; } public static Azure.Core.RequestContent Create(byte[] bytes) { throw null; } @@ -1075,6 +1077,13 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce } namespace Azure.Core.Serialization { + [System.AttributeUsageAttribute(System.AttributeTargets.Class)] + public sealed partial class AbstractHierarchyDeserializerAttribute : System.Attribute + { + public AbstractHierarchyDeserializerAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type typeToActivate) { } + [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] + public System.Type TypeToActivate { get { throw null; } } + } [System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")] public sealed partial class DynamicData : System.Dynamic.IDynamicMetaObjectProvider, System.IDisposable { @@ -1109,6 +1118,16 @@ public partial interface IMemberNameConverter { string? ConvertMemberName(System.Reflection.MemberInfo member); } + public partial interface IModelJsonSerializable : Azure.Core.Serialization.IModelSerializable + { + T Deserialize(ref System.Text.Json.Utf8JsonReader reader, Azure.Core.Serialization.ModelSerializerOptions options); + void Serialize(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.ModelSerializerOptions options); + } + public partial interface IModelSerializable + { + T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions options); + System.BinaryData Serialize(Azure.Core.Serialization.ModelSerializerOptions options); + } public partial class JsonObjectSerializer : Azure.Core.Serialization.ObjectSerializer, Azure.Core.Serialization.IMemberNameConverter { public JsonObjectSerializer() { } @@ -1127,6 +1146,54 @@ public enum JsonPropertyNames UseExact = 0, CamelCase = 1, } + public partial class ModelJsonConverter : System.Text.Json.Serialization.JsonConverter> + { + public ModelJsonConverter() { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerFormat format) { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerOptions options) { } + public Azure.Core.Serialization.ModelSerializerOptions ModelSerializerOptions { get { throw null; } } + public override bool CanConvert(System.Type typeToConvert) { throw null; } + public override Azure.Core.Serialization.IModelJsonSerializable Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } + public override void Write(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.IModelJsonSerializable value, System.Text.Json.JsonSerializerOptions options) { } + } + public static partial class ModelSerializer + { + public static object Deserialize(System.BinaryData data, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type returnType, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static object Deserialize(System.BinaryData data, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type returnType, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static System.BinaryData SerializeCore(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions options) { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct ModelSerializerFormat : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Json; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Wire; + public ModelSerializerFormat(string value) { throw null; } + public bool Equals(Azure.Core.Serialization.ModelSerializerFormat other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals([System.Diagnostics.CodeAnalysis.AllowNullAttribute] object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public static implicit operator Azure.Core.Serialization.ModelSerializerFormat (string value) { throw null; } + public static bool operator !=(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public override string ToString() { throw null; } + } + public partial class ModelSerializerOptions + { + public static readonly Azure.Core.Serialization.ModelSerializerOptions DefaultWireOptions; + public ModelSerializerOptions() { } + public ModelSerializerOptions(Azure.Core.Serialization.ModelSerializerFormat format) { } + public Azure.Core.Serialization.ModelSerializerFormat Format { get { throw null; } } + public System.Func? GenericTypeSerializerCreator { get { throw null; } set { } } + } public abstract partial class ObjectSerializer { protected ObjectSerializer() { } diff --git a/sdk/core/Azure.Core/api/Azure.Core.net6.0.cs b/sdk/core/Azure.Core/api/Azure.Core.net6.0.cs index c10168bea2ae..274566b11857 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.net6.0.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.net6.0.cs @@ -539,6 +539,8 @@ public abstract partial class RequestContent : System.IDisposable { protected RequestContent() { } public static Azure.Core.RequestContent Create(Azure.Core.Serialization.DynamicData content) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } public static Azure.Core.RequestContent Create(System.BinaryData content) { throw null; } public static Azure.Core.RequestContent Create(System.Buffers.ReadOnlySequence bytes) { throw null; } public static Azure.Core.RequestContent Create(byte[] bytes) { throw null; } @@ -1075,6 +1077,13 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce } namespace Azure.Core.Serialization { + [System.AttributeUsageAttribute(System.AttributeTargets.Class)] + public sealed partial class AbstractHierarchyDeserializerAttribute : System.Attribute + { + public AbstractHierarchyDeserializerAttribute([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type typeToActivate) { } + [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] + public System.Type TypeToActivate { get { throw null; } } + } [System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")] public sealed partial class DynamicData : System.Dynamic.IDynamicMetaObjectProvider, System.IDisposable { @@ -1109,6 +1118,16 @@ public partial interface IMemberNameConverter { string? ConvertMemberName(System.Reflection.MemberInfo member); } + public partial interface IModelJsonSerializable : Azure.Core.Serialization.IModelSerializable + { + T Deserialize(ref System.Text.Json.Utf8JsonReader reader, Azure.Core.Serialization.ModelSerializerOptions options); + void Serialize(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.ModelSerializerOptions options); + } + public partial interface IModelSerializable + { + T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions options); + System.BinaryData Serialize(Azure.Core.Serialization.ModelSerializerOptions options); + } public partial class JsonObjectSerializer : Azure.Core.Serialization.ObjectSerializer, Azure.Core.Serialization.IMemberNameConverter { public JsonObjectSerializer() { } @@ -1127,6 +1146,55 @@ public enum JsonPropertyNames UseExact = 0, CamelCase = 1, } + [System.Diagnostics.CodeAnalysis.RequiresUnreferencedCodeAttribute("The constructors of the type being deserialized are dynamically accessed and may be trimmed.")] + public partial class ModelJsonConverter : System.Text.Json.Serialization.JsonConverter> + { + public ModelJsonConverter() { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerFormat format) { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerOptions options) { } + public Azure.Core.Serialization.ModelSerializerOptions ModelSerializerOptions { get { throw null; } } + public override bool CanConvert(System.Type typeToConvert) { throw null; } + public override Azure.Core.Serialization.IModelJsonSerializable Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } + public override void Write(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.IModelJsonSerializable value, System.Text.Json.JsonSerializerOptions options) { } + } + public static partial class ModelSerializer + { + public static object Deserialize(System.BinaryData data, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type returnType, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static object Deserialize(System.BinaryData data, [System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type returnType, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static System.BinaryData SerializeCore(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions options) { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct ModelSerializerFormat : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Json; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Wire; + public ModelSerializerFormat(string value) { throw null; } + public bool Equals(Azure.Core.Serialization.ModelSerializerFormat other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals([System.Diagnostics.CodeAnalysis.AllowNullAttribute] object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public static implicit operator Azure.Core.Serialization.ModelSerializerFormat (string value) { throw null; } + public static bool operator !=(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public override string ToString() { throw null; } + } + public partial class ModelSerializerOptions + { + public static readonly Azure.Core.Serialization.ModelSerializerOptions DefaultWireOptions; + public ModelSerializerOptions() { } + public ModelSerializerOptions(Azure.Core.Serialization.ModelSerializerFormat format) { } + public Azure.Core.Serialization.ModelSerializerFormat Format { get { throw null; } } + public System.Func? GenericTypeSerializerCreator { get { throw null; } set { } } + } public abstract partial class ObjectSerializer { protected ObjectSerializer() { } diff --git a/sdk/core/Azure.Core/api/Azure.Core.netcoreapp2.1.cs b/sdk/core/Azure.Core/api/Azure.Core.netcoreapp2.1.cs index 3f774979daad..9aaf09bb355c 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.netcoreapp2.1.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.netcoreapp2.1.cs @@ -539,6 +539,8 @@ public abstract partial class RequestContent : System.IDisposable { protected RequestContent() { } public static Azure.Core.RequestContent Create(Azure.Core.Serialization.DynamicData content) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } public static Azure.Core.RequestContent Create(System.BinaryData content) { throw null; } public static Azure.Core.RequestContent Create(System.Buffers.ReadOnlySequence bytes) { throw null; } public static Azure.Core.RequestContent Create(byte[] bytes) { throw null; } @@ -1075,6 +1077,12 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce } namespace Azure.Core.Serialization { + [System.AttributeUsageAttribute(System.AttributeTargets.Class)] + public sealed partial class AbstractHierarchyDeserializerAttribute : System.Attribute + { + public AbstractHierarchyDeserializerAttribute(System.Type typeToActivate) { } + public System.Type TypeToActivate { get { throw null; } } + } [System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")] public sealed partial class DynamicData : System.Dynamic.IDynamicMetaObjectProvider, System.IDisposable { @@ -1109,6 +1117,16 @@ public partial interface IMemberNameConverter { string? ConvertMemberName(System.Reflection.MemberInfo member); } + public partial interface IModelJsonSerializable : Azure.Core.Serialization.IModelSerializable + { + T Deserialize(ref System.Text.Json.Utf8JsonReader reader, Azure.Core.Serialization.ModelSerializerOptions options); + void Serialize(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.ModelSerializerOptions options); + } + public partial interface IModelSerializable + { + T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions options); + System.BinaryData Serialize(Azure.Core.Serialization.ModelSerializerOptions options); + } public partial class JsonObjectSerializer : Azure.Core.Serialization.ObjectSerializer, Azure.Core.Serialization.IMemberNameConverter { public JsonObjectSerializer() { } @@ -1127,6 +1145,54 @@ public enum JsonPropertyNames UseExact = 0, CamelCase = 1, } + public partial class ModelJsonConverter : System.Text.Json.Serialization.JsonConverter> + { + public ModelJsonConverter() { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerFormat format) { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerOptions options) { } + public Azure.Core.Serialization.ModelSerializerOptions ModelSerializerOptions { get { throw null; } } + public override bool CanConvert(System.Type typeToConvert) { throw null; } + public override Azure.Core.Serialization.IModelJsonSerializable Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } + public override void Write(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.IModelJsonSerializable value, System.Text.Json.JsonSerializerOptions options) { } + } + public static partial class ModelSerializer + { + public static object Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static object Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static System.BinaryData SerializeCore(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions options) { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct ModelSerializerFormat : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Json; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Wire; + public ModelSerializerFormat(string value) { throw null; } + public bool Equals(Azure.Core.Serialization.ModelSerializerFormat other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public static implicit operator Azure.Core.Serialization.ModelSerializerFormat (string value) { throw null; } + public static bool operator !=(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public override string ToString() { throw null; } + } + public partial class ModelSerializerOptions + { + public static readonly Azure.Core.Serialization.ModelSerializerOptions DefaultWireOptions; + public ModelSerializerOptions() { } + public ModelSerializerOptions(Azure.Core.Serialization.ModelSerializerFormat format) { } + public Azure.Core.Serialization.ModelSerializerFormat Format { get { throw null; } } + public System.Func? GenericTypeSerializerCreator { get { throw null; } set { } } + } public abstract partial class ObjectSerializer { protected ObjectSerializer() { } diff --git a/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs b/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs index 3f774979daad..9aaf09bb355c 100644 --- a/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs +++ b/sdk/core/Azure.Core/api/Azure.Core.netstandard2.0.cs @@ -539,6 +539,8 @@ public abstract partial class RequestContent : System.IDisposable { protected RequestContent() { } public static Azure.Core.RequestContent Create(Azure.Core.Serialization.DynamicData content) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static Azure.Core.RequestContent Create(Azure.Core.Serialization.IModelSerializable model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } public static Azure.Core.RequestContent Create(System.BinaryData content) { throw null; } public static Azure.Core.RequestContent Create(System.Buffers.ReadOnlySequence bytes) { throw null; } public static Azure.Core.RequestContent Create(byte[] bytes) { throw null; } @@ -1075,6 +1077,12 @@ public ServerCertificateCustomValidationArgs(System.Security.Cryptography.X509Ce } namespace Azure.Core.Serialization { + [System.AttributeUsageAttribute(System.AttributeTargets.Class)] + public sealed partial class AbstractHierarchyDeserializerAttribute : System.Attribute + { + public AbstractHierarchyDeserializerAttribute(System.Type typeToActivate) { } + public System.Type TypeToActivate { get { throw null; } } + } [System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")] public sealed partial class DynamicData : System.Dynamic.IDynamicMetaObjectProvider, System.IDisposable { @@ -1109,6 +1117,16 @@ public partial interface IMemberNameConverter { string? ConvertMemberName(System.Reflection.MemberInfo member); } + public partial interface IModelJsonSerializable : Azure.Core.Serialization.IModelSerializable + { + T Deserialize(ref System.Text.Json.Utf8JsonReader reader, Azure.Core.Serialization.ModelSerializerOptions options); + void Serialize(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.ModelSerializerOptions options); + } + public partial interface IModelSerializable + { + T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions options); + System.BinaryData Serialize(Azure.Core.Serialization.ModelSerializerOptions options); + } public partial class JsonObjectSerializer : Azure.Core.Serialization.ObjectSerializer, Azure.Core.Serialization.IMemberNameConverter { public JsonObjectSerializer() { } @@ -1127,6 +1145,54 @@ public enum JsonPropertyNames UseExact = 0, CamelCase = 1, } + public partial class ModelJsonConverter : System.Text.Json.Serialization.JsonConverter> + { + public ModelJsonConverter() { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerFormat format) { } + public ModelJsonConverter(Azure.Core.Serialization.ModelSerializerOptions options) { } + public Azure.Core.Serialization.ModelSerializerOptions ModelSerializerOptions { get { throw null; } } + public override bool CanConvert(System.Type typeToConvert) { throw null; } + public override Azure.Core.Serialization.IModelJsonSerializable Read(ref System.Text.Json.Utf8JsonReader reader, System.Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { throw null; } + public override void Write(System.Text.Json.Utf8JsonWriter writer, Azure.Core.Serialization.IModelJsonSerializable value, System.Text.Json.JsonSerializerOptions options) { } + } + public static partial class ModelSerializer + { + public static object Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static object Deserialize(System.BinaryData data, System.Type returnType, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static T Deserialize(System.BinaryData data, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerFormat format) { throw null; } + public static System.BinaryData Serialize(object model, Azure.Core.Serialization.ModelSerializerOptions? options = null) { throw null; } + public static System.BinaryData SerializeCore(Azure.Core.Serialization.IModelJsonSerializable model, Azure.Core.Serialization.ModelSerializerOptions options) { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerFormat format) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + public static System.BinaryData Serialize(T model, Azure.Core.Serialization.ModelSerializerOptions? options = null) where T : Azure.Core.Serialization.IModelSerializable { throw null; } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct ModelSerializerFormat : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Json; + public static readonly Azure.Core.Serialization.ModelSerializerFormat Wire; + public ModelSerializerFormat(string value) { throw null; } + public bool Equals(Azure.Core.Serialization.ModelSerializerFormat other) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override bool Equals(object obj) { throw null; } + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public override int GetHashCode() { throw null; } + public static bool operator ==(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public static implicit operator Azure.Core.Serialization.ModelSerializerFormat (string value) { throw null; } + public static bool operator !=(Azure.Core.Serialization.ModelSerializerFormat left, Azure.Core.Serialization.ModelSerializerFormat right) { throw null; } + public override string ToString() { throw null; } + } + public partial class ModelSerializerOptions + { + public static readonly Azure.Core.Serialization.ModelSerializerOptions DefaultWireOptions; + public ModelSerializerOptions() { } + public ModelSerializerOptions(Azure.Core.Serialization.ModelSerializerFormat format) { } + public Azure.Core.Serialization.ModelSerializerFormat Format { get { throw null; } } + public System.Func? GenericTypeSerializerCreator { get { throw null; } set { } } + } public abstract partial class ObjectSerializer { protected ObjectSerializer() { } diff --git a/sdk/core/Azure.Core/perf/Azure.Core.Perf.csproj b/sdk/core/Azure.Core/perf/Azure.Core.Perf.csproj index 724b7428071d..be1c0a02238f 100644 --- a/sdk/core/Azure.Core/perf/Azure.Core.Perf.csproj +++ b/sdk/core/Azure.Core/perf/Azure.Core.Perf.csproj @@ -12,6 +12,7 @@ + @@ -24,6 +25,9 @@ Always + + Always + diff --git a/sdk/core/Azure.Core/perf/DynamicObjectBenchmark.cs b/sdk/core/Azure.Core/perf/DynamicObjectBenchmark.cs index 82024b6fdaf7..35874158ba52 100644 --- a/sdk/core/Azure.Core/perf/DynamicObjectBenchmark.cs +++ b/sdk/core/Azure.Core/perf/DynamicObjectBenchmark.cs @@ -12,7 +12,6 @@ namespace Azure.Core.Perf { - [MemoryDiagnoser] [SimpleJob(RuntimeMoniker.NetCoreApp31, baseline: true)] [SimpleJob(RuntimeMoniker.Net462)] [SimpleJob(RuntimeMoniker.Net60)] diff --git a/sdk/core/Azure.Core/perf/EventSourceBenchmark.cs b/sdk/core/Azure.Core/perf/EventSourceBenchmark.cs index bc4d93ac65a3..d05eebd0787a 100644 --- a/sdk/core/Azure.Core/perf/EventSourceBenchmark.cs +++ b/sdk/core/Azure.Core/perf/EventSourceBenchmark.cs @@ -13,7 +13,6 @@ namespace Azure.Core.Perf { - [MemoryDiagnoser] [SimpleJob(RuntimeMoniker.Net462)] [SimpleJob(RuntimeMoniker.Net60)] public class EventSourceBenchmark diff --git a/sdk/core/Azure.Core/perf/FastPropertyBagBenchmark.cs b/sdk/core/Azure.Core/perf/FastPropertyBagBenchmark.cs index 15cd0f603175..cb44f530f8b1 100644 --- a/sdk/core/Azure.Core/perf/FastPropertyBagBenchmark.cs +++ b/sdk/core/Azure.Core/perf/FastPropertyBagBenchmark.cs @@ -73,7 +73,6 @@ namespace Azure.Core.Perf { - [MemoryDiagnoser] [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] [CategoriesColumn] [SimpleJob(RuntimeMoniker.Net60)] diff --git a/sdk/core/Azure.Core/perf/HeaderStringValueToStringVsEnumerator.cs b/sdk/core/Azure.Core/perf/HeaderStringValueToStringVsEnumerator.cs index fb430f16d06a..fb4249dd4321 100644 --- a/sdk/core/Azure.Core/perf/HeaderStringValueToStringVsEnumerator.cs +++ b/sdk/core/Azure.Core/perf/HeaderStringValueToStringVsEnumerator.cs @@ -19,7 +19,6 @@ namespace Azure.Core.Perf { - [MemoryDiagnoser] [SimpleJob(RuntimeMoniker.Net60)] public class HeaderStringValueToStringVsEnumerator { diff --git a/sdk/core/Azure.Core/perf/HttpRequestHeaderVsPipelineHeader.cs b/sdk/core/Azure.Core/perf/HttpRequestHeaderVsPipelineHeader.cs index 359aacc3ceb4..a768a85c42e0 100644 --- a/sdk/core/Azure.Core/perf/HttpRequestHeaderVsPipelineHeader.cs +++ b/sdk/core/Azure.Core/perf/HttpRequestHeaderVsPipelineHeader.cs @@ -52,7 +52,6 @@ namespace Azure.Core.Perf { - [MemoryDiagnoser] [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] [CategoriesColumn] [SimpleJob(RuntimeMoniker.Net60)] diff --git a/sdk/core/Azure.Core/perf/Program.cs b/sdk/core/Azure.Core/perf/Program.cs index c630aee8495d..1c2abb0bcc5c 100644 --- a/sdk/core/Azure.Core/perf/Program.cs +++ b/sdk/core/Azure.Core/perf/Program.cs @@ -1,9 +1,40 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Linq; using System.Reflection; using Azure.Test.Perf; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Diagnosers; +using BenchmarkDotNet.Jobs; +using BenchmarkDotNet.Running; +using Perfolizer.Horology; -await PerfProgram.Main(Assembly.GetExecutingAssembly(), args); -// To run Benchmark.NET benchmarks, comment the line above and uncomment the benchmark test below. -// BenchmarkDotNet.Running.BenchmarkRunner.Run(); +if (!args.Contains("--bm")) + await PerfProgram.Main(Assembly.GetExecutingAssembly(), args); +// To run Benchmark.NET benchmarks, use the --bm flag. + +// To see the list of benchmarks that can be run +// dotnet run -c Release --framework net6.0 --bm --list flat + +// To run a specific benchmark class +// dotnet run -c Release --framework net6.0 --bm --filter Azure.Core.Perf.SerializationBenchmark* + +// To run a specific benchmark method +// dotnet run -c Release --framework net6.0 --bm --filter *SerializationBenchmark.Deserialize_PublicInterface +// or +// dotnet run -c Release --framework net6.0 --bm --filter Azure.Core.Perf.SerializationBenchmark.Deserialize_PublicInterface + +// To run a specific benchmark class and category +// dotnet run -c Release --framework net6.0 --bm --anyCategories PublicInterface --filter Azure.Core.Perf.SerializationBenchmark* + +var config = ManualConfig.Create(DefaultConfig.Instance); +config.Options = ConfigOptions.JoinSummary | ConfigOptions.StopOnFirstError; +config = config.AddDiagnoser(MemoryDiagnoser.Default); +config.AddJob(Job.Default + .WithWarmupCount(1) + .WithIterationTime(TimeInterval.FromMilliseconds(250)) + .WithMinIterationCount(15) + .WithMaxIterationCount(20) + .AsDefault()); +BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args.Where(a => !a.Equals("--bm")).ToArray(), config); diff --git a/sdk/core/Azure.Core/perf/RequestContents/ModelContent/LargeModel.cs b/sdk/core/Azure.Core/perf/RequestContents/ModelContent/LargeModel.cs new file mode 100644 index 000000000000..bec72f6746d2 --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/ModelContent/LargeModel.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Tests.ResourceManager.Resources; + +namespace Azure.Core.Perf.RequestContents.ModelContent +{ + public class LargeModel : ModelContentBenchmark + { + protected override string JsonFileName => "ResourceProviderData.json"; + } +} diff --git a/sdk/core/Azure.Core/perf/RequestContents/ModelContent/ModelContentBenchmark.cs b/sdk/core/Azure.Core/perf/RequestContents/ModelContent/ModelContentBenchmark.cs new file mode 100644 index 000000000000..ac3a6acc3819 --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/ModelContent/ModelContentBenchmark.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Serialization; + +namespace Azure.Core.Perf.RequestContents.ModelContent +{ + public abstract class ModelContentBenchmark : RequestContentBenchmark> where T : class, IModelSerializable + { + protected override RequestContent CreateRequestContent() + { + return RequestContent.Create(_model); + } + } +} diff --git a/sdk/core/Azure.Core/perf/RequestContents/ModelContent/SmallModel.cs b/sdk/core/Azure.Core/perf/RequestContents/ModelContent/SmallModel.cs new file mode 100644 index 000000000000..c485debc8ff8 --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/ModelContent/SmallModel.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Tests.ResourceManager.Compute; + +namespace Azure.Core.Perf.RequestContents.ModelContent +{ + public class SmallModel : ModelContentBenchmark + { + protected override string JsonFileName => "AvailabilitySetData.json"; + } +} diff --git a/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/LargeModel.cs b/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/LargeModel.cs new file mode 100644 index 000000000000..059688835f5a --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/LargeModel.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Tests.ResourceManager.Resources; + +namespace Azure.Core.Perf.RequestContents.ModelJsonContent +{ + public class LargeModel : ModelJsonContentBenchmark + { + protected override string JsonFileName => "ResourceProviderData.json"; + } +} diff --git a/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/ModelJsonContentBenchmark.cs b/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/ModelJsonContentBenchmark.cs new file mode 100644 index 000000000000..c44d7fb23a22 --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/ModelJsonContentBenchmark.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Serialization; + +namespace Azure.Core.Perf.RequestContents.ModelJsonContent +{ + public abstract class ModelJsonContentBenchmark : RequestContentBenchmark> where T : class, IModelJsonSerializable + { + protected override RequestContent CreateRequestContent() + { + return RequestContent.Create(_model); + } + } +} diff --git a/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/SmallModel.cs b/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/SmallModel.cs new file mode 100644 index 000000000000..50c640a6c102 --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/ModelJsonContent/SmallModel.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Tests.ResourceManager.Compute; + +namespace Azure.Core.Perf.RequestContents.ModelJsonContent +{ + public class SmallModel : ModelJsonContentBenchmark + { + protected override string JsonFileName => "AvailabilitySetData.json"; + } +} diff --git a/sdk/core/Azure.Core/perf/RequestContents/RequestContentBenchmark.cs b/sdk/core/Azure.Core/perf/RequestContents/RequestContentBenchmark.cs new file mode 100644 index 000000000000..38f2b2f43a00 --- /dev/null +++ b/sdk/core/Azure.Core/perf/RequestContents/RequestContentBenchmark.cs @@ -0,0 +1,60 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Reflection; +using Azure.Core.Serialization; +using BenchmarkDotNet.Attributes; + +namespace Azure.Core.Perf.RequestContents +{ + public abstract class RequestContentBenchmark where T : class + { + protected abstract string JsonFileName { get; } + protected abstract RequestContent CreateRequestContent(); + + protected T _model; + private RequestContent _serializedContent; + private MemoryStream _stream; + + [GlobalSetup] + public void GlobalSetup() + { + string json = File.ReadAllText(Path.Combine(Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName, "TestData", JsonFileName)); + Type modelType = typeof(T).GetGenericArguments()[0]; + _model = ModelSerializer.Deserialize(BinaryData.FromString(json), modelType) as T; + _serializedContent = CreateRequestContent(); + _serializedContent.TryComputeLength(out long length); + _stream = new MemoryStream((int)length); + } + + [GlobalCleanup] + public void GlobalCleanup() + { + _serializedContent.Dispose(); + _serializedContent = null; + } + + [Benchmark] + public void Construct() + { + using RequestContent content = CreateRequestContent(); + } + + [Benchmark] + public long TryComputeLength() + { + using RequestContent content = CreateRequestContent(); + content.TryComputeLength(out long length); + return length; + } + + [Benchmark] + public void WriteTo() + { + _serializedContent.WriteTo(_stream, default); + _stream.Position = 0; + } + } +} diff --git a/sdk/core/Azure.Core/perf/ResourceIdentifierBenchmark.cs b/sdk/core/Azure.Core/perf/ResourceIdentifierBenchmark.cs index fe01f631c641..51264285fb47 100644 --- a/sdk/core/Azure.Core/perf/ResourceIdentifierBenchmark.cs +++ b/sdk/core/Azure.Core/perf/ResourceIdentifierBenchmark.cs @@ -6,7 +6,6 @@ namespace Azure.Core.Perf { [InProcess] - [MemoryDiagnoser] public class ResourceIdentifierBenchmark { [Benchmark] diff --git a/sdk/core/Azure.Core/perf/Serializations/AvailabilitySetDataModel.cs b/sdk/core/Azure.Core/perf/Serializations/AvailabilitySetDataModel.cs new file mode 100644 index 000000000000..5bb785e4dcd7 --- /dev/null +++ b/sdk/core/Azure.Core/perf/Serializations/AvailabilitySetDataModel.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Text.Json; +using Azure.Core.Tests.ResourceManager.Compute; + +namespace Azure.Core.Perf.Serializations +{ + public class AvailabilitySetDataModel : JsonBenchmark + { + protected override AvailabilitySetData Deserialize(JsonElement jsonElement) + { + return AvailabilitySetData.DeserializeAvailabilitySetData(jsonElement, _options); + } + + protected override void Serialize(Utf8JsonWriter writer) + { + _model.Serialize(writer); + } + + protected override RequestContent CastToRequestContent() + { + return _model; + } + + protected override AvailabilitySetData CastFromResponse() + { + return (AvailabilitySetData)_response; + } + + protected override string JsonFileName => "AvailabilitySetData.json"; + } +} diff --git a/sdk/core/Azure.Core/perf/Serializations/BenchmarkConfig.cs b/sdk/core/Azure.Core/perf/Serializations/BenchmarkConfig.cs new file mode 100644 index 000000000000..4468174c3df3 --- /dev/null +++ b/sdk/core/Azure.Core/perf/Serializations/BenchmarkConfig.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using BenchmarkDotNet.Columns; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Reports; +using Perfolizer.Horology; + +namespace Azure.Core.Perf.Serializations +{ + internal class BenchmarkConfig : ManualConfig + { + public BenchmarkConfig() + { + SummaryStyle = SummaryStyle.Default + .WithTimeUnit(TimeUnit.Microsecond) + .WithSizeUnit(SizeUnit.KB); + } + } +} diff --git a/sdk/core/Azure.Core/perf/Serializations/JsonBenchmark.cs b/sdk/core/Azure.Core/perf/Serializations/JsonBenchmark.cs new file mode 100644 index 000000000000..3bf0044b1ae2 --- /dev/null +++ b/sdk/core/Azure.Core/perf/Serializations/JsonBenchmark.cs @@ -0,0 +1,193 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Reflection; +using System.Text; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.TestFramework; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +namespace Azure.Core.Perf.Serializations +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public abstract class JsonBenchmark where T : class, IModelJsonSerializable + { + private string _json; + protected T _model; + protected Response _response; + protected ModelSerializerOptions _options; + private BinaryData _data; + private JsonDocument _jsonDocument; + + protected abstract T Deserialize(JsonElement jsonElement); + + protected abstract void Serialize(Utf8JsonWriter writer); + + protected abstract RequestContent CastToRequestContent(); + + protected abstract T CastFromResponse(); + + protected abstract string JsonFileName { get; } + + [GlobalSetup] + public void SetUp() + { + _json = File.ReadAllText(Path.Combine(Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName, "TestData", JsonFileName)); + _data = BinaryData.FromString(_json); + _model = ModelSerializer.Deserialize(_data); + _response = new MockResponse(200); + _response.ContentStream = new MemoryStream(Encoding.UTF8.GetBytes(_json)); + _options = ModelSerializerOptions.DefaultWireOptions; + _jsonDocument = JsonDocument.Parse(_json); + } + + [Benchmark] + [BenchmarkCategory("Internal")] + public void Serialize_Internal() + { + using var stream = new MemoryStream(); + using var writer = new Utf8JsonWriter(stream); + Serialize(writer); + writer.Flush(); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public void Serialize_ImplicitCast() + { + using var x = CastToRequestContent(); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public bool Serialize_ImplicitCastWithSerialize() + { + using var x = CastToRequestContent(); + return x.TryComputeLength(out var length); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public void Serialize_ImplicitCastWithUsage() + { + using var x = CastToRequestContent(); + x.TryComputeLength(out var length); + using var stream = new MemoryStream((int)length); + x.WriteTo(stream, default); + } + + [Benchmark] + [BenchmarkCategory("ModelJsonConverter")] + public string Serialize_ModelJsonConverter() + { + JsonSerializerOptions options = new JsonSerializerOptions(); + options.Converters.Add(new ModelJsonConverter(ModelSerializerFormat.Wire)); + return JsonSerializer.Serialize(_model, options); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public BinaryData Serialize_ModelSerializer() + { + return ModelSerializer.Serialize(_model, _options); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public BinaryData Serialize_ModelWriter() + { + using var writer = new ModelWriter(_model, _options); + return writer.ToBinaryData(); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public BinaryData Serialize_ModelSerializerNonGeneric() + { + return ModelSerializer.Serialize((object)_model, _options); + } + + [Benchmark] + [BenchmarkCategory("PublicInterface")] + public void Serialize_PublicInterface() + { + using var stream = new MemoryStream(_data.ToMemory().Length); + using var writer = new Utf8JsonWriter(stream); + _model.Serialize(writer, _options); + writer.Flush(); + } + + [Benchmark] + [BenchmarkCategory("Internal")] + public T Deserialize_Internal() + { + return Deserialize(_jsonDocument.RootElement); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public T Deserialize_ExplicitCast() + { + T result = CastFromResponse(); + _response.ContentStream.Position = 0; //reset for reuse + return result; + } + + [Benchmark] + [BenchmarkCategory("ModelJsonConverter")] + public T Deserialize_ModelJsonConverter() + { + JsonSerializerOptions options = new JsonSerializerOptions(); + options.Converters.Add(new ModelJsonConverter(ModelSerializerFormat.Wire)); + return JsonSerializer.Deserialize(_json, options); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public T Deserialize_ModelSerializerFromBinaryData() + { + return ModelSerializer.Deserialize(_data, _options); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public object Deserialize_ModelSerializerFromBinaryDataNonGeneric() + { + return ModelSerializer.Deserialize(_data, typeof(T), _options); + } + + [Benchmark] + [BenchmarkCategory("PublicInterface")] + public T Deserialize_PublicInterfaceFromBinaryData() + { + return _model.Deserialize(_data, _options); + } + + [Benchmark] + [BenchmarkCategory("PublicInterface")] + public T Deserialize_Utf8JsonReaderFromBinaryData() + { + Utf8JsonReader reader = new Utf8JsonReader(_data); + return _model.Deserialize(ref reader, _options); + } + + [Benchmark] + [BenchmarkCategory("JsonDocument")] + public void JsonDocumentFromReader() + { + Utf8JsonReader reader = new Utf8JsonReader(_data); + using var doc = JsonDocument.ParseValue(ref reader); + } + + [Benchmark] + [BenchmarkCategory("JsonDocument")] + public void JsonDocumentFromBinaryData() + { + using var doc = JsonDocument.Parse(_data); + } + } +} diff --git a/sdk/core/Azure.Core/perf/Serializations/ModelXmlModel.cs b/sdk/core/Azure.Core/perf/Serializations/ModelXmlModel.cs new file mode 100644 index 000000000000..c6beb83843b6 --- /dev/null +++ b/sdk/core/Azure.Core/perf/Serializations/ModelXmlModel.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Xml; +using System.Xml.Linq; +using Azure.Core.Tests.ModelSerializationTests.Models; + +namespace Azure.Core.Perf.Serializations +{ + public class ModelXmlModel : XmlBenchmark + { + protected override string XmlFileName => "ModelXml.xml"; + + protected override ModelXml CastFromResponse() + { + return (ModelXml)_response; + } + + protected override RequestContent CastToRequestContent() + { + return _model; + } + + protected override ModelXml Deserialize(XElement xmlElement) + { + return ModelXml.DeserializeModelXml(xmlElement, _options); + } + + protected override void Serialize(XmlWriter writer) + { + _model.Serialize(writer, null); + } + } +} diff --git a/sdk/core/Azure.Core/perf/Serializations/ResourceProviderDataModel.cs b/sdk/core/Azure.Core/perf/Serializations/ResourceProviderDataModel.cs new file mode 100644 index 000000000000..43ba6583edee --- /dev/null +++ b/sdk/core/Azure.Core/perf/Serializations/ResourceProviderDataModel.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Text.Json; +using Azure.Core.Tests.ResourceManager.Resources; +using BenchmarkDotNet.Attributes; + +namespace Azure.Core.Perf.Serializations +{ + [Config(typeof(BenchmarkConfig))] + public class ResourceProviderDataModel : JsonBenchmark + { + protected override string JsonFileName => "ResourceProviderData.json"; + + protected override ResourceProviderData CastFromResponse() + { + return (ResourceProviderData)_response; + } + + protected override RequestContent CastToRequestContent() + { + return _model; + } + + protected override ResourceProviderData Deserialize(JsonElement jsonElement) + { + return ResourceProviderData.DeserializeResourceProviderData(jsonElement, _options); + } + + protected override void Serialize(Utf8JsonWriter writer) + { + _model.Serialize(writer); + } + } +} diff --git a/sdk/core/Azure.Core/perf/Serializations/XmlBenchmark.cs b/sdk/core/Azure.Core/perf/Serializations/XmlBenchmark.cs new file mode 100644 index 000000000000..5b0803983119 --- /dev/null +++ b/sdk/core/Azure.Core/perf/Serializations/XmlBenchmark.cs @@ -0,0 +1,135 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Reflection; +using System.Text; +using System.Xml; +using System.Xml.Linq; +using Azure.Core.Serialization; +using Azure.Core.TestFramework; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +namespace Azure.Core.Perf.Serializations +{ + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public abstract class XmlBenchmark where T : class, IModelSerializable + { + private string _xml; + protected T _model; + protected Response _response; + protected ModelSerializerOptions _options; + private BinaryData _data; + private XElement _element; + + protected abstract T Deserialize(XElement xmlElement); + + protected abstract void Serialize(XmlWriter writer); + + protected abstract RequestContent CastToRequestContent(); + + protected abstract T CastFromResponse(); + + protected abstract string XmlFileName { get; } + + [GlobalSetup] + public void SetUp() + { + _xml = File.ReadAllText(Path.Combine(Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName, "TestData", XmlFileName)); + _data = BinaryData.FromString(_xml); + _model = ModelSerializer.Deserialize(_data); + _response = new MockResponse(200); + _response.ContentStream = new MemoryStream(Encoding.UTF8.GetBytes(_xml)); + _options = ModelSerializerOptions.DefaultWireOptions; + _element = XElement.Parse(_xml); + } + + [Benchmark] + [BenchmarkCategory("Internal")] + public void Serialize_Internal() + { + using var stream = new MemoryStream(); + using var writer = XmlWriter.Create(stream); + Serialize(writer); + writer.Flush(); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public void Serialize_ImplicitCast() + { + using var x = CastToRequestContent(); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public bool Serialize_ImplicitCastWithSerialize() + { + using var x = CastToRequestContent(); + return x.TryComputeLength(out var length); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public void Serialize_ImplicitCastWithUsage() + { + using var x = CastToRequestContent(); + x.TryComputeLength(out var length); + using var stream = new MemoryStream((int)length); + x.WriteTo(stream, default); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public BinaryData Serialize_ModelSerializer() + { + return ModelSerializer.Serialize(_model, _options); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public BinaryData Serialize_ModelSerializerNonGeneric() + { + return ModelSerializer.Serialize((object)_model, _options); + } + + [Benchmark] + [BenchmarkCategory("Internal")] + public T Deserialize_Internal() + { + return Deserialize(_element); + } + + [Benchmark] + [BenchmarkCategory("Cast")] + public T Deserialize_ExplicitCast() + { + T result = CastFromResponse(); + _response.ContentStream.Position = 0; //reset for reuse + return result; + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public T Deserialize_ModelSerializerFromBinaryData() + { + return ModelSerializer.Deserialize(_data, _options); + } + + [Benchmark] + [BenchmarkCategory("ModelSerializer")] + public object Deserialize_ModelSerializerFromBinaryDataNonGeneric() + { + return ModelSerializer.Deserialize(_data, typeof(T), _options); + } + + [Benchmark] + [BenchmarkCategory("PublicInterface")] + public T Deserialize_PublicInterfaceFromBinaryData() + { + return _model.Deserialize(_data, _options); + } + } +} diff --git a/sdk/core/Azure.Core/src/Azure.Core.csproj b/sdk/core/Azure.Core/src/Azure.Core.csproj index 5442dd31e5c2..77c33dda5ecd 100644 --- a/sdk/core/Azure.Core/src/Azure.Core.csproj +++ b/sdk/core/Azure.Core/src/Azure.Core.csproj @@ -1,4 +1,4 @@ - + This is the implementation of the Azure Client Pipeline Microsoft Azure Client Pipeline @@ -66,6 +66,7 @@ + diff --git a/sdk/core/Azure.Core/src/RequestContent.cs b/sdk/core/Azure.Core/src/RequestContent.cs index fe19517dd70c..f9b4d60cd233 100644 --- a/sdk/core/Azure.Core/src/RequestContent.cs +++ b/sdk/core/Azure.Core/src/RequestContent.cs @@ -86,6 +86,22 @@ public abstract class RequestContent : IDisposable /// An instance of that wraps a serialized version of the object. public static RequestContent Create(object serializable) => Create(serializable, JsonObjectSerializer.Default); + /// + /// Creates an instance of that wraps a serialized version of an object. + /// + /// The to serialize. + /// The to use. + /// An instance of that wraps a serialized version of the object. + public static RequestContent Create(IModelSerializable model, ModelSerializerOptions? options = default) => new ModelSerializableContent(model, options ?? ModelSerializerOptions.DefaultWireOptions); + + /// + /// Creates an instance of that wraps a serialized version of an object. + /// + /// The to serialize. + /// The to use. + /// An instance of that wraps a serialized version of the object. + public static RequestContent Create(IModelJsonSerializable model, ModelSerializerOptions? options = default) => new ModelJsonSerializableContent(model, options ?? ModelSerializerOptions.DefaultWireOptions); + /// /// Creates an instance of that wraps a serialized version of an object. /// @@ -220,6 +236,63 @@ public override void Dispose() } } + private sealed class ModelJsonSerializableContent : RequestContent + { + private readonly IModelJsonSerializable _model; + private readonly ModelSerializerOptions _options; + + public ModelJsonSerializableContent(IModelJsonSerializable model, ModelSerializerOptions options) + { + _model = model; + _options = options; + } + + private ModelWriter? _writer; + private ModelWriter Writer => _writer ??= new ModelWriter(_model, _options); + + public override void Dispose() => _writer?.Dispose(); + + public override void WriteTo(Stream stream, CancellationToken cancellation) => Writer.CopyTo(stream, cancellation); + + public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) => await Writer.CopyToAsync(stream, cancellation).ConfigureAwait(false); + + public override bool TryComputeLength(out long length) => Writer.TryComputeLength(out length); + } + + private sealed class ModelSerializableContent : RequestContent + { + private readonly IModelSerializable _model; + private readonly ModelSerializerOptions _options; + + public ModelSerializableContent(IModelSerializable model, ModelSerializerOptions options) + { + _model = model; + _options = options; + } + + public override void Dispose() { } + + private BinaryData? _data; + private BinaryData Data => _data ??= _model.Serialize(_options); + +#if NETFRAMEWORK || NETSTANDARD2_0 + private byte[]? _bytes; + private byte[] Bytes => _bytes ??= Data.ToArray(); + + public override void WriteTo(Stream stream, CancellationToken cancellation) => stream.Write(Bytes, 0, Bytes.Length); +#else + public override void WriteTo(Stream stream, CancellationToken cancellation) => stream.Write(Data.ToMemory().Span); +#endif + + public override bool TryComputeLength(out long length) + { + length = Data.ToMemory().Length; + return true; + } + + public override async Task WriteToAsync(Stream stream, CancellationToken cancellation) => await stream.WriteAsync(Data.ToMemory(), cancellation).ConfigureAwait(false); + } + private sealed class ArrayContent : RequestContent { private readonly byte[] _bytes; diff --git a/sdk/core/Azure.Core/src/Serialization/AbstractHierarchyDeserializerAttribute.cs b/sdk/core/Azure.Core/src/Serialization/AbstractHierarchyDeserializerAttribute.cs new file mode 100644 index 000000000000..bf16d71561ba --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/AbstractHierarchyDeserializerAttribute.cs @@ -0,0 +1,34 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Azure.Core.Serialization +{ + /// + /// Attribute class that indicates which subtype of an abstract class is the + /// that knows how to deserialize the hierarchy. The type should be able to determine which subtype should be deserialized + /// and return an instance of that subtype. + /// + [AttributeUsage(AttributeTargets.Class)] + public sealed class AbstractHierarchyDeserializerAttribute : Attribute + { + /// + /// Instantiates a new instance of the class. + /// + /// The to activate and call deserialize on. + public AbstractHierarchyDeserializerAttribute([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type typeToActivate) + { + TypeToActivate = typeToActivate; + } + + /// + /// Gets the to activate and call deserialize on. + /// The type must have a public or non-public parameterless constructor. + /// The type must implement where T is the type of the abstract class. + /// + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] + public Type TypeToActivate { get; } + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/IModelJsonSerializable.cs b/sdk/core/Azure.Core/src/Serialization/IModelJsonSerializable.cs new file mode 100644 index 000000000000..6659988e6bd3 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/IModelJsonSerializable.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Text.Json; + +namespace Azure.Core.Serialization +{ + /// + /// Allows an object to control its own JSON serialization and deserialization. + /// + /// The type to deserialize the JSON value into. + public interface IModelJsonSerializable : IModelSerializable + { + /// + /// Serializes the model to the provided . + /// + /// The to serialize into. + /// The to use. + /// If the model does not support the requested . + /// If format is passed in and the model does not use JSON for its wire format. +#pragma warning disable AZC0014 // Avoid using banned types in public API + void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options); +#pragma warning restore AZC0014 // Avoid using banned types in public API + + /// + /// Reads one JSON value (including objects or arrays) from the provided reader and converts it to a model. + /// + /// The to read. + /// The to use. + /// A representation of the JSON value. + /// If the model does not support the requested . + /// If format is passed in and the model does not use JSON for its wire format. +#pragma warning disable AZC0014 // Avoid using banned types in public API + T Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options); +#pragma warning restore AZC0014 // Avoid using banned types in public API + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/IModelSerializable.cs b/sdk/core/Azure.Core/src/Serialization/IModelSerializable.cs new file mode 100644 index 000000000000..91657484a2e0 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/IModelSerializable.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; + +namespace Azure.Core.Serialization +{ + /// + /// Allows an object to control its own serialization and deserialization. + /// The format of the serialization is determined by the implementer. + /// + /// The type the serialized value can be deserialized to. + public interface IModelSerializable + { + /// + /// Serializes the model into a . + /// + /// The to use. + /// A binary representation of the serialized model. + /// If the model does not support the requested . + BinaryData Serialize(ModelSerializerOptions options); + + /// + /// Converts the provided into a model. + /// + /// The to parse. + /// The to use. + /// A representation of the data. + /// If the model does not support the requested . + T Deserialize(BinaryData data, ModelSerializerOptions options); + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/ModelJsonConverter.cs b/sdk/core/Azure.Core/src/Serialization/ModelJsonConverter.cs new file mode 100644 index 000000000000..ee39cd40ad56 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/ModelJsonConverter.cs @@ -0,0 +1,71 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Diagnostics.CodeAnalysis; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Azure.Core.Serialization +{ + /// + /// A generic converter which allows to be able to serialize and deserialize any models that implement . + /// +#pragma warning disable AZC0014 // Avoid using banned types in public API +#if !NET5_0 // RequiresUnreferencedCode in net5.0 doesn't have AttributeTargets.Class as a target, but it was added in net6.0 + [RequiresUnreferencedCode("The constructors of the type being deserialized are dynamically accessed and may be trimmed.")] +#endif + public class ModelJsonConverter : JsonConverter> +#pragma warning restore AZC0014 // Avoid using banned types in public API + { + /// + /// Gets the used to serialize and deserialize models. + /// + public ModelSerializerOptions ModelSerializerOptions { get; } + + /// + /// Initializes a new instance of with a default format of . + /// + public ModelJsonConverter() + : this(ModelSerializerFormat.Json) { } + + /// + /// Initializes a new instance of . + /// + /// The format to serialize to and deserialize from. + public ModelJsonConverter(ModelSerializerFormat format) + : this(ModelSerializerOptions.GetOptions(format)) { } + + /// + /// Initializes a new instance of . + /// + /// The to use. + public ModelJsonConverter(ModelSerializerOptions options) + { + ModelSerializerOptions = options; + } + + /// + public override bool CanConvert(Type typeToConvert) + { + return !Attribute.IsDefined(typeToConvert, typeof(JsonConverterAttribute)); + } + + /// +#pragma warning disable AZC0014 // Avoid using banned types in public API + public override IModelJsonSerializable Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) +#pragma warning restore AZC0014 // Avoid using banned types in public API + { + using JsonDocument document = JsonDocument.ParseValue(ref reader); + return (IModelJsonSerializable)ModelSerializer.Deserialize(BinaryData.FromString(document.RootElement.GetRawText()), typeToConvert, ModelSerializerOptions); + } + + /// +#pragma warning disable AZC0014 // Avoid using banned types in public API + public override void Write(Utf8JsonWriter writer, IModelJsonSerializable value, JsonSerializerOptions options) +#pragma warning restore AZC0014 // Avoid using banned types in public API + { + value.Serialize(writer, ModelSerializerOptions); + } + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/ModelSerializer.cs b/sdk/core/Azure.Core/src/Serialization/ModelSerializer.cs new file mode 100644 index 000000000000..2a057f420e42 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/ModelSerializer.cs @@ -0,0 +1,204 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Azure.Core.Serialization +{ + /// + /// Provides functionality to serialize and deserialize Azure models. + /// + public static class ModelSerializer + { + /// + /// Converts the value of a model into a . + /// + /// The type of the value to serialize. + /// The model to convert. + /// The to use. + /// A representation of the model in the specified by the . + /// If the model does not support the requested . + /// If is null. + public static BinaryData Serialize(T model, ModelSerializerOptions? options = default) where T : IModelSerializable + { + Argument.AssertNotNull(model, nameof(model)); + + options ??= ModelSerializerOptions.DefaultWireOptions; + + return model.Serialize(options); + } + + /// + /// Converts the value of a model into a . + /// + /// The type of the value to serialize. + /// The model to convert. + /// The to use. + /// A representation of the model in the specified by the . + /// If the model does not support the requested . + /// If is null. + public static BinaryData Serialize(T model, ModelSerializerFormat format) + where T : IModelSerializable + => Serialize(model, ModelSerializerOptions.GetOptions(format)); + + /// + /// Converts the value of a model into a . + /// + /// The model to convert. + /// The to use. + /// A representation of the model in the specified by the . + /// Throws if does not implement . + /// If the model does not support the requested . + /// If is null. + public static BinaryData Serialize(object model, ModelSerializerOptions? options = default) + { + Argument.AssertNotNull(model, nameof(model)); + + options ??= ModelSerializerOptions.DefaultWireOptions; + + var iModel = model as IModelSerializable; + if (iModel is null) + { + throw new InvalidOperationException($"{model.GetType().Name} does not implement {nameof(IModelSerializable)}"); + } + + return iModel.Serialize(options); + } + + /// + /// Converts the value of a model into a . + /// + /// The model to convert. + /// The to use. + /// A representation of the model in the specified by the . + /// Throws if does not implement . + /// If the model does not support the requested . + /// If is null. + public static BinaryData Serialize(object model, ModelSerializerFormat format) + => Serialize(model, ModelSerializerOptions.GetOptions(format)); + + /// + /// Converts the into a . + /// + /// The to convert. + /// The to use. + /// A representation of the . + /// Throws if does not have a public or internal parameterless constructor. + /// If the model does not support the requested . + /// If is null. + public static T Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] T>(BinaryData data, ModelSerializerOptions? options = default) where T : IModelSerializable + { + Argument.AssertNotNull(data, nameof(data)); + + options ??= ModelSerializerOptions.DefaultWireOptions; + + return GetInstance().Deserialize(data, options); + } + + /// + /// Converts the into a . + /// + /// The to convert. + /// The to use. + /// A representation of the . + /// Throws if does not have a public or internal parameterless constructor. + /// If the model does not support the requested . + /// If is null. + public static T Deserialize<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] T>(BinaryData data, ModelSerializerFormat format) + where T : IModelSerializable + => Deserialize(data, ModelSerializerOptions.GetOptions(format)); + + /// + /// Converts the into a . + /// + /// The to convert. + /// The type of the objec to convert and return. + /// The to use. + /// A representation of the . + /// Throws if does not implement . + /// Throws if does not have a public or internal parameterless constructor. + /// If the model does not support the requested . + /// If or are null. + public static object Deserialize(BinaryData data, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type returnType, ModelSerializerOptions? options = default) + { + Argument.AssertNotNull(data, nameof(data)); + Argument.AssertNotNull(returnType, nameof(returnType)); + + options ??= ModelSerializerOptions.DefaultWireOptions; + + return GetInstance(returnType).Deserialize(data, options); + } + + /// + /// Converts the into a . + /// + /// The to convert. + /// The type of the objec to convert and return. + /// The to use. + /// A representation of the . + /// Throws if does not implement . + /// Throws if does not have a public or internal parameterless constructor. + /// If the model does not support the requested . + /// If or are null. + public static object Deserialize(BinaryData data, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type returnType, ModelSerializerFormat format) + => Deserialize(data, returnType, ModelSerializerOptions.GetOptions(format)); + + /// + /// Converts the value of a model into a . + /// + /// The model to convert. + /// The to use. + /// A representation of the model in the specified by the . + /// If or are null. + public static BinaryData SerializeCore(IModelJsonSerializable model, ModelSerializerOptions options) + { + Argument.AssertNotNull(model, nameof(model)); + Argument.AssertNotNull(options, nameof(options)); + + using ModelWriter writer = new ModelWriter(model, options); + return writer.ToBinaryData(); + } + + private static IModelSerializable GetInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type returnType) + { + var model = GetObjectInstance(returnType) as IModelSerializable; + if (model is null) + { + throw new InvalidOperationException($"{returnType.Name} does not implement {nameof(IModelSerializable)}"); + } + return model; + } + + private static IModelSerializable GetInstance<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] T>() where T : IModelSerializable + { + var model = GetObjectInstance(typeof(T)) as IModelSerializable; + if (model is null) + { + throw new InvalidOperationException($"{typeof(T).Name} does not implement {nameof(IModelSerializable)}"); + } + return model; + } + + private static object GetObjectInstance([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicConstructors | DynamicallyAccessedMemberTypes.NonPublicConstructors)] Type returnType) + { + Type typeToActivate = returnType; + if (returnType.IsAbstract) + { + AbstractHierarchyDeserializerAttribute? attribute = Attribute.GetCustomAttribute(returnType, typeof(AbstractHierarchyDeserializerAttribute)) as AbstractHierarchyDeserializerAttribute; + if (attribute is null) + { + throw new InvalidOperationException($"{returnType.Name} must have {nameof(AbstractHierarchyDeserializerAttribute)} to be used with {nameof(ModelSerializer)}"); + } + typeToActivate = attribute.TypeToActivate; + } + + var obj = Activator.CreateInstance(typeToActivate, true); + if (obj is null) + { + throw new InvalidOperationException($"Unable to create instance of {typeToActivate.Name}."); + } + return obj; + } + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/ModelSerializerFormat.cs b/sdk/core/Azure.Core/src/Serialization/ModelSerializerFormat.cs new file mode 100644 index 000000000000..7a4b8a7ce7f8 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/ModelSerializerFormat.cs @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.ComponentModel; + +namespace Azure.Core.Serialization +{ + /// + /// A format used to specify how a model should be serialized and deserialized. + /// + public readonly partial struct ModelSerializerFormat : IEquatable + { + internal const string JsonValue = "J"; + internal const string WireValue = "W"; + + /// + /// Default format which will serialize all properties including read-only and additional properties. + /// The format will always be JSON. + /// + public static readonly ModelSerializerFormat Json = new ModelSerializerFormat(JsonValue); + + /// + /// Format used to serialize this model when sending as a request to an Azure service. + /// It may not serialize read-only properties or additional properties. + /// The content-type will vary between JSON, XML, etc., depending on the service. + /// + /// Most use cases should prefer a more complete format like that includes + /// read-only and additional properties. + /// + public static readonly ModelSerializerFormat Wire = new ModelSerializerFormat(WireValue); + + private readonly string _value; + + /// + /// Instantiate a new . + /// + public ModelSerializerFormat(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + /// + /// Determines if two values are the same. + /// + /// The first to compare. + /// The second to compare. + /// True if and are the same; otherwise, false. + public static bool operator ==(ModelSerializerFormat left, ModelSerializerFormat right) => left.Equals(right); + + /// + /// Determines if two values are different. + /// + /// The first to compare. + /// The second to compare. + /// True if and are different; otherwise, false. + public static bool operator !=(ModelSerializerFormat left, ModelSerializerFormat right) => !left.Equals(right); + + /// + /// Converts a string to a . + /// + /// The string value to convert. + public static implicit operator ModelSerializerFormat(string value) => new ModelSerializerFormat(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals([System.Diagnostics.CodeAnalysis.AllowNull] object obj) => obj is ModelSerializerFormat other && Equals(other); + + /// + public bool Equals(ModelSerializerFormat other) => string.Equals(_value, other._value, StringComparison.Ordinal); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + + /// + public override string ToString() => _value; + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/ModelSerializerOptions.cs b/sdk/core/Azure.Core/src/Serialization/ModelSerializerOptions.cs new file mode 100644 index 000000000000..a734b22c56f0 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/ModelSerializerOptions.cs @@ -0,0 +1,74 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; + +namespace Azure.Core.Serialization +{ + /// + /// Provides the client options for serializing models. + /// + public class ModelSerializerOptions + { + private static readonly IReadOnlyDictionary _singletonMap = new Dictionary() + { + { ModelSerializerFormat.Json, new ModelSerializerOptions(ModelSerializerFormat.Json, true) }, + { ModelSerializerFormat.Wire, new ModelSerializerOptions(ModelSerializerFormat.Wire, true) } + }; + + /// + /// Default options for serializing models into the format the Azure serivce is expecting. + /// + public static readonly ModelSerializerOptions DefaultWireOptions = _singletonMap[ModelSerializerFormat.Wire]; + + internal static ModelSerializerOptions GetOptions(ModelSerializerFormat format) + => _singletonMap.TryGetValue(format, out ModelSerializerOptions? options) ? options! : new ModelSerializerOptions(format); + + private bool _isFrozen; + private Func? _genericTypeSerializerCreator; + + /// + /// Initializes a new instance of the class. Defaults to format . + /// + public ModelSerializerOptions() : this(ModelSerializerFormat.Json, false) { } + + /// + /// Initializes a new instance of the class. + /// + /// String that determines of serialized model.. + public ModelSerializerOptions(ModelSerializerFormat format) : this(format, false) { } + + private ModelSerializerOptions(ModelSerializerFormat format, bool isFrozen) + { + Format = format; + _isFrozen = isFrozen; + } + + /// + /// Gets the that determines format of serialized model. + /// + public ModelSerializerFormat Format { get; } + + /// + /// Gets or sets a factory method that returns an based on the provided . + /// Should return null if the type is not supported. + /// + public Func? GenericTypeSerializerCreator + { + get + { + return _genericTypeSerializerCreator; + } + set + { + if (_isFrozen) + { + throw new InvalidOperationException("Cannot modify static options reference."); + } + + _genericTypeSerializerCreator = value; + } + } + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/ModelWriter.SequenceBuilder.cs b/sdk/core/Azure.Core/src/Serialization/ModelWriter.SequenceBuilder.cs new file mode 100644 index 000000000000..ec311ccd0d45 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/ModelWriter.SequenceBuilder.cs @@ -0,0 +1,169 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Buffers; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace Azure.Core.Serialization +{ + internal sealed partial class ModelWriter : IDisposable + { + private sealed class SequenceBuilder : IBufferWriter, IDisposable + { + private struct Buffer + { + public byte[] Array; + public int Written; + } + + private volatile Buffer[] _buffers; // this is an array so items can be accessed by ref + private volatile int _count; + private readonly int _segmentSize; + + /// + /// Initializes a new instance of . + /// + /// The size of each buffer segment. + public SequenceBuilder(int segmentSize = 16384) + { + // we perf tested a very large and a small model and found that the performance + // for 4k, 8k, 16k, 32k, was neglible for the small model but had a 30% alloc improvment + // from 4k to 16k on the very large model. + _segmentSize = segmentSize; + _buffers = Array.Empty(); + } + + /// + /// Notifies the that bytes bytes were written to the output or . + /// You must request a new buffer after calling to continue writing more data; you cannot write to a previously acquired buffer. + /// + /// The number of bytes written to the or . + /// + public void Advance(int bytesWritten) + { + ref Buffer last = ref _buffers[_count - 1]; + last.Written += bytesWritten; + if (last.Written > last.Array.Length) + { + throw new ArgumentOutOfRangeException(nameof(bytesWritten)); + } + } + + /// + /// Returns a to write to that is at least the requested size, as specified by the parameter. + /// + /// The minimum length of the returned . If less than 256, a buffer of size 256 will be returned. + /// A memory buffer of at least bytes. If is less than 256, a buffer of size 256 will be returned. + public Memory GetMemory(int sizeHint = 0) + { + if (sizeHint < 256) + { + sizeHint = 256; + } + + int sizeToRent = sizeHint > _segmentSize ? sizeHint : _segmentSize; + + if (_buffers.Length == 0) + { + ExpandBuffers(sizeToRent); + } + + ref Buffer last = ref _buffers[_count - 1]; + Memory free = last.Array.AsMemory(last.Written); + if (free.Length >= sizeHint) + { + return free; + } + + // else allocate a new buffer: + ExpandBuffers(sizeToRent); + + return _buffers[_count - 1].Array; + } + + private readonly object _lock = new object(); + private void ExpandBuffers(int sizeToRent) + { + lock (_lock) + { + int bufferCount = _count == 0 ? 1 : _count * 2; + + Buffer[] resized = new Buffer[bufferCount]; + if (_count > 0) + { + _buffers.CopyTo(resized, 0); + } + _buffers = resized; + _buffers[_count].Array = ArrayPool.Shared.Rent(sizeToRent); + _count = bufferCount == 1 ? bufferCount : _count + 1; + } + } + + /// + /// Returns a to write to that is at least the requested size, as specified by the parameter. + /// + /// The minimum length of the returned . If less than 256, a buffer of size 256 will be returned. + /// A buffer of at least bytes. If is less than 256, a buffer of size 256 will be returned. + public Span GetSpan(int sizeHint = 0) + { + Memory memory = GetMemory(sizeHint); + return memory.Span; + } + + /// + /// Disposes the SequenceWriter and returns the underlying buffers to the pool. + /// + public void Dispose() + { + int bufferCountToFree; + Buffer[] buffersToFree; + lock (_lock) + { + bufferCountToFree = _count; + buffersToFree = _buffers; + _count = 0; + _buffers = Array.Empty(); + } + + for (int i = 0; i < bufferCountToFree; i++) + { + ArrayPool.Shared.Return(buffersToFree[i].Array); + } + } + + /// + public bool TryComputeLength(out long length) + { + length = 0; + for (int i = 0; i < _count; i++) + { + length += _buffers[i].Written; + } + return true; + } + + /// + public void CopyTo(Stream stream, CancellationToken cancellation) + { + for (int i = 0; i < _count; i++) + { + Buffer buffer = _buffers[i]; + stream.Write(buffer.Array, 0, buffer.Written); + } + } + + /// + public async Task CopyToAsync(Stream stream, CancellationToken cancellation) + { + for (int i = 0; i < _count; i++) + { + Buffer buffer = _buffers[i]; + await stream.WriteAsync(buffer.Array, 0, buffer.Written).ConfigureAwait(false); + } + } + } + } +} diff --git a/sdk/core/Azure.Core/src/Serialization/ModelWriter.cs b/sdk/core/Azure.Core/src/Serialization/ModelWriter.cs new file mode 100644 index 000000000000..0b5cae45eb75 --- /dev/null +++ b/sdk/core/Azure.Core/src/Serialization/ModelWriter.cs @@ -0,0 +1,197 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; + +namespace Azure.Core.Serialization +{ + /// + /// Provides an efficient way to serialize into a using multiple pooled buffers. + /// + internal sealed partial class ModelWriter : IDisposable + { + private readonly IModelJsonSerializable _model; + private readonly ModelSerializerOptions _options; + + private readonly object _writeLock = new object(); + private readonly object _readLock = new object(); + + private volatile SequenceBuilder? _sequenceBuilder; + private volatile bool _isDisposed; + + private volatile int _readCount; + + private ManualResetEvent? _readersFinished; + private ManualResetEvent ReadersFinished => _readersFinished ??= new ManualResetEvent(true); + + /// + /// Initializes a new instance of . + /// + /// The model to serialize. + /// The to use. + /// If the model does not support the requested . + /// If format is passed in and the model does not use JSON for its wire format. + public ModelWriter(IModelJsonSerializable model, ModelSerializerOptions options) + { + _model = model; + _options = options; + } + + private SequenceBuilder GetSequenceBuilder() + { + if (_sequenceBuilder is null) + { + lock (_writeLock) + { + if (_isDisposed) + { + throw new ObjectDisposedException(nameof(ModelWriter)); + } + + if (_sequenceBuilder is null) + { + SequenceBuilder sequenceBuilder = new SequenceBuilder(); + using var jsonWriter = new Utf8JsonWriter(sequenceBuilder); + _model.Serialize(jsonWriter, _options); + jsonWriter.Flush(); + _sequenceBuilder = sequenceBuilder; + } + } + } + return _sequenceBuilder; + } + + internal void CopyTo(Stream stream, CancellationToken cancellation) + { + SequenceBuilder builder = GetSequenceBuilder(); + IncrementRead(); + try + { + builder.CopyTo(stream, cancellation); + } + finally + { + DecrementRead(); + } + } + + internal bool TryComputeLength(out long length) + { + SequenceBuilder builder = GetSequenceBuilder(); + IncrementRead(); + try + { + return builder.TryComputeLength(out length); + } + finally + { + DecrementRead(); + } + } + + internal async Task CopyToAsync(Stream stream, CancellationToken cancellation) + { + SequenceBuilder builder = GetSequenceBuilder(); + IncrementRead(); + try + { + await builder.CopyToAsync(stream, cancellation).ConfigureAwait(false); + } + finally + { + DecrementRead(); + } + } + + /// + /// Converts the to a . + /// + /// A representation of the serialized in JSON format. + public BinaryData ToBinaryData() + { + SequenceBuilder builder = GetSequenceBuilder(); + IncrementRead(); + try + { + bool gotLength = builder.TryComputeLength(out long length); + if (length > int.MaxValue) + { + throw new InvalidOperationException($"Length of serialized model is too long. Value was {length} max is {int.MaxValue}"); + } + Debug.Assert(gotLength); + using var stream = new MemoryStream((int)length); + builder.CopyTo(stream, default); + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + finally + { + DecrementRead(); + } + } + + /// + public void Dispose() + { + if (!_isDisposed) + { + lock (_writeLock) + { + if (!_isDisposed) + { + _isDisposed = true; + + if (_readersFinished is null || _readersFinished.WaitOne()) + { + //only dispose if no readers ever happened or if all readers are done + _sequenceBuilder?.Dispose(); + } + + _sequenceBuilder = null; + _readersFinished?.Dispose(); + _readersFinished = null; + } + } + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void IncrementRead() + { + if (_isDisposed) + { + throw new ObjectDisposedException(nameof(ModelWriter)); + } + + lock (_readLock) + { + Interlocked.Increment(ref _readCount); + ReadersFinished.Reset(); + } + + if (_isDisposed) + { + DecrementRead(); + throw new ObjectDisposedException(nameof(ModelWriter)); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private void DecrementRead() + { + lock (_readLock) + { + if (Interlocked.Decrement(ref _readCount) == 0) + { + // notify we reached zero readers in case dispose is waiting + ReadersFinished.Set(); + } + } + } + } +} diff --git a/sdk/core/Azure.Core/src/Shared/ModelSerializerHelper.cs b/sdk/core/Azure.Core/src/Shared/ModelSerializerHelper.cs new file mode 100644 index 000000000000..45481db3c91a --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/ModelSerializerHelper.cs @@ -0,0 +1,26 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Runtime.CompilerServices; +using Azure.Core.Serialization; + +namespace Azure.Core +{ + internal static class ModelSerializerHelper + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ValidateFormat(IModelSerializable model, ModelSerializerFormat format) + { + bool implementsJson = model is IModelJsonSerializable; + bool isValid = (format == ModelSerializerFormat.Json && implementsJson) || format == ModelSerializerFormat.Wire; + if (!isValid) + { + throw new FormatException($"The model {model.GetType().Name} does not support '{format}' format."); + } + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void ValidateFormat(IModelSerializable model, ModelSerializerFormat format) => ValidateFormat(model, format); + } +} diff --git a/sdk/core/Azure.Core/src/Shared/TrimmingAttribute.cs b/sdk/core/Azure.Core/src/Shared/TrimmingAttribute.cs new file mode 100644 index 000000000000..dbb5e0ce7512 --- /dev/null +++ b/sdk/core/Azure.Core/src/Shared/TrimmingAttribute.cs @@ -0,0 +1,420 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable enable + +namespace System.Diagnostics.CodeAnalysis; + +#if !NET7_0_OR_GREATER +/// +/// Indicates that the specified method requires the ability to generate new code at runtime, +/// for example through . +/// +/// +/// This allows tools to understand which methods are unsafe to call when compiling ahead of time. +/// +[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)] +internal sealed class RequiresDynamicCodeAttribute : Attribute +{ + /// + /// Initializes a new instance of the class + /// with the specified message. + /// + /// + /// A message that contains information about the usage of dynamic code. + /// + public RequiresDynamicCodeAttribute(string message) + { + Message = message; + } + + /// + /// Gets a message that contains information about the usage of dynamic code. + /// + public string Message { get; } + + /// + /// Gets or sets an optional URL that contains more information about the method, + /// why it requires dynamic code, and what options a consumer has to deal with it. + /// + public string? Url { get; set; } +} +#endif + +#if !NET5_0_OR_GREATER +/// +/// Indicates that the specified method requires dynamic access to code that is not referenced +/// statically, for example through . +/// +/// +/// This allows tools to understand which methods are unsafe to call when removing unreferenced +/// code from an application. +/// +[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class, Inherited = false)] +internal sealed class RequiresUnreferencedCodeAttribute : Attribute +{ + /// + /// Initializes a new instance of the class + /// with the specified message. + /// + /// + /// A message that contains information about the usage of unreferenced code. + /// + public RequiresUnreferencedCodeAttribute(string message) + { + Message = message; + } + + /// + /// Gets a message that contains information about the usage of unreferenced code. + /// + public string Message { get; } + + /// + /// Gets or sets an optional URL that contains more information about the method, + /// why it requires unreferenced code, and what options a consumer has to deal with it. + /// + public string? Url { get; set; } +} + +/// +/// Suppresses reporting of a specific rule violation, allowing multiple suppressions on a +/// single code artifact. +/// +/// +/// is different than +/// in that it doesn't have a +/// . So it is always preserved in the compiled assembly. +/// +[AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] +internal sealed class UnconditionalSuppressMessageAttribute : Attribute +{ + /// + /// Initializes a new instance of the + /// class, specifying the category of the tool and the identifier for an analysis rule. + /// + /// The category for the attribute. + /// The identifier of the analysis rule the attribute applies to. + public UnconditionalSuppressMessageAttribute(string category, string checkId) + { + Category = category; + CheckId = checkId; + } + + /// + /// Gets the category identifying the classification of the attribute. + /// + /// + /// The property describes the tool or tool analysis category + /// for which a message suppression attribute applies. + /// + public string Category { get; } + + /// + /// Gets the identifier of the analysis tool rule to be suppressed. + /// + /// + /// Concatenated together, the and + /// properties form a unique check identifier. + /// + public string CheckId { get; } + + /// + /// Gets or sets the scope of the code that is relevant for the attribute. + /// + /// + /// The Scope property is an optional argument that specifies the metadata scope for which + /// the attribute is relevant. + /// + public string? Scope { get; set; } + + /// + /// Gets or sets a fully qualified path that represents the target of the attribute. + /// + /// + /// The property is an optional argument identifying the analysis target + /// of the attribute. An example value is "System.IO.Stream.ctor():System.Void". + /// Because it is fully qualified, it can be long, particularly for targets such as parameters. + /// The analysis tool user interface should be capable of automatically formatting the parameter. + /// + public string? Target { get; set; } + + /// + /// Gets or sets an optional argument expanding on exclusion criteria. + /// + /// + /// The property is an optional argument that specifies additional + /// exclusion where the literal metadata target is not sufficiently precise. For example, + /// the cannot be applied within a method, + /// and it may be desirable to suppress a violation against a statement in the method that will + /// give a rule violation, but not against all statements in the method. + /// + public string? MessageId { get; set; } + + /// + /// Gets or sets the justification for suppressing the code analysis message. + /// + public string? Justification { get; set; } +} + +/// +/// States a dependency that one member has on another. +/// +/// +/// This can be used to inform tooling of a dependency that is otherwise not evident purely from +/// metadata and IL, for example a member relied on via reflection. +/// +[AttributeUsage( + AttributeTargets.Constructor | AttributeTargets.Field | AttributeTargets.Method, + AllowMultiple = true, Inherited = false)] +internal sealed class DynamicDependencyAttribute : Attribute +{ + /// + /// Initializes a new instance of the class + /// with the specified signature of a member on the same type as the consumer. + /// + /// The signature of the member depended on. + public DynamicDependencyAttribute(string memberSignature) + { + MemberSignature = memberSignature; + } + + /// + /// Initializes a new instance of the class + /// with the specified signature of a member on a . + /// + /// The signature of the member depended on. + /// The containing . + public DynamicDependencyAttribute(string memberSignature, Type type) + { + MemberSignature = memberSignature; + Type = type; + } + + /// + /// Initializes a new instance of the class + /// with the specified signature of a member on a type in an assembly. + /// + /// The signature of the member depended on. + /// The full name of the type containing the specified member. + /// The assembly name of the type containing the specified member. + public DynamicDependencyAttribute(string memberSignature, string typeName, string assemblyName) + { + MemberSignature = memberSignature; + TypeName = typeName; + AssemblyName = assemblyName; + } + + /// + /// Initializes a new instance of the class + /// with the specified types of members on a . + /// + /// The types of members depended on. + /// The containing the specified members. + public DynamicDependencyAttribute(DynamicallyAccessedMemberTypes memberTypes, Type type) + { + MemberTypes = memberTypes; + Type = type; + } + + /// + /// Initializes a new instance of the class + /// with the specified types of members on a type in an assembly. + /// + /// The types of members depended on. + /// The full name of the type containing the specified members. + /// The assembly name of the type containing the specified members. + public DynamicDependencyAttribute(DynamicallyAccessedMemberTypes memberTypes, string typeName, string assemblyName) + { + MemberTypes = memberTypes; + TypeName = typeName; + AssemblyName = assemblyName; + } + + /// + /// Gets the signature of the member depended on. + /// + /// + /// Either must be a valid string or + /// must not equal , but not both. + /// + public string? MemberSignature { get; } + + /// + /// Gets the which specifies the type + /// of members depended on. + /// + /// + /// Either must be a valid string or + /// must not equal , but not both. + /// + public DynamicallyAccessedMemberTypes MemberTypes { get; } + + /// + /// Gets the containing the specified member. + /// + /// + /// If neither nor are specified, + /// the type of the consumer is assumed. + /// + public Type? Type { get; } + + /// + /// Gets the full name of the type containing the specified member. + /// + /// + /// If neither nor are specified, + /// the type of the consumer is assumed. + /// + public string? TypeName { get; } + + /// + /// Gets the assembly name of the specified type. + /// + /// + /// is only valid when is specified. + /// + public string? AssemblyName { get; } + + /// + /// Gets or sets the condition in which the dependency is applicable, e.g. "DEBUG". + /// + public string? Condition { get; set; } +} + +/// +/// Indicates that certain members on a specified are accessed dynamically, +/// for example through . +/// +/// +/// This allows tools to understand which members are being accessed during the execution +/// of a program. +/// +/// This attribute is valid on members whose type is or . +/// +/// When this attribute is applied to a location of type , the assumption is +/// that the string represents a fully qualified type name. +/// +/// When this attribute is applied to a class, interface, or struct, the members specified +/// can be accessed dynamically on instances returned from calling +/// on instances of that class, interface, or struct. +/// +/// If the attribute is applied to a method it's treated as a special case and it implies +/// the attribute should be applied to the "this" parameter of the method. As such the attribute +/// should only be used on instance methods of types assignable to System.Type (or string, but no methods +/// will use it there). +/// +[AttributeUsage( + AttributeTargets.Field | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter | + AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Method | + AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Struct, + Inherited = false)] +internal sealed class DynamicallyAccessedMembersAttribute : Attribute +{ + /// + /// Initializes a new instance of the class + /// with the specified member types. + /// + /// The types of members dynamically accessed. + public DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes memberTypes) + { + MemberTypes = memberTypes; + } + + /// + /// Gets the which specifies the type + /// of members dynamically accessed. + /// + public DynamicallyAccessedMemberTypes MemberTypes { get; } +} + +/// +/// Specifies the types of members that are dynamically accessed. +/// +/// This enumeration has a attribute that allows a +/// bitwise combination of its member values. +/// +[Flags] +internal enum DynamicallyAccessedMemberTypes +{ + /// + /// Specifies no members. + /// + None = 0, + + /// + /// Specifies the default, parameterless public constructor. + /// + PublicParameterlessConstructor = 0x0001, + + /// + /// Specifies all public constructors. + /// + PublicConstructors = 0x0002 | PublicParameterlessConstructor, + + /// + /// Specifies all non-public constructors. + /// + NonPublicConstructors = 0x0004, + + /// + /// Specifies all public methods. + /// + PublicMethods = 0x0008, + + /// + /// Specifies all non-public methods. + /// + NonPublicMethods = 0x0010, + + /// + /// Specifies all public fields. + /// + PublicFields = 0x0020, + + /// + /// Specifies all non-public fields. + /// + NonPublicFields = 0x0040, + + /// + /// Specifies all public nested types. + /// + PublicNestedTypes = 0x0080, + + /// + /// Specifies all non-public nested types. + /// + NonPublicNestedTypes = 0x0100, + + /// + /// Specifies all public properties. + /// + PublicProperties = 0x0200, + + /// + /// Specifies all non-public properties. + /// + NonPublicProperties = 0x0400, + + /// + /// Specifies all public events. + /// + PublicEvents = 0x0800, + + /// + /// Specifies all non-public events. + /// + NonPublicEvents = 0x1000, + + /// + /// Specifies all interfaces implemented by the type. + /// + Interfaces = 0x2000, + + /// + /// Specifies all members. + /// + All = ~None +} +#endif diff --git a/sdk/core/Azure.Core/tests/Azure.Core.Tests.csproj b/sdk/core/Azure.Core/tests/Azure.Core.Tests.csproj index aa0afb0ebadc..400e7b683124 100644 --- a/sdk/core/Azure.Core/tests/Azure.Core.Tests.csproj +++ b/sdk/core/Azure.Core/tests/Azure.Core.Tests.csproj @@ -24,6 +24,7 @@ + @@ -45,6 +46,7 @@ + @@ -53,6 +55,7 @@ + diff --git a/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializationContentTests.cs b/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializationContentTests.cs new file mode 100644 index 000000000000..458fbdc875b6 --- /dev/null +++ b/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializationContentTests.cs @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.ModelSerialization +{ + public class ModelSerializationContentTests + { + private const string json = "{\"kind\":\"X\",\"name\":\"Name\",\"xProperty\":100}"; + private ModelX _modelX; + + [OneTimeSetUp] + public void OneTimeSetUp() + { + _modelX = ModelSerializer.Deserialize(BinaryData.FromString(json)); + } + + [Test] + public void CanCalculateLength() + { + //use IModelSerializable + var content = RequestContent.Create((IModelSerializable)_modelX); + Assert.AreEqual("ModelSerializableContent", content.GetType().Name); + content.TryComputeLength(out long lengthNonJson); + Assert.Greater(lengthNonJson, 0); + + //use IModelJsonSerializable + var jsonContent = RequestContent.Create((IModelJsonSerializable)_modelX); + Assert.AreEqual("ModelJsonSerializableContent", jsonContent.GetType().Name); + content.TryComputeLength(out long lengthJson); + Assert.Greater(lengthJson, 0); + + Assert.AreEqual(lengthNonJson, lengthJson); + + //use default + jsonContent = RequestContent.Create(_modelX); + Assert.AreEqual("ModelJsonSerializableContent", jsonContent.GetType().Name); + content.TryComputeLength(out lengthJson); + Assert.Greater(lengthJson, 0); + + Assert.AreEqual(lengthNonJson, lengthJson); + } + + [Test] + public void ValidatePrivateClassType() + { + IModelSerializable modelX = _modelX; + + RequestContent content = RequestContent.Create(modelX); + Assert.AreEqual("ModelSerializableContent", content.GetType().Name); + } + } +} diff --git a/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializerOptionsTests.cs b/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializerOptionsTests.cs new file mode 100644 index 000000000000..8af0ae85e93b --- /dev/null +++ b/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializerOptionsTests.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Reflection; +using Azure.Core.Serialization; +using NUnit.Framework; + +namespace Azure.Core.Tests.ModelSerialization +{ + internal class ModelSerializerOptionsTests + { + [Test] + public void ValidatePropertyIsFrozen() => ValidateFrozenInstance(ModelSerializerOptions.DefaultWireOptions); + + [Test] + public void AllInstancesInMapShouldBeFrozen() + { + Dictionary optionsDictionary = typeof(ModelSerializerOptions) + .GetField("_singletonMap", BindingFlags.NonPublic | BindingFlags.Static) + .GetValue(null) as Dictionary; + foreach (var frozen in optionsDictionary.Values) + { + ValidateFrozenInstance(frozen); + } + } + + public void ValidateFrozenInstance(ModelSerializerOptions frozen) + { + Assert.Throws(() => frozen.GenericTypeSerializerCreator = type => null); + } + + [Test] + public void NewInstanceShouldNotBeFrozen() + { + ModelSerializerOptions nonFrozen = new ModelSerializerOptions(); + Assert.DoesNotThrow(() => nonFrozen.GenericTypeSerializerCreator = type => null); + } + + [Test] + public void MapAndStaticPropertySameObject() + { + Assert.IsTrue(ReferenceEquals(ModelSerializerOptions.DefaultWireOptions, ModelSerializerOptions.GetOptions(ModelSerializerFormat.Wire))); + } + + [Test] + public void MapShouldReturnSingletons() + { + Assert.IsTrue(ReferenceEquals(ModelSerializerOptions.GetOptions(ModelSerializerFormat.Wire), ModelSerializerOptions.GetOptions(ModelSerializerFormat.Wire))); + Assert.IsTrue(ReferenceEquals(ModelSerializerOptions.GetOptions(ModelSerializerFormat.Json), ModelSerializerOptions.GetOptions(ModelSerializerFormat.Json))); + } + + [Test] + public void MapShouldHaveRightValues() + { + var options = ModelSerializerOptions.GetOptions(ModelSerializerFormat.Wire); + Assert.AreEqual(ModelSerializerFormat.Wire, options.Format); + Assert.IsNull(options.GenericTypeSerializerCreator); + + options = ModelSerializerOptions.GetOptions(ModelSerializerFormat.Json); + Assert.AreEqual(ModelSerializerFormat.Json, options.Format); + Assert.IsNull(options.GenericTypeSerializerCreator); + } + } +} diff --git a/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializerTests.cs b/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializerTests.cs new file mode 100644 index 000000000000..0225e20ec098 --- /dev/null +++ b/sdk/core/Azure.Core/tests/ModelSerialization/ModelSerializerTests.cs @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.ModelSerialization +{ + public class ModelSerializerTests + { + [Test] + public void ArgumentExceptions() + { + Assert.Throws(() => ModelSerializer.Deserialize(null)); + Assert.Throws(() => ModelSerializer.Deserialize(null, typeof(BaseWithNoUnknown))); + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(new byte[] { }), null)); + Assert.Throws(() => ModelSerializer.Serialize(null)); + Assert.Throws(() => ModelSerializer.Serialize(null)); + + Assert.Throws(() => ModelSerializer.Deserialize(null, ModelSerializerFormat.Wire)); + Assert.Throws(() => ModelSerializer.Deserialize(null, typeof(BaseWithNoUnknown), ModelSerializerFormat.Wire)); + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(new byte[] { }), null, ModelSerializerFormat.Wire)); + Assert.Throws(() => ModelSerializer.Serialize(null, ModelSerializerFormat.Wire)); + Assert.Throws(() => ModelSerializer.Serialize(null, ModelSerializerFormat.Wire)); + + Assert.Throws(() => ModelSerializer.SerializeCore(null, new ModelSerializerOptions())); + Assert.Throws(() => ModelSerializer.SerializeCore(new ModelX(), null)); + } + + [Test] + public void ValidateErrorIfUnknownDoesntExist() + { + BaseWithNoUnknown baseInstance = new SubType(); + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(Array.Empty()))); + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(Array.Empty()), typeof(BaseWithNoUnknown))); + } + + [Test] + public void ValidateErrorIfNoDefaultCtor() + { + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(Array.Empty()))); + } + + [Test] + public void ValidateErrorIfNotImplementInterface() + { + var ex = Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(Array.Empty()), typeof(DoesntImplementInterface))); + Assert.IsTrue(ex.Message.Contains("does not implement")); + ex = Assert.Throws(() => ModelSerializer.Serialize(new DoesntImplementInterface())); + Assert.IsTrue(ex.Message.Contains("does not implement")); + } + + public class DoesntImplementInterface { } + + private class SubType : BaseWithNoUnknown, IModelJsonSerializable + { + SubType IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + return new SubType(); + } + + SubType IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return new SubType(); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + return; + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + return new BinaryData(Array.Empty()); + } + } + + private abstract class BaseWithNoUnknown : IModelJsonSerializable + { + BaseWithNoUnknown IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + return new SubType(); + } + + BaseWithNoUnknown IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return new SubType(); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + return; + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + return new BinaryData(Array.Empty()); + } + } + + public class ModelWithNoDefaultCtor : IModelJsonSerializable + { + public ModelWithNoDefaultCtor(int x) { } + + ModelWithNoDefaultCtor IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + return new ModelWithNoDefaultCtor(1); + } + + ModelWithNoDefaultCtor IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return new ModelWithNoDefaultCtor(1); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + return; + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + return new BinaryData(Array.Empty()); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/ModelSerialization/ModelWriterTests.cs b/sdk/core/Azure.Core/tests/ModelSerialization/ModelWriterTests.cs new file mode 100644 index 000000000000..960e5e32295c --- /dev/null +++ b/sdk/core/Azure.Core/tests/ModelSerialization/ModelWriterTests.cs @@ -0,0 +1,346 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Reflection; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Azure.Core.Serialization; +using Azure.Core.Tests.Common; +using Azure.Core.Tests.ModelSerializationTests.Models; +using Azure.Core.Tests.ResourceManager.Resources; +using NUnit.Framework; + +namespace Azure.Core.Tests.ModelSerialization +{ + /// + /// Happy path tests are in the public test project in the ModelTests class using the JsonInterfaceStrategy. + /// This class is used for testing the internal properties of ModelWriter. + /// + public class ModelWriterTests + { + private const int _modelSize = 156000; + private static readonly string _json = File.ReadAllText(TestData.GetLocation("ResourceProviderData.json")); + private static readonly ResourceProviderData _resourceProviderData = ModelSerializer.Deserialize(BinaryData.FromString(_json)); + + [Test] + public void ThrowsIfUnsupportedFormat() + { + ModelXml model = ModelSerializer.Deserialize(BinaryData.FromString(File.ReadAllText(TestData.GetLocation("ModelXml.xml")))); + ModelWriter writer = new ModelWriter(model, new ModelSerializerOptions("x")); + Assert.Throws(() => writer.ToBinaryData()); + } + + [Test] + public void ThrowsIfMismatch() + { + ModelXml model = ModelSerializer.Deserialize(BinaryData.FromString(File.ReadAllText(TestData.GetLocation("ModelXml.xml")))); + ModelWriter writer = new ModelWriter(model, ModelSerializerOptions.DefaultWireOptions); + Assert.Throws(() => writer.ToBinaryData()); + } + + [Test] + public async Task HappyPath() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + Assert.IsTrue(writer.TryComputeLength(out var length)); + Assert.AreEqual(_modelSize, length); + + MemoryStream stream1 = new MemoryStream((int)length); + writer.CopyTo(stream1, default); + Assert.AreEqual(_modelSize, stream1.Length); + + MemoryStream stream2 = new MemoryStream((int)length); + await writer.CopyToAsync(stream2, default); + Assert.AreEqual(_modelSize, stream2.Length); + + CollectionAssert.AreEqual(stream1.ToArray(), stream2.ToArray()); + } + + [Test] + public async Task DisposeWhileConvertToBinaryData() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + FieldInfo sequenceField = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance); + object sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + + bool taskStarted = false; + Task result = Task.Factory.StartNew(() => + { + Parallel.For(0, 100000, i => + { + taskStarted = true; + BinaryData data = null; + try + { + data = writer.ToBinaryData(); + Assert.AreEqual(_modelSize, data.ToMemory().Length); + } + catch (ObjectDisposedException) + { + Assert.IsNull(data); + } + }); + }); + + while (!taskStarted) + { + Thread.Sleep(1); + } + + await DisposeAfterStart(writer, sequenceField, result); + } + + [Test] + public async Task DisposeWhileCopyAsync() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + FieldInfo sequenceField = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance); + object sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + + bool taskStarted = false; + Task result = Task.Factory.StartNew(() => + { + Parallel.For(0, 100000, async i => + { + taskStarted = true; + using MemoryStream stream = new MemoryStream(); + try + { + await writer.CopyToAsync(stream, default); + Assert.AreEqual(_modelSize, stream.Length); + } + catch (ObjectDisposedException) + { + Assert.AreEqual(0, stream.Length); + } + }); + }); + + while (!taskStarted) + { + Thread.Sleep(1); + } + + await DisposeAfterStart(writer, sequenceField, result); + } + + private static async Task DisposeAfterStart(ModelWriter writer, FieldInfo sequenceField, Task result) + { + writer.Dispose(); + object sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + + await result; + + sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + } + + [Test] + public async Task DisposeWhileCopy() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + FieldInfo sequenceField = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance); + object sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + + bool taskStarted = false; + Task result = Task.Factory.StartNew(() => + { + Parallel.For(0, 100000, i => + { + taskStarted = true; + using MemoryStream stream = new MemoryStream(); + try + { + writer.CopyTo(stream, default); + Assert.AreEqual(_modelSize, stream.Length); + } + catch (ObjectDisposedException) + { + Assert.AreEqual(0, stream.Length); + } + }); + }); + + while (!taskStarted) + { + Thread.Sleep(1); + } + + await DisposeAfterStart(writer, sequenceField, result); + } + + [Test] + public async Task DisposeWhileGettingLength() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + FieldInfo sequenceField = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance); + object sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + + long length = 0; + bool taskStarted = false; + Task result = Task.Factory.StartNew(() => + { + Parallel.For(0, 100000, i => + { + taskStarted = true; + try + { + Assert.IsTrue(writer.TryComputeLength(out var length)); + Assert.AreEqual(_modelSize, length); + } + catch (ObjectDisposedException) + { + Assert.AreEqual(0, length); + } + }); + }); + + while (!taskStarted) + { + Thread.Sleep(1); + } + + await DisposeAfterStart(writer, sequenceField, result); + } + + private static void Validate(ModelWriter writer, FieldInfo sequenceField, bool exceptionThrown, long length) + { + // sequenceBuilder should be null because the writer was disposed + object sequenceBuilder = sequenceField.GetValue(writer); + Assert.IsNull(sequenceBuilder); + + // The dispose should wait for the serialization to finish + // because of thread timing the dispose might happen before the readCount is incremented + // In this case the length of the stream will be 0 otherwise the length will be the size of the model + // Both cases are expected and valid the idea being that the dispose should wait for the serialization to finish if it starts second + // and if it starts first then the original thread should get an ObjectDisposedException + Assert.AreEqual(exceptionThrown ? 0 : _modelSize, length); + } + + [Test] + public void UseAfterDispose() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + writer.Dispose(); + + Assert.Throws(() => writer.TryComputeLength(out var length)); + Assert.Throws(() => writer.CopyTo(new MemoryStream(), default)); + Assert.ThrowsAsync(async () => await writer.CopyToAsync(new MemoryStream(), default)); + Assert.Throws(() => writer.ToBinaryData()); + Assert.DoesNotThrow(() => writer.Dispose()); + } + + [Test] + public void DisposeWithLoad() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + writer.TryComputeLength(out var length); + Assert.AreEqual(_modelSize, length); + + object sequenceBuilder = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(writer); + Assert.IsNotNull(sequenceBuilder); + + writer.Dispose(); + + // sequenceBuilder should be null because the writer was disposed + sequenceBuilder = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(writer); + Assert.IsNull(sequenceBuilder); + } + + [Test] + public void DisposeWithoutLoad() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + + writer.Dispose(); + + // sequenceBuilder should be null because the writer was disposed + object sequenceBuilder = writer.GetType().GetField("_sequenceBuilder", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(writer); + Assert.IsNull(sequenceBuilder); + } + + [TestCase("J")] + [TestCase("W")] + public void ExceptionsAreBubbledUp(string format) + { + ExplodingModel model = new ExplodingModel(); + ModelSerializerOptions options = new ModelSerializerOptions(format); + MemoryStream stream = new MemoryStream(); + + using ModelWriter writer = new ModelWriter(model, options); + Assert.Throws(() => writer.TryComputeLength(out var length)); + Assert.Throws(() => writer.CopyTo(stream, default)); + Assert.ThrowsAsync(async () => await writer.CopyToAsync(stream, default)); + Assert.Throws(() => writer.ToBinaryData()); + } + + [Test] + public void ParallelComputLength() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + + Parallel.For(0, 1000000, i => + { + Assert.IsTrue(writer.TryComputeLength(out var length)); + Assert.AreEqual(_modelSize, length); + }); + } + + [Test] + public void ParallelCopy() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + + Parallel.For(0, 10000, i => + { + using MemoryStream stream = new MemoryStream(_modelSize); + writer.CopyTo(stream, default); + Assert.AreEqual(_modelSize, stream.Length); + }); + } + + [Test] + public void ParallelCopyAsync() + { + ModelWriter writer = new ModelWriter(_resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + + Parallel.For(0, 10000, async i => + { + using MemoryStream stream = new MemoryStream(_modelSize); + await writer.CopyToAsync(stream, default); + Assert.AreEqual(_modelSize, stream.Length); + }); + } + + private class ExplodingModel : IModelJsonSerializable + { + ExplodingModel IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + throw new NotImplementedException(); + } + + ExplodingModel IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + throw new NotImplementedException(); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + throw new NotImplementedException(); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + throw new NotImplementedException(); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/Azure.Core.Tests.Common.csproj b/sdk/core/Azure.Core/tests/common/Azure.Core.Tests.Common.csproj new file mode 100644 index 000000000000..cb8e22f45568 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/Azure.Core.Tests.Common.csproj @@ -0,0 +1,38 @@ + + + $(RequiredTargetFrameworks) + true + true + true + + + + + + + + + + + + + + + + Always + + + Always + + + Always + + + Always + + + Always + + + + diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ChildModelXml.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ChildModelXml.cs new file mode 100644 index 000000000000..fd65e8e10cd1 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ChildModelXml.cs @@ -0,0 +1,169 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + [XmlRoot("ChildTag")] + public class ChildModelXml : IXmlSerializable, IModelSerializable, IModelJsonSerializable, IUtf8JsonSerializable + { + internal ChildModelXml() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// is null. + public ChildModelXml(string value, string readonlyProperty) + { + Argument.AssertNotNull(value, nameof(value)); + + ChildValue = value; + ChildReadOnlyProperty = readonlyProperty; + } + + /// Gets or sets the value. + [XmlElement("ChildValue")] + public string ChildValue { get; set; } + /// Gets or sets the value. + [XmlElement("ChildReadOnlyProperty")] + public string ChildReadOnlyProperty { get; } + + void IXmlSerializable.Write(XmlWriter writer, string nameHint) => + Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + private void Serialize(XmlWriter writer, ModelSerializerOptions options, string nameHint) + { + writer.WriteStartElement(nameHint ?? "ChildTag"); + writer.WriteStartElement("ChildValue"); + writer.WriteValue(ChildValue); + writer.WriteEndElement(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WriteStartElement("ChildReadOnlyProperty"); + writer.WriteValue(ChildReadOnlyProperty); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + internal static ChildModelXml DeserializeChildModelXml(XElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string value = default; + string readonlyProperty = default; + if (element.Element("ChildValue") is XElement valueElement) + { + value = (string)valueElement; + } + if (element.Element("ChildReadOnlyProperty") is XElement readonlyPropertyElement) + { + readonlyProperty = (string)readonlyPropertyElement; + } + return new ChildModelXml(value, readonlyProperty); + } + + internal static ChildModelXml DeserializeChildModelXml(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string childValue = default; + string childReadOnlyProperty = default; + + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("childValue"u8)) + { + childValue = property.Value.GetString(); + continue; + } + if (property.NameEquals("childReadOnlyProperty"u8)) + { + childReadOnlyProperty = property.Value.GetString(); + continue; + } + } + return new ChildModelXml(childValue, childReadOnlyProperty); + } + + ChildModelXml IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + using var doc = JsonDocument.Parse(data); + return DeserializeChildModelXml(doc.RootElement, options); + } + else + { + return DeserializeChildModelXml(XElement.Load(data.ToStream()), options); + } + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + return ModelSerializer.SerializeCore(this, options); + } + else + { + options ??= ModelSerializerOptions.DefaultWireOptions; + using MemoryStream stream = new MemoryStream(); + using XmlWriter writer = XmlWriter.Create(stream); + Serialize(writer, options, null); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("childValue"u8); + writer.WriteStringValue(ChildValue); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("childReadOnlyProperty"u8); + writer.WriteStringValue(ChildReadOnlyProperty); + } + writer.WriteEndObject(); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + ChildModelXml IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeChildModelXml(doc.RootElement, options); + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => + Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/BaseModel.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/BaseModel.cs new file mode 100644 index 000000000000..6fff06ad2915 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/BaseModel.cs @@ -0,0 +1,151 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + [AbstractHierarchyDeserializer(typeof(UnknownBaseModel))] + public abstract class BaseModel : IUtf8JsonSerializable, IModelJsonSerializable + { + private Dictionary _rawData; + + public static implicit operator RequestContent(BaseModel baseModel) + { + if (baseModel == null) + { + return null; + } + + return RequestContent.Create(baseModel, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator BaseModel(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + using JsonDocument jsonDocument = JsonDocument.Parse(response.ContentStream); + return DeserializeBaseModel(jsonDocument.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + protected internal BaseModel(Dictionary rawData) + { + _rawData = rawData ?? new Dictionary(); + } + + public string Kind { get; internal set; } + public string Name { get; set; } + + protected internal void SerializeRawData(Utf8JsonWriter writer) + { + //write out the raw data + foreach (var property in _rawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind); + if (Optional.IsDefined(Name)) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (options.Format == ModelSerializerFormat.Json) + { + SerializeRawData(writer); + } + writer.WriteEndObject(); + } + + internal static BaseModel DeserializeBaseModel(BinaryData data, ModelSerializerOptions options) + => DeserializeBaseModel(JsonDocument.Parse(data.ToString()).RootElement, options); + + internal static BaseModel DeserializeBaseModel(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + if (element.TryGetProperty("kind", out JsonElement discriminator)) + { + switch (discriminator.GetString()) + { + case "X": + return ModelX.DeserializeModelX(element, options); + case "Y": + return ModelY.DeserializeModelY(element, options); + } + } + + //Deserialize unknown subtype + string kind = default; + Optional name = default; + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("kind"u8)) + { + kind = property.Value.GetString(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + //this means it's an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new UnknownBaseModel(kind, name, rawData); + } + + BaseModel IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return DeserializeBaseModel(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + BaseModel IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeBaseModel(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/ModelX.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/ModelX.cs new file mode 100644 index 000000000000..e79789c50da6 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/ModelX.cs @@ -0,0 +1,144 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + public class ModelX : BaseModel, IUtf8JsonSerializable, IModelJsonSerializable + { + public ModelX() + : base(null) + { + Kind = "X"; + } + + internal ModelX(string kind, string name, int xProperty, Dictionary rawData) + : base(rawData) + { + Kind = kind; + Name = name; + XProperty = xProperty; + } + + public int XProperty { get; private set; } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + public static implicit operator RequestContent(ModelX modelX) + { + if (modelX == null) + { + return null; + } + + return RequestContent.Create(modelX, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator ModelX(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + using JsonDocument jsonDocument = JsonDocument.Parse(response.ContentStream); + return DeserializeModelX(jsonDocument.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind); + if (Optional.IsDefined(Name)) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("xProperty"u8); + writer.WriteNumberValue(XProperty); + } + if (options.Format == ModelSerializerFormat.Json) + { + SerializeRawData(writer); + } + writer.WriteEndObject(); + } + + internal static ModelX DeserializeModelX(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string kind = default; + Optional name = default; + int xProperty = default; + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("kind"u8)) + { + kind = property.Value.GetString(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("xProperty"u8)) + { + xProperty = property.Value.GetInt32(); + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + //this means it's an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new ModelX(kind, name, xProperty, rawData); + } + + ModelX IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return DeserializeModelX(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + //public method to serialize with internal interface + public void Serialize(Utf8JsonWriter writer) + { + ((IUtf8JsonSerializable)this).Write(writer); + } + + ModelX IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeModelX(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/ModelY.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/ModelY.cs new file mode 100644 index 000000000000..6dcfb722b852 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/ModelY.cs @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + public class ModelY : BaseModel, IUtf8JsonSerializable, IModelJsonSerializable + { + public ModelY() + : base(null) + { + Kind = "Y"; + } + + internal ModelY(string kind, string name, string yProperty, Dictionary rawData) + : base(rawData) + { + Kind = kind; + Name = name; + YProperty = yProperty; + } + + public string YProperty { get; private set; } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind); + if (Optional.IsDefined(Name)) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("yProperty"u8); + writer.WriteStringValue(YProperty); + } + if (options.Format == ModelSerializerFormat.Json) + { + SerializeRawData(writer); + } + writer.WriteEndObject(); + } + + internal static ModelY DeserializeModelY(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + string kind = default; + Optional name = default; + Optional yProperty = default; + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("kind"u8)) + { + kind = property.Value.GetString(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("yProperty"u8)) + { + yProperty = property.Value.GetString(); + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + //this means it's an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new ModelY(kind, name, yProperty, rawData); + } + + ModelY IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return DeserializeModelY(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + ModelY IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeModelY(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/UnknownBaseModel.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/UnknownBaseModel.cs new file mode 100644 index 000000000000..0d9ac6ce152e --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/DiscriminatorSet/UnknownBaseModel.cs @@ -0,0 +1,76 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + internal class UnknownBaseModel : BaseModel, IUtf8JsonSerializable, IModelJsonSerializable + { + public UnknownBaseModel() + : base(null) + { + Kind = "Unknown"; + } + + internal UnknownBaseModel(string kind, string name, Dictionary rawData) + : base(rawData) + { + Kind = kind; + Name = name; + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("kind"u8); + writer.WriteStringValue(Kind); + if (Optional.IsDefined(Name)) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (options.Format == ModelSerializerFormat.Json) + { + SerializeRawData(writer); + } + writer.WriteEndObject(); + } + + internal static BaseModel DeserializeUnknownBaseModel(JsonElement element, ModelSerializerOptions options = default) => DeserializeBaseModel(element, options); + + BaseModel IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return DeserializeUnknownBaseModel(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + BaseModel IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeUnknownBaseModel(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelAsStruct.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelAsStruct.cs new file mode 100644 index 000000000000..6eeb5b8bddf3 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelAsStruct.cs @@ -0,0 +1,141 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + /// The InputAdditionalPropertiesModelStruct. + public readonly partial struct ModelAsStruct : IUtf8JsonSerializable, IModelJsonSerializable, IModelJsonSerializable + { + private readonly Dictionary _rawData; + + /// Initializes a new instance of InputAdditionalPropertiesModelStruct. + /// + /// Additional Properties. + /// + /// is null. + public ModelAsStruct(int id, Dictionary rawData) + { + Id = id; + _rawData = rawData; + } + + /// Gets the id. + public int Id { get; } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + writer.WriteStartObject(); + writer.WritePropertyName("id"u8); + writer.WriteNumberValue(Id); + if (_rawData is not null && options.Format == ModelSerializerFormat.Json) + { + foreach (var property in _rawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + writer.WriteEndObject(); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + + public static implicit operator RequestContent(ModelAsStruct model) + { + return RequestContent.Create(model, ModelSerializerOptions.DefaultWireOptions); + } + + ModelAsStruct IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.Parse(data); + return DeserializeInputAdditionalPropertiesModelStruct(doc.RootElement, options); + } + + internal static ModelAsStruct DeserializeInputAdditionalPropertiesModelStruct(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + int id = default; + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + id = property.Value.GetInt32(); + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + continue; + } + } + return new ModelAsStruct(id, rawData); + } + + ModelAsStruct IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeInputAdditionalPropertiesModelStruct(doc.RootElement, options); + } + + public static explicit operator ModelAsStruct(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + using JsonDocument doc = JsonDocument.Parse(response.ContentStream); + return DeserializeInputAdditionalPropertiesModelStruct(doc.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + object IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeInputAdditionalPropertiesModelStruct(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + + object IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.Parse(data); + return DeserializeInputAdditionalPropertiesModelStruct(doc.RootElement, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelXml.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelXml.cs new file mode 100644 index 000000000000..cd5e08b1496d --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/Models/ModelXml.cs @@ -0,0 +1,229 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ModelSerializationTests.Models +{ + [XmlRoot("Tag")] + public class ModelXml : IXmlSerializable, IModelSerializable, IModelJsonSerializable, IUtf8JsonSerializable + { + internal ModelXml() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// + /// or is null. + public ModelXml(string key, string value, string readonlyProperty, ChildModelXml childModel) + { + Argument.AssertNotNull(key, nameof(key)); + Argument.AssertNotNull(value, nameof(value)); + + Key = key; + Value = value; + ReadOnlyProperty = readonlyProperty; + RenamedChildModelXml = childModel; + } + + /// Gets or sets the key. + [XmlElement("Key")] + public string Key { get; set; } + /// Gets or sets the value. + [XmlElement("Value")] + public string Value { get; set; } + /// Gets or sets the value. + [XmlElement("ReadOnlyProperty")] + public string ReadOnlyProperty { get; } + [XmlElement("RenamedChildModelXml")] + public ChildModelXml RenamedChildModelXml { get; set; } + + public static implicit operator RequestContent(ModelXml modelXml) + { + if (modelXml == null) + { + return null; + } + + return RequestContent.Create((IModelSerializable)modelXml, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator ModelXml(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + return DeserializeModelXml(XElement.Load(response.ContentStream), ModelSerializerOptions.DefaultWireOptions); + } + + public void Serialize(XmlWriter writer, string nameHint) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + void IXmlSerializable.Write(XmlWriter writer, string nameHint) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + private void Serialize(XmlWriter writer, ModelSerializerOptions options, string nameHint) + { + writer.WriteStartElement(nameHint ?? "Tag"); + writer.WriteStartElement("Key"); + writer.WriteValue(Key); + writer.WriteEndElement(); + writer.WriteStartElement("Value"); + writer.WriteValue(Value); + writer.WriteEndElement(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WriteStartElement("ReadOnlyProperty"); + writer.WriteValue(ReadOnlyProperty); + writer.WriteEndElement(); + } + writer.WriteObjectValue(RenamedChildModelXml, "RenamedChildModelXml"); + writer.WriteEndElement(); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("key"u8); + writer.WriteStringValue(Key); + writer.WritePropertyName("value"u8); + writer.WriteStringValue(Value); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("readOnlyProperty"u8); + writer.WriteStringValue(ReadOnlyProperty); + } + writer.WritePropertyName("renamedChildModelXml"u8); + writer.WriteObjectValue(RenamedChildModelXml); + writer.WriteEndObject(); + } + + public static ModelXml DeserializeModelXml(XElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readonlyProperty = default; + ChildModelXml childModelXml = default; + if (element.Element("Key") is XElement keyElement) + { + key = (string)keyElement; + } + if (element.Element("Value") is XElement valueElement) + { + value = (string)valueElement; + } + if (element.Element("ReadOnlyProperty") is XElement readonlyPropertyElement) + { + readonlyProperty = (string)readonlyPropertyElement; + } + if (element.Element("RenamedChildModelXml") is XElement renamedChildModelXmlElement) + { + childModelXml = ChildModelXml.DeserializeChildModelXml(renamedChildModelXmlElement, options); + } + return new ModelXml(key, value, readonlyProperty, childModelXml); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + return ModelSerializer.SerializeCore(this, options); + } + else + { + options ??= ModelSerializerOptions.DefaultWireOptions; + using MemoryStream stream = new MemoryStream(); + using XmlWriter writer = XmlWriter.Create(stream); + Serialize(writer, options, null); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + } + + internal static ModelXml DeserializeModelXml(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readOnlyProperty = default; + ChildModelXml childModelXml = default; + + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("key"u8)) + { + key = property.Value.GetString(); + continue; + } + if (property.NameEquals("value"u8)) + { + value = property.Value.GetString(); + continue; + } + if (property.NameEquals("readOnlyProperty"u8)) + { + readOnlyProperty = property.Value.GetString(); + continue; + } + if (property.NameEquals("renamedChildModelXml"u8)) + { + childModelXml = ChildModelXml.DeserializeChildModelXml(property.Value, options); + continue; + } + } + return new ModelXml(key, value, readOnlyProperty, childModelXml); + } + + ModelXml IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + using var doc = JsonDocument.Parse(data); + return DeserializeModelXml(doc.RootElement, options); + } + else + { + return DeserializeModelXml(XElement.Load(data.ToStream()), options); + } + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format != ModelSerializerFormat.Json) + throw new InvalidOperationException($"Must use '{ModelSerializerFormat.Json}' format when calling the {nameof(IModelJsonSerializable)} interface"); + Serialize(writer, options); + } + + ModelXml IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format != ModelSerializerFormat.Json) + throw new InvalidOperationException($"Must use '{ModelSerializerFormat.Json}' format when calling the {nameof(IModelJsonSerializable)} interface"); + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeModelXml(doc.RootElement, options); + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ApiProfile.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ApiProfile.Serialization.cs new file mode 100644 index 000000000000..e67ec83536e8 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ApiProfile.Serialization.cs @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ApiProfile : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ApiProfile DeserializeApiProfile(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional profileVersion = default; + Optional apiVersion = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("profileVersion"u8)) + { + profileVersion = property.Value.GetString(); + continue; + } + if (property.NameEquals("apiVersion"u8)) + { + apiVersion = property.Value.GetString(); + continue; + } + } + return new ApiProfile(profileVersion.Value, apiVersion.Value); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(ProfileVersion)) + { + writer.WritePropertyName("profileVersion"u8); + writer.WriteStringValue(ProfileVersion); + } + if (Optional.IsDefined(ApiVersion)) + { + writer.WritePropertyName("apiVersion"u8); + writer.WriteStringValue(ApiVersion); + } + writer.WriteEndObject(); + } + + private struct ApiProfileProperties + { + public Optional ProfileVersion { get; set; } + public Optional ApiVersion { get; set; } + } + + ApiProfile IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeApiProfile(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref ApiProfileProperties properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("profileVersion"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.ProfileVersion = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("apiVersion"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.ApiVersion = reader.GetString(); + return; + } + reader.Skip(); + } + + ApiProfile IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeApiProfile(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ApiProfile.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ApiProfile.cs new file mode 100644 index 000000000000..2b5e44d73549 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ApiProfile.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The ApiProfile. + public partial class ApiProfile + { + /// Initializes a new instance of ApiProfile. + internal ApiProfile() + { + } + + /// Initializes a new instance of ApiProfile. + /// The profile version. + /// The API version. + internal ApiProfile(string profileVersion, string apiVersion) + { + ProfileVersion = profileVersion; + ApiVersion = apiVersion; + } + + /// The profile version. + public string ProfileVersion { get; } + /// The API version. + public string ApiVersion { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/AvailabilitySetData.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/AvailabilitySetData.Serialization.cs new file mode 100644 index 000000000000..2a99336619a0 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/AvailabilitySetData.Serialization.cs @@ -0,0 +1,283 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.Tests.ResourceManager.Compute.Models; +using Azure.Core.Tests.ResourceManager.Models; +using Azure.Core.Tests.ResourceManager.Resources.Models; + +namespace Azure.Core.Tests.ResourceManager.Compute +{ + public partial class AvailabilitySetData : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id.ToString()); + } + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("type"u8); + writer.WriteStringValue(ResourceType.ToString()); + } + if (Optional.IsDefined(Sku)) + { + writer.WritePropertyName("sku"u8); + writer.WriteObjectValue(Sku); + } + if (Optional.IsCollectionDefined(Tags)) + { + writer.WritePropertyName("tags"u8); + writer.WriteStartObject(); + foreach (var item in Tags) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + writer.WritePropertyName("location"u8); + writer.WriteStringValue(Location); + writer.WritePropertyName("properties"u8); + writer.WriteStartObject(); + if (Optional.IsDefined(PlatformUpdateDomainCount)) + { + writer.WritePropertyName("platformUpdateDomainCount"u8); + writer.WriteNumberValue(PlatformUpdateDomainCount.Value); + } + if (Optional.IsDefined(PlatformFaultDomainCount)) + { + writer.WritePropertyName("platformFaultDomainCount"u8); + writer.WriteNumberValue(PlatformFaultDomainCount.Value); + } + if (Optional.IsCollectionDefined(VirtualMachines)) + { + writer.WritePropertyName("virtualMachines"u8); + writer.WriteStartArray(); + foreach (var item in VirtualMachines) + { + JsonSerializer.Serialize(writer, item); + } + writer.WriteEndArray(); + } + if (Optional.IsDefined(ProximityPlacementGroup)) + { + writer.WritePropertyName("proximityPlacementGroup"u8); + JsonSerializer.Serialize(writer, ProximityPlacementGroup); + } + writer.WriteEndObject(); + writer.WriteEndObject(); + } + + public static AvailabilitySetData DeserializeAvailabilitySetData(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional sku = default; + Optional> tags = default; + AzureLocation location = default; + ResourceIdentifier id = default; + string name = default; + ResourceType type = default; + Optional systemData = default; + Optional platformUpdateDomainCount = default; + Optional platformFaultDomainCount = default; + Optional> virtualMachines = default; + Optional proximityPlacementGroup = default; + Optional> statuses = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("sku"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + sku = ComputeSku.DeserializeComputeSku(property.Value, options); + continue; + } + if (property.NameEquals("tags"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + tags = dictionary; + continue; + } + if (property.NameEquals("location"u8)) + { + location = new AzureLocation(property.Value.GetString()); + continue; + } + if (property.NameEquals("id"u8)) + { + id = new ResourceIdentifier(property.Value.GetString()); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("type"u8)) + { + type = new ResourceType(property.Value.GetString()); + continue; + } + if (property.NameEquals("systemData"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + systemData = JsonSerializer.Deserialize(property.Value.GetRawText()); + continue; + } + if (property.NameEquals("properties"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + property.ThrowNonNullablePropertyIsNull(); + continue; + } + foreach (var property0 in property.Value.EnumerateObject()) + { + if (property0.NameEquals("platformUpdateDomainCount"u8)) + { + if (property0.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + platformUpdateDomainCount = property0.Value.GetInt32(); + continue; + } + if (property0.NameEquals("platformFaultDomainCount"u8)) + { + if (property0.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + platformFaultDomainCount = property0.Value.GetInt32(); + continue; + } + if (property0.NameEquals("virtualMachines"u8)) + { + if (property0.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property0.Value.EnumerateArray()) + { + array.Add(JsonSerializer.Deserialize(item.GetRawText())); + } + virtualMachines = array; + continue; + } + if (property0.NameEquals("proximityPlacementGroup"u8)) + { + if (property0.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + proximityPlacementGroup = JsonSerializer.Deserialize(property0.Value.GetRawText()); + continue; + } + if (property0.NameEquals("statuses"u8)) + { + if (property0.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property0.Value.EnumerateArray()) + { + array.Add(InstanceViewStatus.DeserializeInstanceViewStatus(item, options)); + } + statuses = array; + continue; + } + } + continue; + } + } + return new AvailabilitySetData(id, name, type, systemData.Value, Optional.ToDictionary(tags), location, sku.Value, Optional.ToNullable(platformUpdateDomainCount), Optional.ToNullable(platformFaultDomainCount), Optional.ToList(virtualMachines), proximityPlacementGroup, Optional.ToList(statuses)); + } + + AvailabilitySetData IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.Parse(data); + return DeserializeAvailabilitySetData(doc.RootElement, options); + } + + // only used for public access to internal serialize + public void Serialize(Utf8JsonWriter writer) => ((IUtf8JsonSerializable)this).Write(writer); + + private struct AvailabilitySetDataProperties + { + public Optional Sku { get; set; } + public Optional> Tags { get; set; } + public AzureLocation Location { get; set; } + public ResourceIdentifier Id { get; set; } + public string Name { get; set; } + public ResourceType ResourceType { get; set; } + public Optional SystemData { get; set; } + public Optional PlatformUpdateDomainCount { get; set; } + public Optional PlatformFaultDomainCount { get; set; } + public Optional> VirtualMachines { get; set; } + public Optional ProximityPlacementGroup { get; set; } + public Optional> Statuses { get; set; } + } + + AvailabilitySetData IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeAvailabilitySetData(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/AvailabilitySetData.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/AvailabilitySetData.cs new file mode 100644 index 000000000000..df38269f1da1 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/AvailabilitySetData.cs @@ -0,0 +1,99 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.Tests.ResourceManager.Compute.Models; +using Azure.Core.Tests.ResourceManager.Models; +using Azure.Core.Tests.ResourceManager.Resources.Models; + +namespace Azure.Core.Tests.ResourceManager.Compute +{ + /// + /// A class representing the AvailabilitySet data model. + /// Specifies information about the availability set that the virtual machine should be assigned to. Virtual machines specified in the same availability set are allocated to different nodes to maximize availability. For more information about availability sets, see [Availability sets overview](https://docs.microsoft.com/azure/virtual-machines/availability-set-overview). For more information on Azure planned maintenance, see [Maintenance and updates for Virtual Machines in Azure](https://docs.microsoft.com/azure/virtual-machines/maintenance-and-updates). Currently, a VM can only be added to an availability set at creation time. An existing VM cannot be added to an availability set. + /// + public partial class AvailabilitySetData : TrackedResourceData + { + internal AvailabilitySetData() { } + + public static implicit operator RequestContent(AvailabilitySetData availabilitySetData) + { + if (availabilitySetData is null) + { + return null; + } + + return RequestContent.Create(availabilitySetData, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator AvailabilitySetData(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + using JsonDocument jsonDocument = JsonDocument.Parse(response.ContentStream); + return DeserializeAvailabilitySetData(jsonDocument.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + /// Initializes a new instance of AvailabilitySetData. + /// The location. + public AvailabilitySetData(AzureLocation location) : base(location) + { + VirtualMachines = new ChangeTrackingList(); + Statuses = new ChangeTrackingList(); + } + + /// Initializes a new instance of AvailabilitySetData. + /// The id. + /// The name. + /// The resourceType. + /// The systemData. + /// The tags. + /// The location. + /// Sku of the availability set, only name is required to be set. See AvailabilitySetSkuTypes for possible set of values. Use 'Aligned' for virtual machines with managed disks and 'Classic' for virtual machines with unmanaged disks. Default value is 'Classic'. + /// Update Domain count. + /// Fault Domain count. + /// A list of references to all virtual machines in the availability set. + /// Specifies information about the proximity placement group that the availability set should be assigned to. Minimum api-version: 2018-04-01. + /// The resource status information. + internal AvailabilitySetData(ResourceIdentifier id, string name, ResourceType resourceType, SystemData systemData, IDictionary tags, AzureLocation location, ComputeSku sku, int? platformUpdateDomainCount, int? platformFaultDomainCount, IList virtualMachines, WritableSubResource proximityPlacementGroup, IReadOnlyList statuses) : base(id, name, resourceType, systemData, tags, location) + { + Sku = sku; + PlatformUpdateDomainCount = platformUpdateDomainCount; + PlatformFaultDomainCount = platformFaultDomainCount; + VirtualMachines = virtualMachines; + ProximityPlacementGroup = proximityPlacementGroup; + Statuses = statuses; + } + + /// Sku of the availability set, only name is required to be set. See AvailabilitySetSkuTypes for possible set of values. Use 'Aligned' for virtual machines with managed disks and 'Classic' for virtual machines with unmanaged disks. Default value is 'Classic'. + public ComputeSku Sku { get; set; } + /// Update Domain count. + public int? PlatformUpdateDomainCount { get; set; } + /// Fault Domain count. + public int? PlatformFaultDomainCount { get; set; } + /// A list of references to all virtual machines in the availability set. + public IList VirtualMachines { get; } + /// Specifies information about the proximity placement group that the availability set should be assigned to. Minimum api-version: 2018-04-01. + internal WritableSubResource ProximityPlacementGroup { get; set; } + /// Gets or sets Id. + public ResourceIdentifier ProximityPlacementGroupId + { + get => ProximityPlacementGroup is null ? default : ProximityPlacementGroup.Id; + set + { + if (ProximityPlacementGroup is null) + ProximityPlacementGroup = new WritableSubResource(); + ProximityPlacementGroup.Id = value; + } + } + + /// The resource status information. + public IReadOnlyList Statuses { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeSku.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeSku.Serialization.cs new file mode 100644 index 000000000000..483232080d92 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeSku.Serialization.cs @@ -0,0 +1,130 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Linq; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Compute.Models +{ + public partial class ComputeSku : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Name)) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (Optional.IsDefined(Tier)) + { + writer.WritePropertyName("tier"u8); + writer.WriteStringValue(Tier); + } + if (Optional.IsDefined(Capacity)) + { + writer.WritePropertyName("capacity"u8); + writer.WriteNumberValue(Capacity.Value); + } + writer.WriteEndObject(); + } + + internal static ComputeSku DeserializeComputeSku(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional name = default; + Optional tier = default; + Optional capacity = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("tier"u8)) + { + tier = property.Value.GetString(); + continue; + } + if (property.NameEquals("capacity"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + capacity = property.Value.GetInt64(); + continue; + } + } + return new ComputeSku(name.Value, tier.Value, Optional.ToNullable(capacity)); + } + + private struct ComputeSkuProperties + { + public Optional Name { get; set; } + public Optional Tier { get; set; } + public Optional Capacity { get; set; } + } + + ComputeSku IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeComputeSku(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref ComputeSkuProperties properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("name"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Name = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("tier"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Tier = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("capacity"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Capacity = reader.GetInt64(); + return; + } + reader.Skip(); + } + + ComputeSku IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeComputeSku(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeSku.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeSku.cs new file mode 100644 index 000000000000..ae8ec908b7e1 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeSku.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Compute.Models +{ + /// Describes a virtual machine scale set sku. NOTE: If the new VM SKU is not supported on the hardware the scale set is currently on, you need to deallocate the VMs in the scale set before you modify the SKU name. + public partial class ComputeSku + { + /// Initializes a new instance of ComputeSku. + public ComputeSku() + { + } + + /// Initializes a new instance of ComputeSku. + /// The sku name. + /// Specifies the tier of virtual machines in a scale set.<br /><br /> Possible Values:<br /><br /> **Standard**<br /><br /> **Basic**. + /// Specifies the number of virtual machines in the scale set. + internal ComputeSku(string name, string tier, long? capacity) + { + Name = name; + Tier = tier; + Capacity = capacity; + } + + /// The sku name. + public string Name { get; set; } + /// Specifies the tier of virtual machines in a scale set.<br /><br /> Possible Values:<br /><br /> **Standard**<br /><br /> **Basic**. + public string Tier { get; set; } + /// Specifies the number of virtual machines in the scale set. + public long? Capacity { get; set; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeStatusLevelType.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeStatusLevelType.Serialization.cs new file mode 100644 index 000000000000..879117da9755 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeStatusLevelType.Serialization.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Core.Tests.ResourceManager.Compute.Models +{ + internal static partial class ComputeStatusLevelTypeExtensions + { + public static string ToSerialString(this ComputeStatusLevelType value) => value switch + { + ComputeStatusLevelType.Info => "Info", + ComputeStatusLevelType.Warning => "Warning", + ComputeStatusLevelType.Error => "Error", + _ => throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown ComputeStatusLevelType value.") + }; + + public static ComputeStatusLevelType ToComputeStatusLevelType(this string value) + { + if (StringComparer.OrdinalIgnoreCase.Equals(value, "Info")) return ComputeStatusLevelType.Info; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "Warning")) return ComputeStatusLevelType.Warning; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "Error")) return ComputeStatusLevelType.Error; + throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown ComputeStatusLevelType value."); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeStatusLevelType.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeStatusLevelType.cs new file mode 100644 index 000000000000..196fb7183671 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ComputeStatusLevelType.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Compute.Models +{ + /// The level code. + public enum ComputeStatusLevelType + { + /// Info. + Info, + /// Warning. + Warning, + /// Error. + Error + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/CreatedByType.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/CreatedByType.cs new file mode 100644 index 000000000000..ce682d85bea6 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/CreatedByType.cs @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Core.Tests.ResourceManager.Models +{ + /// The type of identity that created the resource. + public readonly partial struct CreatedByType : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public CreatedByType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string UserValue = "User"; + private const string ApplicationValue = "Application"; + private const string ManagedIdentityValue = "ManagedIdentity"; + private const string KeyValue = "Key"; + + /// User. + public static CreatedByType User { get; } = new CreatedByType(UserValue); + /// Application. + public static CreatedByType Application { get; } = new CreatedByType(ApplicationValue); + /// ManagedIdentity. + public static CreatedByType ManagedIdentity { get; } = new CreatedByType(ManagedIdentityValue); + /// Key. + public static CreatedByType Key { get; } = new CreatedByType(KeyValue); + /// Determines if two values are the same. + public static bool operator ==(CreatedByType left, CreatedByType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(CreatedByType left, CreatedByType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator CreatedByType(string value) => new CreatedByType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is CreatedByType other && Equals(other); + /// + public bool Equals(CreatedByType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/InstanceViewStatus.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/InstanceViewStatus.Serialization.cs new file mode 100644 index 000000000000..472083e903b8 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/InstanceViewStatus.Serialization.cs @@ -0,0 +1,172 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Globalization; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Compute.Models +{ + public partial class InstanceViewStatus : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Code)) + { + writer.WritePropertyName("code"u8); + writer.WriteStringValue(Code); + } + if (Optional.IsDefined(Level)) + { + writer.WritePropertyName("level"u8); + writer.WriteStringValue(Level.Value.ToSerialString()); + } + if (Optional.IsDefined(DisplayStatus)) + { + writer.WritePropertyName("displayStatus"u8); + writer.WriteStringValue(DisplayStatus); + } + if (Optional.IsDefined(Message)) + { + writer.WritePropertyName("message"u8); + writer.WriteStringValue(Message); + } + if (Optional.IsDefined(Time)) + { + writer.WritePropertyName("time"u8); + writer.WriteStringValue(Time.Value, "O"); + } + writer.WriteEndObject(); + } + + internal static InstanceViewStatus DeserializeInstanceViewStatus(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional code = default; + Optional level = default; + Optional displayStatus = default; + Optional message = default; + Optional time = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("code"u8)) + { + code = property.Value.GetString(); + continue; + } + if (property.NameEquals("level"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + level = property.Value.GetString().ToComputeStatusLevelType(); + continue; + } + if (property.NameEquals("displayStatus"u8)) + { + displayStatus = property.Value.GetString(); + continue; + } + if (property.NameEquals("message"u8)) + { + message = property.Value.GetString(); + continue; + } + if (property.NameEquals("time"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + time = property.Value.GetDateTimeOffset("O"); + continue; + } + } + return new InstanceViewStatus(code.Value, Optional.ToNullable(level), displayStatus.Value, message.Value, Optional.ToNullable(time)); + } + + private struct InstanceViewStatusProperties + { + public Optional Code { get; set; } + public Optional Level { get; set; } + public Optional DisplayStatus { get; set; } + public Optional Message { get; set; } + public Optional Time { get; set; } + } + + InstanceViewStatus IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeInstanceViewStatus(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref InstanceViewStatusProperties properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("code"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Code = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("level"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Level = reader.GetString().ToComputeStatusLevelType(); + return; + } + if (propertyName.SequenceEqual("displayStatus"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.DisplayStatus = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("message"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Message = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("time"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Time = DateTimeOffset.Parse(reader.GetString(), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); + return; + } + reader.Skip(); + } + + InstanceViewStatus IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeInstanceViewStatus(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/InstanceViewStatus.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/InstanceViewStatus.cs new file mode 100644 index 000000000000..66891bc6032b --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/InstanceViewStatus.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Core.Tests.ResourceManager.Compute.Models +{ + /// Instance view status. + public partial class InstanceViewStatus + { + /// Initializes a new instance of InstanceViewStatus. + public InstanceViewStatus() + { + } + + /// Initializes a new instance of InstanceViewStatus. + /// The status code. + /// The level code. + /// The short localizable label for the status. + /// The detailed status message, including for alerts and error messages. + /// The time of the status. + internal InstanceViewStatus(string code, ComputeStatusLevelType? level, string displayStatus, string message, DateTimeOffset? time) + { + Code = code; + Level = level; + DisplayStatus = displayStatus; + Message = message; + Time = time; + } + + /// The status code. + public string Code { get; set; } + /// The level code. + public ComputeStatusLevelType? Level { get; set; } + /// The short localizable label for the status. + public string DisplayStatus { get; set; } + /// The detailed status message, including for alerts and error messages. + public string Message { get; set; } + /// The time of the status. + public DateTimeOffset? Time { get; set; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderAuthorizationConsentState.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderAuthorizationConsentState.cs new file mode 100644 index 000000000000..6268124cb3f6 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderAuthorizationConsentState.cs @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The provider authorization consent state. + public readonly partial struct ProviderAuthorizationConsentState : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ProviderAuthorizationConsentState(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string NotSpecifiedValue = "NotSpecified"; + private const string RequiredValue = "Required"; + private const string NotRequiredValue = "NotRequired"; + private const string ConsentedValue = "Consented"; + + /// NotSpecified. + public static ProviderAuthorizationConsentState NotSpecified { get; } = new ProviderAuthorizationConsentState(NotSpecifiedValue); + /// Required. + public static ProviderAuthorizationConsentState Required { get; } = new ProviderAuthorizationConsentState(RequiredValue); + /// NotRequired. + public static ProviderAuthorizationConsentState NotRequired { get; } = new ProviderAuthorizationConsentState(NotRequiredValue); + /// Consented. + public static ProviderAuthorizationConsentState Consented { get; } = new ProviderAuthorizationConsentState(ConsentedValue); + /// Determines if two values are the same. + public static bool operator ==(ProviderAuthorizationConsentState left, ProviderAuthorizationConsentState right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ProviderAuthorizationConsentState left, ProviderAuthorizationConsentState right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ProviderAuthorizationConsentState(string value) => new ProviderAuthorizationConsentState(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ProviderAuthorizationConsentState other && Equals(other); + /// + public bool Equals(ProviderAuthorizationConsentState other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderExtendedLocation.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderExtendedLocation.Serialization.cs new file mode 100644 index 000000000000..790a860f1a99 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderExtendedLocation.Serialization.cs @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ProviderExtendedLocation : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ProviderExtendedLocation DeserializeProviderExtendedLocation(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional location = default; + Optional type = default; + Optional> extendedLocations = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("location"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + location = new AzureLocation(property.Value.GetString()); + continue; + } + if (property.NameEquals("type"u8)) + { + type = property.Value.GetString(); + continue; + } + if (property.NameEquals("extendedLocations"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + extendedLocations = array; + continue; + } + } + return new ProviderExtendedLocation(Optional.ToNullable(location), type.Value, Optional.ToList(extendedLocations)); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Location)) + { + writer.WritePropertyName("location"u8); + writer.WriteStringValue(Location.Value.DisplayName); + } + if (Optional.IsDefined(ProviderExtendedLocationType)) + { + writer.WritePropertyName("type"u8); + writer.WriteStringValue(ProviderExtendedLocationType); + } + if (Optional.IsCollectionDefined(ExtendedLocations)) + { + writer.WritePropertyName("extendedLocations"u8); + writer.WriteStartArray(); + foreach (var item in ExtendedLocations) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + writer.WriteEndObject(); + } + + private struct ProviderExtendedLocationProperties + { + public Optional Location { get; set; } + public Optional ProviderExtendedLocationType { get; set; } + public Optional> ExtendedLocations { get; set; } + } + + ProviderExtendedLocation IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeProviderExtendedLocation(doc.RootElement, options); + } + + ProviderExtendedLocation IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeProviderExtendedLocation(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderExtendedLocation.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderExtendedLocation.cs new file mode 100644 index 000000000000..bcbb99a520d3 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderExtendedLocation.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The provider extended location. + public partial class ProviderExtendedLocation + { + /// Initializes a new instance of ProviderExtendedLocation. + internal ProviderExtendedLocation() + { + ExtendedLocations = new ChangeTrackingList(); + } + + /// Initializes a new instance of ProviderExtendedLocation. + /// The azure location. + /// The extended location type. + /// The extended locations for the azure location. + internal ProviderExtendedLocation(AzureLocation? location, string providerExtendedLocationType, IReadOnlyList extendedLocations) + { + Location = location; + ProviderExtendedLocationType = providerExtendedLocationType; + ExtendedLocations = extendedLocations; + } + + /// The azure location. + public AzureLocation? Location { get; } + /// The extended location type. + public string ProviderExtendedLocationType { get; } + /// The extended locations for the azure location. + public IReadOnlyList ExtendedLocations { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderResourceType.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderResourceType.Serialization.cs new file mode 100644 index 000000000000..cd9cff632635 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderResourceType.Serialization.cs @@ -0,0 +1,283 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ProviderResourceType : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ProviderResourceType DeserializeProviderResourceType(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional resourceType = default; + Optional> locations = default; + Optional> locationMappings = default; + Optional> aliases = default; + Optional> apiVersions = default; + Optional defaultApiVersion = default; + Optional> zoneMappings = default; + Optional> apiProfiles = default; + Optional capabilities = default; + Optional> properties = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("resourceType"u8)) + { + resourceType = property.Value.GetString(); + continue; + } + if (property.NameEquals("locations"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + locations = array; + continue; + } + if (property.NameEquals("locationMappings"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ProviderExtendedLocation.DeserializeProviderExtendedLocation(item, options)); + } + locationMappings = array; + continue; + } + if (property.NameEquals("aliases"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ResourceTypeAlias.DeserializeResourceTypeAlias(item, options)); + } + aliases = array; + continue; + } + if (property.NameEquals("apiVersions"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + apiVersions = array; + continue; + } + if (property.NameEquals("defaultApiVersion"u8)) + { + defaultApiVersion = property.Value.GetString(); + continue; + } + if (property.NameEquals("zoneMappings"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ZoneMapping.DeserializeZoneMapping(item, options)); + } + zoneMappings = array; + continue; + } + if (property.NameEquals("apiProfiles"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ApiProfile.DeserializeApiProfile(item, options)); + } + apiProfiles = array; + continue; + } + if (property.NameEquals("capabilities"u8)) + { + capabilities = property.Value.GetString(); + continue; + } + if (property.NameEquals("properties"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + Dictionary dictionary = new Dictionary(); + foreach (var property0 in property.Value.EnumerateObject()) + { + dictionary.Add(property0.Name, property0.Value.GetString()); + } + properties = dictionary; + continue; + } + } + return new ProviderResourceType(resourceType.Value, Optional.ToList(locations), Optional.ToList(locationMappings), Optional.ToList(aliases), Optional.ToList(apiVersions), defaultApiVersion.Value, Optional.ToList(zoneMappings), Optional.ToList(apiProfiles), capabilities.Value, Optional.ToDictionary(properties)); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if(Optional.IsDefined(ResourceType)) + { + writer.WritePropertyName("resourceType"u8); + writer.WriteStringValue(ResourceType); + } + if (Optional.IsCollectionDefined(Locations)) + { + writer.WritePropertyName("locations"u8); + writer.WriteStartArray(); + foreach (var item in Locations) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsCollectionDefined(ApiVersions)) + { + writer.WritePropertyName("apiVersions"u8); + writer.WriteStartArray(); + foreach (var item in ApiVersions) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsDefined(DefaultApiVersion)) + { + writer.WritePropertyName("defaultApiVersion"u8); + writer.WriteStringValue(DefaultApiVersion); + } + if (Optional.IsCollectionDefined(ApiProfiles)) + { + writer.WritePropertyName("apiProfiles"u8); + writer.WriteStartArray(); + foreach (var item in ApiProfiles) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsCollectionDefined(ZoneMappings)) + { + writer.WritePropertyName("zoneMappings"u8); + writer.WriteStartArray(); + foreach (var item in ZoneMappings) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsCollectionDefined(LocationMappings)) + { + writer.WritePropertyName("locationMappings"u8); + writer.WriteStartArray(); + foreach (var item in LocationMappings) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsDefined(Capabilities)) + { + writer.WritePropertyName("capabilities"u8); + writer.WriteStringValue(Capabilities); + } + if (Optional.IsCollectionDefined(Aliases)) + { + writer.WritePropertyName("aliases"u8); + writer.WriteStartArray(); + foreach (var item in Aliases) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsCollectionDefined(Properties)) + { + writer.WritePropertyName("properties"u8); + writer.WriteStartObject(); + foreach (var item in Properties) + { + writer.WritePropertyName(item.Key); + writer.WriteStringValue(item.Value); + } + writer.WriteEndObject(); + } + writer.WriteEndObject(); + } + + private struct ProviderResourceTypeProperties + { + public Optional ResourceType { get; set; } + public Optional> Locations { get; set; } + public Optional> LocationMappings { get; set; } + public Optional> Aliases { get; set; } + public Optional> ApiVersions { get; set; } + public Optional DefaultApiVersion { get; set; } + public Optional> ZoneMappings { get; set; } + public Optional> ApiProfiles { get; set; } + public Optional Capabilities { get; set; } + public Optional> Properties { get; set; } + } + + ProviderResourceType IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeProviderResourceType(doc.RootElement, options); + } + + ProviderResourceType IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeProviderResourceType(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderResourceType.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderResourceType.cs new file mode 100644 index 000000000000..af95577c5916 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ProviderResourceType.cs @@ -0,0 +1,73 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// Resource type managed by the resource provider. + public partial class ProviderResourceType + { + /// Initializes a new instance of ProviderResourceType. + internal ProviderResourceType() + { + Locations = new ChangeTrackingList(); + LocationMappings = new ChangeTrackingList(); + Aliases = new ChangeTrackingList(); + ApiVersions = new ChangeTrackingList(); + ZoneMappings = new ChangeTrackingList(); + ApiProfiles = new ChangeTrackingList(); + Properties = new ChangeTrackingDictionary(); + } + + /// Initializes a new instance of ProviderResourceType. + /// The resource type. + /// The collection of locations where this resource type can be created. + /// The location mappings that are supported by this resource type. + /// The aliases that are supported by this resource type. + /// The API version. + /// The default API version. + /// + /// The API profiles for the resource provider. + /// The additional capabilities offered by this resource type. + /// The properties. + internal ProviderResourceType(string resourceType, IReadOnlyList locations, IReadOnlyList locationMappings, IReadOnlyList aliases, IReadOnlyList apiVersions, string defaultApiVersion, IReadOnlyList zoneMappings, IReadOnlyList apiProfiles, string capabilities, IReadOnlyDictionary properties) + { + ResourceType = resourceType; + Locations = locations; + LocationMappings = locationMappings; + Aliases = aliases; + ApiVersions = apiVersions; + DefaultApiVersion = defaultApiVersion; + ZoneMappings = zoneMappings; + ApiProfiles = apiProfiles; + Capabilities = capabilities; + Properties = properties; + } + + /// The resource type. + public string ResourceType { get; } + /// The collection of locations where this resource type can be created. + public IReadOnlyList Locations { get; } + /// The location mappings that are supported by this resource type. + public IReadOnlyList LocationMappings { get; } + /// The aliases that are supported by this resource type. + public IReadOnlyList Aliases { get; } + /// The API version. + public IReadOnlyList ApiVersions { get; } + /// The default API version. + public string DefaultApiVersion { get; } + /// Gets the zone mappings. + public IReadOnlyList ZoneMappings { get; } + /// The API profiles for the resource provider. + public IReadOnlyList ApiProfiles { get; } + /// The additional capabilities offered by this resource type. + public string Capabilities { get; } + /// The properties. + public IReadOnlyDictionary Properties { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceData.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceData.cs new file mode 100644 index 000000000000..488468d0d5d7 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceData.cs @@ -0,0 +1,38 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Models +{ + /// Common fields that are returned in the response for all Azure Resource Manager resources. + public abstract partial class ResourceData + { + /// Initializes a new instance of Resource. + protected ResourceData() + { + } + + /// Initializes a new instance of Resource. + /// Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}. + /// The name of the resource. + /// The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts". + /// Azure Resource Manager metadata containing createdBy and modifiedBy information. + protected ResourceData(ResourceIdentifier id, string name, ResourceType resourceType, SystemData systemData) + { + Id = id; + Name = name; + ResourceType = resourceType; + SystemData = systemData; + } + + /// Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}. + public ResourceIdentifier Id { get; } + /// The name of the resource. + public string Name { get; } + /// The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts". + public ResourceType ResourceType { get; } + /// Azure Resource Manager metadata containing createdBy and modifiedBy information. + public SystemData SystemData { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceProviderData.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceProviderData.Serialization.cs new file mode 100644 index 000000000000..4217b5d7054b --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceProviderData.Serialization.cs @@ -0,0 +1,171 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.Tests.ResourceManager.Resources.Models; + +namespace Azure.Core.Tests.ResourceManager.Resources +{ + public partial class ResourceProviderData : IUtf8JsonSerializable, IModelJsonSerializable + { + public static ResourceProviderData DeserializeResourceProviderData(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional id = default; + Optional @namespace = default; + Optional registrationState = default; + Optional registrationPolicy = default; + Optional> resourceTypes = default; + Optional providerAuthorizationConsentState = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + id = new ResourceIdentifier(property.Value.GetString()); + continue; + } + if (property.NameEquals("namespace"u8)) + { + @namespace = property.Value.GetString(); + continue; + } + if (property.NameEquals("registrationState"u8)) + { + registrationState = property.Value.GetString(); + continue; + } + if (property.NameEquals("registrationPolicy"u8)) + { + registrationPolicy = property.Value.GetString(); + continue; + } + if (property.NameEquals("resourceTypes"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ProviderResourceType.DeserializeProviderResourceType(item, options)); + } + resourceTypes = array; + continue; + } + if (property.NameEquals("providerAuthorizationConsentState"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + providerAuthorizationConsentState = new ProviderAuthorizationConsentState(property.Value.GetString()); + continue; + } + } + return new ResourceProviderData(id.Value, @namespace.Value, registrationState.Value, registrationPolicy.Value, Optional.ToList(resourceTypes), Optional.ToNullable(providerAuthorizationConsentState)); + } + + ResourceProviderData IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.Parse(data); + return DeserializeResourceProviderData(doc.RootElement, options); + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + // only used for public access to internal serialize + public void Serialize(Utf8JsonWriter writer) => ((IUtf8JsonSerializable)this).Write(writer); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Id)) + { + writer.WritePropertyName("id"u8); + writer.WriteStringValue(Id); + } + if (Optional.IsDefined(Namespace)) + { + writer.WritePropertyName("namespace"u8); + writer.WriteStringValue(Namespace); + } + if (Optional.IsCollectionDefined(ResourceTypes)) + { + writer.WritePropertyName("resourceTypes"u8); + writer.WriteStartArray(); + foreach (var item in ResourceTypes) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsDefined(RegistrationState)) + { + writer.WritePropertyName("registrationState"u8); + writer.WriteStringValue(RegistrationState); + } + if (Optional.IsDefined(RegistrationPolicy)) + { + writer.WritePropertyName("registrationPolicy"u8); + writer.WriteStringValue(RegistrationPolicy); + } + if (Optional.IsDefined(ProviderAuthorizationConsentState)) + { + writer.WritePropertyName("providerAuthorizationConsentState"u8); + writer.WriteStringValue(ProviderAuthorizationConsentState.ToString()); + } + writer.WriteEndObject(); + } + + private struct ResourceProviderDataProperties + { + public Optional Id { get; set; } + public Optional Namespace { get; set; } + public Optional RegistrationState { get; set; } + public Optional RegistrationPolicy { get; set; } + public Optional> ResourceTypes { get; set; } + public Optional ProviderAuthorizationConsentState { get; set; } + } + + ResourceProviderData IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeResourceProviderData(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceProviderData.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceProviderData.cs new file mode 100644 index 000000000000..edb060d13d6c --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceProviderData.cs @@ -0,0 +1,75 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.Tests.ResourceManager.Resources.Models; + +namespace Azure.Core.Tests.ResourceManager.Resources +{ + /// + /// A class representing the ResourceProvider data model. + /// Resource provider information. + /// + public partial class ResourceProviderData + { + public static implicit operator RequestContent(ResourceProviderData resourceProviderData) + { + if (resourceProviderData == null) + { + return null; + } + + return RequestContent.Create(resourceProviderData, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator ResourceProviderData(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + using JsonDocument jsonDocument = JsonDocument.Parse(response.ContentStream); + return DeserializeResourceProviderData(jsonDocument.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + /// Initializes a new instance of ProviderData. + public ResourceProviderData() + { + ResourceTypes = new ChangeTrackingList(); + } + + /// Initializes a new instance of ProviderData. + /// The provider ID. + /// The namespace of the resource provider. + /// The registration state of the resource provider. + /// The registration policy of the resource provider. + /// The collection of provider resource types. + /// The provider authorization consent state. + internal ResourceProviderData(ResourceIdentifier id, string @namespace, string registrationState, string registrationPolicy, IReadOnlyList resourceTypes, ProviderAuthorizationConsentState? providerAuthorizationConsentState) + { + Id = id; + Namespace = @namespace; + RegistrationState = registrationState; + RegistrationPolicy = registrationPolicy; + ResourceTypes = resourceTypes; + ProviderAuthorizationConsentState = providerAuthorizationConsentState; + } + + /// The provider ID. + public ResourceIdentifier Id { get; } + /// The namespace of the resource provider. + public string Namespace { get; } + /// The registration state of the resource provider. + public string RegistrationState { get; } + /// The registration policy of the resource provider. + public string RegistrationPolicy { get; } + /// The collection of provider resource types. + public IReadOnlyList ResourceTypes { get; } + /// The provider authorization consent state. + public ProviderAuthorizationConsentState? ProviderAuthorizationConsentState { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAlias.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAlias.Serialization.cs new file mode 100644 index 000000000000..2e7c5044e8a8 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAlias.Serialization.cs @@ -0,0 +1,162 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ResourceTypeAlias : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ResourceTypeAlias DeserializeResourceTypeAlias(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional name = default; + Optional> paths = default; + Optional type = default; + Optional defaultPath = default; + Optional defaultPattern = default; + Optional defaultMetadata = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("paths"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(ResourceTypeAliasPath.DeserializeResourceTypeAliasPath(item, options)); + } + paths = array; + continue; + } + if (property.NameEquals("type"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + type = property.Value.GetString().ToResourceTypeAliasType(); + continue; + } + if (property.NameEquals("defaultPath"u8)) + { + defaultPath = property.Value.GetString(); + continue; + } + if (property.NameEquals("defaultPattern"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + defaultPattern = ResourceTypeAliasPattern.DeserializeResourceTypeAliasPattern(property.Value, options); + continue; + } + if (property.NameEquals("defaultMetadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + defaultMetadata = ResourceTypeAliasPathMetadata.DeserializeResourceTypeAliasPathMetadata(property.Value, options); + continue; + } + } + return new ResourceTypeAlias(name.Value, Optional.ToList(paths), Optional.ToNullable(type), defaultPath.Value, defaultPattern.Value, defaultMetadata.Value); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Name)) + { + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + } + if (Optional.IsCollectionDefined(Paths)) + { + writer.WritePropertyName("paths"u8); + writer.WriteStartArray(); + foreach (var item in Paths) + { + writer.WriteObjectValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsDefined(AliasType)) + { + writer.WritePropertyName("type"u8); + writer.WriteStringValue(AliasType.ToString()); + } + if (Optional.IsDefined(DefaultPath)) + { + writer.WritePropertyName("defaultPath"u8); + writer.WriteStringValue(DefaultPath); + } + if (Optional.IsDefined(DefaultPattern)) + { + writer.WritePropertyName("defaultPattern"u8); + writer.WriteObjectValue(DefaultPattern); + } + if (Optional.IsDefined(DefaultMetadata)) + { + writer.WritePropertyName("defaultMetadata"u8); + writer.WriteObjectValue(DefaultMetadata); + } + writer.WriteEndObject(); + } + + private struct ResourceTypeAliasProperties + { + public Optional Name { get; set; } + public Optional> Paths { get; set; } + public Optional AliasType { get; set; } + public Optional DefaultPath { get; set; } + public Optional DefaultPattern { get; set; } + public Optional DefaultMetadata { get; set; } + } + + ResourceTypeAlias IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeResourceTypeAlias(doc.RootElement, options); + } + + ResourceTypeAlias IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeResourceTypeAlias(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAlias.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAlias.cs new file mode 100644 index 000000000000..50d7c42be0c7 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAlias.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The alias type. + public partial class ResourceTypeAlias + { + /// Initializes a new instance of ResourceTypeAlias. + internal ResourceTypeAlias() + { + Paths = new ChangeTrackingList(); + } + + /// Initializes a new instance of ResourceTypeAlias. + /// The alias name. + /// The paths for an alias. + /// The type of the alias. + /// The default path for an alias. + /// The default pattern for an alias. + /// The default alias path metadata. Applies to the default path and to any alias path that doesn't have metadata. + internal ResourceTypeAlias(string name, IReadOnlyList paths, ResourceTypeAliasType? aliasType, string defaultPath, ResourceTypeAliasPattern defaultPattern, ResourceTypeAliasPathMetadata defaultMetadata) + { + Name = name; + Paths = paths; + AliasType = aliasType; + DefaultPath = defaultPath; + DefaultPattern = defaultPattern; + DefaultMetadata = defaultMetadata; + } + + /// The alias name. + public string Name { get; } + /// The paths for an alias. + public IReadOnlyList Paths { get; } + /// The type of the alias. + public ResourceTypeAliasType? AliasType { get; } + /// The default path for an alias. + public string DefaultPath { get; } + /// The default pattern for an alias. + public ResourceTypeAliasPattern DefaultPattern { get; } + /// The default alias path metadata. Applies to the default path and to any alias path that doesn't have metadata. + public ResourceTypeAliasPathMetadata DefaultMetadata { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPath.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPath.Serialization.cs new file mode 100644 index 000000000000..536070ad939b --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPath.Serialization.cs @@ -0,0 +1,134 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ResourceTypeAliasPath : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ResourceTypeAliasPath DeserializeResourceTypeAliasPath(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional path = default; + Optional> apiVersions = default; + Optional pattern = default; + Optional metadata = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("path"u8)) + { + path = property.Value.GetString(); + continue; + } + if (property.NameEquals("apiVersions"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + apiVersions = array; + continue; + } + if (property.NameEquals("pattern"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + pattern = ResourceTypeAliasPattern.DeserializeResourceTypeAliasPattern(property.Value, options); + continue; + } + if (property.NameEquals("metadata"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + metadata = ResourceTypeAliasPathMetadata.DeserializeResourceTypeAliasPathMetadata(property.Value, options); + continue; + } + } + return new ResourceTypeAliasPath(path.Value, Optional.ToList(apiVersions), pattern.Value, metadata.Value); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Path)) + { + writer.WritePropertyName("path"u8); + writer.WriteStringValue(Path); + } + if (Optional.IsCollectionDefined(ApiVersions)) + { + writer.WritePropertyName("apiVersions"u8); + writer.WriteStartArray(); + foreach (var item in ApiVersions) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + if (Optional.IsDefined(Pattern)) + { + writer.WritePropertyName("pattern"u8); + writer.WriteObjectValue(Pattern); + } + if (Optional.IsDefined(Metadata)) + { + writer.WritePropertyName("metadata"u8); + writer.WriteObjectValue(Metadata); + } + writer.WriteEndObject(); + } + + private struct ResourceTypeAliasPathProperties + { + public Optional Path { get; set; } + public Optional> ApiVersions { get; set; } + public Optional Pattern { get; set; } + public Optional Metadata { get; set; } + } + + ResourceTypeAliasPath IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeResourceTypeAliasPath(doc.RootElement, options); + } + + ResourceTypeAliasPath IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeResourceTypeAliasPath(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPath.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPath.cs new file mode 100644 index 000000000000..7fb205533f33 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPath.cs @@ -0,0 +1,43 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The type of the paths for alias. + public partial class ResourceTypeAliasPath + { + /// Initializes a new instance of ResourceTypeAliasPath. + internal ResourceTypeAliasPath() + { + ApiVersions = new ChangeTrackingList(); + } + + /// Initializes a new instance of ResourceTypeAliasPath. + /// The path of an alias. + /// The API versions. + /// The pattern for an alias path. + /// The metadata of the alias path. If missing, fall back to the default metadata of the alias. + internal ResourceTypeAliasPath(string path, IReadOnlyList apiVersions, ResourceTypeAliasPattern pattern, ResourceTypeAliasPathMetadata metadata) + { + Path = path; + ApiVersions = apiVersions; + Pattern = pattern; + Metadata = metadata; + } + + /// The path of an alias. + public string Path { get; } + /// The API versions. + public IReadOnlyList ApiVersions { get; } + /// The pattern for an alias path. + public ResourceTypeAliasPattern Pattern { get; } + /// The metadata of the alias path. If missing, fall back to the default metadata of the alias. + public ResourceTypeAliasPathMetadata Metadata { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathAttributes.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathAttributes.cs new file mode 100644 index 000000000000..f9a82274f61e --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathAttributes.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The attributes of the token that the alias path is referring to. + public readonly partial struct ResourceTypeAliasPathAttributes : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ResourceTypeAliasPathAttributes(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string NoneValue = "None"; + private const string ModifiableValue = "Modifiable"; + + /// The token that the alias path is referring to has no attributes. + public static ResourceTypeAliasPathAttributes None { get; } = new ResourceTypeAliasPathAttributes(NoneValue); + /// The token that the alias path is referring to is modifiable by policies with 'modify' effect. + public static ResourceTypeAliasPathAttributes Modifiable { get; } = new ResourceTypeAliasPathAttributes(ModifiableValue); + /// Determines if two values are the same. + public static bool operator ==(ResourceTypeAliasPathAttributes left, ResourceTypeAliasPathAttributes right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ResourceTypeAliasPathAttributes left, ResourceTypeAliasPathAttributes right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ResourceTypeAliasPathAttributes(string value) => new ResourceTypeAliasPathAttributes(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ResourceTypeAliasPathAttributes other && Equals(other); + /// + public bool Equals(ResourceTypeAliasPathAttributes other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathMetadata.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathMetadata.Serialization.cs new file mode 100644 index 000000000000..ec4303ae5234 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathMetadata.Serialization.cs @@ -0,0 +1,114 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ResourceTypeAliasPathMetadata : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ResourceTypeAliasPathMetadata DeserializeResourceTypeAliasPathMetadata(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional type = default; + Optional attributes = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("type"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + type = new ResourceTypeAliasPathTokenType(property.Value.GetString()); + continue; + } + if (property.NameEquals("attributes"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + attributes = new ResourceTypeAliasPathAttributes(property.Value.GetString()); + continue; + } + } + return new ResourceTypeAliasPathMetadata(Optional.ToNullable(type), Optional.ToNullable(attributes)); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(TokenType)) + { + writer.WritePropertyName("type"u8); + writer.WriteStringValue(TokenType.ToString()); + } + if (Optional.IsDefined(Attributes)) + { + writer.WritePropertyName("attributes"u8); + writer.WriteStringValue(Attributes.ToString()); + } + writer.WriteEndObject(); + } + + private struct ResourceTypeAliasPathMetadataProperties + { + public Optional TokenType { get; set; } + public Optional Attributes { get; set; } + } + + ResourceTypeAliasPathMetadata IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeResourceTypeAliasPathMetadata(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref ResourceTypeAliasPathMetadataProperties properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("type"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.TokenType = new ResourceTypeAliasPathTokenType(reader.GetString()); + return; + } + if (propertyName.SequenceEqual("attributes"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Attributes = new ResourceTypeAliasPathAttributes(reader.GetString()); + return; + } + reader.Skip(); + } + + ResourceTypeAliasPathMetadata IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeResourceTypeAliasPathMetadata(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathMetadata.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathMetadata.cs new file mode 100644 index 000000000000..7b965b6ce2b9 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathMetadata.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The ResourceTypeAliasPathMetadata. + public partial class ResourceTypeAliasPathMetadata + { + /// Initializes a new instance of ResourceTypeAliasPathMetadata. + internal ResourceTypeAliasPathMetadata() + { + } + + /// Initializes a new instance of ResourceTypeAliasPathMetadata. + /// The type of the token that the alias path is referring to. + /// The attributes of the token that the alias path is referring to. + internal ResourceTypeAliasPathMetadata(ResourceTypeAliasPathTokenType? tokenType, ResourceTypeAliasPathAttributes? attributes) + { + TokenType = tokenType; + Attributes = attributes; + } + + /// The type of the token that the alias path is referring to. + public ResourceTypeAliasPathTokenType? TokenType { get; } + /// The attributes of the token that the alias path is referring to. + public ResourceTypeAliasPathAttributes? Attributes { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathTokenType.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathTokenType.cs new file mode 100644 index 000000000000..8b26cdb95a68 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPathTokenType.cs @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The type of the token that the alias path is referring to. + public readonly partial struct ResourceTypeAliasPathTokenType : IEquatable + { + private readonly string _value; + + /// Initializes a new instance of . + /// is null. + public ResourceTypeAliasPathTokenType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string NotSpecifiedValue = "NotSpecified"; + private const string AnyValue = "Any"; + private const string StringValue = "String"; + private const string ObjectValue = "Object"; + private const string ArrayValue = "Array"; + private const string IntegerValue = "Integer"; + private const string NumberValue = "Number"; + private const string BooleanValue = "Boolean"; + + /// The token type is not specified. + public static ResourceTypeAliasPathTokenType NotSpecified { get; } = new ResourceTypeAliasPathTokenType(NotSpecifiedValue); + /// The token type can be anything. + public static ResourceTypeAliasPathTokenType Any { get; } = new ResourceTypeAliasPathTokenType(AnyValue); + /// The token type is string. + public static ResourceTypeAliasPathTokenType String { get; } = new ResourceTypeAliasPathTokenType(StringValue); + /// The token type is object. + public static ResourceTypeAliasPathTokenType Object { get; } = new ResourceTypeAliasPathTokenType(ObjectValue); + /// The token type is array. + public static ResourceTypeAliasPathTokenType Array { get; } = new ResourceTypeAliasPathTokenType(ArrayValue); + /// The token type is integer. + public static ResourceTypeAliasPathTokenType Integer { get; } = new ResourceTypeAliasPathTokenType(IntegerValue); + /// The token type is number. + public static ResourceTypeAliasPathTokenType Number { get; } = new ResourceTypeAliasPathTokenType(NumberValue); + /// The token type is boolean. + public static ResourceTypeAliasPathTokenType Boolean { get; } = new ResourceTypeAliasPathTokenType(BooleanValue); + /// Determines if two values are the same. + public static bool operator ==(ResourceTypeAliasPathTokenType left, ResourceTypeAliasPathTokenType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(ResourceTypeAliasPathTokenType left, ResourceTypeAliasPathTokenType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator ResourceTypeAliasPathTokenType(string value) => new ResourceTypeAliasPathTokenType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is ResourceTypeAliasPathTokenType other && Equals(other); + /// + public bool Equals(ResourceTypeAliasPathTokenType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() => _value?.GetHashCode() ?? 0; + /// + public override string ToString() => _value; + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPattern.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPattern.Serialization.cs new file mode 100644 index 000000000000..0043395ac214 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPattern.Serialization.cs @@ -0,0 +1,129 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ResourceTypeAliasPattern : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ResourceTypeAliasPattern DeserializeResourceTypeAliasPattern(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional phrase = default; + Optional variable = default; + Optional type = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("phrase"u8)) + { + phrase = property.Value.GetString(); + continue; + } + if (property.NameEquals("variable"u8)) + { + variable = property.Value.GetString(); + continue; + } + if (property.NameEquals("type"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + type = property.Value.GetString().ToResourceTypeAliasPatternType(); + continue; + } + } + return new ResourceTypeAliasPattern(phrase.Value, variable.Value, Optional.ToNullable(type)); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Phrase)) + { + writer.WritePropertyName("phrase"u8); + writer.WriteStringValue(Phrase); + } + if (Optional.IsDefined(Variable)) + { + writer.WritePropertyName("variable"u8); + writer.WriteStringValue(Variable); + } + if (Optional.IsDefined(PatternType)) + { + writer.WritePropertyName("type"u8); + writer.WriteStringValue(PatternType.Value.ToSerialString()); + } + writer.WriteEndObject(); + } + + private struct ResourceTypeAliasPatternProperites + { + public Optional Phrase { get; set; } + public Optional Variable { get; set; } + public Optional PatternType { get; set; } + } + + ResourceTypeAliasPattern IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeResourceTypeAliasPattern(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref ResourceTypeAliasPatternProperites properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("phrase"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Phrase = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("variable"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Variable = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("type"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.PatternType = reader.GetString().ToResourceTypeAliasPatternType(); + return; + } + reader.Skip(); + } + + ResourceTypeAliasPattern IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeResourceTypeAliasPattern(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPattern.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPattern.cs new file mode 100644 index 000000000000..5e0c3d71cf69 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPattern.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The type of the pattern for an alias path. + public partial class ResourceTypeAliasPattern + { + /// Initializes a new instance of ResourceTypeAliasPattern. + internal ResourceTypeAliasPattern() + { + } + + /// Initializes a new instance of ResourceTypeAliasPattern. + /// The alias pattern phrase. + /// The alias pattern variable. + /// The type of alias pattern. + internal ResourceTypeAliasPattern(string phrase, string variable, ResourceTypeAliasPatternType? patternType) + { + Phrase = phrase; + Variable = variable; + PatternType = patternType; + } + + /// The alias pattern phrase. + public string Phrase { get; } + /// The alias pattern variable. + public string Variable { get; } + /// The type of alias pattern. + public ResourceTypeAliasPatternType? PatternType { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPatternType.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPatternType.Serialization.cs new file mode 100644 index 000000000000..b6993ddc0de8 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPatternType.Serialization.cs @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + internal static partial class ResourceTypeAliasPatternTypeExtensions + { + public static string ToSerialString(this ResourceTypeAliasPatternType value) => value switch + { + ResourceTypeAliasPatternType.NotSpecified => "NotSpecified", + ResourceTypeAliasPatternType.Extract => "Extract", + _ => throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown ResourceTypeAliasPatternType value.") + }; + + public static ResourceTypeAliasPatternType ToResourceTypeAliasPatternType(this string value) + { + if (StringComparer.OrdinalIgnoreCase.Equals(value, "NotSpecified")) return ResourceTypeAliasPatternType.NotSpecified; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "Extract")) return ResourceTypeAliasPatternType.Extract; + throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown ResourceTypeAliasPatternType value."); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPatternType.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPatternType.cs new file mode 100644 index 000000000000..d54d8e5afe88 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasPatternType.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The type of alias pattern. + public enum ResourceTypeAliasPatternType + { + /// NotSpecified is not allowed. + NotSpecified, + /// Extract is the only allowed value. + Extract + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasType.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasType.Serialization.cs new file mode 100644 index 000000000000..39d50246fe50 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasType.Serialization.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + internal static partial class ResourceTypeAliasTypeExtensions + { + public static string ToSerialString(this ResourceTypeAliasType value) => value switch + { + ResourceTypeAliasType.NotSpecified => "NotSpecified", + ResourceTypeAliasType.PlainText => "PlainText", + ResourceTypeAliasType.Mask => "Mask", + _ => throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown ResourceTypeAliasType value.") + }; + + public static ResourceTypeAliasType ToResourceTypeAliasType(this string value) + { + if (StringComparer.OrdinalIgnoreCase.Equals(value, "NotSpecified")) return ResourceTypeAliasType.NotSpecified; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "PlainText")) return ResourceTypeAliasType.PlainText; + if (StringComparer.OrdinalIgnoreCase.Equals(value, "Mask")) return ResourceTypeAliasType.Mask; + throw new ArgumentOutOfRangeException(nameof(value), value, "Unknown ResourceTypeAliasType value."); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasType.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasType.cs new file mode 100644 index 000000000000..c3fc8585f237 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ResourceTypeAliasType.cs @@ -0,0 +1,20 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The type of the alias. + public enum ResourceTypeAliasType + { + /// Alias type is unknown (same as not providing alias type). + NotSpecified, + /// Alias value is not secret. + PlainText, + /// Alias value is secret. + Mask + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/SystemData.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/SystemData.Serialization.cs new file mode 100644 index 000000000000..0acf92d0db1d --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/SystemData.Serialization.cs @@ -0,0 +1,184 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Globalization; +using System.Text.Json; +using System.Text.Json.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Models +{ + [JsonConverter(typeof(SystemDataConverter))] + public partial class SystemData : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WriteEndObject(); + } + + internal static SystemData DeserializeSystemData(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional createdBy = default; + Optional createdByType = default; + Optional createdAt = default; + Optional lastModifiedBy = default; + Optional lastModifiedByType = default; + Optional lastModifiedAt = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("createdBy"u8)) + { + createdBy = property.Value.GetString(); + continue; + } + if (property.NameEquals("createdByType"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + createdByType = new CreatedByType(property.Value.GetString()); + continue; + } + if (property.NameEquals("createdAt"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + createdAt = property.Value.GetDateTimeOffset("O"); + continue; + } + if (property.NameEquals("lastModifiedBy"u8)) + { + lastModifiedBy = property.Value.GetString(); + continue; + } + if (property.NameEquals("lastModifiedByType"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + lastModifiedByType = new CreatedByType(property.Value.GetString()); + continue; + } + if (property.NameEquals("lastModifiedAt"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + lastModifiedAt = property.Value.GetDateTimeOffset("O"); + continue; + } + } + return new SystemData(createdBy.Value, Optional.ToNullable(createdByType), Optional.ToNullable(createdAt), lastModifiedBy.Value, Optional.ToNullable(lastModifiedByType), Optional.ToNullable(lastModifiedAt)); + } + + private struct SystemDataProperties + { + public Optional CreatedBy { get; set; } + public Optional CreatedByType { get; set; } + public Optional CreatedOn { get; set; } + public Optional LastModifiedBy { get; set; } + public Optional LastModifiedByType { get; set; } + public Optional LastModifiedOn { get; set; } + } + + SystemData IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeSystemData(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref SystemDataProperties properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("createdBy"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.CreatedBy = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("createdByType"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.CreatedByType = new CreatedByType(reader.GetString()); + return; + } + if (propertyName.SequenceEqual("createdAt"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.CreatedOn = DateTimeOffset.Parse(reader.GetString(), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); + return; + } + if (propertyName.SequenceEqual("lastModifiedBy"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.LastModifiedBy = reader.GetString(); + return; + } + if (propertyName.SequenceEqual("lastModifiedByType"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.LastModifiedByType = new CreatedByType(reader.GetString()); + return; + } + if (propertyName.SequenceEqual("lastModifiedAt"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.LastModifiedOn = DateTimeOffset.Parse(reader.GetString(), CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal); + return; + } + reader.Skip(); + } + + SystemData IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeSystemData(doc.RootElement, options); + } + + internal partial class SystemDataConverter : JsonConverter + { + public override void Write(Utf8JsonWriter writer, SystemData model, JsonSerializerOptions options) + { + writer.WriteObjectValue(model); + } + public override SystemData Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + using var document = JsonDocument.ParseValue(ref reader); + return DeserializeSystemData(document.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/SystemData.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/SystemData.cs new file mode 100644 index 000000000000..7df008ba04fe --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/SystemData.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Core.Tests.ResourceManager.Models +{ + /// Metadata pertaining to creation and last modification of the resource. + public partial class SystemData + { + /// Initializes a new instance of SystemData. + public SystemData() + { + } + + /// Initializes a new instance of SystemData. + /// The identity that created the resource. + /// The type of identity that created the resource. + /// The timestamp of resource creation (UTC). + /// The identity that last modified the resource. + /// The type of identity that last modified the resource. + /// The timestamp of resource last modification (UTC). + internal SystemData(string createdBy, CreatedByType? createdByType, DateTimeOffset? createdOn, string lastModifiedBy, CreatedByType? lastModifiedByType, DateTimeOffset? lastModifiedOn) + { + CreatedBy = createdBy; + CreatedByType = createdByType; + CreatedOn = createdOn; + LastModifiedBy = lastModifiedBy; + LastModifiedByType = lastModifiedByType; + LastModifiedOn = lastModifiedOn; + } + + /// The identity that created the resource. + public string CreatedBy { get; } + /// The type of identity that created the resource. + public CreatedByType? CreatedByType { get; } + /// The timestamp of resource creation (UTC). + public DateTimeOffset? CreatedOn { get; } + /// The identity that last modified the resource. + public string LastModifiedBy { get; } + /// The type of identity that last modified the resource. + public CreatedByType? LastModifiedByType { get; } + /// The timestamp of resource last modification (UTC). + public DateTimeOffset? LastModifiedOn { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/TrackedResourceData.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/TrackedResourceData.cs new file mode 100644 index 000000000000..73899a3ea3f7 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/TrackedResourceData.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#nullable disable + +using System.Collections.Generic; + +namespace Azure.Core.Tests.ResourceManager.Models +{ + /// The resource model definition for an Azure Resource Manager tracked top level resource which has 'tags' and a 'location'. + public abstract partial class TrackedResourceData : ResourceData + { + internal TrackedResourceData() { } + + /// Initializes a new instance of TrackedResource. + /// The geo-location where the resource lives. + protected TrackedResourceData(AzureLocation location) + { + Tags = new ChangeTrackingDictionary(); + Location = location; + } + + /// Initializes a new instance of TrackedResource. + /// Fully qualified resource ID for the resource. Ex - /subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/{resourceProviderNamespace}/{resourceType}/{resourceName}. + /// The name of the resource. + /// The type of the resource. E.g. "Microsoft.Compute/virtualMachines" or "Microsoft.Storage/storageAccounts". + /// Azure Resource Manager metadata containing createdBy and modifiedBy information. + /// Resource tags. + /// The geo-location where the resource lives. + protected TrackedResourceData(ResourceIdentifier id, string name, ResourceType resourceType, SystemData systemData, IDictionary tags, AzureLocation location) : base(id, name, resourceType, systemData) + { + Tags = tags; + Location = location; + } + + /// Resource tags. + public IDictionary Tags { get; } + /// The geo-location where the resource lives. + public AzureLocation Location { get; set; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/WritableSubResource.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/WritableSubResource.Serialization.cs new file mode 100644 index 000000000000..ac104b6d0050 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/WritableSubResource.Serialization.cs @@ -0,0 +1,115 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// + /// A class representing a sub-resource that contains only the ID. + /// + [JsonConverter(typeof(WritableSubResourceConverter))] + public partial class WritableSubResource : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + /// + /// Serialize the input WritableSubResource object. + /// + /// Input Json writer. + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + if (writer is null) + { + throw new ArgumentNullException(nameof(writer)); + } + + writer.WriteStartObject(); + if (Optional.IsDefined(Id)) + { + writer.WritePropertyName("id"); + writer.WriteStringValue(Id); + } + writer.WriteEndObject(); + } + + /// + /// Deserialize the input JSON element to a WritableSubResource object. + /// + /// The JSON element to be deserialized. + /// Deserialized WritableSubResource object. + internal static WritableSubResource DeserializeWritableSubResource(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + ResourceIdentifier id = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id")) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + id = new ResourceIdentifier(property.Value.GetString()); + continue; + } + } + return new WritableSubResource(id); + } + + private struct WritableSubResourceProperties + { + public ResourceIdentifier Id { get; set; } + } + + WritableSubResource IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeWritableSubResource(doc.RootElement, options); + } + + private static void SetProperty(ReadOnlySpan propertyName, ref WritableSubResourceProperties properties, ref Utf8JsonReader reader, ModelSerializerOptions options) + { + if (propertyName.SequenceEqual("id"u8)) + { + reader.Read(); + if (reader.TokenType != JsonTokenType.Null) + properties.Id = new ResourceIdentifier(reader.GetString()); + return; + } + reader.Skip(); + } + + WritableSubResource IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeWritableSubResource(doc.RootElement, options); + } + + internal partial class WritableSubResourceConverter : JsonConverter + { + public override void Write(Utf8JsonWriter writer, WritableSubResource model, JsonSerializerOptions options) + { + writer.WriteObjectValue(model); + } + public override WritableSubResource Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + using var document = JsonDocument.ParseValue(ref reader); + return DeserializeWritableSubResource(document.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/WritableSubResource.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/WritableSubResource.cs new file mode 100644 index 000000000000..2267f1e23685 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/WritableSubResource.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// + /// A class representing a sub-resource that contains only the ID. + /// + public partial class WritableSubResource + { + /// + /// Initializes an empty instance of for mocking. + /// + public WritableSubResource() + { + } + + /// Initializes a new instance of . + /// ARM resource Id. + protected internal WritableSubResource(ResourceIdentifier id) + { + Id = id; + } + + /// + /// Gets or sets the ARM resource identifier. + /// + /// + public ResourceIdentifier Id { get; set; } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ZoneMapping.Serialization.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ZoneMapping.Serialization.cs new file mode 100644 index 000000000000..2eb8fe97b0b1 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ZoneMapping.Serialization.cs @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + public partial class ZoneMapping : IUtf8JsonSerializable, IModelJsonSerializable + { + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static ZoneMapping DeserializeZoneMapping(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (element.ValueKind == JsonValueKind.Null) + { + return null; + } + Optional location = default; + Optional> zones = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("location"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + location = new AzureLocation(property.Value.GetString()); + continue; + } + if (property.NameEquals("zones"u8)) + { + if (property.Value.ValueKind == JsonValueKind.Null) + { + continue; + } + List array = new List(); + foreach (var item in property.Value.EnumerateArray()) + { + array.Add(item.GetString()); + } + zones = array; + continue; + } + } + return new ZoneMapping(Optional.ToNullable(location), Optional.ToList(zones)); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (Optional.IsDefined(Location)) + { + writer.WritePropertyName("location"u8); + writer.WriteStringValue(Location.Value.DisplayName); + } + if (Optional.IsCollectionDefined(Zones)) + { + writer.WritePropertyName("zones"u8); + writer.WriteStartArray(); + foreach (var item in Zones) + { + writer.WriteStringValue(item); + } + writer.WriteEndArray(); + } + writer.WriteEndObject(); + } + + private struct ZoneMappingProperties + { + public Optional Location { get; set; } + public Optional> Zones { get; set; } + } + + ZoneMapping IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeZoneMapping(doc.RootElement, options); + } + + ZoneMapping IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + using var doc = JsonDocument.Parse(data); + return DeserializeZoneMapping(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ZoneMapping.cs b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ZoneMapping.cs new file mode 100644 index 000000000000..40f58aaf7f9f --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/ModelSerializationTests/ServiceModels/ZoneMapping.cs @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Collections.Generic; + +namespace Azure.Core.Tests.ResourceManager.Resources.Models +{ + /// The ZoneMapping. + public partial class ZoneMapping + { + /// Initializes a new instance of ZoneMapping. + internal ZoneMapping() + { + Zones = new ChangeTrackingList(); + } + + /// Initializes a new instance of ZoneMapping. + /// The location of the zone mapping. + /// + internal ZoneMapping(AzureLocation? location, IReadOnlyList zones) + { + Location = location; + Zones = zones; + } + + /// The location of the zone mapping. + public AzureLocation? Location { get; } + /// Gets the zones. + public IReadOnlyList Zones { get; } + } +} diff --git a/sdk/core/Azure.Core/tests/TestClients/LowLevelClient/LowLevelClientModels/Pet.Serialization.cs b/sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/LowLevelClientModels/Pet.Serialization.cs similarity index 98% rename from sdk/core/Azure.Core/tests/TestClients/LowLevelClient/LowLevelClientModels/Pet.Serialization.cs rename to sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/LowLevelClientModels/Pet.Serialization.cs index 0f4335399d5e..628110e52d1a 100644 --- a/sdk/core/Azure.Core/tests/TestClients/LowLevelClient/LowLevelClientModels/Pet.Serialization.cs +++ b/sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/LowLevelClientModels/Pet.Serialization.cs @@ -4,7 +4,6 @@ #nullable disable using System.Text.Json; -using Azure.Core; namespace Azure.Core.Experimental.Tests.Models { diff --git a/sdk/core/Azure.Core/tests/TestClients/LowLevelClient/LowLevelClientModels/Pet.cs b/sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/LowLevelClientModels/Pet.cs similarity index 92% rename from sdk/core/Azure.Core/tests/TestClients/LowLevelClient/LowLevelClientModels/Pet.cs rename to sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/LowLevelClientModels/Pet.cs index 86ed1ec831ea..f15a3f2a0a20 100644 --- a/sdk/core/Azure.Core/tests/TestClients/LowLevelClient/LowLevelClientModels/Pet.cs +++ b/sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/LowLevelClientModels/Pet.cs @@ -3,9 +3,7 @@ #nullable disable -using System; using System.Text.Json; -using Azure.Core.Pipeline; namespace Azure.Core.Experimental.Tests.Models { @@ -13,14 +11,14 @@ namespace Azure.Core.Experimental.Tests.Models public partial class Pet { /// Initializes a new instance of Pet. - internal Pet() + public Pet() { } /// Initializes a new instance of Pet. /// /// - internal Pet(string name, string species) + public Pet(string name, string species) { Name = name; Species = species; diff --git a/sdk/core/Azure.Core/tests/TestClients/LowLevelClient/LowLevelClientModels/SerializationHelpers.cs b/sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/LowLevelClientModels/SerializationHelpers.cs similarity index 91% rename from sdk/core/Azure.Core/tests/TestClients/LowLevelClient/LowLevelClientModels/SerializationHelpers.cs rename to sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/LowLevelClientModels/SerializationHelpers.cs index 27c5033cccd4..7a0d5720a2b1 100644 --- a/sdk/core/Azure.Core/tests/TestClients/LowLevelClient/LowLevelClientModels/SerializationHelpers.cs +++ b/sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/LowLevelClientModels/SerializationHelpers.cs @@ -2,11 +2,10 @@ // Licensed under the MIT License. using System.Text.Json; -using Azure.Core; namespace Azure.Core.Experimental.Tests.Models { - internal class SerializationHelpers + public class SerializationHelpers { public delegate void SerializerFunc(ref Utf8JsonWriter writer, T t); diff --git a/sdk/core/Azure.Core/tests/TestClients/LowLevelClient/PetStoreClient.cs b/sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/PetStoreClient.cs similarity index 74% rename from sdk/core/Azure.Core/tests/TestClients/LowLevelClient/PetStoreClient.cs rename to sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/PetStoreClient.cs index 6e98e17764de..5a41b6bbd9e4 100644 --- a/sdk/core/Azure.Core/tests/TestClients/LowLevelClient/PetStoreClient.cs +++ b/sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/PetStoreClient.cs @@ -95,6 +95,48 @@ public virtual Response GetPet(string id, RequestContext context = null) } } + /// Get a pet by its Id. + /// Id of pet to return. + /// The request context. +#pragma warning disable AZC0002 + public virtual async Task CreatePetAsync(string id, RequestContent content, RequestContext context = null) +#pragma warning restore AZC0002 + { + using var scope = _clientDiagnostics.CreateScope("PetStoreClient.GetPet"); + scope.Start(); + try + { + using HttpMessage message = CreateGetPetRequest(id, context); + return await Pipeline.ProcessMessageAsync(message, context).ConfigureAwait(false); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// Get a pet by its Id. + /// Id of pet to return. + /// The request context. +#pragma warning disable AZC0002 + public virtual Response CreatePet(string id, RequestContent content, RequestContext context = null) +#pragma warning restore AZC0002 + { + using var scope = _clientDiagnostics.CreateScope("PetStoreClient.GetPet"); + scope.Start(); + try + { + using HttpMessage message = CreateGetPetRequest(id, context); + return Pipeline.ProcessMessage(message, context); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + /// Create Request for and operations. /// Id of pet to return. /// The request context. diff --git a/sdk/core/Azure.Core/tests/TestClients/LowLevelClient/PetStoreClientOptions.cs b/sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/PetStoreClientOptions.cs similarity index 98% rename from sdk/core/Azure.Core/tests/TestClients/LowLevelClient/PetStoreClientOptions.cs rename to sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/PetStoreClientOptions.cs index f400dd2b82a6..8e83c9c437f9 100644 --- a/sdk/core/Azure.Core/tests/TestClients/LowLevelClient/PetStoreClientOptions.cs +++ b/sdk/core/Azure.Core/tests/common/TestClients/LowLevelClient/PetStoreClientOptions.cs @@ -4,7 +4,6 @@ #nullable disable using System; -using Azure.Core; namespace Azure.Core.Experimental.Tests { diff --git a/sdk/core/Azure.Core/tests/common/TestData.cs b/sdk/core/Azure.Core/tests/common/TestData.cs new file mode 100644 index 000000000000..cac2d67c5614 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData.cs @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.IO; +using System.Text; + +namespace Azure.Core.Tests.Common +{ + public static class TestData + { + public static string GetLocation(string fileName) + { + string testsLocation = Directory.GetParent(typeof(TestData).Assembly.Location).FullName; + StringBuilder builder = new StringBuilder(); + int indexAfter = testsLocation.IndexOf(".Tests") + 6; + builder.Append(testsLocation.Substring(0, indexAfter)); + builder.Append(".Common"); + if (testsLocation[indexAfter] == Path.DirectorySeparatorChar) + { + builder.Append(testsLocation.Substring(indexAfter)); + } + else + { + int dirSeparatorIndex = testsLocation.IndexOf(Path.DirectorySeparatorChar, indexAfter); + builder.Append(testsLocation.Substring(dirSeparatorIndex)); + } + return Path.Combine(builder.ToString(), "TestData", fileName); + } + } +} diff --git a/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData.json b/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData.json new file mode 100644 index 000000000000..0081d88bbfbe --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/AvailabilitySetData.json @@ -0,0 +1,16 @@ +{ + "name": "testAS-3375", + "id": "/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS-3375", + "type": "Microsoft.Compute/availabilitySets", + "location": "eastus", + "tags": { + "key": "value" + }, + "properties": { + "platformUpdateDomainCount": 5, + "platformFaultDomainCount": 3 + }, + "sku": { + "name": "Classic" + } +} diff --git a/sdk/core/Azure.Core/tests/common/TestData/ModelXml.xml b/sdk/core/Azure.Core/tests/common/TestData/ModelXml.xml new file mode 100644 index 000000000000..2d6c52e2cc82 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/ModelXml.xml @@ -0,0 +1,9 @@ + + Color + Red + ReadOnly + + ChildRed + ChildReadOnly + + diff --git a/sdk/core/Azure.Core/tests/common/TestData/ModelXmlX.xml b/sdk/core/Azure.Core/tests/common/TestData/ModelXmlX.xml new file mode 100644 index 000000000000..a6c7329e21d8 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/ModelXmlX.xml @@ -0,0 +1,9 @@ + + Color + Red + ReadOnly + + ChildRed + ChildReadOnly + + diff --git a/sdk/core/Azure.Core/tests/common/TestData/ResourceProviderData-Collapsed.json b/sdk/core/Azure.Core/tests/common/TestData/ResourceProviderData-Collapsed.json new file mode 100644 index 000000000000..174ff6cdbe4d --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/ResourceProviderData-Collapsed.json @@ -0,0 +1 @@ +{"id":"/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/providers/Microsoft.Network","namespace":"Microsoft.Network","resourceTypes":[{"resourceType":"virtualNetworks","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"virtualNetworks/taggedTrafficConsumers","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"None"},{"resourceType":"natGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01"],"defaultApiVersion":"2020-03-01","zoneMappings":[{"location":"Australia East","zones":["2","1","3"]},{"location":"Brazil South","zones":["2","1","3"]},{"location":"Canada Central","zones":["2","1","3"]},{"location":"Central India","zones":["2","1","3"]},{"location":"Central US","zones":["2","1","3"]},{"location":"Central US EUAP","zones":["1","2"]},{"location":"East Asia","zones":["2","1","3"]},{"location":"East US","zones":["2","1","3"]},{"location":"East US 2","zones":["2","1","3"]},{"location":"East US 2 EUAP","zones":["2","1","3"]},{"location":"France Central","zones":["2","1","3"]},{"location":"Germany West Central","zones":["2","1","3"]},{"location":"Japan East","zones":["2","1","3"]},{"location":"Korea Central","zones":["2","1","3"]},{"location":"North Central US","zones":[]},{"location":"North Europe","zones":["2","1","3"]},{"location":"Norway East","zones":["2","1","3"]},{"location":"Qatar Central","zones":["2","1","3"]},{"location":"South Africa North","zones":["2","1","3"]},{"location":"South Central US","zones":["2","1","3"]},{"location":"Southeast Asia","zones":["2","1","3"]},{"location":"Sweden Central","zones":["2","1","3"]},{"location":"Switzerland North","zones":["2","1","3"]},{"location":"UAE North","zones":["2","1","3"]},{"location":"UK South","zones":["2","1","3"]},{"location":"West Europe","zones":["2","1","3"]},{"location":"West US","zones":[]},{"location":"West US 2","zones":["2","1","3"]},{"location":"West US 3","zones":["2","1","3"]},{"location":"Poland Central","zones":["2","1","3"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"publicIPAddresses","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"zoneMappings":[{"location":"Australia East","zones":["2","1","3"]},{"location":"Brazil South","zones":["2","1","3"]},{"location":"Canada Central","zones":["2","1","3"]},{"location":"Central India","zones":["2","1","3"]},{"location":"Central US","zones":["2","1","3"]},{"location":"Central US EUAP","zones":["1","2"]},{"location":"East Asia","zones":["2","1","3"]},{"location":"East US","zones":["2","1","3"]},{"location":"East US 2","zones":["2","1","3"]},{"location":"East US 2 EUAP","zones":["2","1","3"]},{"location":"France Central","zones":["2","1","3"]},{"location":"Germany West Central","zones":["2","1","3"]},{"location":"Japan East","zones":["2","1","3"]},{"location":"Korea Central","zones":["2","1","3"]},{"location":"North Central US","zones":[]},{"location":"North Europe","zones":["2","1","3"]},{"location":"Norway East","zones":["2","1","3"]},{"location":"Qatar Central","zones":["2","1","3"]},{"location":"South Africa North","zones":["2","1","3"]},{"location":"South Central US","zones":["2","1","3"]},{"location":"Southeast Asia","zones":["2","1","3"]},{"location":"Sweden Central","zones":["2","1","3"]},{"location":"Switzerland North","zones":["2","1","3"]},{"location":"UAE North","zones":["2","1","3"]},{"location":"UK South","zones":["2","1","3"]},{"location":"West Europe","zones":["2","1","3"]},{"location":"West US","zones":[]},{"location":"West US 2","zones":["2","1","3"]},{"location":"West US 3","zones":["2","1","3"]},{"location":"Poland Central","zones":["2","1","3"]}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"internalPublicIpAddresses","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01"],"capabilities":"None"},{"resourceType":"customIpPrefixes","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01"],"defaultApiVersion":"2020-06-01","zoneMappings":[{"location":"Australia East","zones":["2","1","3"]},{"location":"Brazil South","zones":["2","1","3"]},{"location":"Canada Central","zones":["2","1","3"]},{"location":"Central India","zones":["2","1","3"]},{"location":"Central US","zones":["2","1","3"]},{"location":"Central US EUAP","zones":["1","2"]},{"location":"East Asia","zones":["2","1","3"]},{"location":"East US","zones":["2","1","3"]},{"location":"East US 2","zones":["2","1","3"]},{"location":"East US 2 EUAP","zones":["2","1","3"]},{"location":"France Central","zones":["2","1","3"]},{"location":"Germany West Central","zones":["2","1","3"]},{"location":"Japan East","zones":["2","1","3"]},{"location":"Korea Central","zones":["2","1","3"]},{"location":"North Central US","zones":[]},{"location":"North Europe","zones":["2","1","3"]},{"location":"Norway East","zones":["2","1","3"]},{"location":"Qatar Central","zones":["2","1","3"]},{"location":"South Africa North","zones":["2","1","3"]},{"location":"South Central US","zones":["2","1","3"]},{"location":"Southeast Asia","zones":["2","1","3"]},{"location":"Sweden Central","zones":["2","1","3"]},{"location":"Switzerland North","zones":["2","1","3"]},{"location":"UAE North","zones":["2","1","3"]},{"location":"UK South","zones":["2","1","3"]},{"location":"West Europe","zones":["2","1","3"]},{"location":"West US","zones":[]},{"location":"West US 2","zones":["2","1","3"]},{"location":"West US 3","zones":["2","1","3"]},{"location":"Poland Central","zones":["2","1","3"]}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkInterfaces","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"dscpConfigurations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01"],"defaultApiVersion":"2020-06-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"privateEndpoints","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01"],"defaultApiVersion":"2020-03-01","locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"privateEndpoints/privateLinkServiceProxies","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01"],"defaultApiVersion":"2020-03-01","capabilities":"None"},{"resourceType":"privateEndpointRedirectMaps","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"loadBalancers","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkSecurityGroups","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"applicationSecurityGroups","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2017-09-01"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"serviceEndpointPolicies","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkIntentPolicies","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"routeTables","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"publicIPPrefixes","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01"],"defaultApiVersion":"2020-03-01","zoneMappings":[{"location":"Australia East","zones":["2","1","3"]},{"location":"Brazil South","zones":["2","1","3"]},{"location":"Canada Central","zones":["2","1","3"]},{"location":"Central India","zones":["2","1","3"]},{"location":"Central US","zones":["2","1","3"]},{"location":"Central US EUAP","zones":["1","2"]},{"location":"East Asia","zones":["2","1","3"]},{"location":"East US","zones":["2","1","3"]},{"location":"East US 2","zones":["2","1","3"]},{"location":"East US 2 EUAP","zones":["2","1","3"]},{"location":"France Central","zones":["2","1","3"]},{"location":"Germany West Central","zones":["2","1","3"]},{"location":"Japan East","zones":["2","1","3"]},{"location":"Korea Central","zones":["2","1","3"]},{"location":"North Central US","zones":[]},{"location":"North Europe","zones":["2","1","3"]},{"location":"Norway East","zones":["2","1","3"]},{"location":"Qatar Central","zones":["2","1","3"]},{"location":"South Africa North","zones":["2","1","3"]},{"location":"South Central US","zones":["2","1","3"]},{"location":"Southeast Asia","zones":["2","1","3"]},{"location":"Sweden Central","zones":["2","1","3"]},{"location":"Switzerland North","zones":["2","1","3"]},{"location":"UAE North","zones":["2","1","3"]},{"location":"UK South","zones":["2","1","3"]},{"location":"West Europe","zones":["2","1","3"]},{"location":"West US","zones":[]},{"location":"West US 2","zones":["2","1","3"]},{"location":"West US 3","zones":["2","1","3"]},{"location":"Poland Central","zones":["2","1","3"]}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkWatchers","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkWatchers/connectionMonitors","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkWatchers/flowLogs","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkWatchers/pingMeshes","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"virtualNetworkGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-03-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"localNetworkGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-03-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"connections","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-03-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"applicationGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","zoneMappings":[{"location":"Australia East","zones":["2","1","3"]},{"location":"Brazil South","zones":["2","1","3"]},{"location":"Canada Central","zones":["2","1","3"]},{"location":"Central India","zones":["2","1","3"]},{"location":"Central US","zones":["2","1","3"]},{"location":"Central US EUAP","zones":["1","2"]},{"location":"East Asia","zones":["2","1","3"]},{"location":"East US","zones":["2","1","3"]},{"location":"East US 2","zones":["2","1","3"]},{"location":"East US 2 EUAP","zones":["2","1","3"]},{"location":"France Central","zones":["2","1","3"]},{"location":"Germany West Central","zones":["2","1","3"]},{"location":"Japan East","zones":["2","1","3"]},{"location":"Korea Central","zones":["2","1","3"]},{"location":"North Central US","zones":[]},{"location":"North Europe","zones":["2","1","3"]},{"location":"Norway East","zones":["2","1","3"]},{"location":"Qatar Central","zones":["2","1","3"]},{"location":"South Africa North","zones":["2","1","3"]},{"location":"South Central US","zones":["2","1","3"]},{"location":"Southeast Asia","zones":["2","1","3"]},{"location":"Sweden Central","zones":["2","1","3"]},{"location":"Switzerland North","zones":["2","1","3"]},{"location":"UAE North","zones":["2","1","3"]},{"location":"UK South","zones":["2","1","3"]},{"location":"West Europe","zones":["2","1","3"]},{"location":"West US","zones":[]},{"location":"West US 2","zones":["2","1","3"]},{"location":"West US 3","zones":["2","1","3"]},{"location":"Poland Central","zones":["2","1","3"]}],"capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"applicationGatewayWebApplicationFirewallPolicies","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"locations","locations":[],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"None"},{"resourceType":"locations/operations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"None"},{"resourceType":"locations/operationResults","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"None"},{"resourceType":"locations/CheckDnsNameAvailability","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"capabilities":"None"},{"resourceType":"locations/setLoadBalancerFrontendPublicIpAddresses","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01"],"capabilities":"None"},{"resourceType":"cloudServiceSlots","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01"],"capabilities":"SupportsExtension"},{"resourceType":"locations/usages","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2015-06-15"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2017-10-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2017-10-01"}],"capabilities":"None"},{"resourceType":"locations/virtualNetworkAvailableEndpointServices","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01"],"capabilities":"None"},{"resourceType":"locations/availableDelegations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"capabilities":"None"},{"resourceType":"locations/ApplicationGatewayWafDynamicManifests","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01"],"capabilities":"None"},{"resourceType":"locations/serviceTags","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01"],"capabilities":"None"},{"resourceType":"locations/availablePrivateEndpointTypes","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01"],"capabilities":"None"},{"resourceType":"locations/availableServiceAliases","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01"],"capabilities":"None"},{"resourceType":"locations/checkPrivateLinkServiceVisibility","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01"],"capabilities":"None"},{"resourceType":"locations/autoApprovedPrivateLinkServices","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01"],"capabilities":"None"},{"resourceType":"locations/batchValidatePrivateEndpointsForResourceMove","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01"],"capabilities":"None"},{"resourceType":"locations/batchNotifyPrivateEndpointsForResourceMove","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01"],"capabilities":"None"},{"resourceType":"locations/supportedVirtualMachineSizes","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"capabilities":"None"},{"resourceType":"locations/setAzureNetworkManagerConfiguration","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01"],"capabilities":"None"},{"resourceType":"locations/publishResources","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01"],"capabilities":"None"},{"resourceType":"locations/getAzureNetworkManagerConfiguration","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01"],"capabilities":"None"},{"resourceType":"locations/checkAcceleratedNetworkingSupport","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"capabilities":"None"},{"resourceType":"locations/validateResourceOwnership","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"capabilities":"None"},{"resourceType":"locations/setResourceOwnership","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"capabilities":"None"},{"resourceType":"locations/effectiveResourceOwnership","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"capabilities":"None"},{"resourceType":"operations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"capabilities":"None"},{"resourceType":"dnszones","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2016-04-01"},{"profileVersion":"2018-03-01-hybrid","apiVersion":"2016-04-01"},{"profileVersion":"2019-03-01-hybrid","apiVersion":"2016-04-01"}],"capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"dnsOperationResults","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnsOperationStatuses","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"getDnsResourceReference","locations":["global"],"apiVersions":["2018-05-01"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"internalNotify","locations":["global"],"apiVersions":["2018-05-01"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/A","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/AAAA","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/CNAME","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/PTR","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/MX","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/TXT","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/SRV","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/SOA","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/NS","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/CAA","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/recordsets","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"dnszones/all","locations":["global"],"apiVersions":["2018-05-01","2018-03-01-preview","2017-10-01","2017-09-15-preview","2017-09-01","2016-04-01","2015-05-04-preview"],"defaultApiVersion":"2018-05-01","capabilities":"None"},{"resourceType":"privateDnsZones","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"privateDnsZones/virtualNetworkLinks","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"privateDnsOperationResults","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsOperationStatuses","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZonesInternal","locations":["global"],"apiVersions":["2020-06-01","2020-01-01"],"defaultApiVersion":"2020-01-01","capabilities":"None"},{"resourceType":"privateDnsZones/A","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/AAAA","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/CNAME","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/PTR","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/MX","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/TXT","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/SRV","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/SOA","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"privateDnsZones/all","locations":["global"],"apiVersions":["2020-06-01","2020-01-01","2018-09-01"],"defaultApiVersion":"2018-09-01","capabilities":"None"},{"resourceType":"virtualNetworks/privateDnsZoneLinks","locations":["global"],"apiVersions":["2020-06-01"],"defaultApiVersion":"2020-06-01","capabilities":"None"},{"resourceType":"dnsResolvers","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"dnsResolvers/inboundEndpoints","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"dnsResolvers/outboundEndpoints","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"dnsForwardingRulesets","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"dnsForwardingRulesets/forwardingRules","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"None"},{"resourceType":"dnsForwardingRulesets/virtualNetworkLinks","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"None"},{"resourceType":"virtualNetworks/listDnsResolvers","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"None"},{"resourceType":"virtualNetworks/listDnsForwardingRulesets","locations":["West Central US","East US 2","West Europe","North Europe","Australia East","UK South","South Central US","East US","North Central US","West US 2","West US 3","Southeast Asia","Central India","Canada Central","Central US","France Central","Japan East","Germany West Central","South Africa North","Korea Central","Sweden Central","East Asia","Switzerland North","Brazil South","West US","Norway East","UAE North","Australia Southeast","Canada East","Japan West","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"None"},{"resourceType":"locations/dnsResolverOperationResults","locations":[],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"None"},{"resourceType":"locations/dnsResolverOperationStatuses","locations":[],"apiVersions":["2022-07-01","2020-04-01-preview"],"defaultApiVersion":"2020-04-01-preview","capabilities":"None"},{"resourceType":"trafficmanagerprofiles","locations":["global"],"apiVersions":["2022-12-01-preview","2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-05-01","2017-03-01","2015-11-01","2015-04-28-preview"],"defaultApiVersion":"2018-08-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"trafficmanagerprofiles/heatMaps","locations":["global"],"apiVersions":["2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-09-01-preview"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"trafficmanagerprofiles/azureendpoints","locations":["global"],"apiVersions":["2022-12-01-preview","2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-05-01","2017-03-01","2015-11-01","2015-04-28-preview"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"trafficmanagerprofiles/externalendpoints","locations":["global"],"apiVersions":["2022-12-01-preview","2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-05-01","2017-03-01","2015-11-01","2015-04-28-preview"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"trafficmanagerprofiles/nestedendpoints","locations":["global"],"apiVersions":["2022-12-01-preview","2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-05-01","2017-03-01","2015-11-01","2015-04-28-preview"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"checkTrafficManagerNameAvailability","locations":["global"],"apiVersions":["2022-12-01-preview","2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-05-01","2017-03-01","2015-11-01","2015-04-28-preview"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"checkTrafficManagerNameAvailabilityV2","locations":["global"],"apiVersions":["2022-12-01-preview"],"defaultApiVersion":"2022-12-01-preview","capabilities":"None"},{"resourceType":"trafficManagerUserMetricsKeys","locations":["global"],"apiVersions":["2022-04-01-preview","2018-08-01","2018-04-01","2017-09-01-preview"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"trafficManagerGeographicHierarchies","locations":["global"],"apiVersions":["2022-12-01-preview","2022-04-01-preview","2018-08-01","2018-04-01","2018-03-01","2018-02-01","2017-05-01","2017-03-01"],"defaultApiVersion":"2018-08-01","capabilities":"None"},{"resourceType":"expressRouteCircuits","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"expressRouteServiceProviders","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"capabilities":"None"},{"resourceType":"applicationGatewayAvailableWafRuleSets","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01"],"capabilities":"None"},{"resourceType":"applicationGatewayAvailableSslOptions","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01"],"capabilities":"None"},{"resourceType":"applicationGatewayAvailableServerVariables","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01"],"capabilities":"None"},{"resourceType":"applicationGatewayAvailableRequestHeaders","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01"],"capabilities":"None"},{"resourceType":"applicationGatewayAvailableResponseHeaders","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01"],"capabilities":"None"},{"resourceType":"routeFilters","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01","2016-11-01","2016-10-01","2016-09-01","2016-08-01","2016-07-01","2016-06-01","2016-03-30","2015-06-15","2015-05-01-preview","2014-12-01-preview"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"bgpServiceCommunities","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01","2017-08-01","2017-06-01","2017-04-01","2017-03-01","2016-12-01"],"capabilities":"None"},{"resourceType":"virtualWans","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"vpnSites","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"vpnServerConfigurations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","South Africa North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"virtualHubs","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"vpnGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"p2sVpnGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","UAE North","South Africa North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"expressRouteGateways","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"locations/hybridEdgeZone","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01"],"capabilities":"None"},{"resourceType":"expressRoutePortsLocations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01"],"capabilities":"None"},{"resourceType":"expressRoutePorts","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","UAE North","South Africa North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"firewallPolicies","locations":["Qatar Central","UAE North","Australia Central 2","UAE Central","Germany North","Central India","Korea South","Switzerland North","Switzerland West","Japan West","France South","South Africa West","West India","Canada East","South India","Germany West Central","Norway East","Norway West","South Africa North","East Asia","Southeast Asia","Korea Central","Brazil South","Brazil Southeast","West US 3","Jio India West","Sweden Central","Japan East","UK West","West US","East US","North Europe","West Europe","West Central US","South Central US","Australia East","Australia Central","Australia Southeast","UK South","East US 2","West US 2","North Central US","Canada Central","France Central","Central US","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01"],"defaultApiVersion":"2020-04-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"ipGroups","locations":["Qatar Central","UAE North","Australia Central 2","UAE Central","Germany North","Central India","Korea South","Switzerland North","Switzerland West","Japan West","France South","South Africa West","West India","Canada East","South India","Germany West Central","Norway East","Norway West","South Africa North","East Asia","Southeast Asia","Korea Central","Brazil South","Brazil Southeast","West US 3","Jio India West","Sweden Central","Japan East","UK West","West US","East US","North Europe","West Europe","South Central US","Australia East","Australia Central","Australia Southeast","UK South","East US 2","West US 2","North Central US","Canada Central","France Central","West Central US","Central US","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01"],"defaultApiVersion":"2020-04-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"azureWebCategories","locations":[],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01"],"defaultApiVersion":"2020-08-01","capabilities":"None"},{"resourceType":"locations/nfvOperations","locations":[],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"capabilities":"None"},{"resourceType":"locations/nfvOperationResults","locations":[],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"capabilities":"None"},{"resourceType":"securityPartnerProviders","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"azureFirewalls","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","France Central","Australia Central","Japan West","Japan East","Korea Central","Korea South","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01"],"defaultApiVersion":"2020-03-01","zoneMappings":[{"location":"Australia East","zones":["2","1","3"]},{"location":"Brazil South","zones":["2","1","3"]},{"location":"Canada Central","zones":["2","1","3"]},{"location":"Central India","zones":["2","1","3"]},{"location":"Central US","zones":["2","1","3"]},{"location":"Central US EUAP","zones":["1","2"]},{"location":"East Asia","zones":["2","1","3"]},{"location":"East US","zones":["2","1","3"]},{"location":"East US 2","zones":["2","1","3"]},{"location":"East US 2 EUAP","zones":["2","1","3"]},{"location":"France Central","zones":["2","1","3"]},{"location":"Germany West Central","zones":["2","1","3"]},{"location":"Japan East","zones":["2","1","3"]},{"location":"Korea Central","zones":["2","1","3"]},{"location":"North Central US","zones":[]},{"location":"North Europe","zones":["2","1","3"]},{"location":"Norway East","zones":["2","1","3"]},{"location":"Qatar Central","zones":["2","1","3"]},{"location":"South Africa North","zones":["2","1","3"]},{"location":"South Central US","zones":["2","1","3"]},{"location":"Southeast Asia","zones":["2","1","3"]},{"location":"Sweden Central","zones":["2","1","3"]},{"location":"Switzerland North","zones":["2","1","3"]},{"location":"UAE North","zones":["2","1","3"]},{"location":"UK South","zones":["2","1","3"]},{"location":"West Europe","zones":["2","1","3"]},{"location":"West US","zones":[]},{"location":"West US 2","zones":["2","1","3"]},{"location":"West US 3","zones":["2","1","3"]},{"location":"Poland Central","zones":["2","1","3"]}],"capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"azureFirewallFqdnTags","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01"],"capabilities":"None"},{"resourceType":"virtualNetworkTaps","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"privateLinkServices","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01"],"defaultApiVersion":"2020-03-01","locationMappings":[{"location":"East US 2 EUAP","type":"EdgeZone","extendedLocations":["microsoftrrdclab1","microsoftrrdclab3"]},{"location":"West US","type":"EdgeZone","extendedLocations":["microsoftlosangeles1"]},{"location":"East US 2","type":"EdgeZone","extendedLocations":["microsoftmiami1"]}],"capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"locations/privateLinkServices","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01"],"capabilities":"None"},{"resourceType":"ddosProtectionPlans","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01"],"defaultApiVersion":"2020-03-01","apiProfiles":[{"profileVersion":"2017-03-09-profile","apiVersion":"2018-02-01"}],"capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"networkProfiles","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01"],"defaultApiVersion":"2020-03-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"checkFrontdoorNameAvailability","locations":["global","Central US","East US","East US 2","North Central US","South Central US","West US","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2021-06-01","2020-07-01","2020-05-01","2020-01-01","2019-08-01","2019-05-01","2019-04-01","2018-08-01"],"defaultApiVersion":"2020-07-01","capabilities":"None"},{"resourceType":"frontdoorWebApplicationFirewallManagedRuleSets","locations":["global","Central US","East US","East US 2","North Central US","South Central US","West US","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2022-05-01","2020-11-01","2020-04-01","2019-10-01","2019-03-01"],"defaultApiVersion":"2020-11-01","capabilities":"None"},{"resourceType":"locations/bareMetalTenants","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01"],"capabilities":"None"},{"resourceType":"bastionHosts","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"virtualRouters","locations":["Qatar Central","UAE North","Australia Central 2","UAE Central","Germany North","Central India","Korea South","Switzerland North","Switzerland West","Japan West","France South","South Africa West","West India","Canada East","South India","Germany West Central","Norway East","Norway West","South Africa North","East Asia","Southeast Asia","Korea Central","Brazil South","Brazil Southeast","West US 3","Jio India West","Sweden Central","Japan East","UK West","West US","East US","North Europe","West Europe","West Central US","South Central US","Australia East","Australia Central","Australia Southeast","UK South","East US 2","West US 2","North Central US","Canada Central","France Central","Central US","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01"],"defaultApiVersion":"2020-04-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"networkVirtualAppliances","locations":["Qatar Central","Brazil Southeast","West US 3","Jio India West","Sweden Central","UAE North","Australia Central 2","UAE Central","Germany North","Central India","Korea South","Switzerland North","Switzerland West","Japan West","France South","South Africa West","West India","Canada East","South India","Germany West Central","Norway East","Norway West","South Africa North","East Asia","Southeast Asia","Korea Central","Brazil South","Japan East","UK West","West US","East US","North Europe","West Europe","West Central US","South Central US","Australia East","Australia Central","Australia Southeast","UK South","East US 2","West US 2","North Central US","Canada Central","France Central","Central US","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01"],"defaultApiVersion":"2020-04-01","capabilities":"SystemAssignedResourceIdentity, SupportsTags, SupportsLocation"},{"resourceType":"ipAllocations","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkManagers","locations":["West Central US","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","Jio India West","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2023-03-01-preview","2022-11-01","2022-09-01","2022-07-01","2022-06-01-preview","2022-05-01","2022-04-01-preview","2022-01-01"],"defaultApiVersion":"2022-05-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"networkManagerConnections","locations":[],"apiVersions":["2023-03-01-preview","2022-11-01","2022-09-01","2022-07-01","2022-06-01-preview","2022-05-01","2022-04-01-preview","2022-01-01"],"defaultApiVersion":"2022-05-01","capabilities":"SupportsExtension"},{"resourceType":"locations/queryNetworkSecurityPerimeter","locations":["West Central US","Jio India West","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2022-02-01-preview","2021-05-01-preview","2021-02-01-preview"],"defaultApiVersion":"2021-02-01-preview","capabilities":"None"},{"resourceType":"virtualNetworks/listNetworkManagerEffectiveConnectivityConfigurations","locations":["West Central US","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","Jio India West","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2023-03-01-preview","2022-11-01","2022-09-01","2022-07-01","2022-06-01-preview","2022-05-01","2022-04-01-preview","2022-01-01"],"defaultApiVersion":"2022-05-01","capabilities":"None"},{"resourceType":"virtualNetworks/listNetworkManagerEffectiveSecurityAdminRules","locations":["West Central US","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","Jio India West","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2023-03-01-preview","2022-11-01","2022-09-01","2022-07-01","2022-06-01-preview","2022-05-01","2022-04-01-preview","2022-01-01"],"defaultApiVersion":"2022-05-01","capabilities":"None"},{"resourceType":"networkGroupMemberships","locations":["West Central US","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","Jio India West","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2022-06-01-preview"],"defaultApiVersion":"2022-06-01-preview","capabilities":"SupportsExtension"},{"resourceType":"locations/commitInternalAzureNetworkManagerConfiguration","locations":["West Central US","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","Jio India West","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2023-03-01-preview","2022-11-01","2022-09-01","2022-07-01","2022-06-01-preview","2022-05-01","2022-04-01-preview","2022-01-01"],"capabilities":"None"},{"resourceType":"locations/internalAzureVirtualNetworkManagerOperation","locations":["West Central US","North Central US","West US","West Europe","UAE Central","Germany North","East US","West India","East US 2","Australia Central","Australia Central 2","South Africa West","Brazil South","UK West","North Europe","Central US","UAE North","Germany West Central","Switzerland West","East Asia","Jio India West","South Africa North","UK South","South India","Australia Southeast","France South","West US 2","Sweden Central","Japan West","Norway East","France Central","West US 3","Central India","Korea South","Brazil Southeast","Korea Central","Southeast Asia","South Central US","Norway West","Australia East","Japan East","Canada East","Canada Central","Switzerland North","Qatar Central","Poland Central","East US 2 EUAP","Central US EUAP"],"apiVersions":["2023-03-01-preview","2022-11-01","2022-09-01","2022-07-01","2022-06-01-preview","2022-05-01","2022-04-01-preview","2022-01-01"],"capabilities":"None"},{"resourceType":"networkVirtualApplianceSkus","locations":[],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01"],"defaultApiVersion":"2020-04-01","capabilities":"None"},{"resourceType":"locations/serviceTagDetails","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01"],"capabilities":"None"},{"resourceType":"locations/dataTasks","locations":["West US","East US","North Europe","West Europe","East Asia","Southeast Asia","North Central US","South Central US","Central US","East US 2","Japan East","Japan West","Brazil South","Australia East","Australia Southeast","Central India","South India","West India","Canada Central","Canada East","West Central US","West US 2","UK West","UK South","Korea Central","Korea South","France Central","Australia Central","South Africa North","UAE North","Switzerland North","Germany West Central","Norway East","West US 3","Jio India West","Sweden Central","Qatar Central","Poland Central","Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01"],"capabilities":"None"},{"resourceType":"networkWatchers/lenses","locations":["Central US EUAP","East US 2 EUAP"],"apiVersions":["2023-02-01","2022-11-01","2022-09-01","2022-07-01","2022-05-01","2022-01-01","2021-12-01","2021-08-01","2021-06-01","2021-05-01","2021-04-01","2021-03-01","2021-02-01","2021-01-01","2020-11-01","2020-08-01","2020-07-01","2020-06-01","2020-05-01","2020-04-01","2020-03-01","2020-01-01","2019-12-01","2019-11-01","2019-09-01","2019-08-01","2019-07-01","2019-06-01","2019-04-01","2019-02-01","2018-12-01","2018-11-01","2018-10-01","2018-08-01","2018-07-01","2018-06-01","2018-05-01","2018-04-01","2018-03-01","2018-02-01","2018-01-01","2017-11-01","2017-10-01","2017-09-01"],"defaultApiVersion":"2020-03-01","capabilities":"CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation"},{"resourceType":"frontdoorOperationResults","locations":["global"],"apiVersions":["2022-05-01","2021-06-01","2020-11-01","2020-07-01","2020-05-01","2020-04-01","2020-01-01","2019-11-01","2019-10-01","2019-08-01","2019-05-01","2019-04-01","2019-03-01","2018-08-01"],"defaultApiVersion":"2020-07-01","capabilities":"None"},{"resourceType":"frontdoors","locations":["Central US EUAP","East US 2 EUAP","global","Central US","East US","East US 2","North Central US","South Central US","West US","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2021-06-01","2020-07-01","2020-05-01","2020-04-01","2020-01-01","2019-08-01","2019-05-01","2019-04-01","2018-08-01"],"defaultApiVersion":"2020-07-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"frontdoors/frontendEndpoints","locations":["Central US EUAP","East US 2 EUAP","global","Central US","East US","East US 2","North Central US","South Central US","West US","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2021-06-01","2020-07-01","2020-05-01","2020-04-01","2020-01-01","2019-08-01","2019-05-01","2019-04-01","2018-08-01"],"defaultApiVersion":"2020-07-01","capabilities":"None"},{"resourceType":"frontdoors/frontendEndpoints/customHttpsConfiguration","locations":["Central US EUAP","East US 2 EUAP","global","Central US","East US","East US 2","North Central US","South Central US","West US","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2021-06-01","2020-07-01","2020-05-01","2020-04-01","2020-01-01","2019-08-01","2019-05-01","2019-04-01","2018-08-01"],"defaultApiVersion":"2020-07-01","capabilities":"None"},{"resourceType":"frontdoorWebApplicationFirewallPolicies","locations":["East US 2 EUAP","global","Central US","East US","East US 2","North Central US","South Central US","West US","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2022-05-01","2020-11-01","2020-04-01","2019-10-01","2019-03-01","2018-08-01"],"defaultApiVersion":"2020-11-01","capabilities":"SupportsTags, SupportsLocation"},{"resourceType":"networkExperimentProfiles","locations":["Central US EUAP","East US 2 EUAP","global","Central US","East US","East US 2","North Central US","South Central US","West US","West US 2","North Europe","West Europe","East Asia","Southeast Asia","Japan East","Japan West","Brazil South","Australia East","Australia Southeast"],"apiVersions":["2019-11-01"],"defaultApiVersion":"2019-11-01","capabilities":"SupportsTags, SupportsLocation"}],"registrationState":"Registered","registrationPolicy":"RegistrationRequired"} diff --git a/sdk/core/Azure.Core/tests/common/TestData/ResourceProviderData.json b/sdk/core/Azure.Core/tests/common/TestData/ResourceProviderData.json new file mode 100644 index 000000000000..5e95ddfd70d2 --- /dev/null +++ b/sdk/core/Azure.Core/tests/common/TestData/ResourceProviderData.json @@ -0,0 +1,11392 @@ +{ + "id": "/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/providers/Microsoft.Network", + "namespace": "Microsoft.Network", + "resourceTypes": [ + { + "resourceType": "virtualNetworks", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "virtualNetworks/taggedTrafficConsumers", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "None" + }, + { + "resourceType": "natGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01" + ], + "defaultApiVersion": "2020-03-01", + "zoneMappings": [ + { + "location": "Australia East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Brazil South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Canada Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central India", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US EUAP", + "zones": [ + "1", + "2" + ] + }, + { + "location": "East Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2 EUAP", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "France Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Germany West Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Japan East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Korea Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "North Central US", + "zones": [] + }, + { + "location": "North Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Norway East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Qatar Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Africa North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Southeast Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Sweden Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Switzerland North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UAE North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UK South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US", + "zones": [] + }, + { + "location": "West US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US 3", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Poland Central", + "zones": [ + "2", + "1", + "3" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "publicIPAddresses", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "zoneMappings": [ + { + "location": "Australia East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Brazil South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Canada Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central India", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US EUAP", + "zones": [ + "1", + "2" + ] + }, + { + "location": "East Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2 EUAP", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "France Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Germany West Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Japan East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Korea Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "North Central US", + "zones": [] + }, + { + "location": "North Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Norway East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Qatar Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Africa North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Southeast Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Sweden Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Switzerland North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UAE North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UK South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US", + "zones": [] + }, + { + "location": "West US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US 3", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Poland Central", + "zones": [ + "2", + "1", + "3" + ] + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "internalPublicIpAddresses", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01" + ], + "capabilities": "None" + }, + { + "resourceType": "customIpPrefixes", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01" + ], + "defaultApiVersion": "2020-06-01", + "zoneMappings": [ + { + "location": "Australia East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Brazil South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Canada Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central India", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US EUAP", + "zones": [ + "1", + "2" + ] + }, + { + "location": "East Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2 EUAP", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "France Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Germany West Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Japan East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Korea Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "North Central US", + "zones": [] + }, + { + "location": "North Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Norway East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Qatar Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Africa North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Southeast Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Sweden Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Switzerland North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UAE North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UK South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US", + "zones": [] + }, + { + "location": "West US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US 3", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Poland Central", + "zones": [ + "2", + "1", + "3" + ] + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkInterfaces", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "dscpConfigurations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01" + ], + "defaultApiVersion": "2020-06-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "privateEndpoints", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01" + ], + "defaultApiVersion": "2020-03-01", + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "privateEndpoints/privateLinkServiceProxies", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "None" + }, + { + "resourceType": "privateEndpointRedirectMaps", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "loadBalancers", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkSecurityGroups", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "applicationSecurityGroups", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2017-09-01" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "serviceEndpointPolicies", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkIntentPolicies", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "routeTables", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "publicIPPrefixes", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01" + ], + "defaultApiVersion": "2020-03-01", + "zoneMappings": [ + { + "location": "Australia East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Brazil South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Canada Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central India", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US EUAP", + "zones": [ + "1", + "2" + ] + }, + { + "location": "East Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2 EUAP", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "France Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Germany West Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Japan East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Korea Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "North Central US", + "zones": [] + }, + { + "location": "North Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Norway East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Qatar Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Africa North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Southeast Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Sweden Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Switzerland North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UAE North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UK South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US", + "zones": [] + }, + { + "location": "West US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US 3", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Poland Central", + "zones": [ + "2", + "1", + "3" + ] + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkWatchers", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkWatchers/connectionMonitors", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkWatchers/flowLogs", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkWatchers/pingMeshes", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "virtualNetworkGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-03-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "localNetworkGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-03-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "connections", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-03-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "applicationGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "zoneMappings": [ + { + "location": "Australia East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Brazil South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Canada Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central India", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US EUAP", + "zones": [ + "1", + "2" + ] + }, + { + "location": "East Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2 EUAP", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "France Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Germany West Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Japan East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Korea Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "North Central US", + "zones": [] + }, + { + "location": "North Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Norway East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Qatar Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Africa North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Southeast Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Sweden Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Switzerland North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UAE North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UK South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US", + "zones": [] + }, + { + "location": "West US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US 3", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Poland Central", + "zones": [ + "2", + "1", + "3" + ] + } + ], + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "applicationGatewayWebApplicationFirewallPolicies", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "locations", + "locations": [], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "None" + }, + { + "resourceType": "locations/operations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "None" + }, + { + "resourceType": "locations/operationResults", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "None" + }, + { + "resourceType": "locations/CheckDnsNameAvailability", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/setLoadBalancerFrontendPublicIpAddresses", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01" + ], + "capabilities": "None" + }, + { + "resourceType": "cloudServiceSlots", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01" + ], + "capabilities": "SupportsExtension" + }, + { + "resourceType": "locations/usages", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2015-06-15" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2017-10-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2017-10-01" + } + ], + "capabilities": "None" + }, + { + "resourceType": "locations/virtualNetworkAvailableEndpointServices", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/availableDelegations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/ApplicationGatewayWafDynamicManifests", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/serviceTags", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/availablePrivateEndpointTypes", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/availableServiceAliases", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/checkPrivateLinkServiceVisibility", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/autoApprovedPrivateLinkServices", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/batchValidatePrivateEndpointsForResourceMove", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/batchNotifyPrivateEndpointsForResourceMove", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/supportedVirtualMachineSizes", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/setAzureNetworkManagerConfiguration", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/publishResources", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/getAzureNetworkManagerConfiguration", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/checkAcceleratedNetworkingSupport", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/validateResourceOwnership", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/setResourceOwnership", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/effectiveResourceOwnership", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "capabilities": "None" + }, + { + "resourceType": "operations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "capabilities": "None" + }, + { + "resourceType": "dnszones", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2016-04-01" + }, + { + "profileVersion": "2018-03-01-hybrid", + "apiVersion": "2016-04-01" + }, + { + "profileVersion": "2019-03-01-hybrid", + "apiVersion": "2016-04-01" + } + ], + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "dnsOperationResults", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnsOperationStatuses", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "getDnsResourceReference", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "internalNotify", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/A", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/AAAA", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/CNAME", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/PTR", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/MX", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/TXT", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/SRV", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/SOA", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/NS", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/CAA", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/recordsets", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "dnszones/all", + "locations": [ + "global" + ], + "apiVersions": [ + "2018-05-01", + "2018-03-01-preview", + "2017-10-01", + "2017-09-15-preview", + "2017-09-01", + "2016-04-01", + "2015-05-04-preview" + ], + "defaultApiVersion": "2018-05-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "privateDnsZones/virtualNetworkLinks", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "privateDnsOperationResults", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsOperationStatuses", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZonesInternal", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01" + ], + "defaultApiVersion": "2020-01-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/A", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/AAAA", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/CNAME", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/PTR", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/MX", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/TXT", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/SRV", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/SOA", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "privateDnsZones/all", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01", + "2020-01-01", + "2018-09-01" + ], + "defaultApiVersion": "2018-09-01", + "capabilities": "None" + }, + { + "resourceType": "virtualNetworks/privateDnsZoneLinks", + "locations": [ + "global" + ], + "apiVersions": [ + "2020-06-01" + ], + "defaultApiVersion": "2020-06-01", + "capabilities": "None" + }, + { + "resourceType": "dnsResolvers", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "dnsResolvers/inboundEndpoints", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "dnsResolvers/outboundEndpoints", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "dnsForwardingRulesets", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "dnsForwardingRulesets/forwardingRules", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "None" + }, + { + "resourceType": "dnsForwardingRulesets/virtualNetworkLinks", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "None" + }, + { + "resourceType": "virtualNetworks/listDnsResolvers", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "None" + }, + { + "resourceType": "virtualNetworks/listDnsForwardingRulesets", + "locations": [ + "West Central US", + "East US 2", + "West Europe", + "North Europe", + "Australia East", + "UK South", + "South Central US", + "East US", + "North Central US", + "West US 2", + "West US 3", + "Southeast Asia", + "Central India", + "Canada Central", + "Central US", + "France Central", + "Japan East", + "Germany West Central", + "South Africa North", + "Korea Central", + "Sweden Central", + "East Asia", + "Switzerland North", + "Brazil South", + "West US", + "Norway East", + "UAE North", + "Australia Southeast", + "Canada East", + "Japan West", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "None" + }, + { + "resourceType": "locations/dnsResolverOperationResults", + "locations": [], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "None" + }, + { + "resourceType": "locations/dnsResolverOperationStatuses", + "locations": [], + "apiVersions": [ + "2022-07-01", + "2020-04-01-preview" + ], + "defaultApiVersion": "2020-04-01-preview", + "capabilities": "None" + }, + { + "resourceType": "trafficmanagerprofiles", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview", + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-05-01", + "2017-03-01", + "2015-11-01", + "2015-04-28-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "trafficmanagerprofiles/heatMaps", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-09-01-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "trafficmanagerprofiles/azureendpoints", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview", + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-05-01", + "2017-03-01", + "2015-11-01", + "2015-04-28-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "trafficmanagerprofiles/externalendpoints", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview", + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-05-01", + "2017-03-01", + "2015-11-01", + "2015-04-28-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "trafficmanagerprofiles/nestedendpoints", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview", + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-05-01", + "2017-03-01", + "2015-11-01", + "2015-04-28-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "checkTrafficManagerNameAvailability", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview", + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-05-01", + "2017-03-01", + "2015-11-01", + "2015-04-28-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "checkTrafficManagerNameAvailabilityV2", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview" + ], + "defaultApiVersion": "2022-12-01-preview", + "capabilities": "None" + }, + { + "resourceType": "trafficManagerUserMetricsKeys", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2017-09-01-preview" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "trafficManagerGeographicHierarchies", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-12-01-preview", + "2022-04-01-preview", + "2018-08-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2017-05-01", + "2017-03-01" + ], + "defaultApiVersion": "2018-08-01", + "capabilities": "None" + }, + { + "resourceType": "expressRouteCircuits", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "expressRouteServiceProviders", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "capabilities": "None" + }, + { + "resourceType": "applicationGatewayAvailableWafRuleSets", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01" + ], + "capabilities": "None" + }, + { + "resourceType": "applicationGatewayAvailableSslOptions", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01" + ], + "capabilities": "None" + }, + { + "resourceType": "applicationGatewayAvailableServerVariables", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01" + ], + "capabilities": "None" + }, + { + "resourceType": "applicationGatewayAvailableRequestHeaders", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01" + ], + "capabilities": "None" + }, + { + "resourceType": "applicationGatewayAvailableResponseHeaders", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01" + ], + "capabilities": "None" + }, + { + "resourceType": "routeFilters", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01", + "2016-11-01", + "2016-10-01", + "2016-09-01", + "2016-08-01", + "2016-07-01", + "2016-06-01", + "2016-03-30", + "2015-06-15", + "2015-05-01-preview", + "2014-12-01-preview" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "bgpServiceCommunities", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01", + "2017-08-01", + "2017-06-01", + "2017-04-01", + "2017-03-01", + "2016-12-01" + ], + "capabilities": "None" + }, + { + "resourceType": "virtualWans", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "vpnSites", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "vpnServerConfigurations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "South Africa North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "virtualHubs", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "vpnGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "p2sVpnGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "UAE North", + "South Africa North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "expressRouteGateways", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "locations/hybridEdgeZone", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01" + ], + "capabilities": "None" + }, + { + "resourceType": "expressRoutePortsLocations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01" + ], + "capabilities": "None" + }, + { + "resourceType": "expressRoutePorts", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "UAE North", + "South Africa North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "firewallPolicies", + "locations": [ + "Qatar Central", + "UAE North", + "Australia Central 2", + "UAE Central", + "Germany North", + "Central India", + "Korea South", + "Switzerland North", + "Switzerland West", + "Japan West", + "France South", + "South Africa West", + "West India", + "Canada East", + "South India", + "Germany West Central", + "Norway East", + "Norway West", + "South Africa North", + "East Asia", + "Southeast Asia", + "Korea Central", + "Brazil South", + "Brazil Southeast", + "West US 3", + "Jio India West", + "Sweden Central", + "Japan East", + "UK West", + "West US", + "East US", + "North Europe", + "West Europe", + "West Central US", + "South Central US", + "Australia East", + "Australia Central", + "Australia Southeast", + "UK South", + "East US 2", + "West US 2", + "North Central US", + "Canada Central", + "France Central", + "Central US", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01" + ], + "defaultApiVersion": "2020-04-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "ipGroups", + "locations": [ + "Qatar Central", + "UAE North", + "Australia Central 2", + "UAE Central", + "Germany North", + "Central India", + "Korea South", + "Switzerland North", + "Switzerland West", + "Japan West", + "France South", + "South Africa West", + "West India", + "Canada East", + "South India", + "Germany West Central", + "Norway East", + "Norway West", + "South Africa North", + "East Asia", + "Southeast Asia", + "Korea Central", + "Brazil South", + "Brazil Southeast", + "West US 3", + "Jio India West", + "Sweden Central", + "Japan East", + "UK West", + "West US", + "East US", + "North Europe", + "West Europe", + "South Central US", + "Australia East", + "Australia Central", + "Australia Southeast", + "UK South", + "East US 2", + "West US 2", + "North Central US", + "Canada Central", + "France Central", + "West Central US", + "Central US", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01" + ], + "defaultApiVersion": "2020-04-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "azureWebCategories", + "locations": [], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01" + ], + "defaultApiVersion": "2020-08-01", + "capabilities": "None" + }, + { + "resourceType": "locations/nfvOperations", + "locations": [], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/nfvOperationResults", + "locations": [], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "capabilities": "None" + }, + { + "resourceType": "securityPartnerProviders", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "azureFirewalls", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "France Central", + "Australia Central", + "Japan West", + "Japan East", + "Korea Central", + "Korea South", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01" + ], + "defaultApiVersion": "2020-03-01", + "zoneMappings": [ + { + "location": "Australia East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Brazil South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Canada Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central India", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Central US EUAP", + "zones": [ + "1", + "2" + ] + }, + { + "location": "East Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "East US 2 EUAP", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "France Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Germany West Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Japan East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Korea Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "North Central US", + "zones": [] + }, + { + "location": "North Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Norway East", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Qatar Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Africa North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "South Central US", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Southeast Asia", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Sweden Central", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Switzerland North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UAE North", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "UK South", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West Europe", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US", + "zones": [] + }, + { + "location": "West US 2", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "West US 3", + "zones": [ + "2", + "1", + "3" + ] + }, + { + "location": "Poland Central", + "zones": [ + "2", + "1", + "3" + ] + } + ], + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "azureFirewallFqdnTags", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01" + ], + "capabilities": "None" + }, + { + "resourceType": "virtualNetworkTaps", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "privateLinkServices", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-03-01", + "locationMappings": [ + { + "location": "East US 2 EUAP", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftrrdclab1", + "microsoftrrdclab3" + ] + }, + { + "location": "West US", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftlosangeles1" + ] + }, + { + "location": "East US 2", + "type": "EdgeZone", + "extendedLocations": [ + "microsoftmiami1" + ] + } + ], + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "locations/privateLinkServices", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01" + ], + "capabilities": "None" + }, + { + "resourceType": "ddosProtectionPlans", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01" + ], + "defaultApiVersion": "2020-03-01", + "apiProfiles": [ + { + "profileVersion": "2017-03-09-profile", + "apiVersion": "2018-02-01" + } + ], + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkProfiles", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "checkFrontdoorNameAvailability", + "locations": [ + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2021-06-01", + "2020-07-01", + "2020-05-01", + "2020-01-01", + "2019-08-01", + "2019-05-01", + "2019-04-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-07-01", + "capabilities": "None" + }, + { + "resourceType": "frontdoorWebApplicationFirewallManagedRuleSets", + "locations": [ + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2022-05-01", + "2020-11-01", + "2020-04-01", + "2019-10-01", + "2019-03-01" + ], + "defaultApiVersion": "2020-11-01", + "capabilities": "None" + }, + { + "resourceType": "locations/bareMetalTenants", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01" + ], + "capabilities": "None" + }, + { + "resourceType": "bastionHosts", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "virtualRouters", + "locations": [ + "Qatar Central", + "UAE North", + "Australia Central 2", + "UAE Central", + "Germany North", + "Central India", + "Korea South", + "Switzerland North", + "Switzerland West", + "Japan West", + "France South", + "South Africa West", + "West India", + "Canada East", + "South India", + "Germany West Central", + "Norway East", + "Norway West", + "South Africa North", + "East Asia", + "Southeast Asia", + "Korea Central", + "Brazil South", + "Brazil Southeast", + "West US 3", + "Jio India West", + "Sweden Central", + "Japan East", + "UK West", + "West US", + "East US", + "North Europe", + "West Europe", + "West Central US", + "South Central US", + "Australia East", + "Australia Central", + "Australia Southeast", + "UK South", + "East US 2", + "West US 2", + "North Central US", + "Canada Central", + "France Central", + "Central US", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01" + ], + "defaultApiVersion": "2020-04-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkVirtualAppliances", + "locations": [ + "Qatar Central", + "Brazil Southeast", + "West US 3", + "Jio India West", + "Sweden Central", + "UAE North", + "Australia Central 2", + "UAE Central", + "Germany North", + "Central India", + "Korea South", + "Switzerland North", + "Switzerland West", + "Japan West", + "France South", + "South Africa West", + "West India", + "Canada East", + "South India", + "Germany West Central", + "Norway East", + "Norway West", + "South Africa North", + "East Asia", + "Southeast Asia", + "Korea Central", + "Brazil South", + "Japan East", + "UK West", + "West US", + "East US", + "North Europe", + "West Europe", + "West Central US", + "South Central US", + "Australia East", + "Australia Central", + "Australia Southeast", + "UK South", + "East US 2", + "West US 2", + "North Central US", + "Canada Central", + "France Central", + "Central US", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01" + ], + "defaultApiVersion": "2020-04-01", + "capabilities": "SystemAssignedResourceIdentity, SupportsTags, SupportsLocation" + }, + { + "resourceType": "ipAllocations", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkManagers", + "locations": [ + "West Central US", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "Jio India West", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2023-03-01-preview", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-06-01-preview", + "2022-05-01", + "2022-04-01-preview", + "2022-01-01" + ], + "defaultApiVersion": "2022-05-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkManagerConnections", + "locations": [], + "apiVersions": [ + "2023-03-01-preview", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-06-01-preview", + "2022-05-01", + "2022-04-01-preview", + "2022-01-01" + ], + "defaultApiVersion": "2022-05-01", + "capabilities": "SupportsExtension" + }, + { + "resourceType": "locations/queryNetworkSecurityPerimeter", + "locations": [ + "West Central US", + "Jio India West", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2022-02-01-preview", + "2021-05-01-preview", + "2021-02-01-preview" + ], + "defaultApiVersion": "2021-02-01-preview", + "capabilities": "None" + }, + { + "resourceType": "virtualNetworks/listNetworkManagerEffectiveConnectivityConfigurations", + "locations": [ + "West Central US", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "Jio India West", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2023-03-01-preview", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-06-01-preview", + "2022-05-01", + "2022-04-01-preview", + "2022-01-01" + ], + "defaultApiVersion": "2022-05-01", + "capabilities": "None" + }, + { + "resourceType": "virtualNetworks/listNetworkManagerEffectiveSecurityAdminRules", + "locations": [ + "West Central US", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "Jio India West", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2023-03-01-preview", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-06-01-preview", + "2022-05-01", + "2022-04-01-preview", + "2022-01-01" + ], + "defaultApiVersion": "2022-05-01", + "capabilities": "None" + }, + { + "resourceType": "networkGroupMemberships", + "locations": [ + "West Central US", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "Jio India West", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2022-06-01-preview" + ], + "defaultApiVersion": "2022-06-01-preview", + "capabilities": "SupportsExtension" + }, + { + "resourceType": "locations/commitInternalAzureNetworkManagerConfiguration", + "locations": [ + "West Central US", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "Jio India West", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2023-03-01-preview", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-06-01-preview", + "2022-05-01", + "2022-04-01-preview", + "2022-01-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/internalAzureVirtualNetworkManagerOperation", + "locations": [ + "West Central US", + "North Central US", + "West US", + "West Europe", + "UAE Central", + "Germany North", + "East US", + "West India", + "East US 2", + "Australia Central", + "Australia Central 2", + "South Africa West", + "Brazil South", + "UK West", + "North Europe", + "Central US", + "UAE North", + "Germany West Central", + "Switzerland West", + "East Asia", + "Jio India West", + "South Africa North", + "UK South", + "South India", + "Australia Southeast", + "France South", + "West US 2", + "Sweden Central", + "Japan West", + "Norway East", + "France Central", + "West US 3", + "Central India", + "Korea South", + "Brazil Southeast", + "Korea Central", + "Southeast Asia", + "South Central US", + "Norway West", + "Australia East", + "Japan East", + "Canada East", + "Canada Central", + "Switzerland North", + "Qatar Central", + "Poland Central", + "East US 2 EUAP", + "Central US EUAP" + ], + "apiVersions": [ + "2023-03-01-preview", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-06-01-preview", + "2022-05-01", + "2022-04-01-preview", + "2022-01-01" + ], + "capabilities": "None" + }, + { + "resourceType": "networkVirtualApplianceSkus", + "locations": [], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01" + ], + "defaultApiVersion": "2020-04-01", + "capabilities": "None" + }, + { + "resourceType": "locations/serviceTagDetails", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01" + ], + "capabilities": "None" + }, + { + "resourceType": "locations/dataTasks", + "locations": [ + "West US", + "East US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "North Central US", + "South Central US", + "Central US", + "East US 2", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast", + "Central India", + "South India", + "West India", + "Canada Central", + "Canada East", + "West Central US", + "West US 2", + "UK West", + "UK South", + "Korea Central", + "Korea South", + "France Central", + "Australia Central", + "South Africa North", + "UAE North", + "Switzerland North", + "Germany West Central", + "Norway East", + "West US 3", + "Jio India West", + "Sweden Central", + "Qatar Central", + "Poland Central", + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01" + ], + "capabilities": "None" + }, + { + "resourceType": "networkWatchers/lenses", + "locations": [ + "Central US EUAP", + "East US 2 EUAP" + ], + "apiVersions": [ + "2023-02-01", + "2022-11-01", + "2022-09-01", + "2022-07-01", + "2022-05-01", + "2022-01-01", + "2021-12-01", + "2021-08-01", + "2021-06-01", + "2021-05-01", + "2021-04-01", + "2021-03-01", + "2021-02-01", + "2021-01-01", + "2020-11-01", + "2020-08-01", + "2020-07-01", + "2020-06-01", + "2020-05-01", + "2020-04-01", + "2020-03-01", + "2020-01-01", + "2019-12-01", + "2019-11-01", + "2019-09-01", + "2019-08-01", + "2019-07-01", + "2019-06-01", + "2019-04-01", + "2019-02-01", + "2018-12-01", + "2018-11-01", + "2018-10-01", + "2018-08-01", + "2018-07-01", + "2018-06-01", + "2018-05-01", + "2018-04-01", + "2018-03-01", + "2018-02-01", + "2018-01-01", + "2017-11-01", + "2017-10-01", + "2017-09-01" + ], + "defaultApiVersion": "2020-03-01", + "capabilities": "CrossResourceGroupResourceMove, CrossSubscriptionResourceMove, SupportsTags, SupportsLocation" + }, + { + "resourceType": "frontdoorOperationResults", + "locations": [ + "global" + ], + "apiVersions": [ + "2022-05-01", + "2021-06-01", + "2020-11-01", + "2020-07-01", + "2020-05-01", + "2020-04-01", + "2020-01-01", + "2019-11-01", + "2019-10-01", + "2019-08-01", + "2019-05-01", + "2019-04-01", + "2019-03-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-07-01", + "capabilities": "None" + }, + { + "resourceType": "frontdoors", + "locations": [ + "Central US EUAP", + "East US 2 EUAP", + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2021-06-01", + "2020-07-01", + "2020-05-01", + "2020-04-01", + "2020-01-01", + "2019-08-01", + "2019-05-01", + "2019-04-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-07-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "frontdoors/frontendEndpoints", + "locations": [ + "Central US EUAP", + "East US 2 EUAP", + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2021-06-01", + "2020-07-01", + "2020-05-01", + "2020-04-01", + "2020-01-01", + "2019-08-01", + "2019-05-01", + "2019-04-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-07-01", + "capabilities": "None" + }, + { + "resourceType": "frontdoors/frontendEndpoints/customHttpsConfiguration", + "locations": [ + "Central US EUAP", + "East US 2 EUAP", + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2021-06-01", + "2020-07-01", + "2020-05-01", + "2020-04-01", + "2020-01-01", + "2019-08-01", + "2019-05-01", + "2019-04-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-07-01", + "capabilities": "None" + }, + { + "resourceType": "frontdoorWebApplicationFirewallPolicies", + "locations": [ + "East US 2 EUAP", + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2022-05-01", + "2020-11-01", + "2020-04-01", + "2019-10-01", + "2019-03-01", + "2018-08-01" + ], + "defaultApiVersion": "2020-11-01", + "capabilities": "SupportsTags, SupportsLocation" + }, + { + "resourceType": "networkExperimentProfiles", + "locations": [ + "Central US EUAP", + "East US 2 EUAP", + "global", + "Central US", + "East US", + "East US 2", + "North Central US", + "South Central US", + "West US", + "West US 2", + "North Europe", + "West Europe", + "East Asia", + "Southeast Asia", + "Japan East", + "Japan West", + "Brazil South", + "Australia East", + "Australia Southeast" + ], + "apiVersions": [ + "2019-11-01" + ], + "defaultApiVersion": "2019-11-01", + "capabilities": "SupportsTags, SupportsLocation" + } + ], + "registrationState": "Registered", + "registrationPolicy": "RegistrationRequired" +} diff --git a/sdk/core/Azure.Core/tests/public/Azure.Core.Tests.Public.csproj b/sdk/core/Azure.Core/tests/public/Azure.Core.Tests.Public.csproj index 729b5f2a54e6..dd5cf6cebc4f 100644 --- a/sdk/core/Azure.Core/tests/public/Azure.Core.Tests.Public.csproj +++ b/sdk/core/Azure.Core/tests/public/Azure.Core.Tests.Public.csproj @@ -1,6 +1,10 @@  $(RequiredTargetFrameworks) + true + true + true + false @@ -8,16 +12,18 @@ + + - - + + diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/AvailabilitySetDataTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/AvailabilitySetDataTests.cs new file mode 100644 index 000000000000..cd6280199568 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/AvailabilitySetDataTests.cs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Azure.Core.Serialization; +using Azure.Core.Tests.ResourceManager.Compute; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class AvailabilitySetDataTests : ModelJsonTests + { + protected override string WirePayload => "{\"name\":\"testAS-3375\",\"id\":\"/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS-3375\",\"type\":\"Microsoft.Compute/availabilitySets\",\"location\":\"eastus\",\"tags\":{\"key\":\"value\"},\"properties\":{\"platformUpdateDomainCount\":5,\"platformFaultDomainCount\":3},\"sku\":{\"name\":\"Classic\",\"extraSku\":\"extraSku\"},\"extraRoot\":\"extraRoot\"}"; + + protected override string JsonPayload => WirePayload; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (AvailabilitySetData)response; + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + var expectedSerializedString = "{"; + if (format == ModelSerializerFormat.Json) + expectedSerializedString += "\"name\":\"testAS-3375\",\"id\":\"/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS-3375\",\"type\":\"Microsoft.Compute/availabilitySets\","; + expectedSerializedString += "\"sku\":{\"name\":\"Classic\""; + //if (!ignoreAdditionalProperties) + // expectedSerializedString += ",\"extraSku\":\"extraSku\""; + expectedSerializedString += "},\"tags\":{\"key\":\"value\"},\"location\":\"eastus\",\"properties\":{\"platformUpdateDomainCount\":5,\"platformFaultDomainCount\":3}"; + //if (!ignoreAdditionalProperties) + // expectedSerializedString += ",\"extraRoot\":\"extraRoot\""; + expectedSerializedString += "}"; + return expectedSerializedString; ; + } + + protected override void VerifyModel(AvailabilitySetData model, ModelSerializerFormat format) + { + Dictionary expectedTags = new Dictionary() { { "key", "value" } }; + + Assert.AreEqual("/subscriptions/e37510d7-33b6-4676-886f-ee75bcc01871/resourceGroups/testRG-6497/providers/Microsoft.Compute/availabilitySets/testAS-3375", model.Id.ToString()); + CollectionAssert.AreEquivalent(expectedTags, model.Tags); + Assert.AreEqual(AzureLocation.EastUS, model.Location); + Assert.AreEqual("testAS-3375", model.Name); + Assert.AreEqual("Microsoft.Compute/availabilitySets", model.ResourceType.ToString()); + Assert.AreEqual(5, model.PlatformUpdateDomainCount); + Assert.AreEqual(3, model.PlatformFaultDomainCount); + Assert.AreEqual("Classic", model.Sku.Name); + } + + protected override void CompareModels(AvailabilitySetData model, AvailabilitySetData model2, ModelSerializerFormat format) + { + Assert.AreEqual(format == ModelSerializerFormat.Wire ? null : model.Id, model2.Id); + Assert.AreEqual(model.Location, model2.Location); + Assert.AreEqual(format == ModelSerializerFormat.Wire ? null : model.Name, model2.Name); + Assert.AreEqual(model.PlatformFaultDomainCount, model2.PlatformFaultDomainCount); + Assert.AreEqual(model.PlatformUpdateDomainCount, model2.PlatformUpdateDomainCount); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual(model.ResourceType, model2.ResourceType); + CollectionAssert.AreEquivalent(model.Tags, model2.Tags); + Assert.AreEqual(model.Sku.Name, model2.Sku.Name); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/BaseModelTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/BaseModelTests.cs new file mode 100644 index 000000000000..8ffd4e4b6db7 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/BaseModelTests.cs @@ -0,0 +1,66 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Linq; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class BaseModelTests : ModelJsonTests + { + protected override BaseModel GetModelInstance() + { + var typeToActivate = typeof(BaseModel).Assembly.GetTypes().FirstOrDefault(t => t.Name == $"Unknown{typeof(BaseModel).Name}"); + return Activator.CreateInstance(typeToActivate, true) as BaseModel; + } + + protected override string JsonPayload => WirePayload; + + protected override string WirePayload => "{\"kind\":\"X\",\"name\":\"xmodel\",\"xProperty\":100,\"extra\":\"stuff\"}"; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (BaseModel)response; + + protected override void CompareModels(BaseModel model, BaseModel model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Name, model2.Name); + Assert.AreEqual(model.Kind, model2.Kind); + if (format == ModelSerializerFormat.Json) + { + var rawData = GetRawData(model); + var rawData2 = GetRawData(model2); + Assert.IsNotNull(rawData); + Assert.IsNotNull(rawData2); + Assert.AreEqual(rawData.Count, rawData2.Count); + Assert.AreEqual(rawData["extra"].ToObjectFromJson(), rawData2["extra"].ToObjectFromJson()); + } + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + string expected = "{\"kind\":\"X\",\"name\":\"xmodel\""; + if (format == ModelSerializerFormat.Json) + expected += ",\"xProperty\":100"; + if (format == ModelSerializerFormat.Json) + expected += ",\"extra\":\"stuff\""; + expected += "}"; + return expected; + } + + protected override void VerifyModel(BaseModel model, ModelSerializerFormat format) + { + Assert.AreEqual("X", model.Kind); + Assert.AreEqual("xmodel", model.Name); + var rawData = GetRawData(model); + Assert.IsNotNull(rawData); + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual("stuff", rawData["extra"].ToObjectFromJson()); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/EnvelopeTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/EnvelopeTests.cs new file mode 100644 index 000000000000..c7b8535e1174 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/EnvelopeTests.cs @@ -0,0 +1,126 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Text; +using Azure.Core.Serialization; +using Newtonsoft.Json; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class EnvelopeTests : ModelJsonTests> + { + protected override string JsonPayload => WirePayload; + + protected override string WirePayload => "{\"readOnlyProperty\":\"read\"," + + "\"modelA\":{\"name\":\"Cat\",\"isHungry\":false,\"weight\":2.5}," + + "\"modelC\":{\"x\":\"hello\",\"y\":\"bye\"}" + + "}"; + + protected override Func, RequestContent> ToRequestContent => model => model; + + protected override Func> FromResponse => response => (Envelope)response; + + protected override Func GetObjectSerializerFactory(ModelSerializerFormat format) + { + if (format == ModelSerializerFormat.Wire) + { + JsonSerializerSettings settings = new JsonSerializerSettings + { + ContractResolver = new IgnoreReadOnlyPropertiesResolver() + }; + return type => type.Equals(typeof(ModelC)) ? new NewtonsoftJsonObjectSerializer(settings) : null; + } + else + { + return type => type.Equals(typeof(ModelC)) ? new NewtonsoftJsonObjectSerializer() : null; + } + } + + protected override void CompareModels(Envelope model, Envelope model2, ModelSerializerFormat format) + { + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual(model.ReadOnlyProperty, model2.ReadOnlyProperty); + Assert.AreEqual(model.ModelA.LatinName, model2.ModelA.LatinName); + Assert.AreEqual(model.ModelA.HasWhiskers, model2.ModelA.HasWhiskers); + } + Assert.AreEqual(model.ModelA.Name, model2.ModelA.Name); + Assert.AreEqual(model.ModelA.IsHungry, model2.ModelA.IsHungry); + Assert.AreEqual(model.ModelA.Weight, model2.ModelA.Weight); + Assert.AreEqual(model.ModelT.X, model2.ModelT.X); + Assert.AreEqual(model.ModelT.Y, model2.ModelT.Y); + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + StringBuilder expectedSerialized = new StringBuilder("{"); + if (format == ModelSerializerFormat.Json) + { + expectedSerialized.Append("\"readOnlyProperty\":\"read\","); + } + expectedSerialized.Append("\"modelA\":{"); + if (format == ModelSerializerFormat.Json) + { + expectedSerialized.Append("\"latinName\":\"Felis catus\",\"hasWhiskers\":false,"); + } + expectedSerialized.Append("\"name\":\"Cat\",\"isHungry\":false,\"weight\":2.5},"); + expectedSerialized.Append("\"modelC\":{\"X\":\"hello\",\"Y\":\"bye\"}"); //using NewtonSoft Serializer + expectedSerialized.Append("}"); + return expectedSerialized.ToString(); + } + + protected override void VerifyModel(Envelope model, ModelSerializerFormat format) + { + Assert.IsNotNull(model.ModelA); + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual("read", model.ReadOnlyProperty); + Assert.AreEqual("Felis catus", model.ModelA.LatinName); + Assert.AreEqual(false, model.ModelA.HasWhiskers); + } + Assert.AreEqual("Cat", model.ModelA.Name); + Assert.AreEqual(false, model.ModelA.IsHungry); + Assert.AreEqual(2.5, model.ModelA.Weight); + Assert.IsNotNull(model.ModelT); + Assert.AreEqual("hello", model.ModelT.X); + Assert.AreEqual("bye", model.ModelT.Y); + } + + // Generate a class that implements the NewtonSoft default contract resolver so that ReadOnly properties are not serialized + // This is used to verify that the ReadOnly properties are not serialized when IgnoreReadOnlyProperties is set to true + private class IgnoreReadOnlyPropertiesResolver : Newtonsoft.Json.Serialization.DefaultContractResolver + { + protected override Newtonsoft.Json.Serialization.JsonProperty CreateProperty(System.Reflection.MemberInfo member, MemberSerialization memberSerialization) + { + Newtonsoft.Json.Serialization.JsonProperty property = base.CreateProperty(member, memberSerialization); + + if (!property.Writable) + { + property.ShouldSerialize = obj => false; + } + + return property; + } + } + + public class ModelC + { + public ModelC(string x1, string y1) + { + X = x1; + Y = y1; + } + + public string X { get; set; } + public string Y { get; set; } + + public static void VerifyModelC(ModelC c1, ModelC c2) + { + Assert.That(c1.X == c2.X); + Assert.That(c1.Y == c2.Y); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelAsStructTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelAsStructTests.cs new file mode 100644 index 000000000000..29e3cdd85a42 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelAsStructTests.cs @@ -0,0 +1,50 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class ModelAsStructTests : ModelJsonTests + { + protected override string JsonPayload => WirePayload; + + protected override string WirePayload => "{\"id\":5,\"extra\":\"stuff\"}"; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (ModelAsStruct)response; + + protected override void CompareModels(ModelAsStruct model, ModelAsStruct model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Id, model2.Id); + var rawData1 = GetRawData(model); + var rawData2 = GetRawData(model2); + Assert.IsNotNull(rawData1); + Assert.IsNotNull(rawData2); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual(rawData1["extra"].ToObjectFromJson(), rawData2["extra"].ToObjectFromJson()); + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + string expected = "{\"id\":5"; + if (format == ModelSerializerFormat.Json) + expected += ",\"extra\":\"stuff\""; + expected += "}"; + return expected; + } + + protected override void VerifyModel(ModelAsStruct model, ModelSerializerFormat format) + { + Assert.AreEqual(5, model.Id); + var rawData = GetRawData(model); + Assert.IsNotNull(rawData); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual("stuff", rawData["extra"].ToObjectFromJson()); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelJsonTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelJsonTests.cs new file mode 100644 index 000000000000..6a9488ec32e1 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelJsonTests.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.Serialization; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal abstract class ModelJsonTests : ModelTests where T : IModelJsonSerializable + { + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithJsonInterfaceOfT(string format) + => RoundTripTest(format, new JsonInterfaceStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithJsonInterfaceNonGeneric(string format) + => RoundTripTest(format, new JsonInterfaceNonGenericStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithJsonInterfaceUtf8Reader(string format) + => RoundTripTest(format, new JsonInterfaceUtf8ReaderStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithJsonInterfaceUtf8ReaderNonGeneric(string format) + => RoundTripTest(format, new JsonInterfaceUtf8ReaderNonGenericStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithModelJsonConverter(string format) + => RoundTripTest(format, new ModelJsonConverterStrategy()); + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelTests.cs new file mode 100644 index 000000000000..8439f2e19529 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelTests.cs @@ -0,0 +1,228 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using Azure.Core.Serialization; +using Microsoft.Extensions.Options; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public abstract class ModelTests where T : IModelSerializable + { + private T _modelInstance; + private T ModelInstance => _modelInstance ??= GetModelInstance(); + + private bool IsXmlWireFormat => WirePayload.StartsWith("<", StringComparison.Ordinal); + + protected virtual T GetModelInstance() + { + return (T)Activator.CreateInstance(typeof(T), true); + } + + protected abstract string GetExpectedResult(ModelSerializerFormat format); + protected abstract void VerifyModel(T model, ModelSerializerFormat format); + protected abstract void CompareModels(T model, T model2, ModelSerializerFormat format); + protected abstract string JsonPayload { get; } + protected abstract string WirePayload { get; } + protected abstract Func ToRequestContent { get; } + protected abstract Func FromResponse { get; } + + protected virtual Func GetObjectSerializerFactory(ModelSerializerFormat format) => null; + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithModelSerializer(string format) + => RoundTripTest(format, new ModelSerializerStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithModelSerializerNonGeneric(string format) + => RoundTripTest(format, new ModelSerializerNonGenericStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithModelSerializerFormatOverload(string format) + { + //if we only pass in the format we can't test BYOM + if (!typeof(T).IsGenericType) + RoundTripTest(format, new ModelSerializerFormatOverloadStrategy()); + } + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithModelInterface(string format) + => RoundTripTest(format, new ModelInterfaceStrategy()); + + [TestCase("J")] + [TestCase("W")] + public void RoundTripWithModelInterfaceNonGeneric(string format) + => RoundTripTest(format, new ModelInterfaceNonGenericStrategy()); + + [Test] + public void RoundTripWithCast() + { + //cast does not work without options + if (!typeof(T).IsGenericType) + RoundTripTest(ModelSerializerFormat.Wire, new CastStrategy(ToRequestContent, FromResponse)); + } + + protected void RoundTripTest(ModelSerializerFormat format, RoundTripStrategy strategy) + { + string serviceResponse = format == ModelSerializerFormat.Json ? JsonPayload : WirePayload; + + ModelSerializerOptions options = new ModelSerializerOptions(format); + options.GenericTypeSerializerCreator = GetObjectSerializerFactory(format); + + var expectedSerializedString = GetExpectedResult(format); + + if (AssertFailures(strategy, format, serviceResponse, options)) + return; + + T model = (T)strategy.Deserialize(serviceResponse, ModelInstance, options); + + VerifyModel(model, format); + var data = strategy.Serialize(model, options); + string roundTrip = data.ToString(); + + Assert.That(roundTrip, Is.EqualTo(expectedSerializedString)); + + T model2 = (T)strategy.Deserialize(roundTrip, ModelInstance, options); + CompareModels(model, model2, format); + } + + private bool AssertFailures(RoundTripStrategy strategy, ModelSerializerFormat format, string serviceResponse, ModelSerializerOptions options) + { + bool result = false; + if (IsXmlWireFormat && (strategy.IsExplicitJsonDeserialize || strategy.IsExplicitJsonSerialize) && format == ModelSerializerFormat.Wire) + { + if (strategy.IsExplicitJsonDeserialize) + { + if (strategy.GetType().Name.StartsWith("ModelJsonConverterStrategy")) + { + //we never get to the interface implementation because JsonSerializer errors before that + Assert.Throws(() => { T model = (T)strategy.Deserialize(serviceResponse, ModelInstance, options); }); + result = true; + } + else + { + Assert.Throws(() => { T model = (T)strategy.Deserialize(serviceResponse, ModelInstance, options); }); + result = true; + } + } + + if (strategy.IsExplicitJsonSerialize) + { + Assert.Throws(() => { var data = strategy.Serialize(ModelInstance, options); }); + result = true; + } + } + else if (ModelInstance is not IModelJsonSerializable && format == ModelSerializerFormat.Json) + { + Assert.Throws(() => { T model = (T)strategy.Deserialize(serviceResponse, ModelInstance, options); }); + Assert.Throws(() => { var data = strategy.Serialize(ModelInstance, options); }); + result = true; + } + return result; + } + + internal static Dictionary GetRawData(object model) + { + Type modelType = model.GetType(); + while (modelType.BaseType != typeof(object) && modelType.BaseType != typeof(ValueType)) + { + modelType = modelType.BaseType; + } + var propertyInfo = modelType.GetField("_rawData", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic); + return propertyInfo.GetValue(model) as Dictionary; + } + + [Test] + public void ThrowsIfUnknownFormat() + { + ModelSerializerOptions options = new ModelSerializerOptions("x"); + Assert.Throws(() => ModelSerializer.Serialize(ModelInstance, options)); + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData("x"), options)); + + Assert.Throws(() => ModelSerializer.Serialize((IModelSerializable)ModelInstance, options)); + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData("x"), typeof(T), options)); + if (ModelInstance is IModelJsonSerializable jsonModel) + { + Assert.Throws(() => jsonModel.Serialize(new Utf8JsonWriter(new MemoryStream()), options)); + Assert.Throws(() => ((IModelJsonSerializable)jsonModel).Serialize(new Utf8JsonWriter(new MemoryStream()), options)); + bool gotException = false; + try + { + Utf8JsonReader reader = default; + jsonModel.Deserialize(ref reader, options); + } + catch (FormatException) + { + gotException = true; + } + finally + { + Assert.IsTrue(gotException); + } + + gotException = false; + try + { + Utf8JsonReader reader = default; + ((IModelJsonSerializable)jsonModel).Deserialize(ref reader, options); + } + catch (FormatException) + { + gotException = true; + } + finally + { + Assert.IsTrue(gotException); + } + } + } + + [Test] + public void ThrowsIfWireIsNotJson() + { + if (ModelInstance is IModelJsonSerializable jsonModel && IsXmlWireFormat) + { + Assert.Throws(() => jsonModel.Serialize(new Utf8JsonWriter(new MemoryStream()), new ModelSerializerOptions(ModelSerializerFormat.Wire))); + Utf8JsonReader reader = new Utf8JsonReader(new byte[] { }); + bool exceptionCaught = false; + try + { + jsonModel.Deserialize(ref reader, new ModelSerializerOptions(ModelSerializerFormat.Wire)); + } + catch (InvalidOperationException) + { + exceptionCaught = true; + } + Assert.IsTrue(exceptionCaught, "Expected InvalidOperationException to be thrown when deserializing wire format as json"); + } + } + + [Test] + public void CastNull() + { + if (typeof(T).IsClass) + { + object model = null; + RequestContent content = ToRequestContent((T)model); + Assert.IsNull(content); + } + else + { + T model = default; + RequestContent content = ToRequestContent(model); + Assert.IsNotNull(content); + } + + Response response = null; + Assert.Throws(() => FromResponse(response)); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXTests.cs new file mode 100644 index 000000000000..3dd3b6c3f5d4 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXTests.cs @@ -0,0 +1,61 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class ModelXTests : ModelJsonTests + { + protected override string JsonPayload => WirePayload; + + protected override string WirePayload => "{\"kind\":\"X\",\"name\":\"xmodel\",\"xProperty\":100,\"extra\":\"stuff\"}"; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (ModelX)response; + + protected override void CompareModels(ModelX model, ModelX model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Name, model2.Name); + Assert.AreEqual(model.Kind, model2.Kind); + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual(model.XProperty, model2.XProperty); + var rawData = GetRawData(model); + var rawData2 = GetRawData(model2); + Assert.IsNotNull(rawData); + Assert.IsNotNull(rawData2); + Assert.AreEqual(rawData.Count, rawData2.Count); + Assert.AreEqual(rawData["extra"].ToObjectFromJson(), rawData2["extra"].ToObjectFromJson()); + } + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + string expected = "{\"kind\":\"X\",\"name\":\"xmodel\""; + if (format == ModelSerializerFormat.Json) + expected += ",\"xProperty\":100"; + if (format == ModelSerializerFormat.Json) + expected += ",\"extra\":\"stuff\""; + expected += "}"; + return expected; + } + + protected override void VerifyModel(ModelX model, ModelSerializerFormat format) + { + Assert.AreEqual("X", model.Kind); + Assert.AreEqual("xmodel", model.Name); + var rawData = GetRawData(model); + Assert.IsNotNull(rawData); + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual(100, model.XProperty); + Assert.AreEqual("stuff", rawData["extra"].ToObjectFromJson()); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlCrossLibraryTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlCrossLibraryTests.cs new file mode 100644 index 000000000000..ce5d94676c97 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlCrossLibraryTests.cs @@ -0,0 +1,88 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Xml; +using Azure.Core.Serialization; +using Azure.Core.Tests.Common; +using Azure.Core.Tests.Public.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class ModelXmlCrossLibraryTests : ModelJsonTests + { + protected override string WirePayload => File.ReadAllText(TestData.GetLocation("ModelXmlX.xml")).TrimEnd(); + + protected override string JsonPayload => "{\"key\":\"Color\",\"value\":\"Red\",\"readOnlyProperty\":\"ReadOnly\",\"childTag\":{\"childValue\":\"ChildRed\",\"childReadOnlyProperty\":\"ChildReadOnly\"}}"; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (ModelXmlCrossLibrary)response; + + [Test] + public void ThrowsIfMismatch() + { + ModelSerializerOptions jsonOptions = new ModelSerializerOptions(ModelSerializerFormat.Json); + ModelXmlCrossLibrary model = ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(JsonPayload)), jsonOptions); + + Assert.Throws(Is.InstanceOf(), () => ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(WirePayload)), jsonOptions)); + + ModelSerializerOptions wireOptions = ModelSerializerOptions.DefaultWireOptions; + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(JsonPayload)), wireOptions)); + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + if (format == ModelSerializerFormat.Wire) + { + var expectedSerializedString = "\uFEFFColorRed"; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += "ReadOnly"; + expectedSerializedString += "ChildRed"; + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Json)) + // expectedSerializedString += "ChildReadOnly"; + expectedSerializedString += ""; + return expectedSerializedString; + } + if (format == ModelSerializerFormat.Json) + { + var expectedSerializedString = "{\"key\":\"Color\",\"value\":\"Red\""; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += ",\"readOnlyProperty\":\"ReadOnly\""; + expectedSerializedString += ",\"childTag\":{\"childValue\":\"ChildRed\""; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += ",\"childReadOnlyProperty\":\"ChildReadOnly\""; + expectedSerializedString += "}}"; + return expectedSerializedString; + } + throw new InvalidOperationException($"Unknown format used in test {format}"); + } + + protected override void VerifyModel(ModelXmlCrossLibrary model, ModelSerializerFormat format) + { + Assert.AreEqual("Color", model.Key); + Assert.AreEqual("Red", model.Value); + Assert.AreEqual("ReadOnly", model.ReadOnlyProperty); + Assert.IsNotNull(model.ChildModelXml); + Assert.AreEqual("ChildRed", model.ChildModelXml.ChildValue); + Assert.AreEqual("ChildReadOnly", model.ChildModelXml.ChildReadOnlyProperty); + } + + protected override void CompareModels(ModelXmlCrossLibrary model, ModelXmlCrossLibrary model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Key, model2.Key); + Assert.AreEqual(model.Value, model2.Value); + if (format.Equals(ModelSerializerFormat.Json)) + Assert.AreEqual(model.ReadOnlyProperty, model2.ReadOnlyProperty); + Assert.AreEqual(model.ChildModelXml.ChildValue, model2.ChildModelXml.ChildValue); + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Data)) + // Assert.AreEqual(model.RenamedChildModelXml.ChildReadOnlyProperty, model2.RenamedChildModelXml.ChildReadOnlyProperty); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlOnlyTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlOnlyTests.cs new file mode 100644 index 000000000000..257b73244a1d --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlOnlyTests.cs @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using Azure.Core.Serialization; +using Azure.Core.Tests.Common; +using Azure.Core.Tests.Public.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class ModelXmlOnlyTests : ModelTests + { + protected override string WirePayload => File.ReadAllText(TestData.GetLocation("ModelXml.xml")).TrimEnd(); + + protected override string JsonPayload => string.Empty; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (ModelXmlOnly)response; + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + var expectedSerializedString = "\uFEFFColorRed"; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += "ReadOnly"; + expectedSerializedString += "ChildRed"; + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Json)) + // expectedSerializedString += "ChildReadOnly"; + expectedSerializedString += ""; + return expectedSerializedString; + } + + protected override void VerifyModel(ModelXmlOnly model, ModelSerializerFormat format) + { + Assert.AreEqual("Color", model.Key); + Assert.AreEqual("Red", model.Value); + Assert.AreEqual("ReadOnly", model.ReadOnlyProperty); + Assert.IsNotNull(model.RenamedChildModelXml); + Assert.AreEqual("ChildRed", model.RenamedChildModelXml.ChildValue); + Assert.AreEqual("ChildReadOnly", model.RenamedChildModelXml.ChildReadOnlyProperty); + } + + protected override void CompareModels(ModelXmlOnly model, ModelXmlOnly model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Key, model2.Key); + Assert.AreEqual(model.Value, model2.Value); + if (format.Equals(ModelSerializerFormat.Json)) + Assert.AreEqual(model.ReadOnlyProperty, model2.ReadOnlyProperty); + Assert.AreEqual(model.RenamedChildModelXml.ChildValue, model2.RenamedChildModelXml.ChildValue); + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Json)) + // Assert.AreEqual(model.RenamedChildModelXml.ChildReadOnlyProperty, model2.RenamedChildModelXml.ChildReadOnlyProperty); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlTests.cs new file mode 100644 index 000000000000..2f7259555061 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ModelXmlTests.cs @@ -0,0 +1,89 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Xml; +using Azure.Core.Serialization; +using Azure.Core.Tests.Common; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class ModelXmlTests : ModelJsonTests + { + protected override string WirePayload => File.ReadAllText(TestData.GetLocation("ModelXml.xml")).TrimEnd(); + + protected override string JsonPayload => "{\"key\":\"Color\",\"value\":\"Red\",\"readOnlyProperty\":\"ReadOnly\",\"renamedChildModelXml\":{\"childValue\":\"ChildRed\",\"childReadOnlyProperty\":\"ChildReadOnly\"}}"; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (ModelXml)response; + + [Test] + public void ThrowsIfMismatch() + { + ModelSerializerOptions jsonOptions = new ModelSerializerOptions(ModelSerializerFormat.Json); + ModelXml model = ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(JsonPayload)), jsonOptions); + + Assert.Throws(Is.InstanceOf(), () => ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(WirePayload)), jsonOptions)); + + ModelSerializerOptions wireOptions = ModelSerializerOptions.DefaultWireOptions; + Assert.Throws(() => ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(JsonPayload)), wireOptions)); + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + if (format == ModelSerializerFormat.Wire) + { + var expectedSerializedString = "\uFEFFColorRed"; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += "ReadOnly"; + expectedSerializedString += "ChildRed"; + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Json)) + // expectedSerializedString += "ChildReadOnly"; + expectedSerializedString += ""; + return expectedSerializedString; + } + if (format == ModelSerializerFormat.Json) + { + var expectedSerializedString = "{\"key\":\"Color\",\"value\":\"Red\""; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += ",\"readOnlyProperty\":\"ReadOnly\""; + expectedSerializedString += ",\"renamedChildModelXml\":{\"childValue\":\"ChildRed\""; + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Json)) + // expectedSerializedString += ",\"childReadOnlyProperty\":\"ChildReadOnly\""; + expectedSerializedString += "}}"; + return expectedSerializedString; + } + throw new InvalidOperationException($"Unknown format used in test {format}"); + } + + protected override void VerifyModel(ModelXml model, ModelSerializerFormat format) + { + Assert.AreEqual("Color", model.Key); + Assert.AreEqual("Red", model.Value); + Assert.AreEqual("ReadOnly", model.ReadOnlyProperty); + Assert.IsNotNull(model.RenamedChildModelXml); + Assert.AreEqual("ChildRed", model.RenamedChildModelXml.ChildValue); + Assert.AreEqual("ChildReadOnly", model.RenamedChildModelXml.ChildReadOnlyProperty); + } + + protected override void CompareModels(ModelXml model, ModelXml model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Key, model2.Key); + Assert.AreEqual(model.Value, model2.Value); + if (format.Equals(ModelSerializerFormat.Json)) + Assert.AreEqual(model.ReadOnlyProperty, model2.ReadOnlyProperty); + Assert.AreEqual(model.RenamedChildModelXml.ChildValue, model2.RenamedChildModelXml.ChildValue); + //TODO this is broken until we update the IXmlSerializable interface to include ModelSerializerOptions + //if (format.Equals(ModelSerializerFormat.Json)) + // Assert.AreEqual(model.RenamedChildModelXml.ChildReadOnlyProperty, model2.RenamedChildModelXml.ChildReadOnlyProperty); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/Animal.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/Animal.cs new file mode 100644 index 000000000000..b6d43ba572e9 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/Animal.cs @@ -0,0 +1,147 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public class Animal : IUtf8JsonSerializable, IModelJsonSerializable + { + private Dictionary RawData { get; set; } = new Dictionary(); + + public bool IsHungry { get; set; } = false; + public double Weight { get; set; } = 1.1d; + public string LatinName { get; private set; } = "Animalia"; + public string Name { get; set; } = "Animal"; + + public Animal() + { + } + + public Animal(double weight, string latinName, string name, bool isHungry) + { + Weight = weight; + LatinName = latinName; + Name = name; + IsHungry = isHungry; + } + + internal Animal(double weight, string latinName, string name, bool isHungry, Dictionary rawData) + { + Weight = weight; + LatinName = latinName; + Name = name; + IsHungry = isHungry; + RawData = rawData; + } + + internal Animal(string name) + { + Name = name; + } + + #region Serialization + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("latinName"u8); + writer.WriteStringValue(LatinName); + } + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("isHungry"u8); + writer.WriteBooleanValue(IsHungry); + writer.WritePropertyName("weight"u8); + writer.WriteNumberValue(Weight); + + if (options.Format == ModelSerializerFormat.Json) + { + //write out the raw data + foreach (var property in RawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + writer.WriteEndObject(); + } + + internal static Animal DeserializeAnimal(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + double weight = default; + string name = ""; + string latinName = ""; + bool isHungry = default; + + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("weight"u8)) + { + weight = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("latinName"u8)) + { + latinName = property.Value.GetString(); + continue; + } + if (property.NameEquals("isHungry"u8)) + { + isHungry = property.Value.GetBoolean(); + continue; + } + + if (options.Format == ModelSerializerFormat.Json) + { + //this means it's an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new Animal(weight, latinName, name, isHungry, rawData); + } + #endregion + + #region InterfaceImplementation + + Animal IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return DeserializeAnimal(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + Animal IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeAnimal(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + + #endregion + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/CatReadOnlyProperty.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/CatReadOnlyProperty.cs new file mode 100644 index 000000000000..0996ac733a73 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/CatReadOnlyProperty.cs @@ -0,0 +1,138 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public class CatReadOnlyProperty : Animal, IModelJsonSerializable, IUtf8JsonSerializable + { + private Dictionary RawData { get; set; } = new Dictionary(); + + public CatReadOnlyProperty(double weight, string latinName, string name, bool isHungry, bool hasWhiskers) : base(weight, "Felis catus", name, isHungry) + { + HasWhiskers = hasWhiskers; + } + + internal CatReadOnlyProperty(double weight, string latinName, string name, bool isHungry, bool hasWhiskers, Dictionary rawData) : this(weight, latinName, name, isHungry, hasWhiskers) + { + RawData = rawData; + } + + internal CatReadOnlyProperty() + { + } + + public bool HasWhiskers { get; private set; } = true; + + #region Serialization + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("latinName"u8); + writer.WriteStringValue(LatinName); + + writer.WritePropertyName("hasWhiskers"u8); + writer.WriteBooleanValue(HasWhiskers); + } + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("isHungry"u8); + writer.WriteBooleanValue(IsHungry); + writer.WritePropertyName("weight"u8); + writer.WriteNumberValue(Weight); + + if (options.Format == ModelSerializerFormat.Json) + { + //write out the raw data + foreach (var property in RawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + writer.WriteEndObject(); + } + + internal static CatReadOnlyProperty DeserializeCatReadOnlyProperty(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + double weight = default; + string name = ""; + string latinName = ""; + bool isHungry = default; + bool hasWhiskers = default; + + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("weight"u8)) + { + weight = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("latinName"u8)) + { + latinName = property.Value.GetString(); + continue; + } + + if (property.NameEquals("isHungry"u8)) + { + isHungry = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("hasWhiskers"u8)) + { + hasWhiskers = property.Value.GetBoolean(); + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + //this means its an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new CatReadOnlyProperty(weight, latinName, name, isHungry, hasWhiskers, rawData); + } + + CatReadOnlyProperty IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return DeserializeCatReadOnlyProperty(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + CatReadOnlyProperty IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeCatReadOnlyProperty(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + + #endregion + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ChildModelXmlOnly.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ChildModelXmlOnly.cs new file mode 100644 index 000000000000..703eb6f1f02f --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ChildModelXmlOnly.cs @@ -0,0 +1,97 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests.Models +{ + [XmlRoot("ChildTag")] + public class ChildModelXmlOnly : IXmlSerializable, IModelSerializable + { + internal ChildModelXmlOnly() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// is null. + public ChildModelXmlOnly(string value, string readonlyProperty) + { + Argument.AssertNotNull(value, nameof(value)); + + ChildValue = value; + ChildReadOnlyProperty = readonlyProperty; + } + + /// Gets or sets the value. + [XmlElement("ChildValue")] + public string ChildValue { get; set; } + /// Gets or sets the value. + [XmlElement("ChildReadOnlyProperty")] + public string ChildReadOnlyProperty { get; } + + void IXmlSerializable.Write(XmlWriter writer, string nameHint) => + Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + private void Serialize(XmlWriter writer, ModelSerializerOptions options, string nameHint) + { + if (options.Format != ModelSerializerFormat.Wire) + throw new NotSupportedException($"{nameof(ChildModelXmlOnly)} does not support '{options.Format}' format"); + + writer.WriteStartElement(nameHint ?? "ChildTag"); + writer.WriteStartElement("ChildValue"); + writer.WriteValue(ChildValue); + writer.WriteEndElement(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WriteStartElement("ChildReadOnlyProperty"); + writer.WriteValue(ChildReadOnlyProperty); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + internal static ChildModelXmlOnly DeserializeChildModelXmlOnly(XElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + if (options.Format != ModelSerializerFormat.Wire) + throw new NotSupportedException($"{nameof(ChildModelXmlOnly)} does not support '{options.Format}' format"); + + string value = default; + string readonlyProperty = default; + if (element.Element("ChildValue") is XElement valueElement) + { + value = (string)valueElement; + } + if (element.Element("ChildReadOnlyProperty") is XElement readonlyPropertyElement) + { + readonlyProperty = (string)readonlyPropertyElement; + } + return new ChildModelXmlOnly(value, readonlyProperty); + } + + ChildModelXmlOnly IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + => DeserializeChildModelXmlOnly(XElement.Load(data.ToStream()), options); + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + using MemoryStream stream = new MemoryStream(); + using XmlWriter writer = XmlWriter.Create(stream); + Serialize(writer, options, null); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/DogListProperty.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/DogListProperty.cs new file mode 100644 index 000000000000..31448ddc11c5 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/DogListProperty.cs @@ -0,0 +1,186 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.Json; +using System.Text.Json.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + [JsonConverter(typeof(DogListPropertyConverter))] + public class DogListProperty : Animal, IModelJsonSerializable, IUtf8JsonSerializable + { + private Dictionary RawData { get; set; } = new Dictionary(); + public IList FoodConsumed { get; private set; } + + public DogListProperty(string name) : base(name) + { + Name = name; + FoodConsumed = new ChangeTrackingList(); + } + + internal DogListProperty(double weight, string latinName, string name, bool isHungry, IList foodConsumed, Dictionary rawData) : base(weight, latinName, name, isHungry, rawData) + { + RawData = rawData; + FoodConsumed = foodConsumed; + } + + public DogListProperty() + { + FoodConsumed = new ChangeTrackingList(); + } + + public static explicit operator DogListProperty(Response response) + { + using JsonDocument jsonDocument = JsonDocument.Parse(response.ContentStream); + return DeserializeDogListProperty(jsonDocument.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + public static implicit operator RequestContent(DogListProperty dog) + { + return RequestContent.Create(dog, ModelSerializerOptions.DefaultWireOptions); + } + + #region Serialization + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("latinName"u8); + writer.WriteStringValue(LatinName); + } + writer.WritePropertyName("name"u8); + writer.WriteStringValue(Name); + writer.WritePropertyName("isHungry"u8); + writer.WriteBooleanValue(IsHungry); + writer.WritePropertyName("weight"u8); + writer.WriteNumberValue(Weight); + + if (Optional.IsCollectionDefined(FoodConsumed)) + { + writer.WritePropertyName("foodConsumed"u8); + writer.WriteStartArray(); + foreach (var item in FoodConsumed) + { + writer.WriteStringValue($"{item}"); + } + writer.WriteEndArray(); + } + + if (options.Format == ModelSerializerFormat.Json) + { + //write out the raw data + foreach (var property in RawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + writer.WriteEndObject(); + } + + internal static DogListProperty DeserializeDogListProperty(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + double weight = default; + string name = ""; + string latinName = ""; + bool isHungry = default; + Dictionary rawData = new Dictionary(); + List foodConsumed = new List(); + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("weight"u8)) + { + weight = property.Value.GetDouble(); + continue; + } + if (property.NameEquals("name"u8)) + { + name = property.Value.GetString(); + continue; + } + if (property.NameEquals("latinName"u8)) + { + latinName = property.Value.GetString(); + continue; + } + if (property.NameEquals("isHungry"u8)) + { + isHungry = property.Value.GetBoolean(); + continue; + } + if (property.NameEquals("foodConsumed"u8)) + { + foreach (var item in property.Value.EnumerateArray()) + { + foodConsumed.Add(item.GetString()); + } + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + //this means its an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new DogListProperty(weight, latinName, name, isHungry, foodConsumed, rawData); + } + #endregion + + internal class DogListPropertyConverter : JsonConverter + { + public override DogListProperty Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var model = DeserializeDogListProperty(JsonDocument.ParseValue(ref reader).RootElement, GetOptions(options)); + //marker used for testing to know if this converter fires + model.RawData.Add("DogListPropertyConverterMarker", new BinaryData("true")); + return model; + } + + public override void Write(Utf8JsonWriter writer, DogListProperty value, JsonSerializerOptions options) + { + ((IModelJsonSerializable)value).Serialize(writer, GetOptions(options)); + } + + private ModelSerializerOptions GetOptions(JsonSerializerOptions options) + { + //pulls the additional properties setting from the ModelJsonConverter if it exists + //if it does not exist it uses the default value of true for azure sdk use cases + var modelConverter = options.Converters.FirstOrDefault(c => c.GetType() == typeof(ModelJsonConverter)) as ModelJsonConverter; + return modelConverter is not null ? modelConverter.ModelSerializerOptions : ModelSerializerOptions.DefaultWireOptions; + } + } + DogListProperty IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return DeserializeDogListProperty(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + DogListProperty IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeDogListProperty(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/DogListPropertyBlankConverter.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/DogListPropertyBlankConverter.cs new file mode 100644 index 000000000000..188048b7250d --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/DogListPropertyBlankConverter.cs @@ -0,0 +1,23 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public class DogListPropertyBlankConverter : JsonConverter + { + public override DogListProperty Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + var model = JsonDocument.ParseValue(ref reader); + return new DogListProperty(); + } + + public override void Write(Utf8JsonWriter writer, DogListProperty value, JsonSerializerOptions options) + { + return; + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/Envelope.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/Envelope.cs new file mode 100644 index 000000000000..b13abca69ef5 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/Envelope.cs @@ -0,0 +1,183 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public class Envelope : IModelJsonSerializable>, IUtf8JsonSerializable + { + private Dictionary RawData { get; set; } = new Dictionary(); + + public string ReadOnlyProperty { get; private set; } = "readonly"; + + public Envelope() + { + } + + public Envelope(string readOnlyProperty) + { + ReadOnlyProperty = readOnlyProperty; + } + + internal Envelope(string readOnlyProperty, CatReadOnlyProperty modelA, T modelT, Dictionary rawData) + { + ReadOnlyProperty = readOnlyProperty; + ModelA = modelA; + ModelT = modelT; + RawData = rawData; + } + + public CatReadOnlyProperty ModelA { get; set; } + public T ModelT { get; set; } + + public static implicit operator RequestContent(Envelope envelope) + { + if (envelope == null) + { + return null; + } + + return RequestContent.Create(envelope, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator Envelope(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + using JsonDocument jsonDocument = JsonDocument.Parse(response.ContentStream); + return DeserializeEnvelope(jsonDocument.RootElement, ModelSerializerOptions.DefaultWireOptions); + } + + #region Serialization + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable>)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + void IModelJsonSerializable>.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + Serialize(writer, options); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("readOnlyProperty"u8); + writer.WriteStringValue(ReadOnlyProperty); + } + + writer.WritePropertyName("modelA"u8); + ((IModelJsonSerializable)ModelA).Serialize(writer, options); + writer.WritePropertyName("modelC"u8); + SerializeT(writer, options); + + if (options.Format == ModelSerializerFormat.Json) + { + //write out the raw data + foreach (var property in RawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + writer.WriteEndObject(); + } + + internal static Envelope DeserializeEnvelope(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string readonlyProperty = ""; + CatReadOnlyProperty modelA = new CatReadOnlyProperty(); + T modelT = default(T); + Dictionary rawData = new Dictionary(); + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("readOnlyProperty"u8)) + { + readonlyProperty = property.Value.GetString(); + continue; + } + if (property.NameEquals("modelA"u8)) + { + modelA = CatReadOnlyProperty.DeserializeCatReadOnlyProperty(property.Value, options); + continue; + } + if (property.NameEquals("modelC"u8)) + { + modelT = DeserializeT(property.Value, options); + continue; + } + + if (options.Format == ModelSerializerFormat.Json) + { + //this means it's an modelC property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new Envelope(readonlyProperty, modelA, modelT, rawData); + } + + private void SerializeT(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ObjectSerializer serializer = GetObjectSerializer(options); + BinaryData data = serializer.Serialize(ModelT); +#if NET6_0_OR_GREATER + writer.WriteRawValue(data); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(data.ToString()).RootElement); +#endif + } + + private static ObjectSerializer GetObjectSerializer(ModelSerializerOptions options) + { + var serializer = options.GenericTypeSerializerCreator is not null ? options.GenericTypeSerializerCreator(typeof(T)) : null; + return serializer ?? JsonObjectSerializer.Default; + } + + private static T DeserializeT(JsonElement element, ModelSerializerOptions options) + { + ObjectSerializer serializer = GetObjectSerializer(options); + MemoryStream m = new MemoryStream(); + Utf8JsonWriter w = new Utf8JsonWriter(m); + element.WriteTo(w); + w.Flush(); + m.Position = 0; + return (T)serializer.Deserialize(m, typeof(T), default); + } + + Envelope IModelSerializable>.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return DeserializeEnvelope(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + Envelope IModelJsonSerializable>.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeEnvelope(doc.RootElement, options); + } + + BinaryData IModelSerializable>.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + #endregion + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/JsonModelForCombinedInterface.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/JsonModelForCombinedInterface.cs new file mode 100644 index 000000000000..e2d6c9317bd8 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/JsonModelForCombinedInterface.cs @@ -0,0 +1,130 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Text.Json; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests.Models +{ + internal class JsonModelForCombinedInterface : IUtf8JsonSerializable, IModelJsonSerializable + { + private Dictionary RawData { get; set; } = new Dictionary(); + + public JsonModelForCombinedInterface() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// + /// or is null. + public JsonModelForCombinedInterface(string key, string value, string readOnlyProperty) + { + Argument.AssertNotNull(key, nameof(key)); + Argument.AssertNotNull(value, nameof(value)); + + Key = key; + Value = value; + ReadOnlyProperty = readOnlyProperty; + } + + internal JsonModelForCombinedInterface(string key, string value, string readOnlyProperty, Dictionary rawData) + { + Key = key; + Value = value; + ReadOnlyProperty = readOnlyProperty; + RawData = rawData; + } + + /// Gets or sets the key. + public string Key { get; set; } + /// Gets or sets the value. + public string Value { get; set; } + public string ReadOnlyProperty { get; } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => ((IModelJsonSerializable)this).Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + + internal static JsonModelForCombinedInterface DeserializeJsonModelForCombinedInterface(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readOnlyProperty = default; + Dictionary rawData = new Dictionary(); + + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("key"u8)) + { + key = property.Value.GetString(); + continue; + } + if (property.NameEquals("value"u8)) + { + value = property.Value.GetString(); + continue; + } + if (property.NameEquals("readOnlyProperty"u8)) + { + readOnlyProperty = property.Value.GetString(); + continue; + } + if (options.Format == ModelSerializerFormat.Json) + { + //this means its an unknown property we got + rawData.Add(property.Name, BinaryData.FromString(property.Value.GetRawText())); + } + } + return new JsonModelForCombinedInterface(key, value, readOnlyProperty, rawData); + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) => Serialize(writer, options); + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("key"u8); + writer.WriteStringValue(Key); + writer.WritePropertyName("value"u8); + writer.WriteStringValue(Value); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("readOnlyProperty"u8); + writer.WriteStringValue(ReadOnlyProperty); + } + if (options.Format == ModelSerializerFormat.Json) + { + //write out the raw data + foreach (var property in RawData) + { + writer.WritePropertyName(property.Key); +#if NET6_0_OR_GREATER + writer.WriteRawValue(property.Value); +#else + JsonSerializer.Serialize(writer, JsonDocument.Parse(property.Value.ToString()).RootElement); +#endif + } + } + writer.WriteEndObject(); + } + + JsonModelForCombinedInterface IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + return DeserializeJsonModelForCombinedInterface(JsonDocument.Parse(data.ToString()).RootElement, options); + } + + JsonModelForCombinedInterface IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeJsonModelForCombinedInterface(doc.RootElement, options); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return ModelSerializer.SerializeCore(this, options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ModelXmlCrossLibrary.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ModelXmlCrossLibrary.cs new file mode 100644 index 000000000000..4b13e96b1e4c --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ModelXmlCrossLibrary.cs @@ -0,0 +1,240 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; + +namespace Azure.Core.Tests.Public.ModelSerializationTests.Models +{ + [XmlRoot("Tag")] + public class ModelXmlCrossLibrary : IXmlSerializable, IModelSerializable, IModelJsonSerializable, IUtf8JsonSerializable + { + internal ModelXmlCrossLibrary() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// + /// or is null. + public ModelXmlCrossLibrary(string key, string value, string readonlyProperty, ChildModelXml childModelXml) + { + Argument.AssertNotNull(key, nameof(key)); + Argument.AssertNotNull(value, nameof(value)); + + Key = key; + Value = value; + ReadOnlyProperty = readonlyProperty; + ChildModelXml = childModelXml; + } + + /// Gets or sets the key. + [XmlElement("Key")] + public string Key { get; set; } + /// Gets or sets the value. + [XmlElement("Value")] + public string Value { get; set; } + /// Gets or sets the value. + [XmlElement("ReadOnlyProperty")] + public string ReadOnlyProperty { get; } + [XmlElement("ChildTag")] + public ChildModelXml ChildModelXml { get; set; } + + public static implicit operator RequestContent(ModelXmlCrossLibrary modelXmlCrossLibrary) + { + if (modelXmlCrossLibrary == null) + { + return null; + } + + return RequestContent.Create((IModelSerializable)modelXmlCrossLibrary, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator ModelXmlCrossLibrary(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + return DeserializeModelXmlCrossLibrary(XElement.Load(response.ContentStream), ModelSerializerOptions.DefaultWireOptions); + } + + public void Serialize(XmlWriter writer, string nameHint) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + void IXmlSerializable.Write(XmlWriter writer, string nameHint) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + private void Serialize(XmlWriter writer, ModelSerializerOptions options, string nameHint) + { + writer.WriteStartElement(nameHint ?? "Tag"); + writer.WriteStartElement("Key"); + writer.WriteValue(Key); + writer.WriteEndElement(); + writer.WriteStartElement("Value"); + writer.WriteValue(Value); + writer.WriteEndElement(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WriteStartElement("ReadOnlyProperty"); + writer.WriteValue(ReadOnlyProperty); + writer.WriteEndElement(); + } + var childModelXml = ModelSerializer.Serialize(ChildModelXml, options); + var bytes = childModelXml.ToArray(); + int start = bytes.AsSpan(1).IndexOf((byte)'>') + 2; + var chars = Encoding.UTF8.GetChars(bytes, start, bytes.Length - start); + writer.WriteRaw(chars, 0, chars.Length); + writer.WriteEndElement(); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("key"u8); + writer.WriteStringValue(Key); + writer.WritePropertyName("value"u8); + writer.WriteStringValue(Value); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("readOnlyProperty"u8); + writer.WriteStringValue(ReadOnlyProperty); + } + writer.WritePropertyName("childTag"u8); + ((IModelJsonSerializable)ChildModelXml).Serialize(writer, options); + writer.WriteEndObject(); + } + + public static ModelXmlCrossLibrary DeserializeModelXmlCrossLibrary(XElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readonlyProperty = default; + ChildModelXml childModelXml = default; + if (element.Element("Key") is XElement keyElement) + { + key = (string)keyElement; + } + if (element.Element("Value") is XElement valueElement) + { + value = (string)valueElement; + } + if (element.Element("ReadOnlyProperty") is XElement readonlyPropertyElement) + { + readonlyProperty = (string)readonlyPropertyElement; + } + if (element.Element("ChildTag") is XElement renamedChildModelXmlElement) + { + using MemoryStream stream = new MemoryStream(); + renamedChildModelXmlElement.Save(stream); + BinaryData data = stream.Position > int.MaxValue + ? BinaryData.FromStream(stream) + : new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + childModelXml = ModelSerializer.Deserialize(data, options); + } + return new ModelXmlCrossLibrary(key, value, readonlyProperty, childModelXml); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + return ModelSerializer.SerializeCore(this, options); + } + else + { + options ??= ModelSerializerOptions.DefaultWireOptions; + using MemoryStream stream = new MemoryStream(); + using XmlWriter writer = XmlWriter.Create(stream); + Serialize(writer, options, null); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + } + + internal static ModelXmlCrossLibrary DeserializeModelXmlCrossLibrary(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readOnlyProperty = default; + ChildModelXml childModelXml = default; + + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("key"u8)) + { + key = property.Value.GetString(); + continue; + } + if (property.NameEquals("value"u8)) + { + value = property.Value.GetString(); + continue; + } + if (property.NameEquals("readOnlyProperty"u8)) + { + readOnlyProperty = property.Value.GetString(); + continue; + } + if (property.NameEquals("childTag"u8)) + { + childModelXml = ModelSerializer.Deserialize(BinaryData.FromString(property.Value.GetRawText()), options);// ChildModelXml.DeserializeChildModelXml(property.Value, options); + continue; + } + } + return new ModelXmlCrossLibrary(key, value, readOnlyProperty, childModelXml); + } + + ModelXmlCrossLibrary IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + using var doc = JsonDocument.Parse(data); + return DeserializeModelXmlCrossLibrary(doc.RootElement, options); + } + else + { + return DeserializeModelXmlCrossLibrary(XElement.Load(data.ToStream()), options); + } + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format != ModelSerializerFormat.Json) + throw new InvalidOperationException($"Must use '{ModelSerializerFormat.Json}' format when calling the {nameof(IModelJsonSerializable)} interface"); + Serialize(writer, options); + } + + ModelXmlCrossLibrary IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format != ModelSerializerFormat.Json) + throw new InvalidOperationException($"Must use '{ModelSerializerFormat.Json}' format when calling the {nameof(IModelJsonSerializable)} interface"); + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeModelXmlCrossLibrary(doc.RootElement, options); + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ModelXmlOnly.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ModelXmlOnly.cs new file mode 100644 index 000000000000..5c8f81f96489 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/ModelXmlOnly.cs @@ -0,0 +1,139 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests.Models +{ + [XmlRoot("Tag")] + public class ModelXmlOnly : IXmlSerializable, IModelSerializable + { + internal ModelXmlOnly() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// + /// or is null. + public ModelXmlOnly(string key, string value, string readonlyProperty, ChildModelXmlOnly childModel) + { + Argument.AssertNotNull(key, nameof(key)); + Argument.AssertNotNull(value, nameof(value)); + + Key = key; + Value = value; + ReadOnlyProperty = readonlyProperty; + RenamedChildModelXml = childModel; + } + + /// Gets or sets the key. + [XmlElement("Key")] + public string Key { get; set; } + /// Gets or sets the value. + [XmlElement("Value")] + public string Value { get; set; } + /// Gets or sets the value. + [XmlElement("ReadOnlyProperty")] + public string ReadOnlyProperty { get; } + [XmlElement("RenamedChildModelXml")] + public ChildModelXmlOnly RenamedChildModelXml { get; set; } + + public static implicit operator RequestContent(ModelXmlOnly modelXml) + { + if (modelXml == null) + { + return null; + } + + return RequestContent.Create(modelXml, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator ModelXmlOnly(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + return DeserializeModelXmlOnly(XElement.Load(response.ContentStream), ModelSerializerOptions.DefaultWireOptions); + } + + public void Serialize(XmlWriter writer, string nameHint) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + void IXmlSerializable.Write(XmlWriter writer, string nameHint) => Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + private void Serialize(XmlWriter writer, ModelSerializerOptions options, string nameHint) + { + writer.WriteStartElement(nameHint ?? "Tag"); + writer.WriteStartElement("Key"); + writer.WriteValue(Key); + writer.WriteEndElement(); + writer.WriteStartElement("Value"); + writer.WriteValue(Value); + writer.WriteEndElement(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WriteStartElement("ReadOnlyProperty"); + writer.WriteValue(ReadOnlyProperty); + writer.WriteEndElement(); + } + writer.WriteObjectValue(RenamedChildModelXml, "RenamedChildModelXml"); + writer.WriteEndElement(); + } + + public static ModelXmlOnly DeserializeModelXmlOnly(XElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readonlyProperty = default; + ChildModelXmlOnly childModelXml = default; + if (element.Element("Key") is XElement keyElement) + { + key = (string)keyElement; + } + if (element.Element("Value") is XElement valueElement) + { + value = (string)valueElement; + } + if (element.Element("ReadOnlyProperty") is XElement readonlyPropertyElement) + { + readonlyProperty = (string)readonlyPropertyElement; + } + if (element.Element("RenamedChildModelXml") is XElement renamedChildModelXmlElement) + { + childModelXml = ChildModelXmlOnly.DeserializeChildModelXmlOnly(renamedChildModelXmlElement, options); + } + return new ModelXmlOnly(key, value, readonlyProperty, childModelXml); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + using MemoryStream stream = new MemoryStream(); + using XmlWriter writer = XmlWriter.Create(stream); + Serialize(writer, options, null); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + + ModelXmlOnly IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + return DeserializeModelXmlOnly(XElement.Load(data.ToStream()), options); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/XmlModelForCombinedInterface.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/XmlModelForCombinedInterface.cs new file mode 100644 index 000000000000..b8d35812b851 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/Models/XmlModelForCombinedInterface.cs @@ -0,0 +1,214 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Xml; +using System.Xml.Linq; +using System.Xml.Serialization; +using Azure.Core.Serialization; + +namespace Azure.Core.Tests.Public.ModelSerializationTests.Models +{ + [XmlRoot("Tag")] + internal class XmlModelForCombinedInterface : IXmlSerializable, IModelSerializable, IModelJsonSerializable, IUtf8JsonSerializable + { + public XmlModelForCombinedInterface() { } + + /// Initializes a new instance of ModelXml for testing. + /// + /// + /// or is null. + public XmlModelForCombinedInterface(string key, string value, string readOnlyProperty) + { + Argument.AssertNotNull(key, nameof(key)); + Argument.AssertNotNull(value, nameof(value)); + + Key = key; + Value = value; + ReadOnlyProperty = readOnlyProperty; + } + + /// Gets or sets the key. + [XmlElement("Key")] + public string Key { get; set; } + /// Gets or sets the value. + [XmlElement("Value")] + public string Value { get; set; } + /// Gets or sets the value. + [XmlElement("ReadOnlyProperty")] + public string ReadOnlyProperty { get; } + + public static implicit operator RequestContent(XmlModelForCombinedInterface xmlModelForCombinedInterface) + { + if (xmlModelForCombinedInterface == null) + { + return null; + } + + return RequestContent.Create((IModelSerializable)xmlModelForCombinedInterface, ModelSerializerOptions.DefaultWireOptions); + } + + public static explicit operator XmlModelForCombinedInterface(Response response) + { + Argument.AssertNotNull(response, nameof(response)); + + return DeserializeXmlModelForCombinedInterface(XElement.Load(response.ContentStream), ModelSerializerOptions.DefaultWireOptions); + } + + void IXmlSerializable.Write(XmlWriter writer, string nameHint) => + Serialize(writer, ModelSerializerOptions.DefaultWireOptions, nameHint); + + internal static XmlModelForCombinedInterface DeserializeXmlModelForCombinedInterface(XElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readOnlyProperty = default; + if (element.Element("Key") is XElement keyElement) + { + key = (string)keyElement; + } + if (element.Element("Value") is XElement valueElement) + { + value = (string)valueElement; + } + if (element.Element("ReadOnlyProperty") is XElement readOnlyPropertyElement) + { + readOnlyProperty = (string)readOnlyPropertyElement; + } + return new XmlModelForCombinedInterface(key, value, readOnlyProperty); + } + + private void Serialize(XmlWriter writer, ModelSerializerOptions options, string nameHint) + { + writer.WriteStartElement(nameHint ?? "Tag"); + writer.WriteStartElement("Key"); + writer.WriteValue(Key); + writer.WriteEndElement(); + writer.WriteStartElement("Value"); + writer.WriteValue(Value); + writer.WriteEndElement(); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WriteStartElement("ReadOnlyProperty"); + writer.WriteValue(ReadOnlyProperty); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + + private void Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + writer.WriteStartObject(); + writer.WritePropertyName("key"u8); + writer.WriteStringValue(Key); + writer.WritePropertyName("value"u8); + writer.WriteStringValue(Value); + if (options.Format == ModelSerializerFormat.Json) + { + writer.WritePropertyName("readOnlyProperty"u8); + writer.WriteStringValue(ReadOnlyProperty); + } + writer.WriteEndObject(); + } + + BinaryData IModelSerializable.Serialize(ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + return ModelSerializer.SerializeCore(this, options); + } + else + { + options ??= ModelSerializerOptions.DefaultWireOptions; + using MemoryStream stream = new MemoryStream(); + using XmlWriter writer = XmlWriter.Create(stream); + Serialize(writer, options, null); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + } + + internal static XmlModelForCombinedInterface DeserializeXmlModelForCombinedInterface(JsonElement element, ModelSerializerOptions options = default) + { + options ??= ModelSerializerOptions.DefaultWireOptions; + + string key = default; + string value = default; + string readOnlyProperty = default; + + Dictionary rawData = new Dictionary(); + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("key"u8)) + { + key = property.Value.GetString(); + continue; + } + if (property.NameEquals("value"u8)) + { + value = property.Value.GetString(); + continue; + } + if (property.NameEquals("readOnlyProperty"u8)) + { + readOnlyProperty = property.Value.GetString(); + continue; + } + } + return new XmlModelForCombinedInterface(key, value, readOnlyProperty); + } + + XmlModelForCombinedInterface IModelSerializable.Deserialize(BinaryData data, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format == ModelSerializerFormat.Json) + { + using var doc = JsonDocument.Parse(data); + return DeserializeXmlModelForCombinedInterface(doc.RootElement, options); + } + else + { + return DeserializeXmlModelForCombinedInterface(XElement.Load(data.ToStream()), options); + } + } + + void IModelJsonSerializable.Serialize(Utf8JsonWriter writer, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format != ModelSerializerFormat.Json) + throw new InvalidOperationException($"Must use '{ModelSerializerFormat.Json}' format when calling the {nameof(IModelJsonSerializable)} interface"); + + Serialize(writer, options); + } + + XmlModelForCombinedInterface IModelJsonSerializable.Deserialize(ref Utf8JsonReader reader, ModelSerializerOptions options) + { + ModelSerializerHelper.ValidateFormat(this, options.Format); + + if (options.Format != ModelSerializerFormat.Json) + throw new InvalidOperationException($"Must use '{ModelSerializerFormat.Json}' format when calling the {nameof(IModelJsonSerializable)} interface"); + + using var doc = JsonDocument.ParseValue(ref reader); + return DeserializeXmlModelForCombinedInterface(doc.RootElement, options); + } + + void IUtf8JsonSerializable.Write(Utf8JsonWriter writer) => + Serialize(writer, ModelSerializerOptions.DefaultWireOptions); + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ResourceProviderDataTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ResourceProviderDataTests.cs new file mode 100644 index 000000000000..f7e32ad4a079 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/ResourceProviderDataTests.cs @@ -0,0 +1,36 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using Azure.Core.Serialization; +using Azure.Core.Tests.Common; +using Azure.Core.Tests.ResourceManager.Resources; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class ResourceProviderDataTests : ModelJsonTests + { + protected override string JsonPayload => WirePayload; + + protected override string WirePayload => File.ReadAllText(TestData.GetLocation("ResourceProviderData-Collapsed.json")).TrimEnd(); + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (ResourceProviderData)response; + + protected override void CompareModels(ResourceProviderData model, ResourceProviderData model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Id, model2.Id); + } + + protected override string GetExpectedResult(ModelSerializerFormat format) => WirePayload; + + protected override void VerifyModel(ResourceProviderData model, ModelSerializerFormat format) + { + Assert.IsNotNull(model); + Assert.IsNotNull(model.Id); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/RoundTripStrategy.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/RoundTripStrategy.cs new file mode 100644 index 000000000000..efc2cb3f4ab5 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/RoundTripStrategy.cs @@ -0,0 +1,262 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.IO; +using System.Reflection.Metadata.Ecma335; +using System.Text; +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.TestFramework; + +#pragma warning disable SA1402 // File may only contain a single type +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public abstract class RoundTripStrategy + { + public abstract object Deserialize(string payload, object model, ModelSerializerOptions options); + public abstract BinaryData Serialize(T model, ModelSerializerOptions options); + public abstract bool IsExplicitJsonSerialize { get; } + public abstract bool IsExplicitJsonDeserialize { get; } + } + + public class ModelSerializerStrategy : RoundTripStrategy where T : IModelSerializable + { + public override bool IsExplicitJsonSerialize => false; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ModelSerializer.Serialize(model, options); + } + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options); + } + } + + public class ModelSerializerFormatOverloadStrategy : RoundTripStrategy where T : IModelSerializable + { + public override bool IsExplicitJsonSerialize => false; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ModelSerializer.Serialize(model, options.Format); + } + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options.Format); + } + } + + public class ModelSerializerNonGenericStrategy : RoundTripStrategy where T : IModelSerializable + { + public override bool IsExplicitJsonSerialize => false; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ModelSerializer.Serialize((object)model, options); + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ModelSerializer.Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), typeof(T), options); + } + } + + public class ModelInterfaceStrategy : RoundTripStrategy where T : IModelSerializable + { + public override bool IsExplicitJsonSerialize => false; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return model.Serialize(options); + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ((IModelSerializable)model).Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options); + } + } + + public class ModelInterfaceNonGenericStrategy : RoundTripStrategy where T : IModelSerializable + { + public override bool IsExplicitJsonSerialize => false; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ((IModelSerializable)model).Serialize(options); + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ((IModelSerializable)model).Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options); + } + } + + public class JsonInterfaceStrategy : RoundTripStrategy where T : IModelJsonSerializable + { + public override bool IsExplicitJsonSerialize => true; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + using MemoryStream stream = new MemoryStream(); + using Utf8JsonWriter writer = new Utf8JsonWriter(stream); + model.Serialize(writer, options); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ((IModelJsonSerializable)model).Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options); + } + } + + public class JsonModelWriterStrategy : RoundTripStrategy where T : IModelJsonSerializable + { + public override bool IsExplicitJsonSerialize => true; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ModelSerializer.SerializeCore(model, options); + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ((IModelJsonSerializable)model).Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options); + } + } + + public class JsonInterfaceNonGenericStrategy : RoundTripStrategy where T : IModelJsonSerializable + { + public override bool IsExplicitJsonSerialize => true; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ModelSerializer.SerializeCore((IModelJsonSerializable)model, options); + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + return ((IModelJsonSerializable)model).Deserialize(new BinaryData(Encoding.UTF8.GetBytes(payload)), options); + } + } + + public class JsonInterfaceUtf8ReaderStrategy : RoundTripStrategy where T : IModelJsonSerializable + { + public override bool IsExplicitJsonSerialize => true; + public override bool IsExplicitJsonDeserialize => true; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + using MemoryStream stream = new MemoryStream(); + using Utf8JsonWriter writer = new Utf8JsonWriter(stream); + model.Serialize(writer, options); + writer.Flush(); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + var reader = new Utf8JsonReader(new BinaryData(Encoding.UTF8.GetBytes(payload))); + return ((IModelJsonSerializable)model).Deserialize(ref reader, options); + } + } + + public class JsonInterfaceUtf8ReaderNonGenericStrategy : RoundTripStrategy where T : IModelJsonSerializable + { + public override bool IsExplicitJsonSerialize => true; + public override bool IsExplicitJsonDeserialize => true; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + return ModelSerializer.SerializeCore((IModelJsonSerializable)model, options); + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + var reader = new Utf8JsonReader(new BinaryData(Encoding.UTF8.GetBytes(payload))); + return ((IModelJsonSerializable)model).Deserialize(ref reader, options); + } + } + + public class CastStrategy : RoundTripStrategy where T : IModelSerializable + { + private Func _toRequestContent; + private Func _fromResponse; + + public CastStrategy(Func toRequestContent, Func fromResponse) + { + _toRequestContent = toRequestContent; + _fromResponse = fromResponse; + } + + public override bool IsExplicitJsonSerialize => false; + public override bool IsExplicitJsonDeserialize => false; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + RequestContent content = _toRequestContent(model); + content.TryComputeLength(out var length); + using var stream = new MemoryStream((int)length); + content.WriteTo(stream, default); + if (stream.Position > int.MaxValue) + { + return BinaryData.FromStream(stream); + } + else + { + return new BinaryData(stream.GetBuffer().AsMemory(0, (int)stream.Position)); + } + } + + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + var response = new MockResponse(200); + response.ContentStream = new MemoryStream(Encoding.UTF8.GetBytes(payload)); + return _fromResponse(response); + } + } + + public class ModelJsonConverterStrategy : RoundTripStrategy where T : IModelJsonSerializable + { + public override bool IsExplicitJsonSerialize => true; + public override bool IsExplicitJsonDeserialize => true; + + public override BinaryData Serialize(T model, ModelSerializerOptions options) + { + JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions(); + jsonSerializerOptions.Converters.Add(new ModelJsonConverter(options)); + return BinaryData.FromString(JsonSerializer.Serialize(model, jsonSerializerOptions)); + } + public override object Deserialize(string payload, object model, ModelSerializerOptions options) + { + JsonSerializerOptions jsonSerializerOptions = new JsonSerializerOptions(); + jsonSerializerOptions.Converters.Add(new ModelJsonConverter(options)); + return JsonSerializer.Deserialize(payload, jsonSerializerOptions); + } + } +} +#pragma warning restore SA1402 // File may only contain a single type diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/UnknownBaseModelTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/UnknownBaseModelTests.cs new file mode 100644 index 000000000000..d81a640721a0 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/UnknownBaseModelTests.cs @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Linq; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class UnknownBaseModelTests : ModelJsonTests + { + protected override BaseModel GetModelInstance() + { + var typeToActivate = typeof(BaseModel).Assembly.GetTypes().FirstOrDefault(t => t.Name == $"Unknown{typeof(BaseModel).Name}"); + return Activator.CreateInstance(typeToActivate, true) as BaseModel; + } + + protected override string JsonPayload => WirePayload; + + protected override string WirePayload => "{\"kind\":\"Z\",\"name\":\"zmodel\",\"zProperty\":1.5,\"extra\":\"stuff\"}"; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (BaseModel)response; + + protected override void CompareModels(BaseModel model, BaseModel model2, ModelSerializerFormat format) + { + Assert.AreEqual("UnknownBaseModel", model.GetType().Name); + Assert.AreEqual("UnknownBaseModel", model2.GetType().Name); + Assert.AreEqual(model.Kind, model2.Kind); + Assert.AreEqual(model.Name, model2.Name); + var rawData = GetRawData(model); + var rawData2 = GetRawData(model2); + Assert.IsNotNull(rawData); + Assert.IsNotNull(rawData2); + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual(rawData.Count, rawData2.Count); + Assert.AreEqual(rawData["zProperty"].ToObjectFromJson(), rawData2["zProperty"].ToObjectFromJson()); + Assert.AreEqual(rawData["extra"].ToObjectFromJson(), rawData2["extra"].ToObjectFromJson()); + } + } + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + string expected = "{\"kind\":\"Z\",\"name\":\"zmodel\""; + if (format == ModelSerializerFormat.Json) + expected += ",\"zProperty\":1.5,\"extra\":\"stuff\""; + expected += "}"; + return expected; + } + + protected override void VerifyModel(BaseModel model, ModelSerializerFormat format) + { + Assert.AreEqual("UnknownBaseModel", model.GetType().Name); + Assert.AreEqual("Z", model.Kind); + Assert.AreEqual("zmodel", model.Name); + var rawData = GetRawData(model); + Assert.IsNotNull(rawData); + if (format == ModelSerializerFormat.Json) + { + Assert.AreEqual(1.5, rawData["zProperty"].ToObjectFromJson()); + Assert.AreEqual("stuff", rawData["extra"].ToObjectFromJson()); + } + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/UsingJsonSerializerTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/UsingJsonSerializerTests.cs new file mode 100644 index 000000000000..4d1a05616025 --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/UsingJsonSerializerTests.cs @@ -0,0 +1,68 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Text.Json; +using Azure.Core.Serialization; +using Azure.Core.Tests.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + public class UsingJsonSerializerTests + { + [TestCase("J")] + [TestCase("W")] + public void CanSerializeTwoModelsWithSameConverter(string format) + { + string modelYResponse = "{\"kind\":\"Y\",\"name\":\"ymodel\",\"yProperty\":\"100\",\"extra\":\"stuff\"}"; + string modelXResponse = "{\"kind\":\"X\",\"name\":\"xmodel\",\"xProperty\":100,\"extra\":\"stuff\"}"; + + var options = new JsonSerializerOptions(); + options.Converters.Add(new ModelJsonConverter(format)); + ModelY modelY = JsonSerializer.Deserialize(modelYResponse, options); + + Assert.AreEqual("Y", modelY.Kind); + Assert.AreEqual("ymodel", modelY.Name); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual("100", modelY.YProperty); + + var additionalProperties = ModelTests.GetRawData(modelY); + Assert.IsNotNull(additionalProperties); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual("stuff", additionalProperties["extra"].ToObjectFromJson()); + + string expectedModelY = "{"; + expectedModelY += "\"kind\":\"Y\",\"name\":\"ymodel\""; + if (format == ModelSerializerFormat.Json) + expectedModelY += ",\"yProperty\":\"100\",\"extra\":\"stuff\""; + expectedModelY += "}"; + + var actualModelY = JsonSerializer.Serialize(modelY, options); + Assert.AreEqual(expectedModelY, actualModelY); + + ModelX modelX = JsonSerializer.Deserialize(modelXResponse, options); + + Assert.AreEqual("X", modelX.Kind); + Assert.AreEqual("xmodel", modelX.Name); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual(100, modelX.XProperty); + + additionalProperties = ModelTests.GetRawData(modelX); + Assert.IsNotNull(additionalProperties); + if (format == ModelSerializerFormat.Json) + Assert.AreEqual("stuff", additionalProperties["extra"].ToObjectFromJson()); + + string expectedModelX = "{"; + expectedModelX += "\"kind\":\"X\""; + expectedModelX += ",\"name\":\"xmodel\""; + if (format == ModelSerializerFormat.Json) + expectedModelX += ",\"xProperty\":100"; + if (format == ModelSerializerFormat.Json) + expectedModelX += ",\"extra\":\"stuff\""; + expectedModelX += "}"; + + var actualModelX = JsonSerializer.Serialize(modelX, options); + Assert.AreEqual(expectedModelX, actualModelX); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/VerifyModels.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/VerifyModels.cs new file mode 100644 index 000000000000..3c8aea67019e --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/VerifyModels.cs @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Azure.Core.Serialization; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class VerifyModels + { + public static void CheckAnimals(Animal x, Animal y, ModelSerializerOptions options) + { + VerifyProperties(x, y, options); + } + + private static void VerifyProperties(Animal x, Animal y, ModelSerializerOptions options) + { + if (options.Format == ModelSerializerFormat.Json) + Assert.That(x.LatinName, Is.EqualTo(y.LatinName)); + Assert.That(x.Name, Is.EqualTo(y.Name)); + Assert.That(x.Weight, Is.EqualTo(y.Weight)); + + if (options.Format == ModelSerializerFormat.Json) + { + var additionalPropertiesX = typeof(Animal).GetProperty("RawData", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(x) as Dictionary; + var additionalPropertiesY = typeof(Animal).GetProperty("RawData", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic).GetValue(y) as Dictionary; + + Assert.AreEqual(additionalPropertiesX.Count, additionalPropertiesY.Count); + + foreach (var additionalProperty in additionalPropertiesX) + { + Assert.IsTrue(additionalPropertiesY.ContainsKey(additionalProperty.Key)); + Assert.AreEqual(additionalProperty.Value.ToString(), additionalPropertiesY[additionalProperty.Key].ToString()); + } + foreach (var additionalProperty in additionalPropertiesY) + { + Assert.IsTrue(additionalPropertiesX.ContainsKey(additionalProperty.Key)); + Assert.AreEqual(additionalProperty.Value.ToString(), additionalPropertiesX[additionalProperty.Key].ToString()); + } + } + } + + public static void CheckCats(CatReadOnlyProperty x, CatReadOnlyProperty y, ModelSerializerOptions options) + { + VerifyProperties(x, y, options); + Assert.That(x.HasWhiskers, Is.EqualTo(y.HasWhiskers)); + } + + public static void CheckDogs(DogListProperty x, DogListProperty y, ModelSerializerOptions options) + { + VerifyProperties(x, y, options); + Assert.That(x.FoodConsumed, Is.EqualTo(y.FoodConsumed)); + } + + public static string NormalizeNewLines(string value) + { + return value + .Replace("\r\n", "\n") + .Replace("\n", Environment.NewLine); + } + } +} diff --git a/sdk/core/Azure.Core/tests/public/ModelSerializationTests/XmlModelForCombinedInterfaceTests.cs b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/XmlModelForCombinedInterfaceTests.cs new file mode 100644 index 000000000000..0543b09a435b --- /dev/null +++ b/sdk/core/Azure.Core/tests/public/ModelSerializationTests/XmlModelForCombinedInterfaceTests.cs @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using Azure.Core.Serialization; +using Azure.Core.Tests.Public.ModelSerializationTests.Models; +using NUnit.Framework; + +namespace Azure.Core.Tests.Public.ModelSerializationTests +{ + internal class XmlModelForCombinedInterfaceTests : ModelJsonTests + { + protected override string JsonPayload => "{\"key\":\"Color\",\"value\":\"Red\",\"readOnlyProperty\":\"ReadOnly\"}"; + + protected override string WirePayload => "" + + "Color" + + "Red" + + "ReadOnly" + + ""; + + protected override Func ToRequestContent => model => model; + + protected override Func FromResponse => response => (XmlModelForCombinedInterface)response; + + protected override string GetExpectedResult(ModelSerializerFormat format) + { + if (format == ModelSerializerFormat.Wire) + { + var expectedSerializedString = "\uFEFFColorRed"; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += "ReadOnly"; + expectedSerializedString += ""; + return expectedSerializedString; + } + if (format == ModelSerializerFormat.Json) + { + var expectedSerializedString = "{\"key\":\"Color\",\"value\":\"Red\""; + if (format.Equals(ModelSerializerFormat.Json)) + expectedSerializedString += ",\"readOnlyProperty\":\"ReadOnly\""; + expectedSerializedString += "}"; + return expectedSerializedString; + } + throw new InvalidOperationException($"Unknown format used in test {format}"); + } + + protected override void VerifyModel(XmlModelForCombinedInterface model, ModelSerializerFormat format) + { + Assert.AreEqual("Color", model.Key); + Assert.AreEqual("Red", model.Value); + if (format.Equals(ModelSerializerFormat.Json)) + Assert.AreEqual("ReadOnly", model.ReadOnlyProperty); + } + + protected override void CompareModels(XmlModelForCombinedInterface model, XmlModelForCombinedInterface model2, ModelSerializerFormat format) + { + Assert.AreEqual(model.Key, model2.Key); + Assert.AreEqual(model.Value, model2.Value); + if (format.Equals(ModelSerializerFormat.Json)) + Assert.AreEqual(model.ReadOnlyProperty, model2.ReadOnlyProperty); + } + } +}