Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DomainMode and ForestMode implemented #199

Merged
merged 52 commits into from
Jun 18, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
e0c295d
Added DomainMode and ForestMode parameters
nyanhp Jun 7, 2018
4ddd82d
Updated tests
nyanhp Jun 7, 2018
c121068
Updated parameters with ValidateSet to comply with tests
nyanhp Jun 7, 2018
16c25d4
Removed ForestName property from testing
nyanhp Jun 7, 2018
8a500b7
Added test cases for DFL/FFL
nyanhp Jun 8, 2018
839d9fc
Updated xADDomain to return strings with Get-TargetResource
nyanhp Jun 8, 2018
f2fe6a8
Added functions to convert DFL/FFL to type requried by Deployment cmd…
nyanhp Jun 8, 2018
173e78d
Updated readme
nyanhp Jun 8, 2018
5626c36
Corrected test case for Forest deployment
nyanhp Jun 8, 2018
65a64f7
Updated tests and moved Mocks to outer scope
nyanhp Jun 8, 2018
8c6b6c9
Added account info to readme.md/unreleased
nyanhp Jun 8, 2018
8b56380
Added examples using Domain and Forest Functional Level
nyanhp Jun 8, 2018
b8b1b4d
Added CRLF to examples.
nyanhp Jun 8, 2018
14a5192
Updated tests
nyanhp Jun 7, 2018
b63824e
Added test cases for DFL/FFL
nyanhp Jun 8, 2018
0c4f221
Updated tests and moved Mocks to outer scope
nyanhp Jun 8, 2018
b1077c4
Changed imported DSC resource in sample scripts
nyanhp Jun 11, 2018
5deee95
Corrected Mode to ModeId
nyanhp Jun 11, 2018
c8ffc7b
Updated phrasing
nyanhp Jun 11, 2018
91dc1fb
Replaced double quotes.
nyanhp Jun 12, 2018
2c8a016
Added class stubs
nyanhp Jun 12, 2018
25a8ef2
Updated ConvertTo-Deployment* cmdlets with correct type
nyanhp Jun 12, 2018
af0e8a0
Added test cases for ConvertTo-Deployment* cmdlets
nyanhp Jun 12, 2018
c040e71
Had to reduce domain/forest level in test cases
nyanhp Jun 12, 2018
eae1f07
Updated readme, moved (optional) up front
nyanhp Jun 14, 2018
dab8b81
Replace $mode with $domainMode and $forestMode
nyanhp Jun 14, 2018
7ab7fc0
Added newlines to EOF
nyanhp Jun 14, 2018
ad64d95
Updated tests for xADDomain
nyanhp Jun 14, 2018
5266cce
Updated xADCommon tsts
nyanhp Jun 14, 2018
545941f
Updated xADComputer tests
nyanhp Jun 14, 2018
4b4d1a2
Updated xADDomainController Tests
nyanhp Jun 14, 2018
e6bccc9
Updated xADDomainDefaultPasswordPolicy tests
nyanhp Jun 14, 2018
2da0c0a
updated xAdGroup tests
nyanhp Jun 14, 2018
939719a
updated xadorgunit tests
nyanhp Jun 14, 2018
cd82ce8
updated xadreplicationsite tests
nyanhp Jun 14, 2018
00cef2f
updated xadreplicationsubnet tests
nyanhp Jun 14, 2018
9331a92
encoding corrected
nyanhp Jun 14, 2018
1763407
Removed previously mocked new cmdlets
nyanhp Jun 14, 2018
0bb845f
Removed unnecessary test for $null
nyanhp Jun 14, 2018
64b9a80
Testing against full .net types for forest and domain mode
nyanhp Jun 14, 2018
0e133c5
Removed MockWith emtpy script blocks
nyanhp Jun 14, 2018
2b0ce41
Grasping at straws
nyanhp Jun 15, 2018
c5aa224
Implemented @johlju suggestion, still working locally
nyanhp Jun 15, 2018
bcc5508
Harmonized appearance of Readme.md
nyanhp Jun 16, 2018
e27a41e
Modified conversion cmdlets to accep null values
nyanhp Jun 16, 2018
b26f90d
Removed empty mocks
nyanhp Jun 16, 2018
8177237
Added -MockWith parameter
nyanhp Jun 16, 2018
4b08e4a
Made conversion functions non-terminating and just return $null instead
nyanhp Jun 16, 2018
7ef2440
Updated conversion tests after returning $null values
nyanhp Jun 16, 2018
b7eb2ba
Changed string conversion to accomodate $Null values
nyanhp Jun 16, 2018
746a13f
AppVeyor is STILL failing
nyanhp Jun 16, 2018
56bf726
Updated readme
nyanhp Jun 18, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
89 changes: 89 additions & 0 deletions DSCResources/MSFT_xADCommon/MSFT_xADCommon.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ data localizedString
MembersIsEmptyError = The Members parameter is empty. At least one group member must be provided.
IncludeAndExcludeConflictError = The member '{0}' is included in both '{1}' and '{2}' parameter values. The same member must not be included in both '{1}' and '{2}' parameter values.
IncludeAndExcludeAreEmptyError = The '{0}' and '{1}' parameters are either both null or empty. At least one member must be specified in one of these parameters.
ModeConversionError = Converted mode {0} is not a {1}.

