Skip to content

Commit f9ab46e

Browse files
authored
[Elastic] Fix for issue Azure#50974 (Azure#51122)
1 parent 5d03793 commit f9ab46e

File tree

4 files changed

+217
-18
lines changed

4 files changed

+217
-18
lines changed

sdk/elastic/Azure.ResourceManager.Elastic/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
### Bugs Fixed
1010

11+
- Fixed serialization issue in `ElasticCloudDeployment` where `ElasticsearchServiceUri`, `KibanaServiceUri`, and `KibanaSsoUri` properties would throw `InvalidOperationException` when containing relative URIs. Added custom serialization hooks to handle both absolute and relative URIs by using `OriginalString` for relative URIs instead of `AbsoluteUri`. This resolves issue #50974.
12+
1113
### Other Changes
1214

1315
## 1.0.0 (2024-12-26)
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
#nullable disable
5+
6+
using System;
7+
using System.ClientModel.Primitives;
8+
using System.Runtime.CompilerServices;
9+
using System.Text.Json;
10+
using Azure.Core;
11+
12+
namespace Azure.ResourceManager.Elastic.Models
13+
{
14+
// This is the fix for issue #50974
15+
[CodeGenSerialization(nameof(ElasticsearchServiceUri), SerializationValueHook = nameof(WriteElasticsearchServiceUri), DeserializationValueHook = nameof(DeserializeElasticsearchServiceUri))]
16+
[CodeGenSerialization(nameof(KibanaServiceUri), SerializationValueHook = nameof(WriteKibanaServiceUri), DeserializationValueHook = nameof(DeserializeKibanaServiceUri))]
17+
[CodeGenSerialization(nameof(KibanaSsoUri), SerializationValueHook = nameof(WriteKibanaSsoUri), DeserializationValueHook = nameof(DeserializeKibanaSsoUri))]
18+
public partial class ElasticCloudDeployment
19+
{
20+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
21+
internal void WriteElasticsearchServiceUri(Utf8JsonWriter writer, ModelReaderWriterOptions options)
22+
{
23+
WriteUri(writer, ElasticsearchServiceUri);
24+
}
25+
26+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
27+
private static void DeserializeElasticsearchServiceUri(JsonProperty property, ref Uri elasticsearchServiceUrl)
28+
{
29+
DeserializeUri(property, ref elasticsearchServiceUrl);
30+
}
31+
32+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
33+
internal void WriteKibanaServiceUri(Utf8JsonWriter writer, ModelReaderWriterOptions options)
34+
{
35+
WriteUri(writer, KibanaServiceUri);
36+
}
37+
38+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
39+
private static void DeserializeKibanaServiceUri(JsonProperty property, ref Uri kibanaServiceUrl)
40+
{
41+
DeserializeUri(property, ref kibanaServiceUrl);
42+
}
43+
44+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
45+
internal void WriteKibanaSsoUri(Utf8JsonWriter writer, ModelReaderWriterOptions options)
46+
{
47+
WriteUri(writer, KibanaSsoUri);
48+
}
49+
50+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
51+
private static void DeserializeKibanaSsoUri(JsonProperty property, ref Uri kibanaSsoUrl)
52+
{
53+
DeserializeUri(property, ref kibanaSsoUrl);
54+
}
55+
56+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
57+
private static void WriteUri(Utf8JsonWriter writer, Uri uri)
58+
{
59+
writer.WriteStringValue(uri.IsAbsoluteUri ? uri.AbsoluteUri : uri.OriginalString);
60+
}
61+
62+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
63+
private static void DeserializeUri(JsonProperty property, ref Uri uri)
64+
{
65+
if (property.Value.ValueKind != JsonValueKind.Null)
66+
{
67+
var uriString = property.Value.GetString();
68+
uri = Uri.TryCreate(uriString, UriKind.Absolute, out var absoluteUri)
69+
? absoluteUri
70+
: new Uri(uriString, UriKind.Relative);
71+
}
72+
}
73+
}
74+
}

sdk/elastic/Azure.ResourceManager.Elastic/src/Generated/Models/ElasticCloudDeployment.Serialization.cs

