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

Show warnings for Agents that run on OS versions not supported by .NET 8 #4885

Merged
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
407dbaf
Add Net Supported OS generic check
ismayilov-ismayil Jul 2, 2024
d0fa855
Draft checkpoint
ismayilov-ismayil Jul 6, 2024
2114e9e
Checkpoint for current stage
ismayilov-ismayil Jul 7, 2024
29d4c79
Move warning message to localization
ismayilov-ismayil Jul 7, 2024
4fc0f7c
Rearrange pragma syntaxis
ismayilov-ismayil Jul 7, 2024
91016ed
Merge branch 'master' into users/ismayilov-ismayil/warning-message-eo…
ismayilov-ismayil Jul 7, 2024
7098b6c
Remove unused loc string
ismayilov-ismayil Jul 7, 2024
10e559e
Merge branch 'users/ismayilov-ismayil/warning-message-eol-net8' of ht…
ismayilov-ismayil Jul 7, 2024
619b7ea
Change string json pretty printed version
ismayilov-ismayil Jul 8, 2024
3f870e1
Remove redundant catch statement
ismayilov-ismayil Jul 9, 2024
223a432
Update PlatformUtil - IsNetVersionSupported method
DenisRumyantsev Jul 11, 2024
8b3e2e8
Merge branch 'master' of https://github.com/microsoft/azure-pipelines…
ismayilov-ismayil Jul 16, 2024
a991fe4
Merge branch 'users/ismayilov-ismayil/warning-message-eol-net8' of ht…
ismayilov-ismayil Jul 16, 2024
154df44
Update details URL
ismayilov-ismayil Jul 16, 2024
9cfafef
Add Net Supported OS generic check
ismayilov-ismayil Jul 2, 2024
bc69185
Draft checkpoint
ismayilov-ismayil Jul 6, 2024
5ff29b5
Checkpoint for current stage
ismayilov-ismayil Jul 7, 2024
56f9c1c
Move warning message to localization
ismayilov-ismayil Jul 7, 2024
17efca7
Rearrange pragma syntaxis
ismayilov-ismayil Jul 7, 2024
87144f3
Remove unused loc string
ismayilov-ismayil Jul 7, 2024
268c50a
Change string json pretty printed version
ismayilov-ismayil Jul 8, 2024
c16c6fc
Remove redundant catch statement
ismayilov-ismayil Jul 9, 2024
d51208f
Update PlatformUtil - IsNetVersionSupported method
DenisRumyantsev Jul 11, 2024
ece96f5
Update details URL
ismayilov-ismayil Jul 16, 2024
08bcf0b
Merge branch 'master' into users/ismayilov-ismayil/warning-message-eo…
ismayilov-ismayil Jul 27, 2024
2fce771
Merge branch 'users/ismayilov-ismayil/warning-message-eol-net8' of ht…
ismayilov-ismayil Jul 30, 2024
64649f4
Add FF to warning message
ismayilov-ismayil Jul 30, 2024
4b6672e
Merge branch 'master' into users/ismayilov-ismayil/warning-message-eo…
ismayilov-ismayil Jul 30, 2024
12b1f35
Merge branch 'master' into users/ismayilov-ismayil/warning-message-eo…
max-zaytsev Aug 1, 2024
6deb988
Use ReadAllTextAsync
DenisRumyantsev Aug 1, 2024
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
2 changes: 1 addition & 1 deletion src/Agent.Listener/Agent.Listener.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
</ItemGroup>

<ItemGroup>
<None Update="net6.json">
<None Update="net8.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
Expand Down
35 changes: 0 additions & 35 deletions src/Agent.Listener/SelfUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,41 +154,6 @@ private async Task<bool> UpdateNeeded(string targetVersion, CancellationToken to
return false;
}