CheckingMembers = Checking for '{0}' members.
MembershipCountMismatch = Membership count is not correct. Expected '{0}' members, actual '{1}' members.
Expand Down Expand Up @@ -599,3 +600,91 @@ function Test-ADReplicationSite

return ($null -ne $site);
}

function ConvertTo-DeploymentForestMode
{
[CmdletBinding()]
[OutputType([Microsoft.DirectoryServices.Deployment.Types.ForestMode])]
param
(
[Parameter(
Mandatory = $true,
ParameterSetName = 'ById')]
[UInt16]
$ModeId,

[Parameter(
Mandatory = $true,
ParameterSetName = 'ByName')]
[AllowNull()]
[System.Nullable``1[Microsoft.ActiveDirectory.Management.ADForestMode]]
$Mode,

[ValidateNotNullOrEmpty()]
[System.String]
$ModuleName = 'xActiveDirectory'
)

$convertedMode = $null

if ($PSCmdlet.ParameterSetName -eq 'ByName' -and $Mode)
{
$convertedMode = $Mode -as [Microsoft.DirectoryServices.Deployment.Types.ForestMode]
}

if ($PSCmdlet.ParameterSetName -eq 'ById')
{
$convertedMode = $ModeId -as [Microsoft.DirectoryServices.Deployment.Types.ForestMode]
}

if ([enum]::GetValues([Microsoft.DirectoryServices.Deployment.Types.ForestMode]) -notcontains $convertedMode)
{
return $null
}

return $convertedMode
}

function ConvertTo-DeploymentDomainMode
{
[CmdletBinding()]
[OutputType([Microsoft.DirectoryServices.Deployment.Types.DomainMode])]
param
(
[Parameter(
Mandatory = $true,
ParameterSetName = 'ById')]
[UInt16]
$ModeId,

[Parameter(
Mandatory = $true,
ParameterSetName = 'ByName')]
[AllowNull()]
[System.Nullable``1[Microsoft.ActiveDirectory.Management.ADDomainMode]]
$Mode,

[ValidateNotNullOrEmpty()]
[System.String]
$ModuleName = 'xActiveDirectory'
)

$convertedMode = $null

if ($PSCmdlet.ParameterSetName -eq 'ByName' -and $Mode)
{
$convertedMode = $Mode -as [Microsoft.DirectoryServices.Deployment.Types.DomainMode]
}

if ($PSCmdlet.ParameterSetName -eq 'ById')
{
$convertedMode = $ModeId -as [Microsoft.DirectoryServices.Deployment.Types.DomainMode]
}

if ([enum]::GetValues([Microsoft.DirectoryServices.Deployment.Types.DomainMode]) -notcontains $convertedMode)
{
return $null
}

return $convertedMode
}
46 changes: 38 additions & 8 deletions DSCResources/MSFT_xADDomain/MSFT_xADDomain.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ data localizedData
ResourceNotInDesiredState = Resource '{0}' is NOT in the desired state.
RetryingGetADDomain = Attempt {0} of {1} to call Get-ADDomain failed, retrying in {2} seconds.
UnhandledError = Unhandled error occured, detail here: {0}
FaultExceptionAndDomainShouldExist = ServiceModel FaultException detected and domain should exist, performing retry...
FaultExceptionAndDomainShouldExist = ServiceModel FaultException detected and domain should exist, performing retry...
'@
}

Expand Down Expand Up @@ -99,7 +99,13 @@ function Get-TargetResource
[String] $LogPath,

[Parameter()] [ValidateNotNullOrEmpty()]
[String] $SysvolPath
[String] $SysvolPath,