Lines changed: 6 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.ClientModel.Primitives;
6+
using System.Collections.Generic;
7+
using System.Text.Json;
8+
using Azure.ResourceManager.Elastic.Models;
9+
using NUnit.Framework;
10+
11+
namespace Azure.ResourceManager.Elastic.Tests
12+
{
13+
/// <summary>
14+
/// Regression tests for ElasticCloudDeployment custom serialization fixes for issue #50974
15+
/// </summary>
16+
public class ElasticCloudDeploymentRegressionTests
17+
{
18+
[Test]
19+
public void SerializeAndDeserialize_AllUriProperties_WithAbsoluteUris()
20+
{
21+
// Arrange
22+
var elasticsearchServiceUri = new Uri("https://elasticsearch.example.com:9200");
23+
var kibanaServiceUri = new Uri("https://kibana.example.com:5601");
24+
var kibanaSsoUri = new Uri("https://kibana.example.com:5601/sso");
25+
26+
var deployment = new ElasticCloudDeployment(
27+
name: "test-deployment",
28+
deploymentId: "dep-123",
29+
azureSubscriptionId: "sub-456",
30+
elasticsearchRegion: "eastus",
31+
elasticsearchServiceUri: elasticsearchServiceUri,
32+
kibanaServiceUri: kibanaServiceUri,
33+
kibanaSsoUri: kibanaSsoUri,
34+
serializedAdditionalRawData: new Dictionary<string, BinaryData>()
35+
);
36+
37+
// Act - Serialize
38+
var model = deployment as IPersistableModel<ElasticCloudDeployment>;
39+
var wire = ModelReaderWriter.Write(model);
40+
var jsonString = wire.ToString();
41+
42+
// Verify serialized JSON contains absolute URIs
43+
var jsonDoc = JsonDocument.Parse(jsonString);
44+
var root = jsonDoc.RootElement;
45+
46+
if (root.TryGetProperty("elasticsearchServiceUrl", out var esElement))
47+
{
48+
Assert.AreEqual("https://elasticsearch.example.com:9200/", esElement.GetString());
49+
}
50+
if (root.TryGetProperty("kibanaServiceUrl", out var kibanaElement))
51+
{
52+
Assert.AreEqual("https://kibana.example.com:5601/", kibanaElement.GetString());
53+
}
54+
if (root.TryGetProperty("kibanaSsoUrl", out var kibanaSsoElement))
55+
{
56+
Assert.AreEqual("https://kibana.example.com:5601/sso", kibanaSsoElement.GetString());
57+
}
58+
59+
// Act - Deserialize
60+
var deserialized = ModelReaderWriter.Read<ElasticCloudDeployment>(wire);
61+
62+
// Assert
63+
Assert.NotNull(deserialized);
64+
Assert.AreEqual(elasticsearchServiceUri, deserialized.ElasticsearchServiceUri);
65+
Assert.AreEqual(kibanaServiceUri, deserialized.KibanaServiceUri);
66+
Assert.AreEqual(kibanaSsoUri, deserialized.KibanaSsoUri);
67+
68+
// Verify all URIs are absolute
69+
Assert.IsTrue(deserialized.ElasticsearchServiceUri.IsAbsoluteUri);
70+
Assert.IsTrue(deserialized.KibanaServiceUri.IsAbsoluteUri);
71+
Assert.IsTrue(deserialized.KibanaSsoUri.IsAbsoluteUri);
72+
}
73+
74+
[Test]
75+
public void SerializeAndDeserialize_AllUriProperties_WithRelativeUris()
76+
{
77+
// Arrange - Use relative paths that don't start with "/" to avoid platform-specific interpretation
78+
var elasticsearchServiceUri = new Uri("elasticsearch", UriKind.Relative);
79+
var kibanaServiceUri = new Uri("kibana", UriKind.Relative);
80+
var kibanaSsoUri = new Uri("kibana/sso", UriKind.Relative);
81+
82+
var deployment = new ElasticCloudDeployment(
83+
name: "test-deployment",
84+
deploymentId: "dep-123",
85+
azureSubscriptionId: "sub-456",
86+
elasticsearchRegion: "eastus",
87+
elasticsearchServiceUri: elasticsearchServiceUri,
88+
kibanaServiceUri: kibanaServiceUri,
89+
kibanaSsoUri: kibanaSsoUri,
90+
serializedAdditionalRawData: new Dictionary<string, BinaryData>()
91+
);
92+
93+
// Act - Serialize
94+
var model = deployment as IPersistableModel<ElasticCloudDeployment>;
95+
var wire = ModelReaderWriter.Write(model);
96+
var jsonString = wire.ToString();
97+
98+
// Verify serialized JSON contains relative URIs as original strings
99+
var jsonDoc = JsonDocument.Parse(jsonString);
100+
var root = jsonDoc.RootElement;
101+
102+
if (root.TryGetProperty("elasticsearchServiceUrl", out var esElement))
103+
{
104+
Assert.AreEqual("elasticsearch", esElement.GetString());
105+
}
106+
if (root.TryGetProperty("kibanaServiceUrl", out var kibanaElement))
107+
{
108+
Assert.AreEqual("kibana", kibanaElement.GetString());
109+
}
110+
if (root.TryGetProperty("kibanaSsoUrl", out var kibanaSsoElement))
111+
{
112+
Assert.AreEqual("kibana/sso", kibanaSsoElement.GetString());
113+
}
114+
115+
// Act - Deserialize
116+
var deserialized = ModelReaderWriter.Read<ElasticCloudDeployment>(wire);
117+
118+
// Assert
119+
Assert.NotNull(deserialized);
120+
Assert.AreEqual(elasticsearchServiceUri, deserialized.ElasticsearchServiceUri);
121+
Assert.AreEqual(kibanaServiceUri, deserialized.KibanaServiceUri);
122+
Assert.AreEqual(kibanaSsoUri, deserialized.KibanaSsoUri);
123+
124+
// Verify all URIs are relative
125+
Assert.IsFalse(deserialized.ElasticsearchServiceUri.IsAbsoluteUri);
126+
Assert.IsFalse(deserialized.KibanaServiceUri.IsAbsoluteUri);
127+
Assert.IsFalse(deserialized.KibanaSsoUri.IsAbsoluteUri);
128+
129+
// Verify original strings are preserved
130+
Assert.AreEqual("elasticsearch", deserialized.ElasticsearchServiceUri.OriginalString);
131+
Assert.AreEqual("kibana", deserialized.KibanaServiceUri.OriginalString);
132+
Assert.AreEqual("kibana/sso", deserialized.KibanaSsoUri.OriginalString);
133+
}
134+
}
135+
}

0 commit comments

Comments
 (0)