diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/Azure.Data.SchemaRegistry.sln b/sdk/schemaregistry/Azure.Data.SchemaRegistry/Azure.Data.SchemaRegistry.sln new file mode 100644 index 000000000000..1925de98e9a4 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/Azure.Data.SchemaRegistry.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29709.97 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Data.SchemaRegistry", "src\Azure.Data.SchemaRegistry.csproj", "{E33D09D9-D809-472C-82E6-6A26BDB86FC2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Data.SchemaRegistry.Tests", "tests\Azure.Data.SchemaRegistry.Tests.csproj", "{4F476D56-DDE7-43D3-8CB4-BA1E77F5A300}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.TestFramework", "..\..\core\Azure.Core.TestFramework\src\Azure.Core.TestFramework.csproj", "{8052009B-2126-44A3-88CD-4F3B17894C64}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E33D09D9-D809-472C-82E6-6A26BDB86FC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E33D09D9-D809-472C-82E6-6A26BDB86FC2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E33D09D9-D809-472C-82E6-6A26BDB86FC2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E33D09D9-D809-472C-82E6-6A26BDB86FC2}.Release|Any CPU.Build.0 = Release|Any CPU + {4F476D56-DDE7-43D3-8CB4-BA1E77F5A300}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F476D56-DDE7-43D3-8CB4-BA1E77F5A300}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F476D56-DDE7-43D3-8CB4-BA1E77F5A300}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F476D56-DDE7-43D3-8CB4-BA1E77F5A300}.Release|Any CPU.Build.0 = Release|Any CPU + {8052009B-2126-44A3-88CD-4F3B17894C64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8052009B-2126-44A3-88CD-4F3B17894C64}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8052009B-2126-44A3-88CD-4F3B17894C64}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8052009B-2126-44A3-88CD-4F3B17894C64}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A97F4B90-2591-4689-B1F8-5F21FE6D6CAE} + EndGlobalSection +EndGlobal diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/CHANGELOG.md b/sdk/schemaregistry/Azure.Data.SchemaRegistry/CHANGELOG.md new file mode 100644 index 000000000000..994786219cf6 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/CHANGELOG.md @@ -0,0 +1,7 @@ +# Release History + +## 1.0.0-beta.1 (2020-09-08) +- Added SchemaRegistryClient with 3 operations: + - RegisterSchema + - GetSchemaId + - GetSchema diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/README.md b/sdk/schemaregistry/Azure.Data.SchemaRegistry/README.md new file mode 100644 index 000000000000..ada3e75fe436 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/README.md @@ -0,0 +1,158 @@ +# Azure Schema Registry client library for .NET + +The Azure Schema Registry service allows developers to provide and retrieve data schemas from a centralized repository for use in messaging systems. + +## Getting started + +### Install the package + +Install the Azure Schema Registry client library for .NET with [NuGet][nuget]: + +```bash +dotnet add package Azure.Data.SchemaRegistry --version 1.0.0-beta.1 +``` + +### Prerequisites + +* An [Azure subscription][azure_sub] +* An [Event Hubs namespace][event_hubs_namespace] + +If you need to [create an Event Hubs namespace][create_event_hubs_namespace], you can use the Azure Portal or [Azure PowerShell][azure_powershell]. + +You can use Azure PowerShell to create the Event Hubs namespace with the following command: + +```PowerShell +New-AzEventHubNamespace -ResourceGroupName myResourceGroup -NamespaceName namespace_name -Location eastus +``` + +### Authenticate the client + +In order to interact with the Azure Schema Registry service, you'll need to create an instance of the [Schema Registry Client][schema_registry_client] class. To create this client, you'll need Azure resource credentials and the Event Hubs namespace hostname. + +#### Get credentials + +To acquire authenicated credentials and start interacting with Azure resources, please see the [quickstart guide here][quickstart_guide]. + +#### Get Event Hubs namespace hostname + +The simpliest way is to use the [Azure portal][azure_portal] and navigate to your Event Hubs namespace. From the Overview tab, you'll see `Host name`. Copy the value from this field. + +#### Create SchemaRegistryClient + +Once you have the Azure resource credentials and the Event Hubs namespace hostname, you can create the [SchemaRegistryClient][schema_registry_client]. You'll also need the [Azure.Identity][azure_identity] package to create the credential. + +```C# Snippet:CreateSchemaRegistryClient +string endpoint = ""; +var credentials = new ClientSecretCredential( + "", + "", + "" +); +var client = new SchemaRegistryClient(endpoint, credentials); +``` + +## Key concepts + +### Schemas + +A schema has 6 components: +- Group Name: The name of the group of schemas in the Schema Registry instance. +- Schema Name: The name of the schema. +- Schema ID: The ID assigned by the Schema Registry instance for the schema. +- Serialization Type: The format used for serialization of the schema. For example, Avro. +- Schema Content: The string representation of the schema. +- Schema Version: The version assigned to the schema in the Schema Registry instance. + +These components play different roles. Some are used as input into the operations and some are outputs. Currently, [SchemaProperties][schema_properties] only exposes those properties that are potential outputs that are used in SchemaRegistry operations. Those exposed properties are `Content` and `Id`. + +## Examples + +The following shows examples of what is available through the SchemaRegistryClient. There are both sync and async methods available for these client operations. + +* [Register a schema](#register-a-schema) +* [Retrieve a schema ID](#retrieve-a-schema-id) +* [Retrieve a schema](#retrieve-a-schema) + +### Register a schema + +Register a schema to be stored in the Azure Schema Registry. + +```C# Snippet:RegisterSchema +string schemaName = ""; +string groupName = ""; +SerializationType schemaType = SerializationType.Avro; +// Example schema's content +string schemaContent = @" +{ + ""type"" : ""record"", + ""namespace"" : ""TestSchema"", + ""name"" : ""Employee"", + ""fields"" : [ + { ""name"" : ""Name"" , ""type"" : ""string"" }, + { ""name"" : ""Age"", ""type"" : ""int"" } + ] +}"; + +Response schemaProperties = client.RegisterSchema(groupName, schemaName, schemaType, schemaContent); +``` + +### Retrieve a schema ID + +Retrieve a previously registered schema ID from the Azure Schema Registry. + +```C# Snippet:RetrieveSchemaId +string schemaName = ""; +string groupName = ""; +SerializationType schemaType = SerializationType.Avro; +// Example schema's content +string schemaContent = @" +{ + ""type"" : ""record"", + ""namespace"" : ""TestSchema"", + ""name"" : ""Employee"", + ""fields"" : [ + { ""name"" : ""Name"" , ""type"" : ""string"" }, + { ""name"" : ""Age"", ""type"" : ""int"" } + ] +}"; + +Response schemaProperties = client.GetSchemaId(groupName, schemaName, schemaType, schemaContent); +string schemaId = schemaProperties.Value.Id; +``` + +### Retrieve a schema + +Retrieve a previously registered schema's content from the Azure Schema Registry. + +```C# Snippet:RetrieveSchema +string schemaId = ""; + +Response schemaProperties = client.GetSchema(schemaId); +string schemaContent = schemaProperties.Value.Content; +``` + +## Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit [cla.microsoft.com][cla]. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct][code_of_conduct]. For more information see the [Code of Conduct FAQ][code_of_conduct_faq] or contact [opencode@microsoft.com][email_opencode] with any additional questions or comments. + +![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-net%2Fsdk%2Ftemplate%2FAzure.Template%2FREADME.png) + + +[nuget]: https://www.nuget.org/ +[event_hubs_namespace]: https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-about +[azure_powershell]: https://docs.microsoft.com/en-us/powershell/azure/ +[create_event_hubs_namespace]: https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-quickstart-powershell#create-an-event-hubs-namespace +[quickstart_guide]: https://github.com/Azure/azure-sdk-for-net/blob/master/doc/mgmt_preview_quickstart.md +[schema_registry_client]: src/SchemaRegistryClient.cs +[azure_portal]: https://ms.portal.azure.com/ +[schema_properties]: src/SchemaProperties.cs +[azure_identity]: https://www.nuget.org/packages/Azure.Identity +[cla]: https://cla.microsoft.com +[code_of_conduct]: https://opensource.microsoft.com/codeofconduct/ +[code_of_conduct_faq]: https://opensource.microsoft.com/codeofconduct/faq/ +[email_opencode]: mailto:opencode@microsoft.com +[azure_sub]: https://azure.microsoft.com/free/ diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/api/Azure.Data.SchemaRegistry.netstandard2.0.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/api/Azure.Data.SchemaRegistry.netstandard2.0.cs new file mode 100644 index 000000000000..d85702224c0d --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/api/Azure.Data.SchemaRegistry.netstandard2.0.cs @@ -0,0 +1,46 @@ +namespace Azure.Data.SchemaRegistry +{ + public partial class SchemaProperties + { + internal SchemaProperties() { } + public string Content { get { throw null; } } + public string Id { get { throw null; } } + } + public partial class SchemaRegistryClient + { + protected SchemaRegistryClient() { } + public SchemaRegistryClient(string endpoint, Azure.Core.TokenCredential credential) { } + public SchemaRegistryClient(string endpoint, Azure.Core.TokenCredential credential, Azure.Data.SchemaRegistry.SchemaRegistryClientOptions options) { } + public virtual Azure.Response GetSchema(string schemaId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task> GetSchemaAsync(string schemaId, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response GetSchemaId(string groupName, string schemaName, Azure.Data.SchemaRegistry.SerializationType serializationType, string schemaContent, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task> GetSchemaIdAsync(string groupName, string schemaName, Azure.Data.SchemaRegistry.SerializationType serializationType, string schemaContent, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual Azure.Response RegisterSchema(string groupName, string schemaName, Azure.Data.SchemaRegistry.SerializationType serializationType, string schemaContent, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + public virtual System.Threading.Tasks.Task> RegisterSchemaAsync(string groupName, string schemaName, Azure.Data.SchemaRegistry.SerializationType serializationType, string schemaContent, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } + } + public partial class SchemaRegistryClientOptions : Azure.Core.ClientOptions + { + public SchemaRegistryClientOptions(Azure.Data.SchemaRegistry.SchemaRegistryClientOptions.ServiceVersion version = Azure.Data.SchemaRegistry.SchemaRegistryClientOptions.ServiceVersion.V2017_04) { } + public enum ServiceVersion + { + V2017_04 = 1, + } + } + [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)] + public readonly partial struct SerializationType : System.IEquatable + { + private readonly object _dummy; + private readonly int _dummyPrimitive; + public SerializationType(string value) { throw null; } + public static Azure.Data.SchemaRegistry.SerializationType Avro { get { throw null; } } + public bool Equals(Azure.Data.SchemaRegistry.SerializationType 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.Data.SchemaRegistry.SerializationType left, Azure.Data.SchemaRegistry.SerializationType right) { throw null; } + public static implicit operator Azure.Data.SchemaRegistry.SerializationType (string value) { throw null; } + public static bool operator !=(Azure.Data.SchemaRegistry.SerializationType left, Azure.Data.SchemaRegistry.SerializationType right) { throw null; } + public override string ToString() { throw null; } + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Azure.Data.SchemaRegistry.csproj b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Azure.Data.SchemaRegistry.csproj new file mode 100644 index 000000000000..7045689ae6af --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Azure.Data.SchemaRegistry.csproj @@ -0,0 +1,29 @@ + + + Azure Schema Registry SDK + Azure Schema Registry SDK + 1.0.0-beta.1 + Azure;Schema Registry;SchemaRegistry;.NET;Data;$(PackageCommonTags) + $(RequiredTargetFrameworks) + + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/Models/SchemaId.Serialization.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/Models/SchemaId.Serialization.cs new file mode 100644 index 000000000000..0e24121aba69 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/Models/SchemaId.Serialization.cs @@ -0,0 +1,29 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System.Text.Json; +using Azure.Core; + +namespace Azure.Data.SchemaRegistry.Models +{ + internal partial struct SchemaId + { + internal static SchemaId DeserializeSchemaId(JsonElement element) + { + Optional id = default; + foreach (var property in element.EnumerateObject()) + { + if (property.NameEquals("id")) + { + id = property.Value.GetString(); + continue; + } + } + return new SchemaId(id.Value); + } + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/Models/SchemaId.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/Models/SchemaId.cs new file mode 100644 index 000000000000..b1ab4b861c03 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/Models/SchemaId.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; + +namespace Azure.Data.SchemaRegistry.Models +{ + /// JSON Object received from the registry containing schema identifiers. + internal readonly partial struct SchemaId + { + /// Initializes a new instance of SchemaId. + /// Schema ID that uniquely identifies a schema in the registry namespace. + /// is null. + internal SchemaId(string id) + { + if (id == null) + { + throw new ArgumentNullException(nameof(id)); + } + + Id = id; + } + + /// Schema ID that uniquely identifies a schema in the registry namespace. + public string Id { get; } + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/Models/SerializationType.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/Models/SerializationType.cs new file mode 100644 index 000000000000..ab887838bd30 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/Models/SerializationType.cs @@ -0,0 +1,48 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.ComponentModel; + +namespace Azure.Data.SchemaRegistry +{ + /// The SerializationType. + public readonly partial struct SerializationType : IEquatable + { + private readonly string _value; + + /// Determines if two values are the same. + /// is null. + public SerializationType(string value) + { + _value = value ?? throw new ArgumentNullException(nameof(value)); + } + + private const string AvroValue = "avro"; + + /// Avro Serialization schema type. + public static SerializationType Avro { get; } = new SerializationType(AvroValue); + /// Determines if two values are the same. + public static bool operator ==(SerializationType left, SerializationType right) => left.Equals(right); + /// Determines if two values are not the same. + public static bool operator !=(SerializationType left, SerializationType right) => !left.Equals(right); + /// Converts a string to a . + public static implicit operator SerializationType(string value) => new SerializationType(value); + + /// + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object obj) => obj is SerializationType other && Equals(other); + /// + public bool Equals(SerializationType 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/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/SchemaGetByIdHeaders.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/SchemaGetByIdHeaders.cs new file mode 100644 index 000000000000..d24948fc4773 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/SchemaGetByIdHeaders.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using Azure; +using Azure.Core; + +namespace Azure.Data.SchemaRegistry +{ + internal class SchemaGetByIdHeaders + { + private readonly Response _response; + public SchemaGetByIdHeaders(Response response) + { + _response = response; + } + /// URL location of schema, identified by schema group, schema name, and version. + public string Location => _response.Headers.TryGetValue("Location", out string value) ? value : null; + /// Serialization type for the schema being stored. + public string XSchemaType => _response.Headers.TryGetValue("X-Schema-Type", out string value) ? value : null; + /// References specific schema in registry namespace. + public string XSchemaId => _response.Headers.TryGetValue("X-Schema-Id", out string value) ? value : null; + /// URL location of schema, identified by schema ID. + public string XSchemaIdLocation => _response.Headers.TryGetValue("X-Schema-Id-Location", out string value) ? value : null; + /// Version of the returned schema. + public int? XSchemaVersion => _response.Headers.TryGetValue("X-Schema-Version", out int? value) ? value : null; + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/SchemaQueryIdByContentHeaders.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/SchemaQueryIdByContentHeaders.cs new file mode 100644 index 000000000000..bdbd563efc2e --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/SchemaQueryIdByContentHeaders.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using Azure; +using Azure.Core; + +namespace Azure.Data.SchemaRegistry +{ + internal class SchemaQueryIdByContentHeaders + { + private readonly Response _response; + public SchemaQueryIdByContentHeaders(Response response) + { + _response = response; + } + /// URL location of schema, identified by schema group, schema name, and version. + public string Location => _response.Headers.TryGetValue("Location", out string value) ? value : null; + /// Serialization type for the schema being stored. + public string XSchemaType => _response.Headers.TryGetValue("X-Schema-Type", out string value) ? value : null; + /// References specific schema in registry namespace. + public string XSchemaId => _response.Headers.TryGetValue("X-Schema-Id", out string value) ? value : null; + /// URL location of schema, identified by schema ID. + public string XSchemaIdLocation => _response.Headers.TryGetValue("X-Schema-Id-Location", out string value) ? value : null; + /// Version of the returned schema. + public int? XSchemaVersion => _response.Headers.TryGetValue("X-Schema-Version", out int? value) ? value : null; + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/SchemaRegisterHeaders.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/SchemaRegisterHeaders.cs new file mode 100644 index 000000000000..09b9ca0a957d --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/SchemaRegisterHeaders.cs @@ -0,0 +1,31 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using Azure; +using Azure.Core; + +namespace Azure.Data.SchemaRegistry +{ + internal class SchemaRegisterHeaders + { + private readonly Response _response; + public SchemaRegisterHeaders(Response response) + { + _response = response; + } + /// URL location of schema, identified by schema group, schema name, and version. + public string Location => _response.Headers.TryGetValue("Location", out string value) ? value : null; + /// Serialization type for the schema being registered. + public string XSchemaType => _response.Headers.TryGetValue("X-Schema-Type", out string value) ? value : null; + /// References specific schema in registry namespace. + public string XSchemaId => _response.Headers.TryGetValue("X-Schema-Id", out string value) ? value : null; + /// URL location of schema, identified by schema ID. + public string XSchemaIdLocation => _response.Headers.TryGetValue("X-Schema-Id-Location", out string value) ? value : null; + /// Version of the returned schema. + public int? XSchemaVersion => _response.Headers.TryGetValue("X-Schema-Version", out int? value) ? value : null; + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/SchemaRestClient.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/SchemaRestClient.cs new file mode 100644 index 000000000000..2ef1035ad788 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/Generated/SchemaRestClient.cs @@ -0,0 +1,328 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// + +#nullable disable + +using System; +using System.Text.Json; +using System.Threading; +using System.Threading.Tasks; +using Azure.Core; +using Azure.Core.Pipeline; +using Azure.Data.SchemaRegistry.Models; + +namespace Azure.Data.SchemaRegistry +{ + internal partial class SchemaRestClient + { + private string endpoint; + private string apiVersion; + private ClientDiagnostics _clientDiagnostics; + private HttpPipeline _pipeline; + + /// Initializes a new instance of SchemaRestClient. + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The Schema Registry service endpoint, for example my-namespace.servicebus.windows.net. + /// Api Version. + /// or is null. + public SchemaRestClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, string apiVersion = "2018-01-01-preview") + { + if (endpoint == null) + { + throw new ArgumentNullException(nameof(endpoint)); + } + if (apiVersion == null) + { + throw new ArgumentNullException(nameof(apiVersion)); + } + + this.endpoint = endpoint; + this.apiVersion = apiVersion; + _clientDiagnostics = clientDiagnostics; + _pipeline = pipeline; + } + + internal HttpMessage CreateGetByIdRequest(string schemaId) + { + var message = _pipeline.CreateMessage(); + var request = message.Request; + request.Method = RequestMethod.Get; + var uri = new RawRequestUriBuilder(); + uri.AppendRaw("https://", false); + uri.AppendRaw(endpoint, false); + uri.AppendPath("/$schemagroups/getSchemaById/", false); + uri.AppendPath(schemaId, true); + uri.AppendQuery("api-version", apiVersion, true); + request.Uri = uri; + request.Headers.Add("Accept", "application/json"); + return message; + } + + /// Gets a registered schema by its unique ID. Azure Schema Registry guarantees that ID is unique within a namespace. + /// References specific schema in registry namespace. + /// The cancellation token to use. + /// is null. + public async Task> GetByIdAsync(string schemaId, CancellationToken cancellationToken = default) + { + if (schemaId == null) + { + throw new ArgumentNullException(nameof(schemaId)); + } + + using var message = CreateGetByIdRequest(schemaId); + await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); + var headers = new SchemaGetByIdHeaders(message.Response); + switch (message.Response.Status) + { + case 200: + { + string value = default; + using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); + value = document.RootElement.GetString(); + return ResponseWithHeaders.FromValue(value, headers, message.Response); + } + default: + throw await _clientDiagnostics.CreateRequestFailedExceptionAsync(message.Response).ConfigureAwait(false); + } + } + + /// Gets a registered schema by its unique ID. Azure Schema Registry guarantees that ID is unique within a namespace. + /// References specific schema in registry namespace. + /// The cancellation token to use. + /// is null. + public ResponseWithHeaders GetById(string schemaId, CancellationToken cancellationToken = default) + { + if (schemaId == null) + { + throw new ArgumentNullException(nameof(schemaId)); + } + + using var message = CreateGetByIdRequest(schemaId); + _pipeline.Send(message, cancellationToken); + var headers = new SchemaGetByIdHeaders(message.Response); + switch (message.Response.Status) + { + case 200: + { + string value = default; + using var document = JsonDocument.Parse(message.Response.ContentStream); + value = document.RootElement.GetString(); + return ResponseWithHeaders.FromValue(value, headers, message.Response); + } + default: + throw _clientDiagnostics.CreateRequestFailedException(message.Response); + } + } + + internal HttpMessage CreateQueryIdByContentRequest(string groupName, string schemaName, SerializationType xSchemaType, string schemaContent) + { + var message = _pipeline.CreateMessage(); + var request = message.Request; + request.Method = RequestMethod.Post; + var uri = new RawRequestUriBuilder(); + uri.AppendRaw("https://", false); + uri.AppendRaw(endpoint, false); + uri.AppendPath("/$schemagroups/", false); + uri.AppendPath(groupName, true); + uri.AppendPath("/schemas/", false); + uri.AppendPath(schemaName, true); + uri.AppendQuery("api-version", apiVersion, true); + request.Uri = uri; + request.Headers.Add("X-Schema-Type", xSchemaType.ToString()); + request.Headers.Add("Content-Type", "application/json"); + request.Headers.Add("Accept", "application/json"); + var content = new Utf8JsonRequestContent(); + content.JsonWriter.WriteStringValue(schemaContent); + request.Content = content; + return message; + } + + /// Gets the ID referencing an existing schema within the specified schema group, as matched by schema content comparison. + /// Schema group under which schema is registered. Group's serialization type should match the serialization type specified in the request. + /// Name of the registered schema. + /// Serialization type for the schema being registered. + /// String representation of the registered schema. + /// The cancellation token to use. + /// , , or is null. + public async Task> QueryIdByContentAsync(string groupName, string schemaName, SerializationType xSchemaType, string schemaContent, CancellationToken cancellationToken = default) + { + if (groupName == null) + { + throw new ArgumentNullException(nameof(groupName)); + } + if (schemaName == null) + { + throw new ArgumentNullException(nameof(schemaName)); + } + if (schemaContent == null) + { + throw new ArgumentNullException(nameof(schemaContent)); + } + + using var message = CreateQueryIdByContentRequest(groupName, schemaName, xSchemaType, schemaContent); + await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); + var headers = new SchemaQueryIdByContentHeaders(message.Response); + switch (message.Response.Status) + { + case 200: + { + SchemaId value = default; + using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); + value = SchemaId.DeserializeSchemaId(document.RootElement); + return ResponseWithHeaders.FromValue(value, headers, message.Response); + } + default: + throw await _clientDiagnostics.CreateRequestFailedExceptionAsync(message.Response).ConfigureAwait(false); + } + } + + /// Gets the ID referencing an existing schema within the specified schema group, as matched by schema content comparison. + /// Schema group under which schema is registered. Group's serialization type should match the serialization type specified in the request. + /// Name of the registered schema. + /// Serialization type for the schema being registered. + /// String representation of the registered schema. + /// The cancellation token to use. + /// , , or is null. + public ResponseWithHeaders QueryIdByContent(string groupName, string schemaName, SerializationType xSchemaType, string schemaContent, CancellationToken cancellationToken = default) + { + if (groupName == null) + { + throw new ArgumentNullException(nameof(groupName)); + } + if (schemaName == null) + { + throw new ArgumentNullException(nameof(schemaName)); + } + if (schemaContent == null) + { + throw new ArgumentNullException(nameof(schemaContent)); + } + + using var message = CreateQueryIdByContentRequest(groupName, schemaName, xSchemaType, schemaContent); + _pipeline.Send(message, cancellationToken); + var headers = new SchemaQueryIdByContentHeaders(message.Response); + switch (message.Response.Status) + { + case 200: + { + SchemaId value = default; + using var document = JsonDocument.Parse(message.Response.ContentStream); + value = SchemaId.DeserializeSchemaId(document.RootElement); + return ResponseWithHeaders.FromValue(value, headers, message.Response); + } + default: + throw _clientDiagnostics.CreateRequestFailedException(message.Response); + } + } + + internal HttpMessage CreateRegisterRequest(string groupName, string schemaName, SerializationType xSchemaType, string schemaContent) + { + var message = _pipeline.CreateMessage(); + var request = message.Request; + request.Method = RequestMethod.Put; + var uri = new RawRequestUriBuilder(); + uri.AppendRaw("https://", false); + uri.AppendRaw(endpoint, false); + uri.AppendPath("/$schemagroups/", false); + uri.AppendPath(groupName, true); + uri.AppendPath("/schemas/", false); + uri.AppendPath(schemaName, true); + uri.AppendQuery("api-version", apiVersion, true); + request.Uri = uri; + request.Headers.Add("X-Schema-Type", xSchemaType.ToString()); + request.Headers.Add("Content-Type", "application/json"); + request.Headers.Add("Accept", "application/json"); + var content = new Utf8JsonRequestContent(); + content.JsonWriter.WriteStringValue(schemaContent); + request.Content = content; + return message; + } + + /// + /// Register new schema. If schema of specified name does not exist in specified group, schema is created at version 1. If schema of specified name exists already in specified group, schema is created at latest version + 1. + /// . + /// + /// Schema group under which schema should be registered. Group's serialization type should match the serialization type specified in the request. + /// Name of schema being registered. + /// Serialization type for the schema being registered. + /// String representation of the schema being registered. + /// The cancellation token to use. + /// , , or is null. + public async Task> RegisterAsync(string groupName, string schemaName, SerializationType xSchemaType, string schemaContent, CancellationToken cancellationToken = default) + { + if (groupName == null) + { + throw new ArgumentNullException(nameof(groupName)); + } + if (schemaName == null) + { + throw new ArgumentNullException(nameof(schemaName)); + } + if (schemaContent == null) + { + throw new ArgumentNullException(nameof(schemaContent)); + } + + using var message = CreateRegisterRequest(groupName, schemaName, xSchemaType, schemaContent); + await _pipeline.SendAsync(message, cancellationToken).ConfigureAwait(false); + var headers = new SchemaRegisterHeaders(message.Response); + switch (message.Response.Status) + { + case 200: + { + SchemaId value = default; + using var document = await JsonDocument.ParseAsync(message.Response.ContentStream, default, cancellationToken).ConfigureAwait(false); + value = SchemaId.DeserializeSchemaId(document.RootElement); + return ResponseWithHeaders.FromValue(value, headers, message.Response); + } + default: + throw await _clientDiagnostics.CreateRequestFailedExceptionAsync(message.Response).ConfigureAwait(false); + } + } + + /// + /// Register new schema. If schema of specified name does not exist in specified group, schema is created at version 1. If schema of specified name exists already in specified group, schema is created at latest version + 1. + /// . + /// + /// Schema group under which schema should be registered. Group's serialization type should match the serialization type specified in the request. + /// Name of schema being registered. + /// Serialization type for the schema being registered. + /// String representation of the schema being registered. + /// The cancellation token to use. + /// , , or is null. + public ResponseWithHeaders Register(string groupName, string schemaName, SerializationType xSchemaType, string schemaContent, CancellationToken cancellationToken = default) + { + if (groupName == null) + { + throw new ArgumentNullException(nameof(groupName)); + } + if (schemaName == null) + { + throw new ArgumentNullException(nameof(schemaName)); + } + if (schemaContent == null) + { + throw new ArgumentNullException(nameof(schemaContent)); + } + + using var message = CreateRegisterRequest(groupName, schemaName, xSchemaType, schemaContent); + _pipeline.Send(message, cancellationToken); + var headers = new SchemaRegisterHeaders(message.Response); + switch (message.Response.Status) + { + case 200: + { + SchemaId value = default; + using var document = JsonDocument.Parse(message.Response.ContentStream); + value = SchemaId.DeserializeSchemaId(document.RootElement); + return ResponseWithHeaders.FromValue(value, headers, message.Response); + } + default: + throw _clientDiagnostics.CreateRequestFailedException(message.Response); + } + } + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SchemaId.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SchemaId.cs new file mode 100644 index 000000000000..154d76331ce7 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SchemaId.cs @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core; + +namespace Azure.Data.SchemaRegistry.Models +{ + [CodeGenModel("SchemaId")] + internal readonly partial struct SchemaId + { + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SchemaProperties.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SchemaProperties.cs new file mode 100644 index 000000000000..f60a757dafa4 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SchemaProperties.cs @@ -0,0 +1,45 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Azure.Data.SchemaRegistry +{ + /// + /// Properties for a SchemaRegistry schema. + /// + public class SchemaProperties + { + internal SchemaProperties(string content, string location, SerializationType xSchemaType, string xSchemaId, int? xSchemaVersion) + { + Content = content; + Id = xSchemaId; + Location = location; + Type = xSchemaType; + Version = xSchemaVersion ?? 0; + } + + /// + /// The schema ID that uniquely identifies a schema in the registry namespace. + /// + public string Id { get; } + + /// + /// The schema content of the SchemaRegistry schema. + /// + public string Content { get; } + + /// + /// The location of the schema. + /// + internal string Location { get; } + + /// + /// Serialization type for the schema being stored. + /// + internal SerializationType Type { get; } + + /// + /// Version of the schema. + /// + internal int Version { get; } + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SchemaRegistryClient.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SchemaRegistryClient.cs new file mode 100644 index 000000000000..81c75e3c81b4 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SchemaRegistryClient.cs @@ -0,0 +1,211 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Threading; +using System.Threading.Tasks; +using Azure.Core; +using Azure.Core.Pipeline; + +namespace Azure.Data.SchemaRegistry +{ + /// + /// The Schema Registry client provides operations to interact with the Schema Registry service. + /// + public class SchemaRegistryClient + { + private readonly ClientDiagnostics _clientDiagnostics; + internal SchemaRestClient RestClient { get; } + private const string CredentialScope = "https://eventhubs.azure.net/.default"; + + /// + /// Initializes a new instance of the . + /// + public SchemaRegistryClient(string endpoint, TokenCredential credential) : this(endpoint, credential, new SchemaRegistryClientOptions()) + { + } + + /// + /// Initializes a new instance of the . + /// + public SchemaRegistryClient(string endpoint, TokenCredential credential, SchemaRegistryClientOptions options) : this( + new ClientDiagnostics(options), + HttpPipelineBuilder.Build(options, new BearerTokenAuthenticationPolicy(credential, CredentialScope)), + endpoint, + options.Version) + { + } + + /// Initializes a new instance of for mocking. + protected SchemaRegistryClient() + { + } + + /// Initializes a new instance of . + /// The handler for diagnostic messaging in the client. + /// The HTTP pipeline for sending and receiving REST requests and responses. + /// The endpoint URI. For example, myschemaregistry.servicebus.windows.net. + /// The API version of the service. + internal SchemaRegistryClient(ClientDiagnostics clientDiagnostics, HttpPipeline pipeline, string endpoint, string apiVersion) + { + RestClient = new SchemaRestClient(clientDiagnostics, pipeline, endpoint, apiVersion); + _clientDiagnostics = clientDiagnostics; + } + + private const string RegisterSchemaScopeName = "SchemaRegistryClient.RegisterSchema"; + private const string GetSchemaIdScopeName = "SchemaRegistryClient.GetSchemaId"; + private const string GetSchemaScopeName = "SchemaRegistryClient.GetSchema"; + + /// + /// Registers a schema with the SchemaRegistry service. + /// + /// The name of the SchemaRegistry group. + /// The name of the schema. + /// The serialization format of the schema. + /// The string representation of the schema's content. + /// The cancellation token for the operation. + /// The properties of the schema. + public virtual async Task> RegisterSchemaAsync(string groupName, string schemaName, SerializationType serializationType, string schemaContent, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope(RegisterSchemaScopeName); + scope.Start(); + try + { + var response = await RestClient.RegisterAsync(groupName, schemaName, serializationType, schemaContent, cancellationToken).ConfigureAwait(false); + var properties = new SchemaProperties(schemaContent, response.Headers.Location, response.Headers.XSchemaType, response.Headers.XSchemaId, response.Headers.XSchemaVersion); + return Response.FromValue(properties, response); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// Registers a schema with the SchemaRegistry service. + /// If the schema did not previously exist in the Schema Registry instance, it is added to the instance and assigned a schema ID. + /// If the schema did previous exist in the Schema Registry instance, a new version of the schema is added to the instance and assigned a new schema ID. + /// + /// The name of the SchemaRegistry group. + /// The name of the schema. + /// The serialization format of the schema. + /// The string representation of the schema's content. + /// The cancellation token for the operation. + /// The properties of the schema. + public virtual Response RegisterSchema(string groupName, string schemaName, SerializationType serializationType, string schemaContent, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope(RegisterSchemaScopeName); + scope.Start(); + try + { + var response = RestClient.Register(groupName, schemaName, serializationType, schemaContent, cancellationToken); + var properties = new SchemaProperties(schemaContent, response.Headers.Location, response.Headers.XSchemaType, response.Headers.XSchemaId, response.Headers.XSchemaVersion); + return Response.FromValue(properties, response); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// Gets the schema ID associated with the schema from the SchemaRegistry service. + /// + /// The name of the SchemaRegistry group. + /// The name of the schema. + /// The serialization format of the schema. + /// The string representation of the schema's content. + /// The cancellation token for the operation. + /// The properties of the schema, including the schema ID provided by the service. + public virtual async Task> GetSchemaIdAsync(string groupName, string schemaName, SerializationType serializationType, string schemaContent, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope(GetSchemaIdScopeName); + scope.Start(); + try + { + var response = await RestClient.QueryIdByContentAsync(groupName, schemaName, serializationType, schemaContent, cancellationToken).ConfigureAwait(false); + var properties = new SchemaProperties(schemaContent, response.Headers.Location, response.Headers.XSchemaType, response.Headers.XSchemaId, response.Headers.XSchemaVersion); + return Response.FromValue(properties, response); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// Gets the schema ID associated with the schema from the SchemaRegistry service. + /// + /// The name of the SchemaRegistry group. + /// The name of the schema. + /// The serialization format of the schema. + /// The string representation of the schema's content. + /// The cancellation token for the operation. + /// The properties of the schema, including the schema ID provided by the service. + public virtual Response GetSchemaId(string groupName, string schemaName, SerializationType serializationType, string schemaContent, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope(GetSchemaIdScopeName); + scope.Start(); + try + { + var response = RestClient.QueryIdByContent(groupName, schemaName, serializationType, schemaContent, cancellationToken); + var properties = new SchemaProperties(schemaContent, response.Headers.Location, response.Headers.XSchemaType, response.Headers.XSchemaId, response.Headers.XSchemaVersion); + return Response.FromValue(properties, response); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// Gets the schema content associated with the schema ID from the SchemaRegistry service. + /// + /// The schema ID of the the schema from the SchemaRegistry. + /// The cancellation token for the operation. + /// The properties of the schema, including the schema content provided by the service. + public virtual async Task> GetSchemaAsync(string schemaId, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope(GetSchemaScopeName); + scope.Start(); + try + { + var response = await RestClient.GetByIdAsync(schemaId, cancellationToken).ConfigureAwait(false); + var properties = new SchemaProperties(response.Value, response.Headers.Location, response.Headers.XSchemaType, response.Headers.XSchemaId, response.Headers.XSchemaVersion); + return Response.FromValue(properties, response); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + + /// + /// Gets the schema content associated with the schema ID from the SchemaRegistry service. + /// + /// The schema ID of the the schema from the SchemaRegistry. + /// The cancellation token for the operation. + /// The properties of the schema, including the schema content provided by the service. + public virtual Response GetSchema(string schemaId, CancellationToken cancellationToken = default) + { + using DiagnosticScope scope = _clientDiagnostics.CreateScope(GetSchemaScopeName); + scope.Start(); + try + { + var response = RestClient.GetById(schemaId, cancellationToken); + var properties = new SchemaProperties(response.Value, response.Headers.Location, response.Headers.XSchemaType, response.Headers.XSchemaId, response.Headers.XSchemaVersion); + return Response.FromValue(properties, response); + } + catch (Exception e) + { + scope.Failed(e); + throw; + } + } + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SchemaRegistryClientOptions.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SchemaRegistryClientOptions.cs new file mode 100644 index 000000000000..8b685ead1937 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SchemaRegistryClientOptions.cs @@ -0,0 +1,41 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Core; + +namespace Azure.Data.SchemaRegistry +{ + /// + /// The options for + /// + public class SchemaRegistryClientOptions : ClientOptions + { + internal string Version { get; } + + /// + /// Initializes a new instance of the . + /// + public SchemaRegistryClientOptions(ServiceVersion version = ServiceVersion.V2017_04) + { + Version = version switch + { + ServiceVersion.V2017_04 => "2017-04", + _ => throw new ArgumentException($"The service version {version} is not supported by this library.", nameof(version)) + }; + } + + /// + /// The Schema Registry service version. + /// + public enum ServiceVersion + { + /// + /// Version 2017-04 of the Schema Registry service. + /// +#pragma warning disable CA1707 // Remove the underscores from member name + V2017_04 = 1 +#pragma warning restore + } + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SerializationType.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SerializationType.cs new file mode 100644 index 000000000000..8f8f7c11c52c --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/SerializationType.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core; + +namespace Azure.Data.SchemaRegistry +{ + /// + /// The format used when serializing SchemaRegistry messages. + /// + [CodeGenModel("SerializationType")] + public readonly partial struct SerializationType + { + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/autorest.md b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/autorest.md new file mode 100644 index 000000000000..fa978170ca67 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/src/autorest.md @@ -0,0 +1,7 @@ +# Generated code configuration + +Run `dotnet msbuild /t:GenerateCode` to generate code. + +``` yaml +require: https://github.com/Azure/azure-rest-api-specs/blob/a90b9146e543d3eec11381bd52d3b6ff271b1b78/specification/schemaregistry/data-plane/readme.md +``` diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/Azure.Data.SchemaRegistry.Tests.csproj b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/Azure.Data.SchemaRegistry.Tests.csproj new file mode 100644 index 000000000000..b909dca15969 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/Azure.Data.SchemaRegistry.Tests.csproj @@ -0,0 +1,25 @@ + + + $(RequiredTargetFrameworks) + + + TRACE + + + + + + + + + + + + + + + + + + + diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/Samples/Sample01_ReadmeSnippets.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/Samples/Sample01_ReadmeSnippets.cs new file mode 100644 index 000000000000..3e87ed29da3c --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/Samples/Sample01_ReadmeSnippets.cs @@ -0,0 +1,94 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.TestFramework; +using Azure.Identity; +using NUnit.Framework; + +namespace Azure.Data.SchemaRegistry.Tests.Samples +{ + public class Sample01_ReadmeSnippets : SamplesBase + { + [Ignore("Only verifying that the sample builds")] + [Test] + public void CreateSchemaRegistryClient() + { + #region Snippet:CreateSchemaRegistryClient + string endpoint = ""; + var credentials = new ClientSecretCredential( + "", + "", + "" + ); + var client = new SchemaRegistryClient(endpoint, credentials); + #endregion + } + + [Ignore("Only verifying that the sample builds")] + [Test] + public void RegisterSchema() + { + var client = new SchemaRegistryClient(TestEnvironment.SchemaRegistryUri, TestEnvironment.Credential); + + #region Snippet:RegisterSchema + string schemaName = ""; + string groupName = ""; + SerializationType schemaType = SerializationType.Avro; + // Example schema's content + string schemaContent = @" + { + ""type"" : ""record"", + ""namespace"" : ""TestSchema"", + ""name"" : ""Employee"", + ""fields"" : [ + { ""name"" : ""Name"" , ""type"" : ""string"" }, + { ""name"" : ""Age"", ""type"" : ""int"" } + ] + }"; + + Response schemaProperties = client.RegisterSchema(groupName, schemaName, schemaType, schemaContent); + #endregion + } + + [Ignore("Only verifying that the sample builds")] + [Test] + public void RetrieveSchemaId() + { + var client = new SchemaRegistryClient(TestEnvironment.SchemaRegistryUri, TestEnvironment.Credential); + + #region Snippet:RetrieveSchemaId + string schemaName = ""; + string groupName = ""; + SerializationType schemaType = SerializationType.Avro; + // Example schema's content + string schemaContent = @" + { + ""type"" : ""record"", + ""namespace"" : ""TestSchema"", + ""name"" : ""Employee"", + ""fields"" : [ + { ""name"" : ""Name"" , ""type"" : ""string"" }, + { ""name"" : ""Age"", ""type"" : ""int"" } + ] + }"; + + Response schemaProperties = client.GetSchemaId(groupName, schemaName, schemaType, schemaContent); + string schemaId = schemaProperties.Value.Id; + #endregion + } + + [Ignore("Only verifying that the sample builds")] + [Test] + public void RetrieveSchema() + { + var client = new SchemaRegistryClient(TestEnvironment.SchemaRegistryUri, TestEnvironment.Credential); + + #region Snippet:RetrieveSchema + string schemaId = ""; + + Response schemaProperties = client.GetSchema(schemaId); + string schemaContent = schemaProperties.Value.Content; + #endregion + } + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SchemaRegistryClientLiveTest.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SchemaRegistryClientLiveTest.cs new file mode 100644 index 000000000000..405985296192 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SchemaRegistryClientLiveTest.cs @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Threading.Tasks; +using Azure.Core.TestFramework; +using NUnit.Framework; + +namespace Azure.Data.SchemaRegistry.Tests +{ + public class SchemaRegistryClientLiveTest : RecordedTestBase + { + public SchemaRegistryClientLiveTest(bool isAsync) : base(isAsync) + { + TestDiagnostics = false; + } + + private SchemaRegistryClient CreateClient() => + InstrumentClient(new SchemaRegistryClient( + TestEnvironment.SchemaRegistryUri, + TestEnvironment.Credential, + Recording.InstrumentClientOptions(new SchemaRegistryClientOptions()) + )); + + [Test] + public async Task CanRegisterSchema() + { + var client = CreateClient(); + var schemaName = "test1"; + var groupName = "miyanni_srgroup"; + var schemaType = SerializationType.Avro; + var schema = @" +{ + ""type"" : ""record"", + ""namespace"" : ""TestSchema"", + ""name"" : ""Employee"", + ""fields"" : [ + { ""name"" : ""Name"" , ""type"" : ""string"" }, + { ""name"" : ""Age"", ""type"" : ""int"" } + ] +}"; + + var schemaProperties = await client.RegisterSchemaAsync(groupName, schemaName, schemaType, schema); + Assert.IsNotNull(schemaProperties.Value); + Assert.IsNotNull(schemaProperties.Value.Id); + Assert.IsTrue(Guid.TryParse(schemaProperties.Value.Id, out Guid _)); + Assert.AreEqual(schema, schemaProperties.Value.Content); + } + + + [Test] + public async Task CanGetSchemaId() + { + var client = CreateClient(); + var schemaName = "test1"; + var groupName = "miyanni_srgroup"; + var schemaType = SerializationType.Avro; + var schema = @" +{ + ""type"" : ""record"", + ""namespace"" : ""TestSchema"", + ""name"" : ""Employee"", + ""fields"" : [ + { ""name"" : ""Name"" , ""type"" : ""string"" }, + { ""name"" : ""Age"", ""type"" : ""int"" } + ] +}"; + + await client.RegisterSchemaAsync(groupName, schemaName, schemaType, schema); + var schemaProperties = await client.GetSchemaIdAsync(groupName, schemaName, schemaType, schema); + Assert.IsNotNull(schemaProperties.Value); + Assert.IsNotNull(schemaProperties.Value.Id); + Assert.IsTrue(Guid.TryParse(schemaProperties.Value.Id, out Guid _)); + Assert.AreEqual(schema, schemaProperties.Value.Content); + } + + [Test] + public async Task CanGetSchema() + { + var client = CreateClient(); + var schemaName = "test1"; + var groupName = "miyanni_srgroup"; + var schemaType = SerializationType.Avro; + var schema = @" +{ + ""type"" : ""record"", + ""namespace"" : ""TestSchema"", + ""name"" : ""Employee"", + ""fields"" : [ + { ""name"" : ""Name"" , ""type"" : ""string"" }, + { ""name"" : ""Age"", ""type"" : ""int"" } + ] +}"; + + var registerProperties = await client.RegisterSchemaAsync(groupName, schemaName, schemaType, schema); + Assert.IsNotNull(registerProperties.Value.Id); + Assert.IsTrue(Guid.TryParse(registerProperties.Value.Id, out Guid _)); + + var schemaProperties = await client.GetSchemaAsync(registerProperties.Value.Id); + Assert.IsNotNull(schemaProperties.Value); + Assert.IsNotNull(schemaProperties.Value.Id); + Assert.IsTrue(Guid.TryParse(schemaProperties.Value.Id, out Guid _)); + Assert.AreEqual(schema, schemaProperties.Value.Content); + } + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SchemaRegistryClientTestEnvironment.cs b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SchemaRegistryClientTestEnvironment.cs new file mode 100644 index 000000000000..99fe105a5bac --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SchemaRegistryClientTestEnvironment.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.TestFramework; + +namespace Azure.Data.SchemaRegistry.Tests +{ + public class SchemaRegistryClientTestEnvironment : TestEnvironment + { + public SchemaRegistryClientTestEnvironment() : base("schemaregistry") + { + } + + public string SchemaRegistryUri => GetRecordedVariable("SCHEMAREGISTRY_URL"); + } +} diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanGetSchema.json b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanGetSchema.json new file mode 100644 index 000000000000..0faa5c8808d1 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanGetSchema.json @@ -0,0 +1,71 @@ +{ + "Entries": [ + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1?api-version=2017-04", + "RequestMethod": "PUT", + "RequestHeaders": { + "Authorization": "Sanitized", + "Content-Length": "369", + "Content-Type": "application/json", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-dev.20200820.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "a9bb4e4bb92bb7199b81a2fe15c1bf1d", + "x-ms-return-client-request-id": "true", + "X-Schema-Type": "avro" + }, + "RequestBody": "\r\n{\r\n \u0022type\u0022 : \u0022record\u0022,\r\n \u0022namespace\u0022 : \u0022TestSchema\u0022,\r\n \u0022name\u0022 : \u0022Employee\u0022,\r\n \u0022fields\u0022 : [\r\n { \u0022name\u0022 : \u0022Name\u0022 , \u0022type\u0022 : \u0022string\u0022 },\r\n { \u0022name\u0022 : \u0022Age\u0022, \u0022type\u0022 : \u0022int\u0022 }\r\n ]\r\n}", + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 21 Aug 2020 01:04:42 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "0e30eb5c747e496cbedd94918fe36fd6", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/0e30eb5c747e496cbedd94918fe36fd6?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/test1/versions?api-version=2017-04" + }, + "ResponseBody": { + "id": "0e30eb5c747e496cbedd94918fe36fd6" + } + }, + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/getSchemaById/0e30eb5c747e496cbedd94918fe36fd6?api-version=2017-04", + "RequestMethod": "GET", + "RequestHeaders": { + "Authorization": "Sanitized", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-dev.20200820.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "789557cb0beea63b2b639b6c79b01992", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 21 Aug 2020 01:04:42 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "0e30eb5c747e496cbedd94918fe36fd6", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/0e30eb5c747e496cbedd94918fe36fd6?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/test1/versions?api-version=2017-04" + }, + "ResponseBody": "\u0022\\u000d\\u000a{\\u000d\\u000a \\\u0022type\\\u0022 : \\\u0022record\\\u0022,\\u000d\\u000a \\\u0022namespace\\\u0022 : \\\u0022TestSchema\\\u0022,\\u000d\\u000a \\\u0022name\\\u0022 : \\\u0022Employee\\\u0022,\\u000d\\u000a \\\u0022fields\\\u0022 : [\\u000d\\u000a { \\\u0022name\\\u0022 : \\\u0022Name\\\u0022 , \\\u0022type\\\u0022 : \\\u0022string\\\u0022 },\\u000d\\u000a { \\\u0022name\\\u0022 : \\\u0022Age\\\u0022, \\\u0022type\\\u0022 : \\\u0022int\\\u0022 }\\u000d\\u000a ]\\u000d\\u000a}\u0022" + } + ], + "Variables": { + "RandomSeed": "1446263238", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanGetSchemaAsync.json b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanGetSchemaAsync.json new file mode 100644 index 000000000000..6c2934a6aa69 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanGetSchemaAsync.json @@ -0,0 +1,71 @@ +{ + "Entries": [ + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1?api-version=2017-04", + "RequestMethod": "PUT", + "RequestHeaders": { + "Authorization": "Sanitized", + "Content-Length": "369", + "Content-Type": "application/json", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-dev.20200820.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "23519c599ecca90a5a65530717191100", + "x-ms-return-client-request-id": "true", + "X-Schema-Type": "avro" + }, + "RequestBody": "\r\n{\r\n \u0022type\u0022 : \u0022record\u0022,\r\n \u0022namespace\u0022 : \u0022TestSchema\u0022,\r\n \u0022name\u0022 : \u0022Employee\u0022,\r\n \u0022fields\u0022 : [\r\n { \u0022name\u0022 : \u0022Name\u0022 , \u0022type\u0022 : \u0022string\u0022 },\r\n { \u0022name\u0022 : \u0022Age\u0022, \u0022type\u0022 : \u0022int\u0022 }\r\n ]\r\n}", + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 21 Aug 2020 01:04:45 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "0e30eb5c747e496cbedd94918fe36fd6", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/0e30eb5c747e496cbedd94918fe36fd6?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/test1/versions?api-version=2017-04" + }, + "ResponseBody": { + "id": "0e30eb5c747e496cbedd94918fe36fd6" + } + }, + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/getSchemaById/0e30eb5c747e496cbedd94918fe36fd6?api-version=2017-04", + "RequestMethod": "GET", + "RequestHeaders": { + "Authorization": "Sanitized", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-dev.20200820.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "fa78deb88eafe71485ee6b337d7d6b2d", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 21 Aug 2020 01:04:46 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "0e30eb5c747e496cbedd94918fe36fd6", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/0e30eb5c747e496cbedd94918fe36fd6?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/test1/versions?api-version=2017-04" + }, + "ResponseBody": "\u0022\\u000d\\u000a{\\u000d\\u000a \\\u0022type\\\u0022 : \\\u0022record\\\u0022,\\u000d\\u000a \\\u0022namespace\\\u0022 : \\\u0022TestSchema\\\u0022,\\u000d\\u000a \\\u0022name\\\u0022 : \\\u0022Employee\\\u0022,\\u000d\\u000a \\\u0022fields\\\u0022 : [\\u000d\\u000a { \\\u0022name\\\u0022 : \\\u0022Name\\\u0022 , \\\u0022type\\\u0022 : \\\u0022string\\\u0022 },\\u000d\\u000a { \\\u0022name\\\u0022 : \\\u0022Age\\\u0022, \\\u0022type\\\u0022 : \\\u0022int\\\u0022 }\\u000d\\u000a ]\\u000d\\u000a}\u0022" + } + ], + "Variables": { + "RandomSeed": "1311802614", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanGetSchemaId.json b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanGetSchemaId.json new file mode 100644 index 000000000000..77b7285719fc --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanGetSchemaId.json @@ -0,0 +1,76 @@ +{ + "Entries": [ + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1?api-version=2017-04", + "RequestMethod": "PUT", + "RequestHeaders": { + "Authorization": "Sanitized", + "Content-Length": "369", + "Content-Type": "application/json", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-dev.20200820.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "2c620897d9de14f8847756ca36bfb1dd", + "x-ms-return-client-request-id": "true", + "X-Schema-Type": "avro" + }, + "RequestBody": "\r\n{\r\n \u0022type\u0022 : \u0022record\u0022,\r\n \u0022namespace\u0022 : \u0022TestSchema\u0022,\r\n \u0022name\u0022 : \u0022Employee\u0022,\r\n \u0022fields\u0022 : [\r\n { \u0022name\u0022 : \u0022Name\u0022 , \u0022type\u0022 : \u0022string\u0022 },\r\n { \u0022name\u0022 : \u0022Age\u0022, \u0022type\u0022 : \u0022int\u0022 }\r\n ]\r\n}", + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 21 Aug 2020 01:04:43 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "0e30eb5c747e496cbedd94918fe36fd6", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/0e30eb5c747e496cbedd94918fe36fd6?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/test1/versions?api-version=2017-04" + }, + "ResponseBody": { + "id": "0e30eb5c747e496cbedd94918fe36fd6" + } + }, + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1?api-version=2017-04", + "RequestMethod": "POST", + "RequestHeaders": { + "Authorization": "Sanitized", + "Content-Length": "369", + "Content-Type": "application/json", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-dev.20200820.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "f81747feb3bdd74d2da2f268fd8a6e28", + "x-ms-return-client-request-id": "true", + "X-Schema-Type": "avro" + }, + "RequestBody": "\r\n{\r\n \u0022type\u0022 : \u0022record\u0022,\r\n \u0022namespace\u0022 : \u0022TestSchema\u0022,\r\n \u0022name\u0022 : \u0022Employee\u0022,\r\n \u0022fields\u0022 : [\r\n { \u0022name\u0022 : \u0022Name\u0022 , \u0022type\u0022 : \u0022string\u0022 },\r\n { \u0022name\u0022 : \u0022Age\u0022, \u0022type\u0022 : \u0022int\u0022 }\r\n ]\r\n}", + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 21 Aug 2020 01:04:43 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "0e30eb5c747e496cbedd94918fe36fd6", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/0e30eb5c747e496cbedd94918fe36fd6?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/test1/versions?api-version=2017-04" + }, + "ResponseBody": { + "id": "0e30eb5c747e496cbedd94918fe36fd6" + } + } + ], + "Variables": { + "RandomSeed": "423990645", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanGetSchemaIdAsync.json b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanGetSchemaIdAsync.json new file mode 100644 index 000000000000..9595a06551b1 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanGetSchemaIdAsync.json @@ -0,0 +1,76 @@ +{ + "Entries": [ + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1?api-version=2017-04", + "RequestMethod": "PUT", + "RequestHeaders": { + "Authorization": "Sanitized", + "Content-Length": "369", + "Content-Type": "application/json", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-dev.20200820.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "5417cde1a45d14a2ae3731d071449823", + "x-ms-return-client-request-id": "true", + "X-Schema-Type": "avro" + }, + "RequestBody": "\r\n{\r\n \u0022type\u0022 : \u0022record\u0022,\r\n \u0022namespace\u0022 : \u0022TestSchema\u0022,\r\n \u0022name\u0022 : \u0022Employee\u0022,\r\n \u0022fields\u0022 : [\r\n { \u0022name\u0022 : \u0022Name\u0022 , \u0022type\u0022 : \u0022string\u0022 },\r\n { \u0022name\u0022 : \u0022Age\u0022, \u0022type\u0022 : \u0022int\u0022 }\r\n ]\r\n}", + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 21 Aug 2020 01:04:46 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "0e30eb5c747e496cbedd94918fe36fd6", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/0e30eb5c747e496cbedd94918fe36fd6?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/test1/versions?api-version=2017-04" + }, + "ResponseBody": { + "id": "0e30eb5c747e496cbedd94918fe36fd6" + } + }, + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1?api-version=2017-04", + "RequestMethod": "POST", + "RequestHeaders": { + "Authorization": "Sanitized", + "Content-Length": "369", + "Content-Type": "application/json", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-dev.20200820.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "ebf572ccf2140bd54101f2c44b198261", + "x-ms-return-client-request-id": "true", + "X-Schema-Type": "avro" + }, + "RequestBody": "\r\n{\r\n \u0022type\u0022 : \u0022record\u0022,\r\n \u0022namespace\u0022 : \u0022TestSchema\u0022,\r\n \u0022name\u0022 : \u0022Employee\u0022,\r\n \u0022fields\u0022 : [\r\n { \u0022name\u0022 : \u0022Name\u0022 , \u0022type\u0022 : \u0022string\u0022 },\r\n { \u0022name\u0022 : \u0022Age\u0022, \u0022type\u0022 : \u0022int\u0022 }\r\n ]\r\n}", + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 21 Aug 2020 01:04:47 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "0e30eb5c747e496cbedd94918fe36fd6", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/0e30eb5c747e496cbedd94918fe36fd6?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/test1/versions?api-version=2017-04" + }, + "ResponseBody": { + "id": "0e30eb5c747e496cbedd94918fe36fd6" + } + } + ], + "Variables": { + "RandomSeed": "1351424262", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanRegisterSchema.json b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanRegisterSchema.json new file mode 100644 index 000000000000..13ec03a47cfe --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanRegisterSchema.json @@ -0,0 +1,43 @@ +{ + "Entries": [ + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1?api-version=2017-04", + "RequestMethod": "PUT", + "RequestHeaders": { + "Authorization": "Sanitized", + "Content-Length": "369", + "Content-Type": "application/json", + "Request-Id": "|fae22771-4509d094581d363d.", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-dev.20200812.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "06149688c0d107fba9beaa6650213cc6", + "x-ms-return-client-request-id": "true", + "X-Schema-Type": "avro" + }, + "RequestBody": "\r\n{\r\n \u0022type\u0022 : \u0022record\u0022,\r\n \u0022namespace\u0022 : \u0022TestSchema\u0022,\r\n \u0022name\u0022 : \u0022Employee\u0022,\r\n \u0022fields\u0022 : [\r\n { \u0022name\u0022 : \u0022Name\u0022 , \u0022type\u0022 : \u0022string\u0022 },\r\n { \u0022name\u0022 : \u0022Age\u0022, \u0022type\u0022 : \u0022int\u0022 }\r\n ]\r\n}", + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Thu, 13 Aug 2020 00:24:21 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "0e30eb5c747e496cbedd94918fe36fd6", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/0e30eb5c747e496cbedd94918fe36fd6?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/test1/versions?api-version=2017-04" + }, + "ResponseBody": { + "id": "0e30eb5c747e496cbedd94918fe36fd6" + } + } + ], + "Variables": { + "RandomSeed": "2024185609", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanRegisterSchemaAsync.json b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanRegisterSchemaAsync.json new file mode 100644 index 000000000000..7f58562b0255 --- /dev/null +++ b/sdk/schemaregistry/Azure.Data.SchemaRegistry/tests/SessionRecords/SchemaRegistryClientLiveTest/CanRegisterSchemaAsync.json @@ -0,0 +1,43 @@ +{ + "Entries": [ + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1?api-version=2017-04", + "RequestMethod": "PUT", + "RequestHeaders": { + "Authorization": "Sanitized", + "Content-Length": "369", + "Content-Type": "application/json", + "Request-Id": "|fae22773-4509d094581d363d.", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-dev.20200812.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "10d841304c76af44a9857366d3cdcece", + "x-ms-return-client-request-id": "true", + "X-Schema-Type": "avro" + }, + "RequestBody": "\r\n{\r\n \u0022type\u0022 : \u0022record\u0022,\r\n \u0022namespace\u0022 : \u0022TestSchema\u0022,\r\n \u0022name\u0022 : \u0022Employee\u0022,\r\n \u0022fields\u0022 : [\r\n { \u0022name\u0022 : \u0022Name\u0022 , \u0022type\u0022 : \u0022string\u0022 },\r\n { \u0022name\u0022 : \u0022Age\u0022, \u0022type\u0022 : \u0022int\u0022 }\r\n ]\r\n}", + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Thu, 13 Aug 2020 00:24:41 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/test1/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "0e30eb5c747e496cbedd94918fe36fd6", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/0e30eb5c747e496cbedd94918fe36fd6?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/test1/versions?api-version=2017-04" + }, + "ResponseBody": { + "id": "0e30eb5c747e496cbedd94918fe36fd6" + } + } + ], + "Variables": { + "RandomSeed": "341051900", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/CHANGELOG.md b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/CHANGELOG.md new file mode 100644 index 000000000000..e15e131f1e44 --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/CHANGELOG.md @@ -0,0 +1,8 @@ +# Release History + +## 1.0.0-beta.1 (2020-09-08) +- Added SchemaRegistryAvroObjectSerializer + - Derives from ObjectSerializer + - Works with 2 Avro types: + - SpecificRecord + - GenericRecord \ No newline at end of file diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/Directory.Build.props b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/Directory.Build.props new file mode 100644 index 000000000000..cd1ea9e1673a --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/Directory.Build.props @@ -0,0 +1,7 @@ + + + true + + + + diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.sln b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.sln new file mode 100644 index 000000000000..afe1df921037 --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.sln @@ -0,0 +1,43 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29709.97 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.Data.SchemaRegistry.ApacheAvro", "src\Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.csproj", "{E33D09D9-D809-472C-82E6-6A26BDB86FC2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.Tests", "tests\Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.Tests.csproj", "{4F476D56-DDE7-43D3-8CB4-BA1E77F5A300}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Core.TestFramework", "..\..\core\Azure.Core.TestFramework\src\Azure.Core.TestFramework.csproj", "{8052009B-2126-44A3-88CD-4F3B17894C64}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Azure.Data.SchemaRegistry", "..\Azure.Data.SchemaRegistry\src\Azure.Data.SchemaRegistry.csproj", "{D451EE68-ADE4-4780-A002-2D13DEA888A2}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E33D09D9-D809-472C-82E6-6A26BDB86FC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E33D09D9-D809-472C-82E6-6A26BDB86FC2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E33D09D9-D809-472C-82E6-6A26BDB86FC2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E33D09D9-D809-472C-82E6-6A26BDB86FC2}.Release|Any CPU.Build.0 = Release|Any CPU + {4F476D56-DDE7-43D3-8CB4-BA1E77F5A300}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F476D56-DDE7-43D3-8CB4-BA1E77F5A300}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F476D56-DDE7-43D3-8CB4-BA1E77F5A300}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F476D56-DDE7-43D3-8CB4-BA1E77F5A300}.Release|Any CPU.Build.0 = Release|Any CPU + {8052009B-2126-44A3-88CD-4F3B17894C64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8052009B-2126-44A3-88CD-4F3B17894C64}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8052009B-2126-44A3-88CD-4F3B17894C64}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8052009B-2126-44A3-88CD-4F3B17894C64}.Release|Any CPU.Build.0 = Release|Any CPU + {D451EE68-ADE4-4780-A002-2D13DEA888A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D451EE68-ADE4-4780-A002-2D13DEA888A2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D451EE68-ADE4-4780-A002-2D13DEA888A2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D451EE68-ADE4-4780-A002-2D13DEA888A2}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A97F4B90-2591-4689-B1F8-5F21FE6D6CAE} + EndGlobalSection +EndGlobal diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/README.md b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/README.md new file mode 100644 index 000000000000..818fc3000022 --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/README.md @@ -0,0 +1,147 @@ +# Azure Schema Registry Apache Avro library for .NET + +This library provides an Apache Avro serialization and deserialization API using the Azure Schema Registry service. + +## Getting started + +### Install the package + +Install the Azure Schema Registry Apache Avro library for .NET with [NuGet][nuget]: + +```bash +dotnet add package Microsoft.Azure.Data.SchemaRegistry.ApacheAvro --version 1.0.0-beta.1 +``` + +### Prerequisites + +* An [Azure subscription][azure_sub] +* An [Event Hubs namespace][event_hubs_namespace] + +If you need to [create an Event Hubs namespace][create_event_hubs_namespace], you can use the Azure Portal or [Azure PowerShell][azure_powershell]. + +You can use Azure PowerShell to create the Event Hubs namespace with the following command: + +```PowerShell +New-AzEventHubNamespace -ResourceGroupName myResourceGroup -NamespaceName namespace_name -Location eastus +``` + +### Authenticate the client + +In order to interact with the Azure Schema Registry service, you'll need to create an instance of the [Schema Registry Client][schema_registry_client] class. To create this client, you'll need Azure resource credentials and the Event Hubs namespace hostname. + +#### Get credentials + +To acquire authenicated credentials and start interacting with Azure resources, please see the [quickstart guide here][quickstart_guide]. + +#### Get Event Hubs namespace hostname + +The simpliest way is to use the [Azure portal][azure_portal] and navigate to your Event Hubs namespace. From the Overview tab, you'll see `Host name`. Copy the value from this field. + +#### Create SchemaRegistryClient + +Once you have the Azure resource credentials and the Event Hubs namespace hostname, you can create the [SchemaRegistryClient][schema_registry_client]. You'll also need the [Azure.Identity][azure_identity] package to create the credential. + +```C# Snippet:CreateSchemaRegistryClient +string endpoint = ""; +var credentials = new ClientSecretCredential( + "", + "", + "" +); +var client = new SchemaRegistryClient(endpoint, credentials); +``` + +## Key concepts + +### ObjectSerializer + +This library provides a serializer, [SchemaRegistryAvroObjectSerializer][schema_registry_avro_serializer], that implements the [ObjectSerializer][object_serializer] abstract class. This allows a developer to use this serializer in any .NET Azure SDKs that utilize ObjectSerializer. The SchemaRegistryAvroObjectSerializer utilitizes a SchemaRegistryClient to construct messages using a wire format containing schema information such as a schema ID. + +This serializer requires the [Apache Avro library][apache_avro_library]. The payload types accepted by this serializer include [GenericRecord][generic_record] and [ISpecificRecord][specific_record]. + +### Wire Format + +The serializer in this library creates messages in a wire format. The format is the following: + +- Bytes [0-3] – record format indicator – currently is \x00\x00\x00\x00 +- Bytes [4-35] – UTF-8 GUID, identifying the schema in a Schema Registry instance +- Bytes [36-end] – serialized payload bytes + +## Examples + +The following shows examples of what is available through the SchemaRegistryAvroObjectSerializer. There are both sync and async methods available for these operations. These examples use a generated Apache Avro class [Employee.cs][employee] created using this schema: + +```json +{ + "type" : "record", + "namespace" : "TestSchema", + "name" : "Employee", + "fields" : [ + { "name" : "Name" , "type" : "string" }, + { "name" : "Age", "type" : "int" } + ] +} +``` + +Details on generating a class using the Apache Avro library can be found in the [Avro C# Documentation][avro_csharp_documentation]. + +* [Serialize](#register-a-schema) +* [Deserialize](#retrieve-a-schema-id) + +### Serialize + +Register a schema to be stored in the Azure Schema Registry. + +```C# Snippet:Serialize +var employee = new Employee { Age = 42, Name = "John Doe" }; +string groupName = ""; + +using var memoryStream = new MemoryStream(); +var serializer = new SchemaRegistryAvroObjectSerializer(client, groupName, new SchemaRegistryAvroObjectSerializerOptions { AutoRegisterSchemas = true }); +serializer.Serialize(memoryStream, employee, typeof(Employee), CancellationToken.None); +``` + +### Deserialize + +Retrieve a previously registered schema ID from the Azure Schema Registry. + +```C# Snippet:Deserialize +string groupName = ""; + +var serializer = new SchemaRegistryAvroObjectSerializer(client, groupName, new SchemaRegistryAvroObjectSerializerOptions { AutoRegisterSchemas = true }); +memoryStream.Position = 0; +Employee employee = (Employee)serializer.Deserialize(memoryStream, typeof(Employee), CancellationToken.None); +``` + +## Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit [cla.microsoft.com][cla]. + +When you submit a pull request, a CLA-bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. + +This project has adopted the [Microsoft Open Source Code of Conduct][code_of_conduct]. For more information see the [Code of Conduct FAQ][code_of_conduct_faq] or contact [opencode@microsoft.com][email_opencode] with any additional questions or comments. + +![Impressions](https://azure-sdk-impressions.azurewebsites.net/api/impressions/azure-sdk-for-net%2Fsdk%2Ftemplate%2FAzure.Template%2FREADME.png) + + +[nuget]: https://www.nuget.org/ +[event_hubs_namespace]: https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-about +[azure_powershell]: https://docs.microsoft.com/en-us/powershell/azure/ +[create_event_hubs_namespace]: https://docs.microsoft.com/en-us/azure/event-hubs/event-hubs-quickstart-powershell#create-an-event-hubs-namespace +[quickstart_guide]: https://github.com/Azure/azure-sdk-for-net/blob/master/doc/mgmt_preview_quickstart.md +[schema_registry_client]: src/SchemaRegistryClient.cs +[azure_portal]: https://ms.portal.azure.com/ +[schema_properties]: src/SchemaProperties.cs +[azure_identity]: https://www.nuget.org/packages/Azure.Identity +[cla]: https://cla.microsoft.com +[code_of_conduct]: https://opensource.microsoft.com/codeofconduct/ +[code_of_conduct_faq]: https://opensource.microsoft.com/codeofconduct/faq/ +[email_opencode]: mailto:opencode@microsoft.com +[object_serializer]: https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/core/Azure.Core/src/Serialization/ObjectSerializer.cs +[schema_registry_avro_serializer]: src/SchemaRegistryAvroObjectSerializer.cs +[employee]: tests\Models\Employee.cs +[avro_csharp_documentation]: https://avro.apache.org/docs/current/api/csharp/html/index.html +[apache_avro_library]: https://www.nuget.org/packages/Apache.Avro/ +[generic_record]: https://avro.apache.org/docs/current/api/csharp/html/classAvro_1_1Generic_1_1GenericRecord.html +[specific_record]: https://avro.apache.org/docs/current/api/csharp/html/interfaceAvro_1_1Specific_1_1ISpecificRecord.html +[azure_sub]: https://azure.microsoft.com/free/ diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/api/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.netstandard2.0.cs b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/api/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.netstandard2.0.cs new file mode 100644 index 000000000000..338fd2b7eaeb --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/api/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.netstandard2.0.cs @@ -0,0 +1,16 @@ +namespace Microsoft.Azure.Data.SchemaRegistry.ApacheAvro +{ + public partial class SchemaRegistryAvroObjectSerializer : Azure.Core.Serialization.ObjectSerializer + { + public SchemaRegistryAvroObjectSerializer(Azure.Data.SchemaRegistry.SchemaRegistryClient client, string groupName, Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.SchemaRegistryAvroObjectSerializerOptions options = null) { } + public override object Deserialize(System.IO.Stream stream, System.Type returnType, System.Threading.CancellationToken cancellationToken) { throw null; } + public override System.Threading.Tasks.ValueTask DeserializeAsync(System.IO.Stream stream, System.Type returnType, System.Threading.CancellationToken cancellationToken) { throw null; } + public override void Serialize(System.IO.Stream stream, object value, System.Type inputType, System.Threading.CancellationToken cancellationToken) { } + public override System.Threading.Tasks.ValueTask SerializeAsync(System.IO.Stream stream, object value, System.Type inputType, System.Threading.CancellationToken cancellationToken) { throw null; } + } + public partial class SchemaRegistryAvroObjectSerializerOptions + { + public SchemaRegistryAvroObjectSerializerOptions() { } + public bool AutoRegisterSchemas { get { throw null; } set { } } + } +} diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/src/GlobalSuppressions.cs b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/src/GlobalSuppressions.cs new file mode 100644 index 000000000000..46d6862a442c --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/src/GlobalSuppressions.cs @@ -0,0 +1,11 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// This file is used by Code Analysis to maintain SuppressMessage +// attributes that are applied to this project. +// Project-level suppressions either have no target or are given +// a specific target and scoped to a namespace, type, member, etc. + +using System.Diagnostics.CodeAnalysis; + +[assembly: SuppressMessage("Usage", "AZC0001:Use one of the following pre-approved namespace groups (https://azure.github.io/azure-sdk/registered_namespaces.html): Azure.AI, Azure.Analytics, Azure.Data, Azure.DigitalTwins, Azure.Iot, Azure.Learn, Azure.Media, Azure.Management, Azure.Messaging, Azure.Search, Azure.Security, Azure.Storage, Azure.Template, Azure.Identity, Microsoft.Extensions.Azure", Justification = "", Scope = "namespace", Target = "~N:Microsoft.Azure.Data.SchemaRegistry.ApacheAvro")] diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/src/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.csproj b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/src/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.csproj new file mode 100644 index 000000000000..1b0d2d333c53 --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/src/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.csproj @@ -0,0 +1,28 @@ + + + Microsoft Azure Schema Registry Apache Avro SDK + Microsoft Azure Schema Registry Apache Avro SDK + 1.0.0-beta.1 + Azure;Schema Registry;SchemaRegistry;.NET;Data;Apache;Avro;$(PackageCommonTags) + $(RequiredTargetFrameworks) + + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/src/SchemaRegistryAvroObjectSerializer.cs b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/src/SchemaRegistryAvroObjectSerializer.cs new file mode 100644 index 000000000000..45dd707a8784 --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/src/SchemaRegistryAvroObjectSerializer.cs @@ -0,0 +1,232 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Avro; +using Avro.Generic; +using Avro.IO; +using Avro.Specific; +using Azure.Core; +using Azure.Core.Serialization; +using Azure.Data.SchemaRegistry; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading; +using System.Threading.Tasks; + +namespace Microsoft.Azure.Data.SchemaRegistry.ApacheAvro +{ + /// + /// A implementation that uses for Avro serialization/deserialization. + /// + public class SchemaRegistryAvroObjectSerializer : ObjectSerializer + { + private readonly SchemaRegistryClient _client; + private readonly string _groupName; + private readonly SchemaRegistryAvroObjectSerializerOptions _options; + + /// + /// Initializes new instance of . + /// + public SchemaRegistryAvroObjectSerializer(SchemaRegistryClient client, string groupName, SchemaRegistryAvroObjectSerializerOptions options = null) + { + _client = client ?? throw new ArgumentNullException(nameof(client)); + _groupName = groupName ?? throw new ArgumentNullException(nameof(groupName)); + _options = options; + } + + private static readonly byte[] EmptyRecordFormatIndicator = { 0, 0, 0, 0 }; + private static readonly Encoding Utf8Encoding = new UTF8Encoding(false); + + private const int RecordFormatIndicatorLength = 4; + private const int SchemaIdLength = 32; + private const int PayloadStartPosition = RecordFormatIndicatorLength + SchemaIdLength; + private readonly Dictionary _cachedSchemas = new Dictionary(); + + private enum SupportedType + { + SpecificRecord, + GenericRecord + } + + private static SupportedType GetSupportedTypeOrThrow(Type type) + { + if (typeof(ISpecificRecord).IsAssignableFrom(type)) + { + return SupportedType.SpecificRecord; + } + + if (typeof(GenericRecord).IsAssignableFrom(type)) + { + return SupportedType.GenericRecord; + } + + throw new ArgumentException($"Type {type.Name} is not supported for serialization operations."); + } + + private string GetSchemaId(Schema schema, CancellationToken cancellationToken) + { + var schemaProperties = _options.AutoRegisterSchemas + ? _client.RegisterSchema(_groupName, schema.Fullname, SerializationType.Avro, schema.ToString(), cancellationToken) + : _client.GetSchemaId(_groupName, schema.Fullname, SerializationType.Avro, schema.ToString(), cancellationToken); + return schemaProperties.Value.Id; + } + + private async Task GetSchemaIdAsync(Schema schema, CancellationToken cancellationToken) + { + var schemaProperties = await (_options.AutoRegisterSchemas + ? _client.RegisterSchemaAsync(_groupName, schema.Fullname, SerializationType.Avro, schema.ToString(), cancellationToken) + : _client.GetSchemaIdAsync(_groupName, schema.Fullname, SerializationType.Avro, schema.ToString(), cancellationToken)) + .ConfigureAwait(false); + return schemaProperties.Value.Id; + } + + private static DatumWriter GetWriterAndSchema(object value, SupportedType supportedType, out Schema schema) + { + switch (supportedType) + { + case SupportedType.SpecificRecord: + schema = ((ISpecificRecord)value).Schema; + return new SpecificDatumWriter(schema); + case SupportedType.GenericRecord: + schema = ((GenericRecord)value).Schema; + return new GenericDatumWriter(schema); + default: + throw new ArgumentException($"Invalid supported type value: {supportedType}"); + } + } + + /// + public override void Serialize(Stream stream, object value, Type inputType, CancellationToken cancellationToken) + { + Argument.AssertNotNull(stream, nameof(stream)); + Argument.AssertNotNull(value, nameof(value)); + Argument.AssertNotNull(inputType, nameof(inputType)); + + var supportedType = GetSupportedTypeOrThrow(inputType); + var writer = GetWriterAndSchema(value, supportedType, out var schema); + var schemaId = GetSchemaId(schema, cancellationToken); + + var binaryEncoder = new BinaryEncoder(stream); + stream.Write(EmptyRecordFormatIndicator, 0, RecordFormatIndicatorLength); + stream.Write(Utf8Encoding.GetBytes(schemaId), 0, SchemaIdLength); + writer.Write(value, binaryEncoder); + binaryEncoder.Flush(); + } + + /// + public override async ValueTask SerializeAsync(Stream stream, object value, Type inputType, CancellationToken cancellationToken) + { + Argument.AssertNotNull(stream, nameof(stream)); + Argument.AssertNotNull(value, nameof(value)); + Argument.AssertNotNull(inputType, nameof(inputType)); + + var supportedType = GetSupportedTypeOrThrow(inputType); + var writer = GetWriterAndSchema(value, supportedType, out var schema); + var schemaId = await GetSchemaIdAsync(schema, cancellationToken).ConfigureAwait(false); + + var binaryEncoder = new BinaryEncoder(stream); + await stream.WriteAsync(EmptyRecordFormatIndicator, 0, RecordFormatIndicatorLength, cancellationToken).ConfigureAwait(false); + await stream.WriteAsync(Utf8Encoding.GetBytes(schemaId), 0, SchemaIdLength, cancellationToken).ConfigureAwait(false); + writer.Write(value, binaryEncoder); + binaryEncoder.Flush(); + } + + private Schema GetSchemaById(string schemaId, CancellationToken cancellationToken) + { + if (_cachedSchemas.TryGetValue(schemaId, out var cachedSchema)) + { + return cachedSchema; + } + + var schemaContent = _client.GetSchema(schemaId, cancellationToken).Value.Content; + var schema = Schema.Parse(schemaContent); + _cachedSchemas.Add(schemaId, schema); + return schema; + } + + private async Task GetSchemaByIdAsync(string schemaId, CancellationToken cancellationToken) + { + if (_cachedSchemas.TryGetValue(schemaId, out var cachedSchema)) + { + return cachedSchema; + } + + var schemaContent = (await _client.GetSchemaAsync(schemaId, cancellationToken).ConfigureAwait(false)).Value.Content; + var schema = Schema.Parse(schemaContent); + _cachedSchemas.Add(schemaId, schema); + return schema; + } + + private static DatumReader GetReader(Schema schema, SupportedType supportedType) + { + switch (supportedType) + { + case SupportedType.SpecificRecord: + return new SpecificDatumReader(schema, schema); + case SupportedType.GenericRecord: + return new GenericDatumReader(schema, schema); + default: + throw new ArgumentException($"Invalid supported type value: {supportedType}"); + } + } + + private static ReadOnlyMemory CopyToReadOnlyMemory(Stream stream) + { + using var tempMemoryStream = new MemoryStream(); + stream.CopyTo(tempMemoryStream); + return new ReadOnlyMemory(tempMemoryStream.ToArray()); + } + + private static void ValidateRecordFormatIdentifier(ReadOnlyMemory message) + { + var recordFormatIdentifier = message.Slice(0, RecordFormatIndicatorLength).ToArray(); + if (!recordFormatIdentifier.SequenceEqual(EmptyRecordFormatIndicator)) + { + throw new InvalidDataContractException( + $"The record format identifier ({recordFormatIdentifier[0]:X} {recordFormatIdentifier[1]:X} {recordFormatIdentifier[2]:X} {recordFormatIdentifier[3]:X}) for the message is invalid."); + } + } + + /// + public override object Deserialize(Stream stream, Type returnType, CancellationToken cancellationToken) + { + Argument.AssertNotNull(stream, nameof(stream)); + Argument.AssertNotNull(returnType, nameof(returnType)); + + var supportedType = GetSupportedTypeOrThrow(returnType); + var message = CopyToReadOnlyMemory(stream); + ValidateRecordFormatIdentifier(message); + var schemaIdBytes = message.Slice(RecordFormatIndicatorLength, SchemaIdLength).ToArray(); + var schemaId = Utf8Encoding.GetString(schemaIdBytes); + var schema = GetSchemaById(schemaId, cancellationToken); + using var valueStream = new MemoryStream(message.Slice(PayloadStartPosition, message.Length - PayloadStartPosition).ToArray()); + + var binaryDecoder = new BinaryDecoder(valueStream); + var reader = GetReader(schema, supportedType); + return reader.Read(reuse: null, binaryDecoder); + } + + /// + public override async ValueTask DeserializeAsync(Stream stream, Type returnType, CancellationToken cancellationToken) + { + Argument.AssertNotNull(stream, nameof(stream)); + Argument.AssertNotNull(returnType, nameof(returnType)); + + var supportedType = GetSupportedTypeOrThrow(returnType); + var message = CopyToReadOnlyMemory(stream); + ValidateRecordFormatIdentifier(message); + var schemaIdBytes = message.Slice(RecordFormatIndicatorLength, SchemaIdLength).ToArray(); + var schemaId = Utf8Encoding.GetString(schemaIdBytes); + var schema = await GetSchemaByIdAsync(schemaId, cancellationToken).ConfigureAwait(false); + using var valueStream = new MemoryStream(message.Slice(PayloadStartPosition, message.Length - PayloadStartPosition).ToArray()); + + var binaryDecoder = new BinaryDecoder(valueStream); + var reader = GetReader(schema, supportedType); + return reader.Read(reuse: null, binaryDecoder); + } + } +} diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/src/SchemaRegistryAvroObjectSerializerOptions.cs b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/src/SchemaRegistryAvroObjectSerializerOptions.cs new file mode 100644 index 000000000000..6942dcaadcbe --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/src/SchemaRegistryAvroObjectSerializerOptions.cs @@ -0,0 +1,19 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.Azure.Data.SchemaRegistry.ApacheAvro +{ + /// + /// Options for . + /// + public class SchemaRegistryAvroObjectSerializerOptions + { + /// + /// Gets or sets the automatic registration of schemas flag. + /// When true, automatically registers the provided schema with the SchemaRegistry during serialization. + /// When false, the schema is only acquired from the SchemaRegistry. + /// The default is false. + /// + public bool AutoRegisterSchemas { get; set; } + } +} diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.Tests.csproj b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.Tests.csproj new file mode 100644 index 000000000000..dd8c8f45a807 --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.Tests.csproj @@ -0,0 +1,26 @@ + + + $(RequiredTargetFrameworks) + + + TRACE + + + + + + + + + + + + + + + + + + + + diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/Models/Employee.cs b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/Models/Employee.cs new file mode 100644 index 000000000000..1294eca5c59b --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/Models/Employee.cs @@ -0,0 +1,70 @@ +// ------------------------------------------------------------------------------ +// +// Generated by ApacheAvroTestTool, version 1.10.0.0 +// Changes to this file may cause incorrect behavior and will be lost if code +// is regenerated +// +// ------------------------------------------------------------------------------ +namespace TestSchema +{ + using System; + using System.Collections.Generic; + using System.Text; + using Avro; + using Avro.Specific; + + public partial class Employee : ISpecificRecord + { + public static Schema _SCHEMA = Avro.Schema.Parse("{\"type\":\"record\",\"name\":\"Employee\",\"namespace\":\"TestSchema\",\"fields\":[{\"name\":\"Na" + + "me\",\"type\":\"string\"},{\"name\":\"Age\",\"type\":\"int\"}]}"); + private string _Name; + private int _Age; + public virtual Schema Schema + { + get + { + return Employee._SCHEMA; + } + } + public string Name + { + get + { + return this._Name; + } + set + { + this._Name = value; + } + } + public int Age + { + get + { + return this._Age; + } + set + { + this._Age = value; + } + } + public virtual object Get(int fieldPos) + { + switch (fieldPos) + { + case 0: return this.Name; + case 1: return this.Age; + default: throw new AvroRuntimeException("Bad index " + fieldPos + " in Get()"); + }; + } + public virtual void Put(int fieldPos, object fieldValue) + { + switch (fieldPos) + { + case 0: this.Name = (System.String)fieldValue; break; + case 1: this.Age = (System.Int32)fieldValue; break; + default: throw new AvroRuntimeException("Bad index " + fieldPos + " in Put()"); + }; + } + } +} diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/Samples/Sample01_ReadmeSnippets.cs b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/Samples/Sample01_ReadmeSnippets.cs new file mode 100644 index 000000000000..3daf069bca29 --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/Samples/Sample01_ReadmeSnippets.cs @@ -0,0 +1,63 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.TestFramework; +using Azure.Data.SchemaRegistry; +using Azure.Identity; +using NUnit.Framework; +using System.IO; +using System.Threading; +using TestSchema; + +namespace Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.Tests.Samples +{ + public class Sample01_ReadmeSnippets : SamplesBase + { + [Ignore("Only verifying that the sample builds")] + [Test] + public void CreateSchemaRegistryClient() + { + #region Snippet:CreateSchemaRegistryClient + string endpoint = ""; + var credentials = new ClientSecretCredential( + "", + "", + "" + ); + var client = new SchemaRegistryClient(endpoint, credentials); + #endregion + } + + [Ignore("Only verifying that the sample builds")] + [Test] + public void Serialize() + { + var client = new SchemaRegistryClient(TestEnvironment.SchemaRegistryUri, TestEnvironment.Credential); + + #region Snippet:Serialize + var employee = new Employee { Age = 42, Name = "John Doe" }; + string groupName = ""; + + using var memoryStream = new MemoryStream(); + var serializer = new SchemaRegistryAvroObjectSerializer(client, groupName, new SchemaRegistryAvroObjectSerializerOptions { AutoRegisterSchemas = true }); + serializer.Serialize(memoryStream, employee, typeof(Employee), CancellationToken.None); + #endregion + } + + [Ignore("Only verifying that the sample builds")] + [Test] + public void Deserialize() + { + var client = new SchemaRegistryClient(TestEnvironment.SchemaRegistryUri, TestEnvironment.Credential); + using var memoryStream = new MemoryStream(); + + #region Snippet:Deserialize + string groupName = ""; + + var serializer = new SchemaRegistryAvroObjectSerializer(client, groupName, new SchemaRegistryAvroObjectSerializerOptions { AutoRegisterSchemas = true }); + memoryStream.Position = 0; + Employee employee = (Employee)serializer.Deserialize(memoryStream, typeof(Employee), CancellationToken.None); + #endregion + } + } +} diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SchemaRegistryAvroObjectSerializerLiveTest.cs b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SchemaRegistryAvroObjectSerializerLiveTest.cs new file mode 100644 index 000000000000..5007c3947661 --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SchemaRegistryAvroObjectSerializerLiveTest.cs @@ -0,0 +1,96 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Avro; +using Avro.Generic; +using Azure.Core.TestFramework; +using Azure.Data.SchemaRegistry; +using NUnit.Framework; +using System; +using System.IO; +using System.Threading; +using System.Threading.Tasks; +using TestSchema; + +namespace Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.Tests +{ + public class SchemaRegistryAvroObjectSerializerLiveTest : RecordedTestBase + { + public SchemaRegistryAvroObjectSerializerLiveTest(bool isAsync) : base(isAsync) + { + TestDiagnostics = false; + } + + private SchemaRegistryClient CreateClient() => + InstrumentClient(new SchemaRegistryClient( + TestEnvironment.SchemaRegistryUri, + TestEnvironment.Credential, + Recording.InstrumentClientOptions(new SchemaRegistryClientOptions()) + )); + + [Test] + public async Task CanSerializeAndDeserialize() + { + var client = CreateClient(); + var groupName = "miyanni_srgroup"; + var employee = new Employee { Age = 42, Name = "Caketown" }; + + using var memoryStream = new MemoryStream(); + var serializer = new SchemaRegistryAvroObjectSerializer(client, groupName, new SchemaRegistryAvroObjectSerializerOptions { AutoRegisterSchemas = true }); + await serializer.SerializeAsync(memoryStream, employee, typeof(Employee), CancellationToken.None); + + memoryStream.Position = 0; + var deserializedObject = await serializer.DeserializeAsync(memoryStream, typeof(Employee), CancellationToken.None); + var readEmployee = deserializedObject as Employee; + Assert.IsNotNull(readEmployee); + Assert.AreEqual("Caketown", readEmployee.Name); + Assert.AreEqual(42, readEmployee.Age); + } + + [Test] + public async Task CanSerializeAndDeserializeGenericRecord() + { + var client = CreateClient(); + var groupName = "miyanni_srgroup"; + var record = new GenericRecord((RecordSchema)Employee._SCHEMA); + record.Add("Name", "Caketown"); + record.Add("Age", 42); + + using var memoryStream = new MemoryStream(); + var serializer = new SchemaRegistryAvroObjectSerializer(client, groupName, new SchemaRegistryAvroObjectSerializerOptions { AutoRegisterSchemas = true }); + await serializer.SerializeAsync(memoryStream, record, typeof(GenericRecord), CancellationToken.None); + + memoryStream.Position = 0; + var deserializedObject = await serializer.DeserializeAsync(memoryStream, typeof(GenericRecord), CancellationToken.None); + var readRecord = deserializedObject as GenericRecord; + Assert.IsNotNull(readRecord); + Assert.AreEqual("Caketown", readRecord.GetValue(0)); + Assert.AreEqual(42, readRecord.GetValue(1)); + } + + [Test] + public async Task CannotSerializeUnsupportedType() + { + var client = CreateClient(); + var groupName = "miyanni_srgroup"; + var timeZoneInfo = TimeZoneInfo.Utc; + + using var memoryStream = new MemoryStream(); + var serializer = new SchemaRegistryAvroObjectSerializer(client, groupName, new SchemaRegistryAvroObjectSerializerOptions { AutoRegisterSchemas = true }); + Assert.ThrowsAsync(async () => await serializer.SerializeAsync(memoryStream, timeZoneInfo, typeof(TimeZoneInfo), CancellationToken.None)); + await Task.CompletedTask; + } + + [Test] + public async Task CannotDeserializeUnsupportedType() + { + var client = CreateClient(); + var groupName = "miyanni_srgroup"; + + using var memoryStream = new MemoryStream(); + var serializer = new SchemaRegistryAvroObjectSerializer(client, groupName, new SchemaRegistryAvroObjectSerializerOptions { AutoRegisterSchemas = true }); + Assert.ThrowsAsync(async () => await serializer.DeserializeAsync(memoryStream, typeof(TimeZoneInfo), CancellationToken.None)); + await Task.CompletedTask; + } + } +} diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SchemaRegistryClientTestEnvironment.cs b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SchemaRegistryClientTestEnvironment.cs new file mode 100644 index 000000000000..fe811ae8ca4f --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SchemaRegistryClientTestEnvironment.cs @@ -0,0 +1,16 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core.TestFramework; + +namespace Microsoft.Azure.Data.SchemaRegistry.ApacheAvro.Tests +{ + public class SchemaRegistryClientTestEnvironment : TestEnvironment + { + public SchemaRegistryClientTestEnvironment() : base("schemaregistry") + { + } + + public string SchemaRegistryUri => GetRecordedVariable("SCHEMAREGISTRY_URL"); + } +} diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CanSerializeAndDeserialize.json b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CanSerializeAndDeserialize.json new file mode 100644 index 000000000000..b2bc10d23865 --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CanSerializeAndDeserialize.json @@ -0,0 +1,73 @@ +{ + "Entries": [ + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee?api-version=2017-04", + "RequestMethod": "PUT", + "RequestHeaders": { + "Accept": "application/json", + "Authorization": "Sanitized", + "Content-Length": "283", + "Content-Type": "application/json", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-alpha.20200903.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "868a705e78e1eacc39ee20f0603590e1", + "x-ms-return-client-request-id": "true", + "X-Schema-Type": "avro" + }, + "RequestBody": "{\u0022type\u0022:\u0022record\u0022,\u0022name\u0022:\u0022Employee\u0022,\u0022namespace\u0022:\u0022TestSchema\u0022,\u0022fields\u0022:[{\u0022name\u0022:\u0022Name\u0022,\u0022type\u0022:\u0022string\u0022},{\u0022name\u0022:\u0022Age\u0022,\u0022type\u0022:\u0022int\u0022}]}", + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 04 Sep 2020 04:17:14 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "34fa96c2ac67489da0df6d4a245265a7", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/34fa96c2ac67489da0df6d4a245265a7?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions?api-version=2017-04" + }, + "ResponseBody": { + "id": "34fa96c2ac67489da0df6d4a245265a7" + } + }, + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/getSchemaById/34fa96c2ac67489da0df6d4a245265a7?api-version=2017-04", + "RequestMethod": "GET", + "RequestHeaders": { + "Accept": "application/json", + "Authorization": "Sanitized", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-alpha.20200903.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "fce63c5a3b2209ffbf3241fcd47809a7", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 04 Sep 2020 04:17:14 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "34fa96c2ac67489da0df6d4a245265a7", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/34fa96c2ac67489da0df6d4a245265a7?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions?api-version=2017-04" + }, + "ResponseBody": "{\u0022type\u0022:\u0022record\u0022,\u0022name\u0022:\u0022Employee\u0022,\u0022namespace\u0022:\u0022TestSchema\u0022,\u0022fields\u0022:[{\u0022name\u0022:\u0022Name\u0022,\u0022type\u0022:\u0022string\u0022},{\u0022name\u0022:\u0022Age\u0022,\u0022type\u0022:\u0022int\u0022}]}" + } + ], + "Variables": { + "RandomSeed": "720748394", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CanSerializeAndDeserializeAsync.json b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CanSerializeAndDeserializeAsync.json new file mode 100644 index 000000000000..ecba1315c80c --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CanSerializeAndDeserializeAsync.json @@ -0,0 +1,73 @@ +{ + "Entries": [ + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee?api-version=2017-04", + "RequestMethod": "PUT", + "RequestHeaders": { + "Accept": "application/json", + "Authorization": "Sanitized", + "Content-Length": "283", + "Content-Type": "application/json", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-alpha.20200903.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "9194a80ecb3e28d6d988eee20cb5ed95", + "x-ms-return-client-request-id": "true", + "X-Schema-Type": "avro" + }, + "RequestBody": "{\u0022type\u0022:\u0022record\u0022,\u0022name\u0022:\u0022Employee\u0022,\u0022namespace\u0022:\u0022TestSchema\u0022,\u0022fields\u0022:[{\u0022name\u0022:\u0022Name\u0022,\u0022type\u0022:\u0022string\u0022},{\u0022name\u0022:\u0022Age\u0022,\u0022type\u0022:\u0022int\u0022}]}", + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 04 Sep 2020 04:17:17 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "34fa96c2ac67489da0df6d4a245265a7", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/34fa96c2ac67489da0df6d4a245265a7?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions?api-version=2017-04" + }, + "ResponseBody": { + "id": "34fa96c2ac67489da0df6d4a245265a7" + } + }, + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/getSchemaById/34fa96c2ac67489da0df6d4a245265a7?api-version=2017-04", + "RequestMethod": "GET", + "RequestHeaders": { + "Accept": "application/json", + "Authorization": "Sanitized", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-alpha.20200903.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "bbd7ee0ffba0cfc5c3b161ee35b7e4ec", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 04 Sep 2020 04:17:17 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "34fa96c2ac67489da0df6d4a245265a7", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/34fa96c2ac67489da0df6d4a245265a7?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions?api-version=2017-04" + }, + "ResponseBody": "{\u0022type\u0022:\u0022record\u0022,\u0022name\u0022:\u0022Employee\u0022,\u0022namespace\u0022:\u0022TestSchema\u0022,\u0022fields\u0022:[{\u0022name\u0022:\u0022Name\u0022,\u0022type\u0022:\u0022string\u0022},{\u0022name\u0022:\u0022Age\u0022,\u0022type\u0022:\u0022int\u0022}]}" + } + ], + "Variables": { + "RandomSeed": "1605448636", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CanSerializeAndDeserializeGenericRecord.json b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CanSerializeAndDeserializeGenericRecord.json new file mode 100644 index 000000000000..b957cf8c672e --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CanSerializeAndDeserializeGenericRecord.json @@ -0,0 +1,73 @@ +{ + "Entries": [ + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee?api-version=2017-04", + "RequestMethod": "PUT", + "RequestHeaders": { + "Accept": "application/json", + "Authorization": "Sanitized", + "Content-Length": "283", + "Content-Type": "application/json", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-alpha.20200903.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "62af9d4468e15d9ba239fef902b0ae57", + "x-ms-return-client-request-id": "true", + "X-Schema-Type": "avro" + }, + "RequestBody": "{\u0022type\u0022:\u0022record\u0022,\u0022name\u0022:\u0022Employee\u0022,\u0022namespace\u0022:\u0022TestSchema\u0022,\u0022fields\u0022:[{\u0022name\u0022:\u0022Name\u0022,\u0022type\u0022:\u0022string\u0022},{\u0022name\u0022:\u0022Age\u0022,\u0022type\u0022:\u0022int\u0022}]}", + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 04 Sep 2020 04:17:16 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "34fa96c2ac67489da0df6d4a245265a7", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/34fa96c2ac67489da0df6d4a245265a7?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions?api-version=2017-04" + }, + "ResponseBody": { + "id": "34fa96c2ac67489da0df6d4a245265a7" + } + }, + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/getSchemaById/34fa96c2ac67489da0df6d4a245265a7?api-version=2017-04", + "RequestMethod": "GET", + "RequestHeaders": { + "Accept": "application/json", + "Authorization": "Sanitized", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-alpha.20200903.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "28b59f1d4676f2b691ef41bd27d253ab", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 04 Sep 2020 04:17:16 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "34fa96c2ac67489da0df6d4a245265a7", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/34fa96c2ac67489da0df6d4a245265a7?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions?api-version=2017-04" + }, + "ResponseBody": "{\u0022type\u0022:\u0022record\u0022,\u0022name\u0022:\u0022Employee\u0022,\u0022namespace\u0022:\u0022TestSchema\u0022,\u0022fields\u0022:[{\u0022name\u0022:\u0022Name\u0022,\u0022type\u0022:\u0022string\u0022},{\u0022name\u0022:\u0022Age\u0022,\u0022type\u0022:\u0022int\u0022}]}" + } + ], + "Variables": { + "RandomSeed": "993263430", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CanSerializeAndDeserializeGenericRecordAsync.json b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CanSerializeAndDeserializeGenericRecordAsync.json new file mode 100644 index 000000000000..4976695a2082 --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CanSerializeAndDeserializeGenericRecordAsync.json @@ -0,0 +1,73 @@ +{ + "Entries": [ + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee?api-version=2017-04", + "RequestMethod": "PUT", + "RequestHeaders": { + "Accept": "application/json", + "Authorization": "Sanitized", + "Content-Length": "283", + "Content-Type": "application/json", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-alpha.20200903.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "29665161b7b0e47e8e47525f0cf322fd", + "x-ms-return-client-request-id": "true", + "X-Schema-Type": "avro" + }, + "RequestBody": "{\u0022type\u0022:\u0022record\u0022,\u0022name\u0022:\u0022Employee\u0022,\u0022namespace\u0022:\u0022TestSchema\u0022,\u0022fields\u0022:[{\u0022name\u0022:\u0022Name\u0022,\u0022type\u0022:\u0022string\u0022},{\u0022name\u0022:\u0022Age\u0022,\u0022type\u0022:\u0022int\u0022}]}", + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 04 Sep 2020 04:17:18 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "34fa96c2ac67489da0df6d4a245265a7", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/34fa96c2ac67489da0df6d4a245265a7?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions?api-version=2017-04" + }, + "ResponseBody": { + "id": "34fa96c2ac67489da0df6d4a245265a7" + } + }, + { + "RequestUri": "https://sr-playground.servicebus.windows.net/$schemagroups/getSchemaById/34fa96c2ac67489da0df6d4a245265a7?api-version=2017-04", + "RequestMethod": "GET", + "RequestHeaders": { + "Accept": "application/json", + "Authorization": "Sanitized", + "User-Agent": [ + "azsdk-net-Data.SchemaRegistry/1.0.0-alpha.20200903.1", + "(.NET Core 4.6.28801.04; Microsoft Windows 10.0.19041 )" + ], + "x-ms-client-request-id": "6a2d0bdc0bba5cc6479100de284925b6", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 200, + "ResponseHeaders": { + "Content-Type": "application/json", + "Date": "Fri, 04 Sep 2020 04:17:18 GMT", + "Location": "https://sr-playground.servicebus.windows.net/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions/1?api-version=2017-04", + "Server": "Microsoft-HTTPAPI/2.0", + "Strict-Transport-Security": "max-age=31536000", + "Transfer-Encoding": "chunked", + "X-Schema-Id": "34fa96c2ac67489da0df6d4a245265a7", + "X-Schema-Id-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/getschemabyid/34fa96c2ac67489da0df6d4a245265a7?api-version=2017-04", + "X-Schema-Type": "Avro", + "X-Schema-Version": "1", + "X-Schema-Versions-Location": "https://sr-playground.servicebus.windows.net:443/$schemagroups/miyanni_srgroup/schemas/TestSchema.Employee/versions?api-version=2017-04" + }, + "ResponseBody": "{\u0022type\u0022:\u0022record\u0022,\u0022name\u0022:\u0022Employee\u0022,\u0022namespace\u0022:\u0022TestSchema\u0022,\u0022fields\u0022:[{\u0022name\u0022:\u0022Name\u0022,\u0022type\u0022:\u0022string\u0022},{\u0022name\u0022:\u0022Age\u0022,\u0022type\u0022:\u0022int\u0022}]}" + } + ], + "Variables": { + "RandomSeed": "1337710688", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CannotDeserializeUnsupportedType.json b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CannotDeserializeUnsupportedType.json new file mode 100644 index 000000000000..d46a3d442f04 --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CannotDeserializeUnsupportedType.json @@ -0,0 +1,7 @@ +{ + "Entries": [], + "Variables": { + "RandomSeed": "838895729", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CannotDeserializeUnsupportedTypeAsync.json b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CannotDeserializeUnsupportedTypeAsync.json new file mode 100644 index 000000000000..7f4c2ab72703 --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CannotDeserializeUnsupportedTypeAsync.json @@ -0,0 +1,7 @@ +{ + "Entries": [], + "Variables": { + "RandomSeed": "592153647", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CannotSerializeUnsupportedType.json b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CannotSerializeUnsupportedType.json new file mode 100644 index 000000000000..8686dacebc09 --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CannotSerializeUnsupportedType.json @@ -0,0 +1,7 @@ +{ + "Entries": [], + "Variables": { + "RandomSeed": "977456895", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CannotSerializeUnsupportedTypeAsync.json b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CannotSerializeUnsupportedTypeAsync.json new file mode 100644 index 000000000000..720db6220d8f --- /dev/null +++ b/sdk/schemaregistry/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro/tests/SessionRecords/SchemaRegistryAvroObjectSerializerLiveTest/CannotSerializeUnsupportedTypeAsync.json @@ -0,0 +1,7 @@ +{ + "Entries": [], + "Variables": { + "RandomSeed": "504944443", + "SCHEMAREGISTRY_URL": "sr-playground.servicebus.windows.net" + } +} \ No newline at end of file diff --git a/sdk/schemaregistry/ci.yml b/sdk/schemaregistry/ci.yml new file mode 100644 index 000000000000..5697f59839ad --- /dev/null +++ b/sdk/schemaregistry/ci.yml @@ -0,0 +1,33 @@ +# NOTE: Please refer to https://aka.ms/azsdk/engsys/ci-yaml before editing this file. +trigger: + branches: + include: + - master + - hotfix/* + - release/* + paths: + include: + - sdk/schemaregistry/ + +pr: + branches: + include: + - master + - feature/* + - hotfix/* + - release/* + paths: + include: + - sdk/schemaregistry/ + - eng/common/ + +extends: + template: ../../eng/pipelines/templates/stages/archetype-sdk-client.yml + parameters: + ServiceDirectory: schemaregistry + ArtifactName: packages + Artifacts: + - name: Azure.Data.SchemaRegistry + safeName: AzureDataSchemaRegistry + - name: Microsoft.Azure.Data.SchemaRegistry.ApacheAvro + safeName: MicrosoftAzureDataSchemaRegistryApacheAvro \ No newline at end of file diff --git a/sdk/schemaregistry/tests.yml b/sdk/schemaregistry/tests.yml new file mode 100644 index 000000000000..379b7aeb30ba --- /dev/null +++ b/sdk/schemaregistry/tests.yml @@ -0,0 +1,6 @@ +trigger: none + +extends: + template: ../../eng/pipelines/templates/jobs/archetype-sdk-tests.yml + parameters: + ServiceDirectory: schemaregistry \ No newline at end of file