cDscDocker.psm1
enum Ensure { Present Absent } enum Swarm { Active Inactive } [DscResource()] class cDscDocker { [DscProperty(Key)] [string]$docker [DscProperty(Mandatory)] [Ensure]$Ensure [DscProperty()] [string]$swarmToken [DscProperty()] [string]$swarmURI [DscProperty(Mandatory)] [Swarm]$swarm [DscProperty()] [string]$daemonInterface #must be in format of tcp://0.0.0.0:2375 [DscProperty()] [bool]$exposeApi #Equivalent of Set-TargetResource #Executes the current operation necessary to get the system to the desired state [void] Set() { $dockerProviderAvailable = $this.CheckDockerProvider() $dockerInstalled = $this.CheckDocker() $dockerInSwarm = $this.CheckDockerSwarm() $apiExposed = $this.CheckDaemonAPI() Write-Verbose "Settings" Write-Verbose "Docker $($this.Ensure)" Write-Verbose "Swarm $($this.swarm)" switch($this.Ensure) { Present{ if(-not $dockerProviderAvailable) { Write-Verbose "Docker Provider not Available; Installing Provider" $this.InstallDockerProvider() } if(-not $dockerInstalled) { Write-Verbose "Docker not installed; installing docker" $this.InstallDocker() } if($global:DSCMachineStatus -ne 1) { Write-Verbose "Not pending reboot" Write-Verbose "Entering Switch" switch($this.swarm) { Active{ Write-Verbose "Setting Swarm to Active" if(-not $dockerInSwarm){ Write-Verbose "Not in docker swarm; executing join method" $this.JoinDockerSwarm() } } Inactive{ Write-Verbose "Setting swarm to inactive" if($dockerInSwarm){ $this.LeaveDockerSwarm() } } } if($apiExposed -eq $false){ $this.ConfigureDaemonAPI() } } } Absent{ if($dockerInSwarm){ $this.LeaveDockerSwarm() } if($dockerInstalled){ $this.UninstallDocker() } } } } #Equivalent of Test-TargetResource #Returns true if system is in the state specified; false if a modification needs to take place [bool] Test() { $objectValidState = $false $dockerPresent = $this.CheckDocker() if($dockerPresent) { $dockerSwarm = $this.CheckDockerSwarm() $dockerApiStatus = $this.CheckDaemonAPI() } else { $dockerSwarm = $false $dockerApiStatus = $false } if ($this.Ensure -eq [Ensure]::Present) { if ($dockerPresent) { if($this.swarm -eq [Swarm]::Active) { if($dockerSwarm -eq $true) { Write-Verbose "Docker is present (Expect: Present). Swarm is Active (Expect: Active). VALID STATE" $objectValidState = $true; } if($dockerSwarm -eq $false) { Write-Verbose "Docker is present (Expect: Present). Swarm is Inactive (Expect: Active). INVALID STATE" return $false; } } elseif($this.swarm -eq [Swarm]::Inactive) { if($dockerSwarm -eq $true) { Write-Verbose "Docker is present (Expect: Present). Swarm is Active (Expect: Inactive). INVALID STATE" return $false; } elseif($dockerSwarm -eq $false) { Write-Verbose "Docker is present (Expect: Present). Swarm is Inactive (Expect: Inactive). VALID STATE" $objectValidState = $true } } if($this.exposeApi -eq $true){ if($dockerApiStatus -eq $false){ return $false } elseif($dockerApiStatus -eq $true){ $objectValidState = $true } } elseif($this.exposeApi -eq $false){ if($dockerApiStatus -eq $true){ return $false } elseif($dockerApiStatus -eq $false){ $objectValidState = $true } } #Fallback; setting this item in case return route is missed $objectValidState = $true } if (-not $dockerPresent) { Write-Verbose "Docker is Absent (Expect: Present). INVALID STATE" return $false } } Else { if ($dockerPresent) { Write-Verbose "Docker is Present (Expect: Absent). INVALID STATE" return $false } if (-not $dockerPresent) { Write-Verbose "Docker is Absent (Expect: Absent). VALID STATE" $objectValidState = $true } } return $objectValidState } #Equivalent of the Get-TargetResource #Get's the current state of the system in cDscDocker object form [cDscDocker] Get() { if ($this.CheckDocker()) { $this.Ensure = [Ensure]::Present } else { $this.Ensure = [Ensure]::Absent } return $this } #Swarm Action, join [void]JoinDockerSwarm() { Write-Verbose "Joining Docker Swarm" docker swarm join --token $($this.swarmToken) $($this.swarmURI) } #Swarm action, leave [void]LeaveDockerSwarm() { docker swarm leave --force } [bool]CheckDockerSwarm() { $returnValue = $false if($this.CheckDocker()){ $info = docker info foreach($item in $info) { if($item -match "swarm") { if($item -match "\sactive") { return $true } elseif($item -match "inactive") { return $false } } } } return $returnValue } #Docker Action, Verify [bool]CheckDocker() { $installed = $false if($this.CheckDockerProvider()) { $packages = Get-Package -ProviderName DockerMsftProvider foreach ($p in $packages) { if ($p.Name -eq 'docker') { $installed = $true } } #In case this was installed as a service via other means; e.g. not the DockerMsftProvider $services = Get-Service | Where-Object {$_.Name -like "docker"} if ($services.Length ) { $installed = $true } } return $installed } #Docker Action, Install [void]InstallDocker() { Install-Package -Name docker -ProviderName DockerMsftProvider -Force $global:DSCMachineStatus = 1 } #Docker Action, Uninstall [void]UninstallDocker() { Uninstall-Package -ProviderName DockerMsftProvider -Name docker -Force #Uninstall docker; will move to a function if re-used elsewhere } #Docker Provider Action; verify [bool]CheckDockerProvider() { $available = $false $providers = Get-PackageProvider -ListAvailable foreach($provider in $providers) { if ($provider.Name -eq "DockerMsftProvider") { $available = $true } } return $available } #Docker Provider Action; install [void]InstallDockerProvider() { Install-Module -Name DockerMsftProvider -Repository psgallery -Force } #Daemon API Checks [bool]CheckDaemonAPI() { if(Test-Path "C:\ProgramData\docker\config\daemon.json"){ $daemon = ((Get-Content 'C:\ProgramData\docker\config\daemon.json') | ConvertFrom-Json) if($daemon.PSObject.Properties['hosts']){ #daemon has hosts key if(($daemon.hosts -contains $this.daemonInterface) -and ($daemon.hosts -contains "npipe://")){ return $true } } } else{ return $false } return $false } #create keys and values as needed [void]ConfigureDaemonAPI() { $daemon = New-Object PSObject #Verify and create daemon.json if necessary if(-not (Test-Path "C:\ProgramData\docker\config\daemon.json")){ New-Item -ItemType File -Path "C:\ProgramData\docker\config\daemon.json" -Force } else{ $contents = ((Get-Content 'C:\ProgramData\docker\config\daemon.json') | ConvertFrom-Json) if(-not ($contents -eq $null)){ $daemon = $contents } } #Verify if json object contains hosts key if($daemon.PSObject.Properties['hosts']){ $daemon.PSObject.Properties.Remove('hosts') #remove the hosts key in order to clear it entirely of bad values / previous entries if($this.exposeApi -eq $true){ $daemon | Add-Member -Name "hosts" -MemberType NoteProperty -Value @($this.daemonInterface, "npipe://") } } elseif($this.exposeApi -eq $true){ #if full hosts key missing; add it with the values necessary $daemon | Add-Member -Name "hosts" -MemberType NoteProperty -Value @($this.daemonInterface, "npipe://") #create values } $daemon | ConvertTo-Json | Out-File 'C:\ProgramData\docker\config\daemon.json' -Encoding ascii -Force } } |