SkunkLabAks.psm1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
#AKS Functions

function Add-CertManager
{
    kubectl get namespace "cert-manager"
    
    if($LastExitCode -ne 0)
    {    
        kubectl create namespace "cert-manager"
    }
    
    kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.14.1/cert-manager.yaml
    helm repo add jetstack https://charts.jetstack.io
    helm repo update
}

function Add-Issuer 
{
    param([string]$Email, [string]$IssuerPath, [string]$IssuerDestination, [string]$Namespace = "kube-system")

    Copy-Item -Path $IssuerPath -Destination $IssuerDestination
    Update-Yaml -NewValue $Email -MatchString "EMAILREF" -Filename $IssuerDestination           
    kubectl apply -f $IssuerDestination -n $Namespace --validate=false
    Remove-Item -Path $IssuerDestination
}

function Add-NGINX
{
    param([string]$Namespace = "kube-system")
    
    kubectl get namespace $Namespace
    if($LastExitCode -ne 0)
    {
        kubectl create namespace $Namespace
    }
    
    helm repo add nginx-stable https://helm.nginx.com/stable
    helm repo update
    
    $looper = $true
    while($looper)
    {
        try
        {
            #helm install nginx nginx-stable/ingress-nginx --namespace $Namespace --set controller.replicaCount=1
             #helm install nginx nginx-stable/nginx-ingress --namespace $Namespace --set controller.image.repository=myregistry.example.com/nginx-plus-ingress --set controller.nginxplus=true
             helm install nginx nginx-stable/nginx-ingress --namespace $Namespace  
            if($LASTEXITCODE -ne 0 )
            {
                Write-Host "Error installing NGINX, waiting 20 seconds to try install NGINX again..." -ForegroundColor Yellow
                Start-Sleep -Seconds 20
            }
            else
            {
                $looper = $false
            }            
        }
        catch
        {
            Write-Host "Waiting 20 seconds to try install NGINX again..." -ForegroundColor Yellow
            Start-Sleep -Seconds 20
        }
    }
}

function Add-NodePool
{
    param([string]$ResourceGroupName, [string]$ClusterName, [string]$NodePoolName, [int]$NodeCount, [string]$VmSize)

    az aks nodepool add --resource-group $ResourceGroupName --cluster-name $ClusterName --name $NodePoolName --node-count $NodeCount --node-vm-size $VmSize
}

function Get-AksClusterExists
{
    param([string]$SubscriptionName, [string]$ClusterName)

    $aksList = az aks list --subscription "$SubscriptionName" | ConvertFrom-Json

    foreach($item in $aksList)
    {
        $id = $item.id
        $parts = $id.Split("/")
        $name = $parts[$parts.Length - 1]

        if($name -eq $ClusterName)
        {
            return $true
        }
    }

    return $false
}

function Get-AksCredentials
{
    param([string]$ResourceGroupName, [string]$ClusterName)

    $looper = $true
    while($looper)
    {
        try
        {         
            az aks get-credentials --resource-group $ResourceGroupName --name $ClusterName            
            $looper = $false
        }
        catch
        {
            Write-Host "Waiting 30 seconds to try get aks credentials again..." -ForegroundColor Yellow
            Start-Sleep -Seconds 30
        }    
    }
}

function Get-ExternalIP
{
    param([string]$Namespace = "kube-system")
    $looper = $TRUE
    while($looper)
    {   $externalIP = ""                  
        #$lineValue = kubectl get service -l app=nginx-ingress --namespace $Namespace
        #lineValue = kubectl get svc nginx-ingress-nginx-controller -n $Namespace
        $lineValue = kubectl get svc nginx-nginx-ingress -n $Namespace
        Write-Host "Last Exit Code for get external ip $LASTEXITCODE" -ForegroundColor White
        if($LASTEXITCODE -ne 0 )
        {
            Write-Host "Try get external ip...waiting 30 seconds" -ForegroundColor Yellow
            Start-Sleep -Seconds 30
        }  
        elseif($lineValue.Length -gt 0)
        {
            $line = $lineValue[1]
            $lineout = $line -split '\s+'
            $externalIP = $lineout[3]              
        }
        
              
        if($externalIP -eq "<pending>")
        {        
            Write-Host "External IP is pending...waiting 30 seconds" -ForegroundColor Yellow
            Start-Sleep -Seconds 30
        }
        elseif($externalIP.Length -eq 0)
        {
            Write-Host "External IP is zero length...waiting 30 seconds" -ForegroundColor Yellow
            Start-Sleep -Seconds 30
        }
        else
        {
            $looper = $FALSE
            Write-Host "External IP is $externalIP" -ForegroundColor Magenta
            return $externalIP
        }
    }
}

function New-AksCluster
{
    param([string]$ClusterName, [string]$ResourceGroupName, [string]$AppID, [string]$Password, [string]$VmSize, [int]$NodeCount)

    az aks create --resource-group $ResourceGroupName --name $ClusterName --node-count $NodeCount --service-principal $AppID --client-secret $Password --node-vm-size $VmSize --generate-ssh-keys
}

function New-KubectlApply
{
    param([string]$Filename, [string]$Namespace = "kube-system")
    
    $looper = $true
    while($looper)
    {    
        kubectl apply -f $Filename -n $Namespace --validate=false
        if($LASTEXITCODE -ne 0)
        {
            Write-Host "Waiting 30 to re-apply file..." -ForegroundColor Yellow
            Start-Sleep -Seconds 30
        }
        else
        {
            $looper = $false
        }
    }
}

