Skip to content

feat: add RFC 7386 JSON Merge Patch overlays for environment lab configs#139

Merged
l50 merged 7 commits into
mainfrom
feat/config-and-hostname-updates
Apr 22, 2026
Merged

feat: add RFC 7386 JSON Merge Patch overlays for environment lab configs#139
l50 merged 7 commits into
mainfrom
feat/config-and-hostname-updates

Conversation

@l50
Copy link
Copy Markdown
Contributor

@l50 l50 commented Apr 22, 2026

Key Changes:

  • Introduced environment overlay (*-overlay.json) support for lab configs
  • Implemented RFC 7386 JSON Merge Patch for config merging and overlays
  • Updated CLI and internal APIs to resolve, cache, and use overlays at runtime
  • Refactored variant generator and test coverage to support new overlay model

Added:

  • Overlay config support - Environments can now use {env}-overlay.json files in
    ad/GOAD/data/ to override only the fields that differ from the base
    config.json, reducing duplication
  • RFC 7386 JSON Merge Patch implementation - New cli/internal/jsonmerge
    package provides diff/patch logic and round-trip test coverage
  • Test overlays and overlay resolution tests - Added test, dev, and staging
    overlays and CLI/config tests to ensure overlay merging produces correct
    configs
  • Overlay documentation - Detailed overlay usage, format, and resolution order
    added to docs/cli.md, provisioning, and developer docs

Changed:

  • Lab config resolution logic - CLI and labmap loading now merge overlays at
    runtime (using cached merged outputs in .dreadgoad/cache/) and fall back to
    legacy {env}-config.json or config.json if overlays are not present
  • dreadgoad env create and variant generator - Overlay files are now handled
    separately from full configs, and overlays are generated or transformed as
    needed for new environments
  • Inventory, variant, and config APIs - Refactored to use new overlay-aware
    resolution and merging logic throughout the CLI and provisioning codebase
  • Ansible playbook vars and docs - Minor updates to reflect overlay-driven
    configuration and clarify steps in host/domain state logic

Removed:

  • Full per-environment config files - Legacy {env}-config.json files are no
    longer created for new environments (but still supported for backward
    compatibility)
  • Redundant config duplication - Overlay model eliminates the need for full
    environment config copies, reducing maintenance effort and merge conflicts

l50 added 5 commits April 21, 2026 09:54
…rce handling

**Added:**

- Introduced strongly typed LabConfig, HostConfig, DomainConfig, and related
  struct types to represent GOAD config.json structure in the variant generator
- Added fileExists utility for robust file existence checks in config package
- Implemented additional test coverage for variant and config logic, especially
  around variant config resolution and new struct-based generator operations

**Changed:**

- Refactored generator to operate directly on typed config structures instead of
  generic map[string]any, improving code safety and maintainability
- Updated all transformation, mapping, and fixing functions in the generator to
  use typed access (e.g., config.Lab.Hosts) rather than dynamic map traversal
- Improved error handling for file and resource closing throughout the codebase,
  now logging or propagating close errors for log files, inventory, and builders
- Enhanced variant config resolution logic to properly prioritize variant configs
  if present, and fall back to base config otherwise
- Generator now validates structure counts using strongly typed config for
  consistency checks

**Removed:**

- Removed legacy dynamic JSON traversal helpers (jsonPath, jsonStr) from the
  generator in favor of direct typed field access
**Added:**

- Automated detection of current hostname, domain join state, and DC status
- Automated removal of ADCS features before DC demotion, including conditional
  reboots and timeout handling
- Automated domain controller demotion with secure admin password usage and
  conditional reboot
- Automated domain unjoin process with PowerShell and WMI fallback, plus
  conditional reboot before hostname change

**Changed:**

- Updated role documentation to reflect new pre-flight and cleanup automation
  steps in the hostname change workflow
- Reorganized main task file to sequence pre-flight, ADCS removal, DC demotion,
  domain unjoin, and required reboots before changing the hostname
… for dc demotion

**Added:**

- Introduced `domain`, `domain_username`, and `domain_password` variables in
  the AD servers playbook to support module authentication

**Changed:**

- Switched ADCS feature removal from a custom PowerShell script to the
  `ansible.windows.win_feature` module for clearer intent and reliability
