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
    
    
    #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()
        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()
                            }

                        }
                    }
                }


            }
            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()
        }
        else
        {
            $dockerSwarm = $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
                    }
                }
                
                
                #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
    }


}