@@ -63,22 +63,34 @@ public static LibraryInfo GetLibraryInfo(Assembly assembly)
63
63
/// </summary>
64
64
public static string ? GetDotnetPath ( )
65
65
{
66
+ var environmentOverride = Environment . GetEnvironmentVariable ( "DOTNET_ROOT" ) ;
67
+ if ( ! string . IsNullOrEmpty ( environmentOverride ) && Directory . Exists ( environmentOverride ) )
68
+ {
69
+ var execFileName =
70
+ #if NET6_0_OR_GREATER
71
+ OperatingSystem . IsWindows ( )
72
+ #else
73
+ RuntimeInformation . IsOSPlatform ( OSPlatform . Windows )
74
+ #endif
75
+ ? "dotnet.exe"
76
+ : "dotnet"
77
+ ;
78
+ var dotnetExePath = Path . Combine ( environmentOverride , execFileName ) ;
79
+ if ( File . Exists ( dotnetExePath ) )
80
+ return dotnetExePath ;
81
+
82
+ throw new InvalidOperationException ( $ "dotnet executable file not found under specified DOTNET_ROOT { environmentOverride } ") ;
83
+ }
66
84
return ResolvePath ( "dotnet" ) ;
67
85
}
68
86
69
87
public static string GetDotnetDirectory ( )
70
88
{
71
- var environmentOverride = Environment . GetEnvironmentVariable ( "DOTNET_MSBUILD_SDK_RESOLVER_CLI_DIR" ) ;
72
- if ( ! string . IsNullOrEmpty ( environmentOverride ) )
73
- {
74
- return environmentOverride ;
75
- }
76
-
77
89
var dotnetExe = GetDotnetPath ( ) ;
78
90
79
91
if ( dotnetExe . IsNotNullOrEmpty ( ) && ! InteropHelper . RunningOnWindows )
80
92
{
81
- // e.g. on Linux the 'dotnet' command from PATH is a symlink so we need to
93
+ // e.g. on Linux the 'dotnet' command from PATH is a symbol link so we need to
82
94
// resolve it to get the actual path to the binary
83
95
dotnetExe = InteropHelper . Unix . RealPath ( dotnetExe ) ?? dotnetExe ;
84
96
}
@@ -97,15 +109,15 @@ public static string GetDotnetDirectory()
97
109
98
110
public static string ? ResolvePath ( string execName ) => ResolvePath ( execName , ".exe" ) ;
99
111
100
- public static string ? ResolvePath ( string execName , string ? ext )
112
+ public static string ? ResolvePath ( string execName , string ? windowsExt )
101
113
{
102
114
var executableName = execName ;
103
115
if ( RuntimeInformation . IsOSPlatform ( OSPlatform . Windows )
104
116
&& ! Path . HasExtension ( execName )
105
- && string . IsNullOrEmpty ( ext )
117
+ && ! string . IsNullOrEmpty ( windowsExt )
106
118
)
107
119
{
108
- executableName += ext ;
120
+ executableName = $ " { executableName } { windowsExt } " ;
109
121
}
110
122
var searchPaths = Guard . NotNull ( Environment . GetEnvironmentVariable ( "PATH" ) )
111
123
. Split ( new [ ] { Path . PathSeparator } , options : StringSplitOptions . RemoveEmptyEntries )
@@ -125,7 +137,7 @@ private static RuntimeInfo GetRuntimeInfo()
125
137
#else
126
138
var currentProcess = System . Diagnostics . Process . GetCurrentProcess ( ) ;
127
139
#endif
128
- return new RuntimeInfo ( )
140
+ var runtimeInfo = new RuntimeInfo ( )
129
141
{
130
142
Version = Environment . Version . ToString ( ) ,
131
143
ProcessorCount = Environment . ProcessorCount ,
@@ -144,33 +156,45 @@ private static RuntimeInfo GetRuntimeInfo()
144
156
OSDescription = RuntimeInformation . OSDescription ,
145
157
OSVersion = Environment . OSVersion . ToString ( ) ,
146
158
MachineName = Environment . MachineName ,
159
+ UserName = Environment . UserName ,
147
160
148
161
IsInContainer = IsInContainer ( ) ,
149
162
IsInKubernetes = IsInKubernetesCluster ( ) ,
163
+ KubernetesNamespace = GetKubernetesNamespace ( ) ,
150
164
151
165
LibraryVersion = libInfo . LibraryVersion ,
152
166
LibraryHash = libInfo . LibraryHash ,
153
167
RepositoryUrl = libInfo . RepositoryUrl ,
154
168
} ;
169
+ return runtimeInfo ;
155
170
}
156
171
157
172
#region ContainerEnvironment
173
+ // container environment
174
+ // https://github.com/dotnet/dotnet-docker/blob/d90d458deada9057d7889f76d58fc0a7194a0c06/src/runtime-deps/6.0/alpine3.20/amd64/Dockerfile#L7
175
+
176
+ /// <summary>
177
+ /// Whether running inside a container
178
+ /// </summary>
158
179
private static bool IsInContainer ( )
159
180
{
160
- // https://github.com/dotnet/dotnet-docker/blob/9b731e901dd4a343fc30da7b8b3ab7d305a4aff9/src/runtime-deps/7.0/cbl-mariner2.0/amd64/Dockerfile#L18
161
181
return "true" . Equals ( Environment . GetEnvironmentVariable ( "DOTNET_RUNNING_IN_CONTAINER" ) ,
162
182
StringComparison . OrdinalIgnoreCase ) ;
163
183
}
164
184
185
+ // Kubernetes environment
186
+ // https://github.com/kubernetes-client/csharp/blob/36a02046439d01f1256aed4e5071cb7f1b57d6eb/src/KubernetesClient/KubernetesClientConfiguration.InCluster.cs#L41
165
187
private static readonly string ServiceAccountPath =
166
188
Path . Combine (
167
189
[
168
190
$ "{ Path . DirectorySeparatorChar } var", "run" , "secrets" , "kubernetes.io" , "serviceaccount" ,
169
191
] ) ;
170
192
private const string ServiceAccountTokenKeyFileName = "token" ;
171
193
private const string ServiceAccountRootCAKeyFileName = "ca.crt" ;
194
+ private const string ServiceAccountNamespaceFileName = "namespace" ;
195
+
172
196
/// <summary>
173
- /// Whether running in k8s cluster
197
+ /// Whether running inside a k8s cluster
174
198
/// </summary>
175
199
/// <returns></returns>
176
200
private static bool IsInKubernetesCluster ( )
@@ -191,8 +215,17 @@ private static bool IsInKubernetesCluster()
191
215
var certPath = Path . Combine ( ServiceAccountPath , ServiceAccountRootCAKeyFileName ) ;
192
216
return File . Exists ( certPath ) ;
193
217
}
194
- #endregion ContainerEnvironment
195
218
219
+ /// <summary>
220
+ /// Get Kubernetes namespace
221
+ /// </summary>
222
+ /// <returns>The namespace current workload in</returns>
223
+ private static string ? GetKubernetesNamespace ( )
224
+ {
225
+ var namespaceFilePath = Path . Combine ( ServiceAccountPath , ServiceAccountNamespaceFileName ) ;
226
+ return File . Exists ( namespaceFilePath ) ? File . ReadAllText ( namespaceFilePath ) . Trim ( ) : null ;
227
+ }
228
+ #endregion ContainerEnvironment
196
229
}
197
230
198
231
public class LibraryInfo
@@ -202,7 +235,7 @@ public class LibraryInfo
202
235
public required string RepositoryUrl { get ; init ; }
203
236
}
204
237
205
- public sealed class RuntimeInfo : LibraryInfo
238
+ public class RuntimeInfo : LibraryInfo
206
239
{
207
240
public required string Version { get ; init ; }
208
241
public required string FrameworkDescription { get ; init ; }
@@ -211,6 +244,7 @@ public sealed class RuntimeInfo : LibraryInfo
211
244
public required string OSDescription { get ; init ; }
212
245
public required string OSVersion { get ; init ; }
213
246
public required string MachineName { get ; init ; }
247
+ public required string UserName { get ; init ; }
214
248
215
249
#if NET6_0_OR_GREATER
216
250
public required string RuntimeIdentifier { get ; init ; }
@@ -229,4 +263,9 @@ public sealed class RuntimeInfo : LibraryInfo
229
263
/// Is running in a Kubernetes cluster
230
264
/// </summary>
231
265
public required bool IsInKubernetes { get ; init ; }
266
+
267
+ /// <summary>
268
+ /// Kubernetes namespace when running in a Kubernetes cluster
269
+ /// </summary>
270
+ public string ? KubernetesNamespace { get ; init ; }
232
271
}
0 commit comments