[Parameter()] [ValidateSet('Win2008', 'Win2008R2', 'Win2012', 'Win2012R2', 'WinThreshold')]
[String] $ForestMode,

[Parameter()] [ValidateSet('Win2008', 'Win2008R2', 'Win2012', 'Win2012R2', 'WinThreshold')]
[String] $DomainMode
)

Assert-Module -ModuleName 'ADDSDeployment';
Expand All @@ -117,10 +123,12 @@ function Get-TargetResource
## We're already a domain member, so take the credentials out of the equation
Write-Verbose ($localizedData.QueryDomainADWithLocalCredentials -f $domainFQDN);
$domain = Get-ADDomain -Identity $domainFQDN -ErrorAction Stop;
$forest = Get-ADForest -Identity $domain.Forest -ErrorAction Stop
}
else {
Write-Verbose ($localizedData.QueryDomainWithCredential -f $domainFQDN);
$domain = Get-ADDomain -Identity $domainFQDN -Credential $DomainAdministratorCredential -ErrorAction Stop;
$domain = Get-ADDomain -Identity $domainFQDN -Credential $DomainAdministratorCredential -ErrorAction Stop
$forest = Get-ADForest -Identity $domain.Forest -Credential $DomainAdministratorCredential -ErrorAction Stop
}

## No need to check whether the node is actually a domain controller. If we don't throw an exception,
Expand All @@ -132,6 +140,8 @@ function Get-TargetResource
DomainName = $domain.DnsRoot;
ParentDomainName = $domain.ParentDomain;
DomainNetBIOSName = $domain.NetBIOSName;
ForestMode = (ConvertTo-DeploymentForestMode -Mode $forest.ForestMode) -as [String]
DomainMode = (ConvertTo-DeploymentDomainMode -Mode $domain.DomainMode) -as [String]
}

return $targetResource;
Expand Down Expand Up @@ -207,7 +217,13 @@ function Test-TargetResource
[String] $LogPath,

[Parameter()] [ValidateNotNullOrEmpty()]
[String] $SysvolPath
[String] $SysvolPath,

[Parameter()] [ValidateSet('Win2008', 'Win2008R2', 'Win2012', 'Win2012R2', 'WinThreshold')]
[String] $ForestMode,

[Parameter()] [ValidateSet('Win2008', 'Win2008R2', 'Win2012', 'Win2012R2', 'WinThreshold')]
[String] $DomainMode
)

$targetResource = Get-TargetResource @PSBoundParameters
Expand Down Expand Up @@ -280,11 +296,17 @@ function Set-TargetResource
[String] $LogPath,

[Parameter()] [ValidateNotNullOrEmpty()]
[String] $SysvolPath
[String] $SysvolPath,

[Parameter()] [ValidateSet('Win2008', 'Win2008R2', 'Win2012', 'Win2012R2', 'WinThreshold')]
[String] $ForestMode,

[Parameter()] [ValidateSet('Win2008', 'Win2008R2', 'Win2012', 'Win2012R2', 'WinThreshold')]
[String] $DomainMode
)

# Debug can pause Install-ADDSForest/Install-ADDSDomain, so we remove it.
[ref] $null = $PSBoundParameters.Remove("Debug");
[ref] $null = $PSBoundParameters.Remove('Debug');
## Not entirely necessary, but run Get-TargetResouece to ensure we raise any pre-flight errors.
$targetResource = Get-TargetResource @PSBoundParameters;

Expand All @@ -311,7 +333,11 @@ function Set-TargetResource
{
$installADDSParams['SysvolPath'] = $SysvolPath;
}

if ($PSBoundParameters.ContainsKey('DomainMode'))
{
$installADDSParams['DomainMode'] = $DomainMode;
}

if ($PSBoundParameters.ContainsKey('ParentDomainName'))
{
Write-Verbose -Message ($localizedData.CreatingChildDomain -f $DomainName, $ParentDomainName);
Expand All @@ -334,11 +360,15 @@ function Set-TargetResource
{
$installADDSParams['DomainNetbiosName'] = $DomainNetBIOSName;
}
if ($PSBoundParameters.ContainsKey('ForestMode'))
{
$installADDSParams['ForestMode'] = $ForestMode
}
Install-ADDSForest @installADDSParams;
Write-Verbose -Message ($localizedData.CreatedForest -f $DomainName);
}

"Finished" | Out-File -FilePath (Get-TrackingFilename -DomainName $DomainName) -Force
'Finished' | Out-File -FilePath (Get-TrackingFilename -DomainName $DomainName) -Force

