Examples/05/BenGelens_CWindowsContainer.ps1
enum Ensure { Absent Present } enum ContainerType { Default HyperV } enum AccessMode { ReadWrite ReadOnly } [DscResource()] class cWindowsContainer { [DscProperty(Key)] [String] $Name [DscProperty(Mandatory)] [Ensure] $Ensure [DscProperty(Mandatory)] [String] $ContainerImageName [DscProperty()] [String] $ContainerImagePublisher [DscProperty()] [String] $ContainerImageVersion [DscProperty()] [String] $SwitchName [DscProperty()] [String] $StartUpScript [DscProperty(NotConfigurable)] [String] $IPAddress [DscProperty(NotConfigurable)] [String] $ContainerId [DscProperty()] [String] $ContainerComputerName [DscProperty()] [String] $SourcePath [DscProperty()] [String] $DestinationPath [DscProperty()] [AccessMode] $AccessMode = 'ReadOnly' [DscProperty()] [ContainerType] $ContainerType = [ContainerType]::Default [void] Set () { try { if ($this.Ensure -eq [Ensure]::Present) { Write-Verbose -Message 'Starting creation of new Container' #region start build New-Container parameters $ContainerNewParams = [System.Collections.Hashtable]::new() $ContainerNewParams.Add('Name',$this.Name) $ContainerNewParams.Add('RuntimeType',$this.ContainerType) if ($null -ne $this.ContainerComputerName) { $ContainerNewParams.Add('ContainerComputerName',$this.ContainerComputerName) } #endregion start build New-Container parameters #region ContainerImage $ContainerImageParams = [System.Collections.Hashtable]::new() $ContainerImageParams.Add('Name',$this.ContainerImageName) if ($null -ne $this.ContainerImagePublisher) { $ContainerImageParams.Add('Publisher',$this.ContainerImagePublisher) } if ($null -ne $this.ContainerImageVersion) { $ContainerImageParams.Add('Version',$this.ContainerImageVersion) } Write-Verbose -Message "Searching for image: $($ContainerImageParams | Out-String)" if ($null -eq ($Image = Get-ContainerImage @ContainerImageParams)) { Write-Error -Message "ContainerImage with properties $($ContainerImageParams | Out-String) was not found" -ErrorAction Stop } else { $ContainerNewParams.Add('ContainerImage',$Image) } #endregion ContainerImage #region Switch Write-Verbose -Message "Searching for specified switch: $($this.SwitchName)" if ($this.SwitchName -and ($null -ne (Get-VMSwitch -Name $this.SwitchName))) { Write-Verbose -Message 'Switch was found and will be bound' $ContainerNewParams.Add('SwitchName',$this.SwitchName) } elseif ($this.SwitchName -and ($null -eq (Get-VMSwitch -Name $this.SwitchName))) { Write-Error -Message "Switch with name $($this.SwitchName) was not found" -ErrorAction Stop } #endregion Switch #region Create Container Write-Verbose -Message "Creating Container: $($ContainerNewParams | Out-String)" $Container = New-Container @ContainerNewParams #endregion Create Container #region add SharedFolder Write-Verbose -Message "Validating if a SharedFolder is needed" if ($this.SourcePath) { if ((Test-Path $this.SourcePath) -and ($this.DestinationPath -ne "")) { Write-Verbose -Message "Mapping $($this.sourcePath) to $($this.DestinationPath)" $SharedFolderNewParams = [System.Collections.Hashtable]::new() $SharedFolderNewParams.Add('ContainerName',$this.Name) $SharedFolderNewParams.Add('SourcePath',$this.SourcePath) $SharedFolderNewParams.Add('DestinationPath',$this.DestinationPath) $SharedFolderNewParams.Add('AccessMode',$this.AccessMode) Add-ContainerSharedFolder @SharedFolderNewParams } else { Write-Error -Message "$($this.SourcePath) isn't available or missing destination path in configuration" } } else { Write-Verbose -Message "No SharedFolder needed" } #region start Container Write-Verbose -Message "Starting Container $($this.Name)" $Container | Start-Container #endregion start container #region run startup script if ($null -ne $this.StartUpScript) { Write-Verbose -Message 'Startup Script specified, passing script to InvokeScript method' [void] $this.InvokeScript(([scriptblock]::Create($this.StartUpScript)),$Container.ContainerId) } #endregion run startup script } else { Write-Verbose -Message 'Removing Container' Get-Container -Name $this.Name | Stop-Container -Passthru | Remove-Container -Force } } catch { Write-Error -ErrorRecord $_ -ErrorAction Stop } } [bool] Test () { if ((Get-Container -Name $this.Name -ErrorAction SilentlyContinue) -and ($this.Ensure -eq [Ensure]::Present)) { $value = $true $SharedFolder = Get-ContainerSharedFolder -ContainerName $this.Name -ErrorAction SilentlyContinue if (($SharedFolder.SourcePath -eq $this.SourcePath) -and ($SharedFolder.DestinationPath -eq $this.DestinationPath) -and ($SharedFolder.AccessMode -eq $this.AccessMode)) { $Value = $true } else { $Value = $false } return $value } else { return $false } } [String] InvokeScript ([String] $Script, [String] $ContainerId) { $Output = Invoke-Command -ContainerId $ContainerId -RunAsAdministrator -ScriptBlock ([scriptblock]::Create($Script)) -ErrorAction Stop return $Output } [cWindowsContainer] Get () { $Configuration = [System.Collections.Hashtable]::new() $Configuration.Add('Name',$this.Name) $Configuration.Add('ContainerComputerName',$this.ContainerComputerName) $Configuration.Add('ContainerImageName',$this.ContainerImageName) $Configuration.Add('ContainerImagePublisher',$this.ContainerImagePublisher) $Configuration.Add('ContainerImageVersion',$this.ContainerImageVersion) $Configuration.Add('SwitchName',$this.SwitchName) $Configuration.Add('StartUpScript',$this.StartUpScript) $Configuration.Add('ContainerType',$this.ContainerType) if (($this.Ensure -eq [Ensure]::Present) -and ($this.Test())) { Write-Verbose -Message 'Acquiring ContainerId' $Configuration.Add('ContainerId',(Get-Container -Name $this.Name).ContainerId) $Configuration.Add('Ensure','Present') Write-Verbose -Message 'Acquiring IPAddress' if ($null -ne $this.SwitchName) { $Configuration.Add('IPAddress',$this.InvokeScript('(Get-NetIPAddress -AddressFamily IPv4 -PrefixOrigin Manual).IPAddress',$Configuration.ContainerId)) } if ($this.SourcePath) { $SharedFolder = Get-ContainerSharedFolder -ContainerName $this.Name $Configuration.Add('SourcePath',$SharedFolder.SourcePath) $Configuration.Add('DestinationPath',$SharedFolder.DestinationPath) $Configuration.Add('AccessMode',$SharedFolder.AccessMode) } } else { $Configuration.Add('Ensure','Absent') } return $Configuration } } |