//Checking if current system support .NET 6 agent
if (agentVersion.Major == 2 && serverVersion.Major == 3)
{
Trace.Verbose("Checking if your system supports .NET 6");

try
{
string systemId = PlatformUtil.GetSystemId();
SystemVersion systemVersion = PlatformUtil.GetSystemVersion();

Trace.Verbose($"The system you are running on: \"{systemId}\" ({systemVersion})");

if (await PlatformUtil.DoesSystemPersistsInNet6Whitelist())
{
// Check version of the system
if (!await PlatformUtil.IsNet6Supported())
{
Trace.Warning($"The operating system the agent is running on is \"{systemId}\" ({systemVersion}), which will not be supported by the .NET 6 based v3 agent. Please upgrade the operating system of this host to ensure compatibility with the v3 agent. See https://aka.ms/azdo-pipeline-agent-version");
return false;
}
}
else
{
Trace.Warning($"The operating system the agent is running on is \"{systemId}\" ({systemVersion}), which has not been tested with the .NET 6 based v3 agent. The v2 agent wil not automatically upgrade to the v3 agent. You can manually download the .NET 6 based v3 agent from https://github.com/microsoft/azure-pipelines-agent/releases. See https://aka.ms/azdo-pipeline-agent-version");
return false;
}

Trace.Verbose("The system persists in the list of systems supporting .NET 6");
}
catch (Exception ex)
{
Trace.Error($"Error has occurred while checking if system supports .NET 6: {ex}");
}
}

if (serverVersion.CompareTo(agentVersion) > 0)
{
return true;
Expand Down
53 changes: 23 additions & 30 deletions src/Agent.Listener/net6.json → src/Agent.Listener/net8.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"id": "alpine",
"versions": [
{
"name": "3.13+"
"name": "3.17+"
}
]
},
Expand All @@ -12,126 +12,119 @@
"versions": [
{
"name": "2"
}
]
},
{
"id": "centos",
"versions": [
},
{
"name": "7+"
"name": "2023"
}
]
},
{
"id": "debian",
"versions": [
{
"name": "10+"
"name": "11+"
}
]
},
{
"id": "fedora",
"versions": [
{
"name": "33+"
"name": "39+"
}
]
},
{
"id": "macOS",
"versions": [
{
"name": "10.15+"
"name": "12+"
}
]
},
{
"id": "mariner",
"versions": [
{
"name": "1.0+"
"name": "2.0+"
}
]
},
{
"id": "opensuse-leap",
"versions": [
{
"name": "15+"
"name": "15.5+"
}
]
},
{
"id": "rhel",
"versions": [
{
"name": "7+"
"name": "8+"
}
]
},
{
"id": "sles",
"versions": [
{
"name": "12.2+"
"name": "15+"
}
]
},
{
"id": "ubuntu",
"versions": [
{
"name": "16.04"
"name": "20.04"
},
{
"name": "22.04"
},
{
"name": "18.04"
"name": "23.10"
},
{
"name": "20.04+"
"name": "24.04"
}

]
},
{
"id": "Windows Client",
"versions": [
{
"name": "7",
"version": "7601+"
},
{
"name": "8.1"
"name": "10",
"version": "1607+"
},
{
"name": "10",
"version": "14393+"
"name": "11"
}
]
},
{
"id": "Windows Nano Server",
"versions": [
{
"version": "17763+"
"version": "1809+"
}
]
},
{
"id": "Windows Server",
"versions": [
{
"name": "2012+"
"name": "2016+"
}
]
},
{
"id": "Windows Server Core",
"versions": [
{
"name": "2012+"
"name": "2016+"
}
]
}
]
]
7 changes: 1 addition & 6 deletions src/Agent.Sdk/Knob/AgentKnobs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,7 @@ public class AgentKnobs

public static readonly Knob AgentFailOnIncompatibleOS = new Knob(
ismayilov-ismayil marked this conversation as resolved.
Show resolved Hide resolved
nameof(AgentFailOnIncompatibleOS),
"Allow agent to fail pipelines on incampatible OS",
"Allow agent to fail pipelines on incompatible OS",
new EnvironmentKnobSource("AGENT_FAIL_ON_INCOMPATIBLE_OS"),
new RuntimeKnobSource("AGENT_FAIL_ON_INCOMPATIBLE_OS"),
new BuiltInDefaultKnobSource("false"));
Expand Down Expand Up @@ -592,11 +592,6 @@ public class AgentKnobs
new EnvironmentKnobSource("AGENT_DISABLE_DRAIN_QUEUES_AFTER_TASK"),
new BuiltInDefaultKnobSource("false"));