# Signal to the LCM to reboot the node to compensate for the one we
# suppressed from Install-ADDSForest/Install-ADDSDomain
Expand Down
2 changes: 2 additions & 0 deletions DSCResources/MSFT_xADDomain/MSFT_xADDomain.schema.mof
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,6 @@ class MSFT_xADDomain : OMI_BaseResource
[Write, Description("Path to a directory that contains the domain database")] String DatabasePath;
[Write, Description("Path to a directory for the log file that will be written")] String LogPath;
[Write, Description("Path to a directory where the Sysvol file will be written")] String SysvolPath;
[Write, Description("The Forest Functional Level for the entire forest"), ValueMap{"Win2008", "Win2008R2", "Win2012", "Win2012R2", "WinThreshold"}, Values{"Win2008", "Win2008R2", "Win2012", "Win2012R2", "WinThreshold"}] String ForestMode;
[Write, Description("The Domain Functional Level for the entire domain"), ValueMap{"Win2008", "Win2008R2", "Win2012", "Win2012R2", "WinThreshold"}, Values{"Win2008", "Win2008R2", "Win2012", "Win2012R2", "WinThreshold"}] String DomainMode;
};
61 changes: 61 additions & 0 deletions Examples/Resources/xADDomain/1-NewForest.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<#
.EXAMPLE
This example will create a new domain with a new forest and a forest functional level of Server 2016
#>
$ConfigurationData = @{
AllNodes = @(
@{
NodeName = 'localhost'
FFL = 'WinThreshold'
DomainName = 'contoso.com'

<#
NOTE! THIS IS NOT RECOMMENDED IN PRODUCTION.
This is added so that AppVeyor automatic tests can pass, otherwise
the tests will fail on passwords being in plain text and not being
encrypted. Because it is not possible to have a certificate in
AppVeyor to encrypt the passwords we need to add the parameter
'PSDscAllowPlainTextPassword'.
NOTE! THIS IS NOT RECOMMENDED IN PRODUCTION.
#>
PSDscAllowPlainTextPassword = $true
}
)
}

configuration Example
{
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCredential]
$DomainAdministratorCredential
)

Import-DscResource -ModuleName PSDscResources
Import-DscResource -ModuleName xActiveDirectory
node $AllNodes.NodeName
{
WindowsFeature ADDS
{
Name = 'AD-Domain-Services'
Ensure = 'Present'
}

WindowsFeature RSAT
{
Name = 'RSAT-AD-PowerShell'
Ensure = 'Present'
}

xADDomain $Node.DomainName
{
DomainName = $Node.DomainName
DomainAdministratorCredential = $DomainAdministratorCredential
SafemodeAdministratorPassword = $DomainAdministratorCredential
ForestMode = $Node.FFL
}
}

}
63 changes: 63 additions & 0 deletions Examples/Resources/xADDomain/2-NewChildDomain.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<#
.EXAMPLE
This example will create a new child domain in an existing forest with a Domain Functional Level of Windows Server 2012R2
#>
$ConfigurationData = @{
AllNodes = @(
@{
NodeName = 'localhost'
DFL = 'Win2012R2'
DomainName = 'child'
ParentDomain = 'contoso.com'

<#
NOTE! THIS IS NOT RECOMMENDED IN PRODUCTION.
This is added so that AppVeyor automatic tests can pass, otherwise
the tests will fail on passwords being in plain text and not being
encrypted. Because it is not possible to have a certificate in
AppVeyor to encrypt the passwords we need to add the parameter
'PSDscAllowPlainTextPassword'.
NOTE! THIS IS NOT RECOMMENDED IN PRODUCTION.
#>
PSDscAllowPlainTextPassword = $true
}
)
}

configuration Example
{
param
(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[System.Management.Automation.PSCredential]
$DomainAdministratorCredential
)

Import-DscResource -ModuleName PSDscResources
Import-DscResource -ModuleName xActiveDirectory
node $AllNodes.NodeName
{
WindowsFeature ADDS
{
Name = 'AD-Domain-Services'
Ensure = 'Present'
}

WindowsFeature RSAT
{
Name = 'RSAT-AD-PowerShell'
Ensure = 'Present'
}

xADDomain $Node.DomainName
{
DomainName = $Node.DomainName
DomainAdministratorCredential = $DomainAdministratorCredential
SafemodeAdministratorPassword = $DomainAdministratorCredential
DomainMode = $Node.DFL
ParentDomainName = $node.ParentDomain
}
}

}
Loading