feat(operating_systems): bootstrap Windows Server 2022 - #83
Merged
Conversation
Adds Windows_Server_2022 beside Windows_Server_2025. The dispatcher detects Windows before facts are available, so it can only route an OS family to one role; the mapped role owns strict release validation itself. A consumer with mixed releases selects this one per play by overriding os_bootstrap_role_map, which is a role parameter and outranks the utility's own vars. Server 2022 is NT 10.0 build 20348. No released Windows client shares that build -- unlike 26100, which Windows 11 24H2 also carries -- but the product type is asserted regardless so the role states what it supports rather than relying on a build number happening to be unambiguous. Both roles now accept product type 'domain_controller' alongside 'server'. A domain controller IS a server; ProductType reports it separately only to name the role the machine holds, and the previous equality rejected a legitimate installation of the release each role is named for. The role does not install OpenSSH. Server 2022 ships without it, so the guest arrives over SSH only because something installed and started sshd before Ansible connected -- reaching the host is itself the proof, and a check here could only re-verify what the connection already established.
…lected The Adding an OS section says to extend os_bootstrap_role_map, which is right for a new family and wrong for a second release of one already mapped. Windows detection resolves before facts, so the map cannot tell 2022 from 2025; editing it routes every Windows host to one role and fails the other's support assertion. The consumer overrides the map per play instead, which works because a role parameter outranks role vars.
Detection resolves an OS FAMILY, and on Windows it resolves before facts exist because the bootstrap is what repairs the transport those facts travel over. The map therefore holds one role per family and cannot tell Server 2022 from Server 2025 -- but the inventory that launched the image already knows which it is. os_bootstrap_role, set on a host, now wins over the map. A host variable is the only override that arrives before detection and does not become a role parameter, which callers are told never to pass because one outranks the connection scoping the pre-flip stage depends on. Empty falls through to the map, so hosts that say nothing keep the default and no existing consumer changes behaviour. Replaces the README guidance added a commit ago, which suggested a role parameter and so contradicted that rule.
NWarila
pushed a commit
that referenced
this pull request
Sep 1, 2026
🤖 I have created a release *beep* *boop* --- ## [0.1.7](v0.1.6...v0.1.7) (2026-09-01) ### Features * four namespaces, two site-policy roles, and a readiness role that knows its platform ([#77](#77)) ([363c5b4](363c5b4)) * **operating_systems:** bootstrap Windows Server 2022 ([#83](#83)) ([a372c4a](a372c4a)) * read deployment secrets through one URL-addressed lookup ([#81](#81)) ([c584528](c584528)) ### Bug Fixes * **domain_member:** decide on the machine account, not only the membership ([#82](#82)) ([076eb02](076eb02)) * **windows_disk_manager:** let a host with one declared disk find it ([#80](#80)) ([7568f6d](7568f6d)) --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Adds a
Windows_Server_2022bootstrap role besideWindows_Server_2025, so a consumer canbring up a Server 2022 guest. Today a 2022 host reaches
Windows_Server_2025, has its transportmodified, and then fails that role's
build == 26100assertion.Also widens the product-type assertion in both Windows roles, and documents how a second
release of an already-mapped family is selected.
Type of change
feat:)docs:)Checklist
pre-commit run --all-fileslocally and all hooks pass —pre-commitis not installed on this workstation; CI will run itansible-lintandyamllintlocally and no errors are reportedTesting
ansible-lintandyamllintreport identical results for the new role and its 2025 sibling —24 warnings, 0 failures each — so the addition introduces no new findings. The warnings are the
existing
#regionbanner idiom shared across this repository.Structural check: every file except
tasks/bootstrap.ymlis byte-identical to the sibling oncerelease identity is normalised, and
bootstrap.ymldiffers only in the release comment block.Banner and region widths match the sibling exactly.
Not yet exercised against a live Server 2022 host. The consumer that needs it
(
pdq-deploy-inventory) pins a framework SHA and cannot reach this role until a release is cutand that pin moves. First live use is the reason for the change, not evidence for it.
Additional notes
Routing. The map is deliberately left alone. Detection yields an OS family, and on Windows
it resolves before facts exist, so
os_bootstrap_role_mapholds one role per family and cannottell 2022 from 2025 — pointing
Windowsat either routes every Windows host to it and fails theother's assertion. A consumer running both overrides the map per play, which works because a role
parameter outranks role vars. That is now written down in the
os_bootstrapREADME, because the"Adding an OS" section previously said to extend the map and following it literally would break
every existing 2025 consumer.
Product type. Both roles previously required
os_product_type == 'server'. A domaincontroller reports
domain_controller, so the equality rejected a legitimate installation of therelease each role is named for. Both now accept either: a domain controller is a server, and
ProductTypereports it separately only to name the role the machine holds. This changesbehaviour for
Windows_Server_2025as well, which is why it is called out rather than buried.Duplication, accepted deliberately. This is a fork of the 2025 role: of 451 lines the diff is
names, comments and the expected build. The two must now be maintained in lockstep, and nothing
enforces that —
tests/is empty in both. The alternative was one role accepting several builds,which changes the role-per-release shape this repository already uses for Rocky 8/9/10. The
fork was chosen to match that existing pattern.
No OpenSSH handling here. Server 2022 ships without OpenSSH, but installing it is not this
role's job: a guest reached over SSH proves
sshdis already installed and running, so a checkhere could only re-verify what the connection established. Provisioning installs it — in the AWS
case via the Feature-on-Demand cab that
aws-terraform-frameworkfetches whenwindows_fod_sourceis set.