winspray.psm1
#TODO : validate config against JSON Schema #TODO : ensure possible envs&group_vars outside of samples #TDOO : no localmount but current dir for pure docker image runtime (no additional archive for module nor git) #TODO : few synopsys $script:PSModule = $ExecutionContext.SessionState.Module $script:PSModuleRoot = $script:PSModule.ModuleBase $script:kubesprayVersion = "2.13.1" function Remove-Winspray-Cluster { Write-Host ( "# Winspray - destroying current VMs") Write-Verbose ( "### Winspray - launching vagrant destroy -f" ) vagrant destroy -f if (!$?) { throw ("Exiting $?") } # FIXME should exit and say use -Force $targetDir = "old-{0}" -f (Get-Date -Format "MM-dd-yyyy-HH-mm") Write-Verbose( "### Winspray - Moving current to $targetDir" ) Get-ChildItem -Path "$pwd/current" -Recurse | Move-Item -Destination "$targetDir" -Force Write-Host ( "## Winspray - destroy done `n" ) -ForegroundColor DarkGreen } function Backup-Winspray-Cluster { [CmdletBinding()] Param( [parameter( ValueFromPipeline )] [string]$BackupName = "" ) Write-Host ("# Winspray - start backup with name '$BackupName'" ) Get-VM | Where-Object {$_.Name -like 'k8s-*'} | ForEach-Object -Process {Checkpoint-VM -Name $_.Name -SnapshotName "$BackupName"} if (!$?) { exit -1 } Write-Host ( "## Winspray - backup '$BackupName' ok `n") -ForegroundColor DarkGreen } function Restore-Winspray-Cluster{ [CmdletBinding()] Param( [parameter( ValueFromPipeline )] [string]$BackupName = "installed" ) Write-Host ("# Winspray - start restore with name '$BackupName'" ) Get-VM | Where-Object {$_.Name -like 'k8s-*'} | ForEach-Object -Process {Restore-VMSnapshot -Confirm:$false -Name "$BackupName" -VMName $_.Name } if (!$?) { exit -1 } Write-Host ( "## Winspray - restore '$BackupName' ok `n") -ForegroundColor DarkGreen } function Start-Winspray-Cluster { Write-Host ("# Winspray - start existing VMS" ) Get-VM | Where-Object {$_.Name -like 'k8s-*' -and $_.State -ne "Running" } | ForEach-Object -Process { Start-VM $_.Name } Write-Host ( "## Winspray - VMS started ok `n") -ForegroundColor DarkGreen } function Stop-Winspray-Cluster { Write-Host ("# Winspray - start existing VMS" ) Get-VM | Where-Object {$_.Name -like 'k8s-*'} | ForEach-Object -Process {Stop-VM $_.Name } Write-Host ( "## Winspray - VMS started ok `n") -ForegroundColor DarkGreen } function Prepare-Winspray-Cluster( ) { #FIXME : how to good inject Debug flag (from this direct cal plus from New-Winspray-Cluster) $AnsibleDebug = If ( $Debug ) {"-vvv"} Else {""} Write-Host ( "# Winspray - preparing VMs for kubernetes" ) Write-Verbose ( " ### Winspray - launching ansible-playbook --become -i /.../$KubernetesInfra.yaml /.../playbooks/prepare.yaml " ) docker run --rm -v "/var/run/docker.sock:/var/run/docker.sock" -e ANSIBLE_CONFIG=/opt/winspray/ansible.cfg -v ${PWD}:/opt/winspray -t jseguillon/winspray:$script:kubesprayVersion bash -c "ansible-playbook $AnsibleDebug --become -i /opt/winspray/current/hosts.yaml /winspray/playbooks/prepare.yaml -e '@/opt/winspray/config/kubespray.vars.json' -e '@/opt/winspray/config/network.vars.json' -e '@/opt/winspray/config/authent.vars.json'" if (!$?) { throw "Exiting $?" } Write-Host ( "## Winspray - VMs prepared for kubespray `n" ) -ForegroundColor DarkGreen } function Install-Winspray-Cluster( ) { #FIXME : how to good inject Debug flag (from this direct cal plus from New-Winspray-Cluster) $AnsibleDebug = If ( $Debug ) {"-vvv"} Else {""} Write-Host ( "# Winspray - install kubernetes" ) Write-Verbose ( "** launching ansible-playbook --become -i /...$KubernetesInfra /.../cluster.yml" ) docker run --rm -v "/var/run/docker.sock:/var/run/docker.sock" -e ANSIBLE_CONFIG=/opt/winspray/ansible.cfg -v ${PWD}:/opt/winspray -t jseguillon/winspray:$script:kubesprayVersion bash -c "ansible-playbook $AnsibleDebug --become -i /opt/winspray/current/hosts.yaml cluster.yml -e '@/opt/winspray/config/kubespray.vars.json' -e '@/opt/winspray/config/network.vars.json' -e '@/opt/winspray/config/authent.vars.json'" if (!$?) { throw "Exiting $?" } Write-Host ( "## Winspray - kubernetes installed `n" ) -ForegroundColor DarkGreen } function Do-Winspray-Bash( ) { Write-Host ( "" ) Write-Host ( "** Going to bash. Here are usefull commands : " ) Write-Host ( " pip install -r /opt/winspray/kubespray/requirements.txt" ) Write-Host ( " ansible-playbook --network host --become -i /opt/winspray/current/hosts.yaml cluster.yml -e '@/opt/winspray/config/kubespray.vars.json' -e '@/opt/winspray/config/network.vars.json' -e '@/opt/winspray/config/authent.vars.json'" ) Write-Host ( "" ) docker run -it --rm -v "/var/run/docker.sock:/var/run/docker.sock" -v ${PWD}:/opt/winspray -t jseguillon/winspray:$script:kubesprayVersion bash if (!$?) { throw "Exiting $?" } } function Test-Winspray-Env { Write-Host ("# Winspray - check env" ) $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent()) if ( ! $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator) ) { throw ( "** ERROR *** Please launch Powershell as administrator" ) } if( (Get-WindowsOptionalFeature -Online -FeatureName *hyperv* | Measure-Object -Line).Lines -eq 0 ) { throw ( "** ERROR *** Please install and acivate HyperV" ) } vagrant -v if(!$?) { throw ( "** ERROR *** Please install vagrant" ) } docker version if(!$?) { throw ( "** ERROR *** Please install and start docker" ) } Write-Host ( "## Winspray - check ok `n" ) -ForegroundColor DarkGreen } function New-Winspray-Config () { if ( ! [System.IO.Directory]::Exists("$pwd\config" ) ) { Write-Verbose ( "### Winspray - create Vagrantfile" ) Copy-Item $script:PSModuleRoot/config . -Recurse } } function New-Winspray-Inventory ( ) { [CmdletBinding()] Param( [parameter( ValueFromPipeline, Mandatory=$true )] [string]$KubernetesInfra ) Write-Host ("# Winspray - create kubespray inventory and vagant config" ) # FIXME : no more add dir nor extension copy ./samples/$KubernetesInfra.yml current/infra.yaml if (!$?) { throw ( "** ERROR *** could not find ./samples/$KubernetesInfra.yml or could not copy it to 'current/' " ) } # launch ansible templates that renders in current/vagrant.vars.rb current/inventory.yaml + groups vars from example docker run -v "/var/run/docker.sock:/var/run/docker.sock" --rm -v ${PWD}:/opt/winspray -it jseguillon/winspray:$script:kubesprayVersion ansible-playbook $AnsibleDebug --become --limit=localhost /winspray/playbooks/inventory_create.yaml if (!$?) { throw ( "** ERROR *** Found error while creating inventory" ) } #FIXME : move to prepare playbook Copy-Item ./samples/group_vars -Destination current/ -Recurse Write-Host ( "## Winspray - inventory and vagrant config created `n") -ForegroundColor DarkGreen } function New-Winspray-Cluster () { [CmdletBinding()] Param( [parameter( ValueFromPipeline, Mandatory=$true )] [string]$KubernetesInfra, [switch]$Force, [switch]$ContinueExisting ) $StartMs = Get-Date # FIXME debug [bool]$ContinueExisting = ( $PSBoundParameters.ContainsKey( 'ContinueExisting' ) ) [bool]$Force = ( $PSBoundParameters.ContainsKey( 'Force' ) ) Test-Winspray-Env if ( ! [System.IO.Directory]::Exists("$pwd\current") ) { Write-Verbose ( "### Winspray - create 'current' dir" ) $ret = mkdir $pwd/current/ | Out-Null if(!$?) { throw ("** ERROR *** could not create $pwd/current/ directory. $ret" ) } } if ( ! [System.IO.File]::Exists("$pwd\Vagrantfile" ) ) { Write-Verbose ( "### Winspray - create Vagrantfile" ) Copy-Item $script:PSModuleRoot/Vagrantfile . } New-Winspray-Config # Existing vagrant config file and Force flag ? : ok to destroy if we got new target if ( [System.IO.File]::Exists("$pwd\current\vagrant.vars.rb") -and (! $ContinueExisting ) ) { if ( $Force ) { Remove-Winspray-Cluster } else { Write-Host ( "Found existing cluster. Maybe you wanted to Start-Winspray-Cluster ?" ) throw "Please remove exiting cluster first or use -Force flag or start existing cluster " } } # Do not replay if going with ContinueExisting if ( ! [System.IO.File]::Exists("$pwd\current\vagrant.vars.rb") ) { New-Winspray-Inventory ($KubernetesInfra); Write-Host ("# Winspray - create new VMs" ) Write-Verbose ( "### Winspray - launching vagrant up" ) # Export root module path so vagrant can call script $env:WINSPRAYROOT=$script:PSModuleRoot vagrant up if (!$?) { throw "Exiting $?"; } Write-Host ( "## Winspray - VMs created ok `n" ) -ForegroundColor DarkGreen } # not new cluster ? quick start VMs for ContinueExisting mode else { Start-Winspray-Cluster } #cluster not yet prepared ? run prepare playbook if ( ! [System.IO.File]::Exists("$pwd\current\prepared.ok") ) { Prepare-Winspray-Cluster echo "ok" > $pwd\current\prepared.ok Backup-Winspray-Cluster ("prepared") } else { Write-Host ("# Winspray - VMS already prepared `n" ) } # kubernetes not installed ? run cluster playbook if ( ! [System.IO.File]::Exists("$pwd\current\installed.ok") ) { Install-Winspray-Cluster echo "ok" > $pwd\current\installed.ok Backup-Winspray-Cluster ("installed") } else { Write-Host ("# Winspray - Kubernetes already installed. Nothing to do `n" ) } $timeExec = (Get-Date) - $StartMs Write-Host ("# Winspray - kubernetes now running `n " ) -ForegroundColor DarkGreen Write-Host ("# Winspray - Time to start {0}h {1}m {2}s" -f ($timeExec.Hours, $timeExec.Minutes, $timeExec.Seconds )) } Export-ModuleMember -Function New-Winspray-Cluster, Remove-Winspray-Cluster, Start-Winspray-Cluster, Backup-Winspray-Cluster, Restore-Winspray-Cluster, Stop-Winspray-Cluster, Prepare-Winspray-Hosts, Install-Winspray-Hosts, Do-Winspray-Bash, Test-Winspray-Env, Set-Winspray-Inventory, Prepare-Winspray-Runtime, Do-Winspray-Bash |