- Replaced DC demotion PowerShell script with `microsoft.ad.domain_controller`
  module, allowing use of domain credentials and improved idempotency
- Updated domain unjoin logic to use `microsoft.ad.membership` instead of
  PowerShell/WMI, providing better error handling and integration
- Enhanced reboot logic after DC demotion and domain unjoin to account for
  module-reported reboot requirements
- Updated `settings_hostname` role documentation to reflect use of native
  Ansible modules instead of PowerShell scripts

**Removed:**

- Eliminated custom PowerShell scripts for ADCS removal, DC demotion, and domain
  unjoin, reducing complexity and risk of script errors
refactor: switch to win_powershell for LAPS and GPO tasks, improve reliability
**Added:**

- Introduced a dedicated task to wait for LAPS CSE to process GPO after
  refresh in the `laps_server` role, ensuring password is set properly

**Changed:**

- Replaced `win_shell` with `win_powershell` for moving servers to LAPS OU,
  adding explicit error handling and idempotency to improve reliability in
  `laps_dc` role
- Updated documentation in `laps_dc/README.md` and `laps_server/README.md` to
  reflect use of `win_powershell` instead of `win_shell` for relevant tasks
- Refined GPO refresh logic in `laps_server` install workflow to use
  `win_powershell` and added a wait step for LAPS CSE processing, improving
  clarity and idempotency
- Changed WMI query to use `Get-CimInstance` instead of `Get-WmiObject` for
  checking computer system state in hostname settings role, aligning with
  modern PowerShell best practices
- Simplified reboot conditionals in hostname settings role by removing
  checks for `reboot_required` and relying solely on change detection

**Removed:**

- Removed use of deprecated `Get-WmiObject` cmdlet in favor of `Get-CimInstance`
- Eliminated unnecessary or redundant reboot conditional logic in hostname
  settings tasks
```
…e utilities

**Added:**

- Introduced overlay-based environment config system using RFC 7386 JSON Merge Patch
- Added `.dreadgoad/` and `.envrc` to `.gitignore` for improved local dev ergonomics
- Implemented `cli/internal/jsonmerge/` package for JSON Merge Patch diff and merge
- Added comprehensive unit tests for JSON merge/diff utilities
- Created new overlay files (`*-overlay.json`) for dev, staging, and test in GOAD lab data
- Documented overlay system and merge semantics in `docs/cli.md`, `add_lab.md`, and `provisioning.md`
- Updated `env create` to generate overlay files instead of full config copies

**Changed:**

- Switched CLI and labmap resolution logic to prefer `{env}-overlay.json` merged with `config.json`, falling back to legacy `{env}-config.json` if needed
- Updated `LabConfigPath` logic to cache merged configs in `.dreadgoad/cache/` and auto-invalidate on source change
- Refactored CLI env listing, creation, and variant generation to use overlay system
- Updated variant generator to preserve "password in description" for users during transformation
- Enhanced `ansible/roles/ad/tasks/users.yml` to update user descriptions if changed

**Removed:**

- Deleted full per-environment lab config files (`dev-config.json`, `staging-config.json`, `test-config.json`) in favor of overlays
- Removed legacy logic in env scaffolding that copied entire config files for each environment
@dreadnode-renovate-bot dreadnode-renovate-bot Bot added lab/GOAD Changes made to GOAD lab area/playbooks Changes made to playbooks directory area/ad-labs Changes made to AD lab definitions area/roles Changes made to Ansible roles area/docs Changes made to documentation labels Apr 22, 2026
l50 added 2 commits April 22, 2026 11:39
**Changed:**

- Enhance error handling for cache file renaming by returning combined error if
  both the rename and cleanup (temporary file removal) fail, providing more
  context for debugging in `mergedConfigPath` function
@l50 l50 merged commit ecf02aa into main Apr 22, 2026
8 checks passed
@l50 l50 deleted the feat/config-and-hostname-updates branch April 22, 2026 17:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/ad-labs Changes made to AD lab definitions area/docs Changes made to documentation area/playbooks Changes made to playbooks directory area/roles Changes made to Ansible roles lab/GOAD Changes made to GOAD lab

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant