Skip to content

Commit

Permalink
Add --no-default-labels config option to self-hosted runners (actions…
Browse files Browse the repository at this point in the history
…#2443)

* Add --no-default-labels option

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>

* Add tests

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>

* .

---------

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
Co-authored-by: Tingluo Huang <tingluohuang@github.com>
  • Loading branch information
gabriel-samfira and TingluoHuang authored May 11, 2023
1 parent f8a28c3 commit eeb0cf6
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/Runner.Common/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ public static class Flags
public static readonly string GenerateServiceConfig = "generateServiceConfig";
public static readonly string Help = "help";
public static readonly string Local = "local";
public static readonly string NoDefaultLabels = "no-default-labels";
public static readonly string Replace = "replace";
public static readonly string DisableUpdate = "disableupdate";
public static readonly string Once = "once"; // Keep this around since customers still relies on it
Expand Down
8 changes: 5 additions & 3 deletions src/Runner.Listener/CommandSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,15 +29,16 @@ public sealed class CommandSettings
private readonly Dictionary<string, string[]> validOptions = new()
{
// Valid configure flags and args
[Constants.Runner.CommandLine.Commands.Configure] =
new string[]
[Constants.Runner.CommandLine.Commands.Configure] =
new string[]
{
Constants.Runner.CommandLine.Flags.DisableUpdate,
Constants.Runner.CommandLine.Flags.Ephemeral,
Constants.Runner.CommandLine.Flags.GenerateServiceConfig,
Constants.Runner.CommandLine.Flags.Replace,
Constants.Runner.CommandLine.Flags.RunAsService,
Constants.Runner.CommandLine.Flags.Unattended,
Constants.Runner.CommandLine.Flags.NoDefaultLabels,
Constants.Runner.CommandLine.Args.Auth,
Constants.Runner.CommandLine.Args.Labels,
Constants.Runner.CommandLine.Args.MonitorSocketAddress,
Expand Down Expand Up @@ -85,6 +86,7 @@ public sealed class CommandSettings
public bool Ephemeral => TestFlag(Constants.Runner.CommandLine.Flags.Ephemeral);
public bool GenerateServiceConfig => TestFlag(Constants.Runner.CommandLine.Flags.GenerateServiceConfig);
public bool Help => TestFlag(Constants.Runner.CommandLine.Flags.Help);
public bool NoDefaultLabels => TestFlag(Constants.Runner.CommandLine.Flags.NoDefaultLabels);
public bool Unattended => TestFlag(Constants.Runner.CommandLine.Flags.Unattended);
public bool Version => TestFlag(Constants.Runner.CommandLine.Flags.Version);
public bool RemoveLocalConfig => TestFlag(Constants.Runner.CommandLine.Flags.Local);
Expand Down Expand Up @@ -182,7 +184,7 @@ public string GetCommandName()
{
command = Constants.Runner.CommandLine.Commands.Warmup;
}

return command;
}

Expand Down
34 changes: 24 additions & 10 deletions src/Runner.Listener/Configuration/ConfigurationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ public async Task ConfigureAsync(CommandSettings command)
if (command.GetReplace())
{
// Update existing agent with new PublicKey, agent version.
agent = UpdateExistingAgent(agent, publicKey, userLabels, runnerSettings.Ephemeral, command.DisableUpdate);
agent = UpdateExistingAgent(agent, publicKey, userLabels, runnerSettings.Ephemeral, command.DisableUpdate, command.NoDefaultLabels);

try
{
Expand Down Expand Up @@ -293,7 +293,7 @@ public async Task ConfigureAsync(CommandSettings command)
else
{
// Create a new agent.
agent = CreateNewAgent(runnerSettings.AgentName, publicKey, userLabels, runnerSettings.Ephemeral, command.DisableUpdate);
agent = CreateNewAgent(runnerSettings.AgentName, publicKey, userLabels, runnerSettings.Ephemeral, command.DisableUpdate, command.NoDefaultLabels);

try
{
Expand Down Expand Up @@ -554,7 +554,7 @@ private ICredentialProvider GetCredentialProvider(CommandSettings command, strin
}


private TaskAgent UpdateExistingAgent(TaskAgent agent, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral, bool disableUpdate)
private TaskAgent UpdateExistingAgent(TaskAgent agent, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral, bool disableUpdate, bool noDefaultLabels)
{
ArgUtil.NotNull(agent, nameof(agent));
agent.Authorization = new TaskAgentAuthorization
Expand All @@ -571,9 +571,16 @@ private TaskAgent UpdateExistingAgent(TaskAgent agent, RSAParameters publicKey,

agent.Labels.Clear();

agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System));
agent.Labels.Add(new AgentLabel(VarUtil.OS, LabelType.System));
agent.Labels.Add(new AgentLabel(VarUtil.OSArchitecture, LabelType.System));
if (!noDefaultLabels)
{
agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System));
agent.Labels.Add(new AgentLabel(VarUtil.OS, LabelType.System));
agent.Labels.Add(new AgentLabel(VarUtil.OSArchitecture, LabelType.System));
}
else if (userLabels.Count == 0)
{
throw new NotSupportedException("Disabling default labels via --no-default-labels without specifying --labels is not supported");
}

foreach (var userLabel in userLabels)
{
Expand All @@ -583,7 +590,7 @@ private TaskAgent UpdateExistingAgent(TaskAgent agent, RSAParameters publicKey,
return agent;
}

private TaskAgent CreateNewAgent(string agentName, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral, bool disableUpdate)
private TaskAgent CreateNewAgent(string agentName, RSAParameters publicKey, ISet<string> userLabels, bool ephemeral, bool disableUpdate, bool noDefaultLabels)
{
TaskAgent agent = new(agentName)
{
Expand All @@ -598,9 +605,16 @@ private TaskAgent CreateNewAgent(string agentName, RSAParameters publicKey, ISet
DisableUpdate = disableUpdate
};

agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System));
agent.Labels.Add(new AgentLabel(VarUtil.OS, LabelType.System));
agent.Labels.Add(new AgentLabel(VarUtil.OSArchitecture, LabelType.System));
if (!noDefaultLabels)
{
agent.Labels.Add(new AgentLabel("self-hosted", LabelType.System));
agent.Labels.Add(new AgentLabel(VarUtil.OS, LabelType.System));
agent.Labels.Add(new AgentLabel(VarUtil.OSArchitecture, LabelType.System));
}
else if (userLabels.Count == 0)
{
throw new NotSupportedException("Disabling default labels via --no-default-labels without specifying --labels is not supported");
}

foreach (var userLabel in userLabels)
{
Expand Down
3 changes: 2 additions & 1 deletion src/Runner.Listener/Runner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -683,7 +683,8 @@ private void PrintUsage(CommandSettings command)
--token string Registration token. Required if unattended
--name string Name of the runner to configure (default {Environment.MachineName ?? "myrunner"})
--runnergroup string Name of the runner group to add this runner to (defaults to the default runner group)
--labels string Extra labels in addition to the default: 'self-hosted,{Constants.Runner.Platform},{Constants.Runner.PlatformArchitecture}'
--labels string Custom labels that will be added to the runner. This option is mandatory if --no-default-labels is used.
--no-default-labels Disables adding the default labels: 'self-hosted,{Constants.Runner.Platform},{Constants.Runner.PlatformArchitecture}'
--local Removes the runner config files from your local machine. Used as an option to the remove command
--work string Relative runner work directory (default {Constants.Path.WorkDirectory})
--replace Replace any existing runner with the same name (default false)
Expand Down
101 changes: 101 additions & 0 deletions src/Test/L0/Listener/Configuration/ConfigurationManagerL0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,107 @@ public async Task CanEnsureConfigure()
}
}

[Fact]
[Trait("Level", "L0")]
[Trait("Category", "ConfigurationManagement")]
public async Task ConfigureErrorDefaultLabelsDisabledWithNoCustomLabels()
{
using (TestHostContext tc = CreateTestContext())
{
Tracing trace = tc.GetTrace();

trace.Info("Creating config manager");
IConfigurationManager configManager = new ConfigurationManager();
configManager.Initialize(tc);

trace.Info("Preparing command line arguments");
var command = new CommandSettings(
tc,
new[]
{
"configure",
"--url", _expectedServerUrl,
"--name", _expectedAgentName,
"--runnergroup", _secondRunnerGroupName,
"--work", _expectedWorkFolder,
"--auth", _expectedAuthType,
"--token", _expectedToken,
"--no-default-labels",
"--ephemeral",
"--disableupdate",
"--unattended",
});
trace.Info("Constructed.");
_store.Setup(x => x.IsConfigured()).Returns(false);
_configMgrAgentSettings = null;

trace.Info("Ensuring configure fails if default labels are disabled and no custom labels are set");
var ex = await Assert.ThrowsAsync<NotSupportedException>(() => configManager.ConfigureAsync(command));

Assert.Contains("--no-default-labels without specifying --labels is not supported", ex.Message);
}
}

[Fact]
[Trait("Level", "L0")]
[Trait("Category", "ConfigurationManagement")]
public async Task ConfigureDefaultLabelsDisabledWithCustomLabels()
{
using (TestHostContext tc = CreateTestContext())
{
Tracing trace = tc.GetTrace();

trace.Info("Creating config manager");
IConfigurationManager configManager = new ConfigurationManager();
configManager.Initialize(tc);

var userLabels = "userlabel1,userlabel2";

trace.Info("Preparing command line arguments");
var command = new CommandSettings(
tc,
new[]
{
"configure",
"--url", _expectedServerUrl,
"--name", _expectedAgentName,
"--runnergroup", _secondRunnerGroupName,
"--work", _expectedWorkFolder,
"--auth", _expectedAuthType,
"--token", _expectedToken,
"--labels", userLabels,
"--no-default-labels",
"--ephemeral",
"--disableupdate",
"--unattended",
});
trace.Info("Constructed.");
_store.Setup(x => x.IsConfigured()).Returns(false);
_configMgrAgentSettings = null;

trace.Info("Ensuring all the required parameters are available in the command line parameter");
await configManager.ConfigureAsync(command);

_store.Setup(x => x.IsConfigured()).Returns(true);

trace.Info("Configured, verifying all the parameter value");
var s = configManager.LoadSettings();
Assert.NotNull(s);
Assert.True(s.ServerUrl.Equals(_expectedServerUrl));
Assert.True(s.AgentName.Equals(_expectedAgentName));
Assert.True(s.PoolId.Equals(_secondRunnerGroupId));
Assert.True(s.WorkFolder.Equals(_expectedWorkFolder));
Assert.True(s.Ephemeral.Equals(true));

// validate GetAgentPoolsAsync gets called twice with automation pool type
_runnerServer.Verify(x => x.GetAgentPoolsAsync(It.IsAny<string>(), It.Is<TaskAgentPoolType>(p => p == TaskAgentPoolType.Automation)), Times.Exactly(2));

var expectedLabels = userLabels.Split(",").ToList();

_runnerServer.Verify(x => x.AddAgentAsync(It.IsAny<int>(), It.Is<TaskAgent>(a => a.Labels.Select(x => x.Name).ToHashSet().SetEquals(expectedLabels))), Times.Once);
}
}

[Fact]
[Trait("Level", "L0")]
[Trait("Category", "ConfigurationManagement")]
Expand Down

0 comments on commit eeb0cf6

Please sign in to comment.