public static readonly Knob EnableFetchingNet6List = new Knob(
nameof(EnableFetchingNet6List),
"Forces the agent to fetch list of .NET 6 supporting systems from server",
new EnvironmentKnobSource("AGENT_ENABLE_FETCHING_NET6_LIST"),
new BuiltInDefaultKnobSource("false"));

public static readonly Knob EnableResourceUtilizationWarnings = new Knob(
nameof(EnableResourceUtilizationWarnings),
Expand Down
55 changes: 16 additions & 39 deletions src/Agent.Sdk/Util/PlatformUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
using Newtonsoft.Json;
using System.ServiceProcess;
using Agent.Sdk.Util;
using System.Collections.Generic;

namespace Agent.Sdk
{
public static class PlatformUtil
{
private static UtilKnobValueContext _knobContext = UtilKnobValueContext.Instance();
private static OperatingSystem[] net6SupportedSystems;
private static HttpClient httpClient = new HttpClient();
private static Dictionary<string, OperatingSystem[]> netSupportedSystems = new Dictionary<string, OperatingSystem[]>();

private static readonly string[] linuxReleaseFilePaths = new string[2] { "/etc/os-release", "/usr/lib/os-release" };

Expand Down Expand Up @@ -393,59 +393,36 @@ public static bool UseLegacyHttpHandler
get => AgentKnobs.UseLegacyHttpHandler.GetValue(_knobContext).AsBoolean();
}

private async static Task<OperatingSystem[]> GetNet6SupportedSystems()
private async static Task<OperatingSystem[]> GetSupportedSystemsByNetVersion(string netVersion = "net6")
{
string serverFileUrl = "https://raw.githubusercontent.com/microsoft/azure-pipelines-agent/master/src/Agent.Listener/net6.json";
string supportOSfilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "net6.json");
string supportOSfileContent;
string supportOSfilePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), $"{netVersion}.json");
bool supportOSfileExists = File.Exists(supportOSfilePath);

if ((!supportOSfileExists || File.GetLastWriteTimeUtc(supportOSfilePath) < DateTime.UtcNow.AddHours(-1))
&& AgentKnobs.EnableFetchingNet6List.GetValue(_knobContext).AsBoolean())
if (netSupportedSystems != null && netSupportedSystems.ContainsKey(netVersion))
{
HttpResponseMessage response = await httpClient.GetAsync(serverFileUrl);
if (!response.IsSuccessStatusCode)
{
throw new Exception($"Getting file \"net6.json\" from server failed. Status code: {response.StatusCode}");
}
supportOSfileContent = await response.Content.ReadAsStringAsync();
await File.WriteAllTextAsync(supportOSfilePath, supportOSfileContent);
return netSupportedSystems[netVersion];
}
else
{
if (net6SupportedSystems != null)
{
return net6SupportedSystems;
}

if (!supportOSfileExists)
{
throw new FileNotFoundException("File with list of systems supporting .NET 6 is absent", supportOSfilePath);
}

supportOSfileContent = await File.ReadAllTextAsync(supportOSfilePath);
if (!supportOSfileExists)
{
throw new FileNotFoundException($"File with list of systems supporting {netVersion} is absent", supportOSfilePath);
}

net6SupportedSystems = JsonConvert.DeserializeObject<OperatingSystem[]>(supportOSfileContent);
return net6SupportedSystems;
string supportOSfileContent = await File.ReadAllTextAsync(supportOSfilePath);

netSupportedSystems.Add(netVersion, JsonConvert.DeserializeObject<OperatingSystem[]>(supportOSfileContent));
return netSupportedSystems[netVersion];
}

public async static Task<bool> IsNet6Supported()
public async static Task<bool> IsNetVersionSupported(string netVersion)
{
OperatingSystem[] net6SupportedSystems = await GetNet6SupportedSystems();
OperatingSystem[] supportedSystems = await GetSupportedSystemsByNetVersion(netVersion);

string systemId = PlatformUtil.GetSystemId();
SystemVersion systemVersion = PlatformUtil.GetSystemVersion();
return net6SupportedSystems.Any((s) => s.Equals(systemId, systemVersion));
return supportedSystems.Any((s) => s.Equals(systemId, systemVersion));
}

public async static Task<bool> DoesSystemPersistsInNet6Whitelist()
{
OperatingSystem[] net6SupportedSystems = await GetNet6SupportedSystems();
string systemId = PlatformUtil.GetSystemId();

return net6SupportedSystems.Any((s) => s.Equals(systemId));
}
public static bool DetectDockerContainer()
{
bool isDockerContainer = false;
Expand Down
57 changes: 18 additions & 39 deletions src/Agent.Worker/JobExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,51 +75,30 @@ public async Task<List<IStep>> InitializeJob(IExecutionContext jobContext, Pipel
context.Start();
context.Section(StringUtil.Loc("StepStarting", StringUtil.Loc("InitializeJob")));

// Check if a system supports .NET 6
PackageVersion agentVersion = new PackageVersion(BuildConstants.AgentPackage.Version);
if (agentVersion.Major < 3)
// Check if a system supports .NET 8
try
{
try
{
Trace.Verbose("Checking if your system supports .NET 6");

string systemId = PlatformUtil.GetSystemId();
SystemVersion systemVersion = PlatformUtil.GetSystemVersion();
string notSupportNet6Message = null;
Trace.Verbose("Checking if your system supports .NET 8");

if (await PlatformUtil.DoesSystemPersistsInNet6Whitelist())
{
// Check version of the system
if (!await PlatformUtil.IsNet6Supported())
{
notSupportNet6Message = $"The operating system the agent is running on is \"{systemId}\" ({systemVersion}), which will not be supported by the .NET 6 based v3 agent. Please upgrade the operating system of this host to ensure compatibility with the v3 agent. See https://aka.ms/azdo-pipeline-agent-version";
if (AgentKnobs.AgentFailOnIncompatibleOS.GetValue(jobContext).AsBoolean() &&
!AgentKnobs.AcknowledgeNoUpdates.GetValue(jobContext).AsBoolean())
{
throw new UnsupportedOsException(StringUtil.Loc("FailAgentOnUnsupportedOs"));
}
}
}
else
{
notSupportNet6Message = $"The operating system the agent is running on is \"{systemId}\" ({systemVersion}), which has not been tested with the .NET 6 based v3 agent. The v2 agent wil not automatically upgrade to the v3 agent. You can manually download the .NET 6 based v3 agent from https://github.com/microsoft/azure-pipelines-agent/releases. See https://aka.ms/azdo-pipeline-agent-version";
}
string systemId = PlatformUtil.GetSystemId();
SystemVersion systemVersion = PlatformUtil.GetSystemVersion();

if (!string.IsNullOrWhiteSpace(notSupportNet6Message))
{
context.Warning(notSupportNet6Message);
}
}
catch (UnsupportedOsException)
{
throw;
}
catch (Exception ex)
// Check version of the system
if (!await PlatformUtil.IsNetVersionSupported("net8"))
{
Trace.Error($"Error has occurred while checking if system supports .NET 6: {ex}");
context.Warning(ex.Message);
context.Warning(StringUtil.Loc("UnsupportedOsVersionByNet8", $"{systemId} {systemVersion}"));
}
}
catch (UnsupportedOsException)
{
throw;
}
catch (Exception ex)
{
Trace.Error($"Error has occurred while checking if system supports .NET 8: {ex}");
context.Warning(ex.Message);
}

// Set agent version variable.
context.SetVariable(Constants.Variables.Agent.Version, BuildConstants.AgentPackage.Version);
Expand Down Expand Up @@ -392,7 +371,7 @@ public async Task<List<IStep>> InitializeJob(IExecutionContext jobContext, Pipel
}

ArgUtil.NotNull(jobContext, nameof(jobContext)); // I am not sure why this is needed, but static analysis flagged all uses of jobContext below this point
// create execution context for all pre-job steps
// create execution context for all pre-job steps
foreach (var step in preJobSteps)
{
if (PlatformUtil.RunningOnWindows && step is ManagementScriptStep)
Expand Down
Loading
Loading