Skip to content

Commit

Permalink
Create a Windows Server label with os.name (#1201)
Browse files Browse the repository at this point in the history
The Jenkins agent list shows the value of the Java `os.name` property to
users in the "Architecture" column.  This change adds a new label for
agents based on the value in that architecture column.  It is enabled by
default.

For most Linux distributions (CentOS, Debian, openSUSE, Red Hat,
Ubuntu), the value will be "Linux".  FreeBSD agents will have the value
"FreeBSD".  Windows agents will have a value that depends on the Windows
version that is installed.  Some examples include:

* Windows11
* Windows10
* WindowsServer2016
* WindowsServer2019
* WindowsServer2023

The operating system name label can be enabled and disabled globally and
can be enabled and disabled on each agent individually.

Fixes #612

Existing labels are unaffected by the addition.  Windows agents will
still be labeled "windows", as controlled by the "Generate label with
OS name" setting.  Debian agents will still be labeled "Debian".

Interactive testing has been performed to verify Windows and Linux
agents are labeled as expected with the various configurations.
  • Loading branch information
MarkEWaite authored Nov 18, 2023
1 parent f27fe52 commit 8f074df
Show file tree
Hide file tree
Showing 12 changed files with 148 additions and 7 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ Labels commonly include operating system name, version, architecture, and Window
| Ubuntu 20 | `Ubuntu` | `20.04` | `amd64` | // EOL: 2 Apr 2025
| Ubuntu 22 | `Ubuntu` | `22.04` | `amd64` | // EOL: 1 Apr 2027
| Windows 10 | `windows` | `10.0` | `amd64` | // EOL: 14 Oct 2025
| Windows Server 2016 | `WindowsServer2016`| `10.0` | `amd64` | // EOL: 12 Jan 2027
| Windows Server 2019 | `WindowsServer2019`| `10.0` | `amd64` | // EOL: 9 Jan 2029
| Windows Server 2022 | `WindowsServer2022`| `10.0` | `amd64` | // EOL: 14 Oct 2031

## ARM 64 bit (aarch64)

Expand Down Expand Up @@ -103,6 +106,7 @@ unclassified:
architectureNameVersion: false
name: true
nameVersion: false
osName: true
version: true
windowsFeatureUpdate: false
```
Expand All @@ -125,6 +129,7 @@ jenkins:
architectureNameVersion: false
name: true
nameVersion: false
osName: true
version: true
windowsFeatureUpdate: false
remoteFS: "C:\\Users\\Jenkins\\agent"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ public class LabelConfig extends AbstractDescribableImpl<LabelConfig> {
private boolean name = true;
private boolean version = true;
private boolean windowsFeatureUpdate = true;
private boolean osName = true;
private boolean architectureName = true;
private boolean nameVersion = true;
private boolean architectureNameVersion = true;
Expand All @@ -30,6 +31,7 @@ public LabelConfig() {
this.name = srcLabelConfig.name;
this.version = srcLabelConfig.version;
this.windowsFeatureUpdate = srcLabelConfig.windowsFeatureUpdate;
this.osName = srcLabelConfig.osName;
this.architectureName = srcLabelConfig.architectureName;
this.nameVersion = srcLabelConfig.nameVersion;
this.architectureNameVersion = srcLabelConfig.architectureNameVersion;
Expand Down Expand Up @@ -99,6 +101,15 @@ public void setWindowsFeatureUpdate(boolean includeWindowsFeatureUpdate) {
this.windowsFeatureUpdate = includeWindowsFeatureUpdate;
}

public boolean isOsName() {
return osName;
}

@DataBoundSetter
public void setOsName(boolean osName) {
this.osName = osName;
}

@Extension
@Symbol("platformlabelerconfig")
public static class DescriptorImpl extends Descriptor<LabelConfig> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,10 @@ Collection<LabelAtom> getLabelsForNode(final Node node) {
result.add(jenkins.getLabelAtom(pp.getWindowsFeatureUpdate()));
}

if (labelConfig.isOsName() && pp.getOsName() != null) {

Check warning on line 231 in src/main/java/org/jvnet/hudson/plugins/platformlabeler/NodeLabelCache.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 231 is only partially covered, one branch is missing
result.add(jenkins.getLabelAtom(pp.getOsName()));
}

return result;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class PlatformDetails implements Serializable {
private final String architecture;
private final String version;
private final String windowsFeatureUpdate;
private final String osName;
private final String architectureNameVersion;
private final String architectureName;
private final String nameVersion;
Expand All @@ -26,11 +27,11 @@ public class PlatformDetails implements Serializable {
*/
@Deprecated
public PlatformDetails(@NonNull String name, @NonNull String architecture, @NonNull String version) {
this(name, architecture, version, null);
this(name, architecture, version, null, null);
}

/**
* Platform details constructor.
* Platform details constructor (deprecated).
*
* @param name name of operating system, as in windows, debian, ubuntu, etc.
* @param architecture hardware architecture, as in amd64, aarch64, etc.
Expand All @@ -43,6 +44,25 @@ public PlatformDetails(
@NonNull String architecture,
@NonNull String version,
@CheckForNull String windowsFeatureUpdate) {
this(name, architecture, version, windowsFeatureUpdate, null);
}

Check warning on line 48 in src/main/java/org/jvnet/hudson/plugins/platformlabeler/PlatformDetails.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered lines

Lines 47-48 are not covered by tests

/**
* Platform details constructor.
*
* @param name name of operating system, as in windows, debian, ubuntu, etc.
* @param architecture hardware architecture, as in amd64, aarch64, etc.
* @param version version of operating system, as in 9.1, 14.04, etc.
* @param windowsFeatureUpdate windows feature update version string, as in 1809, 1903, 2009,
* 2103, etc.
* @param osName name of operating system as provided by the Java os.name property
*/
public PlatformDetails(
@NonNull String name,
@NonNull String architecture,
@NonNull String version,
@CheckForNull String windowsFeatureUpdate,
@CheckForNull String osName) {
this.name = name;
this.architecture = architecture;
this.version = version;
Expand All @@ -54,6 +74,10 @@ public PlatformDetails(
featureUpdate = null;
}
this.windowsFeatureUpdate = featureUpdate;
if (osName != null && osName.isEmpty()) {
osName = null;
}
this.osName = osName;
}

@NonNull
Expand Down Expand Up @@ -90,4 +114,9 @@ public String getNameVersion() {
public String getWindowsFeatureUpdate() {
return windowsFeatureUpdate;
}

@CheckForNull
public String getOsName() {
return osName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ protected PlatformDetails computeLabels(
String computedArch = arch;
String computedVersion = version;
String windowsFeatureUpdate = null;
String osName = name; // os.name Java property of agent JVM
if (computedName.startsWith("windows")) {
computedName = "windows";
computedArch = checkWindows32Bit(
Expand All @@ -223,6 +224,21 @@ protected PlatformDetails computeLabels(
windowsFeatureUpdate = null;
}
}
if (osName.startsWith("Windows Server")) {
if (osName.contains("2022")) {
osName = "WindowsServer2022";
} else if (osName.contains("2019")) {
osName = "WindowsServer2019";
} else if (osName.contains("2016")) {
osName = "WindowsServer2016";
} else {
osName = "WindowsServer";
}
}
if (osName.startsWith("Windows 1")) {
// Remove spaces from osName for modern Windows desktop versions
osName = osName.replace(" ", "");
}
} else if (computedName.startsWith("linux")) {
if (release == null) {
release = new LsbRelease();
Expand Down Expand Up @@ -308,7 +324,7 @@ protected PlatformDetails computeLabels(
computedName = "mac";
}
PlatformDetails properties =
new PlatformDetails(computedName, computedArch, computedVersion, windowsFeatureUpdate);
new PlatformDetails(computedName, computedArch, computedVersion, windowsFeatureUpdate, osName);
return properties;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@
<f:entry field="windowsFeatureUpdate" title="${%Generate.LabelWithWindowsFeatureUpdate}">
<f:checkbox default="true"/>
</f:entry>
<f:entry field="osName" title="${%Generate.LabelWithOsName}">
<f:checkbox default="true"/>
</f:entry>
<f:entry field="architectureName" title="${%Generate.LabelWithOSArchitectureAndName}">
<f:checkbox default="true"/>
</f:entry>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
Generate.LabelWithOSArchitecture=Generate label with OS architecture
Generate.LabelWithOSName=Generate label with OS name
Generate.LabelWithOSVersion=Generate label with OS version
Generate.LabelWithWindowsFeatureUpdate=Generate label with Windows feature update (like 1809, 1903, 2009, or 2103)
Generate.LabelWithWindowsFeatureUpdate=Generate label with Windows feature update (like 1607. 1809, 21H2, and 22H2)
Generate.LabelWithOsName=Generate label with operating system name (Java property os.name)
Generate.LabelWithOSArchitectureAndName=Generate label with OS architecture and name
Generate.LabelWithOSNameAndVersion=Generate label with OS name and version
Generate.LabelWithOSArchitectureNameAndVersion=Generate label with OS architecture, name, and version
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public void configuredNameOnlyLabel() {
labelConfig.setVersion(false);
labelConfig.setNameVersion(false);
labelConfig.setWindowsFeatureUpdate(false);
labelConfig.setOsName(false);
nodeProperty.setLabelConfig(labelConfig);
r.jenkins.getNodeProperties().add(nodeProperty);

Expand All @@ -66,6 +67,7 @@ public void configuredTwoLabels() {
labelConfig.setName(false);
labelConfig.setNameVersion(false);
labelConfig.setWindowsFeatureUpdate(false);
labelConfig.setOsName(false);
nodeProperty.setLabelConfig(labelConfig);
r.jenkins.getNodeProperties().add(nodeProperty);

Expand Down Expand Up @@ -109,6 +111,7 @@ public void configuredAllLabelsOnEphemeralNode() throws Exception {
*/
expected.add(r.jenkins.getLabelAtom(platformDetails.getWindowsFeatureUpdate()));
}
expected.add(r.jenkins.getLabelAtom(platformDetails.getOsName()));

// Static labels of the agent
expected.add(r.jenkins.getLabelAtom("agent"));
Expand Down Expand Up @@ -145,6 +148,7 @@ public void configuredAllLabelsOnNode() {
*/
expected.add(r.jenkins.getLabelAtom(platformDetails.getWindowsFeatureUpdate()));
}
expected.add(r.jenkins.getLabelAtom(platformDetails.getOsName()));

Set<LabelAtom> labelsAfter = computer.getNode().getAssignedLabels();
assertThat(labelsAfter, is(expected));
Expand All @@ -167,6 +171,7 @@ public void nodeConfigOverridesGlobalConfig() {
LabelConfig labelConfig = new LabelConfig();
labelConfig.setVersion(false);
labelConfig.setWindowsFeatureUpdate(false);
labelConfig.setOsName(false);
nodeProperty.setLabelConfig(labelConfig);
r.jenkins.getNodeProperties().add(nodeProperty);

Expand Down Expand Up @@ -195,6 +200,7 @@ public void globalConfigOnlyArchitecture() {
globalLabelConfig.setVersion(false);
globalLabelConfig.setName(false);
globalLabelConfig.setWindowsFeatureUpdate(false);
globalLabelConfig.setOsName(false);
globalLabelConfig.setArchitectureName(false);
globalLabelConfig.setArchitectureNameVersion(false);
globalLabelConfig.setNameVersion(false);
Expand Down Expand Up @@ -223,5 +229,6 @@ public void configRoundTripTest() throws Exception {
assertThat(globalLabelConfigBefore.isVersion(), is(globalLabelConfigAfter.isVersion()));
assertThat(
globalLabelConfigBefore.isWindowsFeatureUpdate(), is(globalLabelConfigAfter.isWindowsFeatureUpdate()));
assertThat(globalLabelConfigBefore.isOsName(), is(globalLabelConfigAfter.isOsName()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ public class LabelConfigTest {
private boolean randomIsNameVersion;
private boolean randomIsArchitectureNameVersion;
private boolean randomIsWindowsFeatureUpdate;
private boolean randomIsOsName;

public LabelConfigTest() {}

Expand All @@ -35,6 +36,7 @@ public void setUp() {
randomIsNameVersion = random.nextBoolean();
randomIsArchitectureNameVersion = random.nextBoolean();
randomIsWindowsFeatureUpdate = random.nextBoolean();
randomIsOsName = random.nextBoolean();

randomSrcLabelConfig.setArchitecture(randomIsArchitecture);
randomSrcLabelConfig.setName(randomIsName);
Expand All @@ -43,6 +45,7 @@ public void setUp() {
randomSrcLabelConfig.setNameVersion(randomIsNameVersion);
randomSrcLabelConfig.setArchitectureNameVersion(randomIsArchitectureNameVersion);
randomSrcLabelConfig.setWindowsFeatureUpdate(randomIsWindowsFeatureUpdate);
randomSrcLabelConfig.setOsName(randomIsOsName);

defaultConfig = new LabelConfig();
randomConfig = new LabelConfig(randomSrcLabelConfig);
Expand Down Expand Up @@ -142,4 +145,16 @@ public void testSetWindowsFeatureUpdate() {
defaultConfig.setWindowsFeatureUpdate(!randomIsWindowsFeatureUpdate);
assertThat(defaultConfig.isWindowsFeatureUpdate(), is(!randomIsWindowsFeatureUpdate));
}

@Test
public void testIsOsName() {
assertThat(defaultConfig.isOsName(), is(true));
assertThat(randomConfig.isOsName(), is(randomIsOsName));
}

@Test
public void testSetOsName() {
defaultConfig.setOsName(!randomIsOsName);
assertThat(defaultConfig.isOsName(), is(!randomIsOsName));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ public void testRequestComputerPlatformDetails() throws Exception {
assertThat(platformDetails.getName(), is(localDetails.getName()));
assertThat(platformDetails.getVersion(), is(localDetails.getVersion()));
assertThat(platformDetails.getWindowsFeatureUpdate(), is(localDetails.getWindowsFeatureUpdate()));
assertThat(platformDetails.getOsName(), is(localDetails.getOsName()));
}

@Test
Expand All @@ -145,6 +146,7 @@ public void testGetLabelsForNode() throws IOException {
is(localDetails.getName()),
is(localDetails.getNameVersion()),
is(localDetails.getVersion()),
is(localDetails.getOsName()),
is(localDetails.getWindowsFeatureUpdate())));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,13 @@ void testComputeLabels(String name, String arch, String version) throws Exceptio
String expectedName = computeExpectedName(name);
String expectedArch = computeExpectedArch(name, arch);
String expectedVersion = computeVersion(name, version);
String expectedOsName = computeExpectedOsName(name);
PlatformDetailsTask details = new PlatformDetailsTask();
PlatformDetails result = details.computeLabels(arch, name, version);
assertThat(result.getArchitecture(), is(expectedArch));
assertThat(result.getName(), is(expectedName));
assertThat(result.getVersion(), is(expectedVersion));
assertThat(result.getOsName(), is(expectedOsName));
}

private static String computeExpectedArch(String name, String arch) {
Expand Down Expand Up @@ -143,6 +145,23 @@ private String computeExpectedName(String name) {
return name.toLowerCase(Locale.ENGLISH);
}

private String computeExpectedOsName(String name) {
if (name.startsWith("Windows Server")) {
if (name.contains("2022")) {
return "WindowsServer2022";
} else if (name.contains("2019")) {
return "WindowsServer2019";
} else if (name.contains("2016")) {
return "WindowsServer2016";
}
return "WindowsServer";
}
if (name.startsWith("Windows 1")) {
return name.replace(" ", "");
}
return name;
}

private String computeVersion(String name, String version) {
if (name.startsWith("Windows")) {
switch (version) {
Expand Down
Loading

0 comments on commit 8f074df

Please sign in to comment.