Computer: Remove deletion of AD computer object when using PasswordPass and UnsecuredJoin options or JoinReadOnly option
Pull Request (PR) description
When using PasswordPass and UnsecuredJoin options or JoinReadOnly option means AD computer object has been pre-created within Active Directory prior to domain join and should not be deleted
This Pull Request (PR) fixes the following issues
- Fixes #446
Task list
- [x] Added an entry to the change log under the Unreleased section of the file CHANGELOG.md. Entry should say what was changed and how that affects users (if applicable), and reference the issue being resolved (if applicable).
- [x] Resource documentation added/updated in README.md.
- [x] Resource parameter descriptions added/updated in README.md, schema.mof and comment-based help.
- [x] Comment-based help added/updated.
- [x] Localization strings added/updated in all localization files as appropriate.
- [x] Examples appropriately added/updated.
- [x] Unit tests added/updated. See DSC Community Testing Guidelines.
- [x] Integration tests added/updated (where possible). See DSC Community Testing Guidelines.
- [x] New/changed code adheres to DSC Community Style Guidelines.
Walkthrough
The changes modify the DSC_Computer resource to conditionally preserve pre-created Active Directory computer objects when using specific options (PasswordPass and UnsecuredJoin or JoinReadOnly), preventing deletion during domain join operations that expect the object to already exist.
Changes
| Cohort / File(s) | Summary |
|---|---|
Documentation CHANGELOG.md |
Added entry documenting that the computer object is no longer deleted when PasswordPass and UnsecuredJoin options or JoinReadOnly option are used (Issue #446). |
Resource Logic source/DSCResources/DSC_Computer/DSC_Computer.psm1 |
Introduces conditional logic to detect precreated computer object requirements via $requiresPrecreated based on JoinReadOnly or (PasswordPass and UnsecuredJoin) options. When precreation is required and object doesn't exist, raises ObjectNotFoundException. When precreation is not required and object exists, proceeds with deletion. Includes minor comment correction. |
Localization source/DSCResources/DSC_Computer/en-US/DSC_Computer.strings.psd1 |
Added new string resource ComputerObjectNotFound for localized error message when computer object is not found in domain. |
Sequence Diagram(s)
sequenceDiagram
participant Caller as DSC Configuration
participant Resource as DSC_Computer<br/>(Set-TargetResource)
participant AD as Active Directory
participant Error as Error Handler
Caller->>Resource: Invoke Set-TargetResource
Note over Resource: Detect precreated requirement<br/>($requiresPrecreated = JoinReadOnly OR<br/>(PasswordPass AND UnsecuredJoin))
Resource->>AD: Query for existing computer object
alt Object Exists
alt Precreation NOT Required
Resource->>AD: Delete computer object
Resource->>Caller: ✓ Proceed with join
else Precreation Required
Resource->>Caller: ✓ Object exists, continue
end
else Object Does NOT Exist
alt Precreation Required
Resource->>Error: Raise ObjectNotFoundException
Error->>Caller: ✗ Computer object not found error
else Precreation NOT Required
Resource->>Caller: ✓ Proceed (no deletion needed)
end
end
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~20 minutes
The changes introduce a new conditional control flow with multiple branches based on precreation detection and object existence, requiring careful verification that the option combinations and error conditions are correct. The logic is focused but depends on accurate interpretation of the PasswordPass, UnsecuredJoin, and JoinReadOnly options.
Pre-merge checks
✅ Passed checks (5 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title Check | ✅ Passed | The title clearly identifies the resource and concisely describes the primary change of preventing deletion of the AD computer object when using the specified options, directly reflecting the main focus of the changeset. |
| Linked Issues Check | ✅ Passed | The changes implement logic to detect and preserve pre-created AD computer objects when using PasswordPass, UnsecuredJoin, or JoinReadOnly options and add corresponding error handling and localization, fully satisfying the objectives of linked issue #446. |
| Out of Scope Changes Check | ✅ Passed | All modifications are confined to adjusting the computer resource behavior for pre-created objects and updating related localization and documentation, with no unrelated or extraneous changes introduced. |
| Description Check | ✅ Passed | The description succinctly explains the rationale behind the change, clarifies that pre-created AD computer objects should not be deleted when using the specified options, and references the related issue, making it clearly relevant to the changeset. |
| Docstring Coverage | ✅ Passed | No functions found in the changes. Docstring coverage check skipped. |
📜 Recent review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📥 Commits
Reviewing files that changed from the base of the PR and between 17e10f3b5c778db2c5cde0848888ca8fbe3af2a5 and 06fe4cbf82abfc3f3eddda461adf215750184a0b.
📒 Files selected for processing (3)
-
CHANGELOG.md(1 hunks) -
source/DSCResources/DSC_Computer/DSC_Computer.psm1(1 hunks) -
source/DSCResources/DSC_Computer/en-US/DSC_Computer.strings.psd1(1 hunks)
🧰 Additional context used
📓 Path-based instructions (5)
**
⚙️ CodeRabbit configuration file
**: # DSC Community GuidelinesTerminology
- Command: Public command
- Function: Private function
- Resource: DSC class-based resource
Build & Test Workflow Requirements
- Run PowerShell script files from repository root
- Setup build and test environment (once per
pwshsession):./build.ps1 -Tasks noop- Build project before running tests:
./build.ps1 -Tasks build- Always run tests in new
pwshsession:Invoke-Pester -Path @({test paths}) -Output DetailedFile Organization
- Public commands:
source/Public/{CommandName}.ps1- Private functions:
source/Private/{FunctionName}.ps1- Unit tests:
tests/Unit/{Classes|Public|Private}/{Name}.Tests.ps1- Integration tests:
tests/Integration/Commands/{CommandName}.Integration.Tests.ps1Requirements
- Follow instructions over existing code patterns
- Follow PowerShell style and test guideline instructions strictly
- Always update CHANGELOG.md Unreleased section
- Localize all strings using string keys; remove any orphaned string keys
- Check DscResource.Common before creating private functions
- Separate reusable logic into private functions
- DSC resources should always be created as class-based resources
- Add unit tests for all commands/functions/resources
- Add integration tests for all public commands and resources
Files:
-
source/DSCResources/DSC_Computer/en-US/DSC_Computer.strings.psd1 -
source/DSCResources/DSC_Computer/DSC_Computer.psm1 -
CHANGELOG.md
{**/*.ps1,**/*.psm1,**/*.psd1}
⚙️ CodeRabbit configuration file
{**/*.ps1,**/*.psm1,**/*.psd1}: # PowerShell GuidelinesNaming
- Use descriptive names (3+ characters, no abbreviations)
- Functions: PascalCase with Verb-Noun format using approved verbs
- Parameters: PascalCase
- Variables: camelCase
- Keywords: lower-case
- Classes: PascalCase
- Include scope for script/global/environment variables:
$script:,$global:,$env:File naming
- Class files:
###.ClassName.ps1format (e.g.001.SqlReason.ps1,004.StartupParameters.ps1)Formatting
Indentation & Spacing
- Use 4 spaces (no tabs)
- One space around operators:
$a = 1 + 2- One space between type and variable:
[String] $name- One space between keyword and parenthesis:
if ($condition)- No spaces on empty lines
- Try to limit lines to 120 characters
Braces
- Newline before opening brace (except variable assignments)
- One newline after opening brace
- Two newlines after closing brace (one if followed by another brace or continuation)
Quotes
- Use single quotes unless variable expansion is needed:
'text'vs"text $variable"Arrays
- Single line:
@('one', 'two', 'three')- Multi-line: each element on separate line with proper indentation
- Do not use the unary comma operator (
,) in return statements to force an arrayHashtables
- Empty:
@{}- Each property on separate line with proper indentation
- Properties: Use PascalCase
Comments
- Single line:
# Comment(capitalized, on own line)- Multi-line:
<# Comment #>format (opening and closing brackets on own line), and indent text- No commented-out code
Comment-based help
- Always add comment-based help to all functions and scripts
- Comment-based help: SYNOPSIS, DESCRIPTION (40+ chars), PARAMETER, EXAMPLE sections before function/class
- Comment-based help indentation: keywords 4 spaces, text 8 spaces
- Include examples for all parameter sets and combinations
- INPUTS: List each pipeline‑accepted type (one per line) with a 1‑line description...
Files:
-
source/DSCResources/DSC_Computer/en-US/DSC_Computer.strings.psd1 -
source/DSCResources/DSC_Computer/DSC_Computer.psm1
source/DSCResources/**/*.psm1
⚙️ CodeRabbit configuration file
source/DSCResources/**/*.psm1: # MOF-based Desired State Configuration (DSC) Resources GuidelinesRequired Functions
- Every DSC resource must define:
Get-TargetResource,Set-TargetResource,Test-TargetResource- Export using
*-TargetResourcepatternFunction Return Types
Get-TargetResource: Must return hashtable with all resource propertiesTest-TargetResource: Must return boolean ($true/$false)Set-TargetResource: Must not return anything (void)Parameter Guidelines
Get-TargetResource: Only include parameters needed to retrieve actual current state valuesGet-TargetResource: Remove non-mandatory parameters that are never usedSet-TargetResourceandTest-TargetResource: Must have identical parametersSet-TargetResourceandTest-TargetResource: Unused mandatory parameters: Add "Not used in <function_name>" to help commentRequired Elements
- Each function must include
Write-Verboseat least once
Get-TargetResource: Use verbose message starting with "Getting the current state of..."Set-TargetResource: Use verbose message starting with "Setting the desired state of..."Test-TargetResource: Use verbose message starting with "Determining the current state of..."- Use localized strings for all messages (Write-Verbose, Write-Error, etc.)
- Import localized strings using
Get-LocalizedDataat module topError Handling
- Do not use
throwfor terminating errors- Use
try/catchblocks to handle exceptions- Throw localized exceptions using the appropriate
New-*Exceptioncmdlet:
New‑InvalidDataExceptionNew-ArgumentExceptionNew-InvalidOperationException- [
New-ObjectNotFoundException](https:/...
Files:
-
source/DSCResources/DSC_Computer/DSC_Computer.psm1
**/*.md
⚙️ CodeRabbit configuration file
**/*.md: # Markdown Style Guidelines
- Wrap lines at word boundaries when over 80 characters (except tables/code blocks)
- Use 2 spaces for indentation
- Use '1.' for all items in ordered lists (1/1/1 numbering style)
- Disable
MD013rule by adding a comment for tables/code blocks exceeding 80 characters- Empty lines required before/after code blocks and headings (except before line 1)
- Escape backslashes in file paths only (not in code blocks)
- Code blocks must specify language identifiers
Text Formatting
- Parameters: bold
- Values/literals:
inline code- Resource/module/product names: italic
- Commands/files/paths:
inline code
Files:
-
CHANGELOG.md
CHANGELOG.md
⚙️ CodeRabbit configuration file
CHANGELOG.md: # Changelog Guidelines
- Always update the Unreleased section in CHANGELOG.md
- Use Keep a Changelog format
- Describe notable changes briefly, ≤2 items per change type
- Reference issues using format issue #<issue_number>
- No empty lines between list items in same section
- Skip adding entry if same change already exists in Unreleased section
- No duplicate sections or items in Unreleased section
Files:
-
CHANGELOG.md
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: dsccommunity.ComputerManagementDsc (Build Package Module)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
Codecov Report
:x: Patch coverage is 71.42857% with 2 lines in your changes missing coverage. Please review.
:white_check_mark: Project coverage is 86%. Comparing base (17e10f3) to head (06fe4cb).
| Files with missing lines | Patch % | Lines |
|---|---|---|
| source/DSCResources/DSC_Computer/DSC_Computer.psm1 | 71% | 2 Missing :warning: |
Additional details and impacted files
@@ Coverage Diff @@
## main #447 +/- ##
===================================
- Coverage 86% 86% -1%
===================================
Files 21 21
Lines 2083 2088 +5
===================================
+ Hits 1805 1808 +3
- Misses 278 280 +2
| Files with missing lines | Coverage Δ | |
|---|---|---|
| source/DSCResources/DSC_Computer/DSC_Computer.psm1 | 89% <71%> (-1%) |
:arrow_down: |
:rocket: New features to boost your workflow:
- :snowflake: Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
[!NOTE] Unit test generation is an Early Access feature. Expect some limitations and changes as we gather feedback and continue to improve it.
Generating unit tests... This may take up to 20 minutes.
[!NOTE] Unit test generation is an Early Access feature. Expect some limitations and changes as we gather feedback and continue to improve it.
Generating unit tests... This may take up to 20 minutes.
[!CAUTION] CodeRabbit failed during planning: Script execution failed: Command failed with exit code 1: jk_chrootlaunch --jail /inmem/6553/21e489e2-4643-4d6d-bc9c-97f5bf37d490 --group jailuser --user jailuser --exec /usr/bin/env -- '/bin/bash --norc --noprofile -c "cd '''/home/jailuser/git''' && bash -x /.coderabbit_commands_65c9413d-5e6e-4cf9-9c9f-9d6d60f7e1e3.sh"'
- set -euo pipefail
- test_file=tests/Unit/DSC_Computer.Tests.ps1
- sed -i '/^Describe '''DSC_Computer\Test-TargetResource''' {$/,/^}$/ { /^(}\s*)$/!b }' tests/Unit/DSC_Computer.Tests.ps1
- sed -i '/^}\s*$/{ h }' tests/Unit/DSC_Computer.Tests.ps1
- sed -i '/^Describe '''DSC_Computer\Get-TargetResource''' {/i
\ Context '''When description parameter is empty but current description is empty''' {\n\ BeforeAll {\n\ Mock -CommandName Get-CimInstance -MockWith {\n\ [PSCustomObject] @{ Description = "" }\n\ }\n\ }\n\n\ BeforeDiscovery {\n\ $testCases = @(\n\ @{ Name = $env:COMPUTERNAME }\n\ @{ Name = '''localhost''' }\n\ )\n\ }\n\n\ It '''Should return $true when Name is <Name>''' -ForEach $testCases {\n\ InModuleScope -Parameters $_ -ScriptBlock {\n\ Set-StrictMode -Version 1.0\n\n\ $testTargetParams = @{ Name = $Name; Description = "" }\n\ Test-TargetResource @testTargetParams | Should -BeTrue\n\ }\n\ }\n\ }\n\n\ Context '''When Domain is specified with empty username credential''' {\n\ It '''Should throw correct error''' {\n\ InModuleScope -ScriptBlock {\n\ Set-StrictMode -Version 1.0\n\n\ $secure = New-Object -Type SecureString\n\ $emptyUserCred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList ,$secure\n\n\ $errorRecord = Get-InvalidArgumentRecord\n\ -Message ($LocalizedData.CredentialsNotSpecifiedError)\n\ -ArgumentName '''Credentials'''\n\n\ $testTargetParams = @{ Name = $env:COMPUTERNAME; DomainName = '''contoso.com'''; Credential = $emptyUserCred }\n\ { Test-TargetResource @testTargetParams } | Should -Throw -ExpectedMessage $errorRecord\n\ }\n\ }\n\ }\n' tests/Unit/DSC_Computer.Tests.ps1- sed -i '/^\sIt '''Should return a hashtable containing Name, DomainName, JoinOU, CurrentOU, Credential, UnjoinCredential, WorkGroupName and Description''' {/,/^\s}\s*$/ { /}\s*$/a
\ It '''Should return expected types for core properties''' {\n\ InModuleScope -ScriptBlock {\n\ Set-StrictMode -Version 1.0\n\n\ $getTargetParams = @{ Name = $env:COMPUTERNAME }\n\ $result = Get-TargetResource @getTargetParams\n\ ($result.Name -is [string]) | Should -BeTrue\n\ $result.ContainsKey(Credential) | Should -BeTrue\n\ if ($null -ne $result.Credential) { ($result.Credential -is [System.Management.Automation.PSCredential]) | Should -BeTrue }\n\ $result.ContainsKey(UnjoinCredential) | Should -BeTrue\n\ if ($null -ne $result.UnjoinCredential) { ($result.UnjoinCredential -is [System.Management.Automation.PSCredential]) | Should -BeTrue }\n\ }\n\ }\n} ' tests/Unit/DSC_Computer.Tests.ps1 sed: -e expression #1, char 0: unmatched `{'
[!CAUTION] CodeRabbit timed out while planning changes for Tests/CHANGELOG.Tests.ps1. Skipping this file.