function New-KubectlClusterCleanup
{
    param([string]$ClusterName, [string]$ResourceGroupName)

    #Remove previous deployments from kubectl
    $cleanup = Read-Host "Clean up previous kubectl deployment [y/n] ? "
    if($cleanup.ToLowerInvariant() -eq "y")
    {
        $cleanupClusterName = Read-Host "Enter previous cluster name [Enter blank == $ClusterName] "
        $cleanupResourceGroup = Read-Host "Enter previous resource group name [Enter blank == $ResourceGroupName] "
        
        if($cleanupClusterName.Length -eq 0)
        {
            $cleanupClusterName = $ClusterName
        }
        
        if($cleanupResourceGroup.Length -eq 0)
        {
            $cleanupResourceGroup = $ResourceGroupName
        }
        
        $condition1 = "users.clusterUser_" + $cleanupResourceGroup + "_" + $cleanupClusterName
        $condition2 = "clusters." + $cleanupClusterName
        kubectl config unset $condition1
        kubectl config unset $condition2
    }
}

function Remove-AksCluster
{
    param([string]$ClusterName, [string]$ResourceGroupName)

    $clusterLine = az aks list --query "[?contains(name, '$ClusterName')]" --output table
    if($clusterLine.Length -gt 0)
    {
        az aks delete --name $ClusterName --resource-group $ResourceGroupName --yes
    }
}

function Set-ApplyYaml
{
    param([string]$File, [string]$Namespace)

    $looper = $true
    while($looper)
    {
        kubectl apply -f $File -n $Namespace --validate=false
        if($LASTEXITCODE -ne 0)
        {
            Write-Host "kubectl apply failed for $File. Waiting 10 seconds to try again..." -ForegroundColor Yellow
            Start-Sleep -Seconds 10
        }
        else
        {
            $looper = $false
        }
    }
}

function Set-Certificate
{
    param([string]$Dns, [string]$Location, [string]$Path, [string]$Destination, [string]$Namespace = "cert-manager")

    Copy-Item -Path $Path -Destination $Destination
    Update-Yaml -NewValue $Dns -MatchString "INGRESSDNS" -Filename $Destination
    Update-Yaml -NewValue $Location -MatchString "LOCATION" -Filename $Destination
    New-KubectlApply -Filename $Destination -Namespace $Namespace
    Remove-Item -Path $Destination
}

function Set-Ingress
{
    param([string]$Dns, [string]$Location, [string]$Path, [string]$Destination, [string]$Namespace = "kube-system")
    
    Copy-Item -Path $Path -Destination $Destination
    Update-Yaml -NewValue $Dns -matchString "INGRESSDNS" -filename $Destination
    Update-Yaml -newValue $Location -matchString "LOCATION" -filename $Destination
    New-KubectlApply -Filename $Destination -Namespace $Namespace
    Remove-Item -Path $Destination
}

function Set-NodeLabel
{
    param([string]$NodeMatchValue, [string]$Key, [string]$Value)
    
    $looper = $true
    while($looper)
    {    
        $nodes = kubectl get nodes
        if($LASTEXITCODE -ne 0)
        {
            Write-Host "Waiting 10 seconds to get nodes from kubectl..." -ForegroundColor Yellow
            Start-Sleep -Seconds 10
        }
        else
        {
            foreach($node in $nodes)
            {
               $nodeVal = $node.Split(" ")[0]
               if($nodeVal.Contains($NodeMatchValue))
               {
                    kubectl label nodes $nodeVal "$Key=$Value"
                    if($LASTEXITCODE -ne 0)
                    {
                        Write-Host "Set node label failed. Waiting 10 seconds to try again..." -ForegroundColor Yellow
                        Start-Sleep -Seconds 10
                    }
                    else
                    {
                        $looper = $false
                    }
               }
            }
        }
    }
}

function Set-Timer
{
    param([string]$Message, [int]$Seconds)

    Write-Host $Message -ForegroundColor Yellow
    Start-Sleep -Seconds $Seconds    
}

function Set-WaitForApiServices
{
    $v = kubectl get apiservice
    $ft = $true
    while(([string]$v).IndexOf("False") -ne -1)
    {
        if($ft)
        {
            Write-Host("K8 metrics-server and/or cert-manager-webhook is offline right now. We'll keep waiting until they are online") -ForegroundColor Yellow
            $ft = $false
        }
        else
        {
            Write-Host("Waiting 60 secs for the K8 apiservices to come back online, yuck...") -ForegroundColor Yellow
        }
        Start-Sleep -Seconds 60
        $v = kubectl get apiservice
    }
}

function Update-PublicIP
{
    param([string]$PublicIP, [string]$Dns, [string]$SubscriptionName)

    if($subscriptionNameOrId.Length -ne 0)
    {
      az network public-ip update --ids $PublicIP --dns-name $Dns --subscription $SubscriptionName
    }
    else
    {
      az network public-ip update --ids $PublicIP --dns-name $Dns
    }
}

function Update-Step
{
    param([int]$Step, [string]$Message, [DateTime]$Start)
    
        $endTime = Get-Date
        $timeSpan = New-TimeSpan -Start $Start -End $endTime
        $val = $timeSpan.ToString("mm\:ss")
        
        Write-Host "--Step $Step - $Message - $val" -ForegroundColor Green    
}

function Update-Yaml
{
    Param ([string]$NewValue, [string]$MatchString, [string]$Filename)

    (Get-Content $Filename) -replace $MatchString,$NewValue | out-file $Filename -Encoding ascii
}