diff --git a/manifests/dotnet.yml b/manifests/dotnet.yml index 207d6d06f29..4a1fe6702bf 100644 --- a/manifests/dotnet.yml +++ b/manifests/dotnet.yml @@ -698,7 +698,7 @@ manifest: tests/docker_ssi/test_docker_ssi_appsec.py::TestDockerSSIAppsecFeatures::test_telemetry_source_ssi: v3.36.0 tests/ffe/test_dynamic_evaluation.py: v3.36.0 tests/ffe/test_exposures.py: v3.36.0 - tests/ffe/test_flag_eval_metrics.py: missing_feature + tests/ffe/test_flag_eval_metrics.py: v3.43.0-dev tests/integration_frameworks/llm/anthropic/test_anthropic_llmobs.py::TestAnthropicLlmObsMessages::test_create_error: bug (MLOB-1234) tests/integrations/crossed_integrations/test_kafka.py::Test_Kafka: v2.0.0-prerelease tests/integrations/crossed_integrations/test_kinesis.py::Test_Kinesis_PROPAGATION_VIA_MESSAGE_ATTRIBUTES: missing_feature diff --git a/utils/build/docker/dotnet/poc.Dockerfile b/utils/build/docker/dotnet/poc.Dockerfile index 81ed8d0c22a..803354f7187 100644 --- a/utils/build/docker/dotnet/poc.Dockerfile +++ b/utils/build/docker/dotnet/poc.Dockerfile @@ -1,6 +1,12 @@ FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build-app WORKDIR /app +# Copy binaries folder for local NuGet packages (for testing with local builds) +COPY binaries/ /binaries/ +RUN if ls /binaries/*.nupkg 1> /dev/null 2>&1; then \ + dotnet nuget add source /binaries --name local-packages; \ + fi + # dotnet restore COPY utils/build/docker/dotnet/weblog/app.csproj app.csproj RUN dotnet restore diff --git a/utils/build/docker/dotnet/weblog/Controllers/FeatureFlagEvaluatorController.cs b/utils/build/docker/dotnet/weblog/Controllers/FeatureFlagEvaluatorController.cs index 3e21989b49f..3d0ad54290b 100644 --- a/utils/build/docker/dotnet/weblog/Controllers/FeatureFlagEvaluatorController.cs +++ b/utils/build/docker/dotnet/weblog/Controllers/FeatureFlagEvaluatorController.cs @@ -7,6 +7,7 @@ using OpenFeature.Model; using System; using System.Collections.Generic; +using System.Text.Json; using System.Text.Json.Serialization; using System.Threading.Tasks; @@ -52,17 +53,15 @@ public async Task Evaluate([FromBody] EvaluateRequest request) { value = request.VariationType?.ToUpper() switch { - "BOOLEAN" => await _client.GetBooleanValueAsync(request.Flag, Convert.ToBoolean(request.DefaultValue), context), - "STRING" => await _client.GetStringValueAsync(request.Flag, request.DefaultValue?.ToString(), context), - "INTEGER" => await _client.GetIntegerValueAsync(request.Flag, Convert.ToInt32(request.DefaultValue), context), - "NUMERIC" => await _client.GetDoubleValueAsync(request.Flag, Convert.ToDouble(request.DefaultValue), context), - // "JSON" => (await _client.GetObjectValueAsync(request.Flag, Value.FromObject(request.DefaultValue), context)).AsStructure(), + "BOOLEAN" => await _client.GetBooleanValueAsync(request.Flag, GetDefaultValueAsBool(request.DefaultValue), context), + "STRING" => await _client.GetStringValueAsync(request.Flag, GetDefaultValueAsString(request.DefaultValue), context), + "INTEGER" => await _client.GetIntegerValueAsync(request.Flag, GetDefaultValueAsInt(request.DefaultValue), context), + "NUMERIC" => await _client.GetDoubleValueAsync(request.Flag, GetDefaultValueAsDouble(request.DefaultValue), context), _ => request.DefaultValue }; } - catch (Exception ex) + catch (Exception) { - // _logger.LogError(ex, "Error on resolution"); value = request.DefaultValue; reason = "ERROR"; } @@ -70,6 +69,60 @@ public async Task Evaluate([FromBody] EvaluateRequest request) return Ok(new { reason, value }); } + private static bool GetDefaultValueAsBool(object defaultValue) + { + if (defaultValue is JsonElement jsonElement) + { + return jsonElement.ValueKind switch + { + JsonValueKind.True => true, + JsonValueKind.False => false, + JsonValueKind.String => bool.Parse(jsonElement.GetString()), + _ => false + }; + } + return Convert.ToBoolean(defaultValue); + } + + private static string GetDefaultValueAsString(object defaultValue) + { + if (defaultValue is JsonElement jsonElement) + { + return jsonElement.ValueKind == JsonValueKind.String + ? jsonElement.GetString() + : jsonElement.ToString(); + } + return defaultValue?.ToString(); + } + + private static int GetDefaultValueAsInt(object defaultValue) + { + if (defaultValue is JsonElement jsonElement) + { + return jsonElement.ValueKind switch + { + JsonValueKind.Number => jsonElement.GetInt32(), + JsonValueKind.String => int.Parse(jsonElement.GetString()), + _ => 0 + }; + } + return Convert.ToInt32(defaultValue); + } + + private static double GetDefaultValueAsDouble(object defaultValue) + { + if (defaultValue is JsonElement jsonElement) + { + return jsonElement.ValueKind switch + { + JsonValueKind.Number => jsonElement.GetDouble(), + JsonValueKind.String => double.Parse(jsonElement.GetString()), + _ => 0.0 + }; + } + return Convert.ToDouble(defaultValue); + } + private static EvaluationContext CreateContext(EvaluateRequest request) { var builder = EvaluationContext.Builder(); @@ -79,8 +132,16 @@ private static EvaluationContext CreateContext(EvaluateRequest request) { foreach (var attr in request.Attributes) { - builder.Set(attr.Key, attr.Value as string); - // builder.Set(attr.Key, Value.FromObject(attr.Value)); + // System.Text.Json deserializes to JsonElement, not string + var value = attr.Value switch + { + JsonElement jsonElement => jsonElement.ValueKind == JsonValueKind.String + ? jsonElement.GetString() + : jsonElement.ToString(), + string s => s, + _ => attr.Value?.ToString() + }; + builder.Set(attr.Key, value); } } return builder.Build(); diff --git a/utils/build/docker/dotnet/weblog/app.csproj b/utils/build/docker/dotnet/weblog/app.csproj index d7db52d83a5..07e8575ae29 100644 --- a/utils/build/docker/dotnet/weblog/app.csproj +++ b/utils/build/docker/dotnet/weblog/app.csproj @@ -46,8 +46,8 @@ - - + +