Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/environment #43

Merged
merged 3 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Argon.Server.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
<s:Boolean x:Key="/Default/InstalledDictionaries/InstalledDictionaries/=C_003A_005Cgit_005Chunspell_002Ddictionaries_005Cru_005FRU_005Cru_005FRU_002Edic/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=appsettings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Behaviours/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=dockerenv/@EntryIndexedValue">True</s:Boolean>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

???

<s:Boolean x:Key="/Default/UserDictionary/Words/=hwnd/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=livekit/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Rebalance/@EntryIndexedValue">True</s:Boolean>
Expand Down
2 changes: 1 addition & 1 deletion src/Argon.Api/Argon.Api.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

??????????


<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
Expand Down
35 changes: 35 additions & 0 deletions src/Argon.Api/Features/Env/EnvironmentExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace Argon.Api.Features.Env;

using static File;

Comment on lines +1 to +4
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Add missing imports

The code is using IHostEnvironment but the import is missing. Also, the static import of File could be more explicit.

Add these imports:

namespace Argon.Api.Features.Env;

+ using Microsoft.Extensions.Hosting;
- using static File;
+ using static System.IO.File;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
namespace Argon.Api.Features.Env;
using static File;
namespace Argon.Api.Features.Env;
using Microsoft.Extensions.Hosting;
using static System.IO.File;

public static class EnvironmentExtensions
{
public static bool IsKube(this IHostEnvironment env)
=> env.Determine() == ArgonEnvironmentKind.Kubernetes;

public static bool IsDocker(this IHostEnvironment env)
=> env.Determine() == ArgonEnvironmentKind.Docker;

public static bool IsClassicHost(this IHostEnvironment env)
=> env.Determine() == ArgonEnvironmentKind.HostMachine;

public static bool IsManaged(this IHostEnvironment env)
=> env.IsDocker() || env.IsKube();

public static ArgonEnvironmentKind Determine(this IHostEnvironment _)
{
if (Environment.GetEnvironmentVariable("KUBERNETES_SERVICE_HOST") != null)
return ArgonEnvironmentKind.Kubernetes;
if (Exists("/.dockerenv") || Directory.Exists("/proc/self/cgroup") &&
ReadAllText("/proc/self/cgroup").Contains("docker"))
return ArgonEnvironmentKind.Docker;
return ArgonEnvironmentKind.HostMachine;
}
}
Comment on lines +19 to +28
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Consider improving environment detection robustness and performance

The current implementation has several areas for improvement:

  1. File operations should include exception handling
  2. Docker detection could be more comprehensive
  3. Results should be cached to avoid repeated file system operations
  4. The unused parameter could be removed if not needed

Consider this improved implementation:

- public static ArgonEnvironmentKind Determine(this IHostEnvironment _)
+ public static ArgonEnvironmentKind Determine(this IHostEnvironment env)
+ {
+     // Cache the result in a static field
+     private static ArgonEnvironmentKind? _cachedKind;
+     
+     if (_cachedKind.HasValue)
+         return _cachedKind.Value;
+         
+     _cachedKind = DetermineInternal();
+     return _cachedKind.Value;
+ }
+ 
+ private static ArgonEnvironmentKind DetermineInternal()
  {
      if (Environment.GetEnvironmentVariable("KUBERNETES_SERVICE_HOST") != null)
          return ArgonEnvironmentKind.Kubernetes;

-     if (Exists("/.dockerenv") || Directory.Exists("/proc/self/cgroup") &&
-         ReadAllText("/proc/self/cgroup").Contains("docker"))
+     try 
+     {
+         // Check multiple indicators for Docker
+         if (Exists("/.dockerenv"))
+             return ArgonEnvironmentKind.Docker;
+             
+         if (Directory.Exists("/proc/self/cgroup"))
+         {
+             var cgroupContent = ReadAllText("/proc/self/cgroup");
+             if (cgroupContent.Contains("docker") || cgroupContent.Contains("containerd"))
+                 return ArgonEnvironmentKind.Docker;
+         }
+     }
+     catch (IOException)
+     {
+         // Silently fall through to default if file operations fail
+     }
      return ArgonEnvironmentKind.HostMachine;
  }

Committable suggestion skipped: line range outside the PR's diff.


public enum ArgonEnvironmentKind
{
HostMachine,
Docker,
Kubernetes,
}
5 changes: 3 additions & 2 deletions src/Argon.Api/Features/Orleanse/BalanceRule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ namespace Argon.Api.Features;

using System.Collections.Concurrent;
using System.Globalization;
using Env;
using k8s;
using Orleans.Placement.Repartitioning;
using static Math;
Expand All @@ -13,7 +14,7 @@ public static IServiceCollection AddKubeResources(this WebApplicationBuilder bui
{
var services = builder.Services;

if (builder.Environment.IsProduction())
if (builder.Environment.IsKube())
{
var config = KubernetesClientConfiguration.InClusterConfig();
services.AddSingleton(config);
Expand Down Expand Up @@ -49,7 +50,7 @@ public async ValueTask FetchAsync()

private async Task<double> GetAvgCpu()
{
if (!env.IsProduction())
if (!env.IsManaged())
return 10;
await using var
scope = serviceProvider.CreateAsyncScope();
Expand Down
7 changes: 4 additions & 3 deletions src/Argon.Api/Features/Orleanse/OrleansExtension.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace Argon.Api.Features;

using Contracts;
using Env;
using Extensions;
using Orleans.Clustering.Kubernetes;
using Orleans.Configuration;
Expand Down Expand Up @@ -32,10 +33,10 @@ public static WebApplicationBuilder AddOrleans(this WebApplicationBuilder builde
.AddPersistentStreams(IArgonEvent.ProviderId, NatsAdapterFactory.Create, options => { }).UseDashboard(o => o.Port = 22832);
#pragma warning restore ORLEANSEXP001

if (builder.Environment.IsDevelopment())
siloBuilder.UseLocalhostClustering();
else
if (builder.Environment.IsKube())
siloBuilder.UseKubeMembership();
else
siloBuilder.UseLocalhostClustering();
});

return builder;
Expand Down
5 changes: 3 additions & 2 deletions src/Argon.Api/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using Argon.Api.Extensions;
using Argon.Api.Features;
using Argon.Api.Features.EmailForms;
using Argon.Api.Features.Env;
using Argon.Api.Features.Jwt;
using Argon.Api.Features.Otp;
using Argon.Api.Grains.Interfaces;
Expand All @@ -25,7 +26,7 @@
builder.AddNatsJetStream();
builder.AddNpgsqlDbContext<ApplicationDbContext>("DefaultConnection");
builder.Services.AddSingleton<IPasswordHashingService, PasswordHashingService>();
if (!builder.Environment.IsProduction())
if (!builder.Environment.IsManaged())
{
builder.AddJwt();
builder.Services.AddControllers().AddNewtonsoftJson();
Expand All @@ -46,7 +47,7 @@
builder.Services.AddAutoMapper(typeof(User).Assembly); // TODO
var app = builder.Build();

if (!builder.Environment.IsProduction())
if (!builder.Environment.IsManaged())
{
app.UseWebSockets();
app.MapRpcWebSocketServer();
Expand Down