SkunkLabVirtualRtu.psm1
function New-FullVrtuDeploy { param([string]$Path, [string]$File, [string]$SubscriptionName , [string]$ResourceGroupName , [string]$Location, [string]$Email, [string]$PiraeusDns, [string]$MonitorDns, [string]$VirtualRtuId, [string]$PiraeusClusterName, [string]$VrtuClusterName, [string]$MonitorClusterName, [string]$OrleansStorageAcctName, [string]$VrtuStorageAcctName, [string]$Domain, [int]$Port, [string]$IoTHubName, [string]$ConfigAppName, [string]$DeployAppName, [string]$DeployTemplatePath, [string]$AppID, [string]$Password, [string]$LogLevel) $start = Get-Date New-PiraeusDeployment -Path $Path -File $File -SubscriptionName $SubscriptionName -ResourceGroupName $ResourceGroupName -Location $Location -Email $Email -Dns $PiraeusDns -ClusterName $PiraeusClusterName -AppID $AppID -Password $Password -OrleansStorageAcctName $OrleansStorageAcctName -LogLevel $LogLevel #read the config file $config = Get-Content -Raw -Path $File | ConvertFrom-Json $symmetricKey = $config.symmetricKey $hostname = $config.piraeusHostname $appId = $config.appId $pwd = $config.pwd New-VrtuVnetDeploy -Path $Path -File $File -SubscriptionName $SubscriptionName -ResourceGroupName $ResourceGroupName -Location $Location -VirtualRtuId $VirtualRtuId -Hostname $hostname -SymmetricKey $symmetricKey -IoTHubName $IoTHubName -StorageAcctName $VrtuStorageAcctName -ClusterName $VrtuClusterName -AppID $appId -Password $pwd -LogLevel $LogLevel -StartTime $start New-WebMonitorDeploy -Path $Path -File $File -SubscriptionName $SubscriptionName -ResourceGroupName $ResourceGroupName -Location $Location -PiraeusHostname $hostname -VirtualRtuId $VirtualRtuId -StorageAcctName $VrtuStorageAcctName -SymmetricKey $symmetricKey -Dns $MonitorDns -Email $Email -ClusterName $MonitorClusterName -Domain $Domain -Port $Port -AppID $appId -Password $pwd -LogLevel $LogLevel -StartTime $start $funcUrl = New-DeployFunctions -Path $Path -File $File -ConfigAppName $ConfigAppName -DeployAppName $DeployAppName -DeployTemplatePath $DeployTemplatePath -Location $Location -ResourceGroupName $ResourceGroupName -SubscriptionName $SubscriptionName return $funcUrl } function New-DeviceDeploy { param ([string]$File, [string]$Url = "http://localhost:7071/api/DeploymentFunction", [string]$Key = $null, [bool]$Update = $false) $config = [System.IO.File]::ReadAllBytes($File) $requestUrl = $null if($Key -eq $null) { if($Update -eq $false) { $requestUrl = $Url } else { $requestUrl = $Url + "?type=update" } } else { $requestUrl = $Url + "?code=" + $Key if($Update -ne $false) { $requestUrl = $requestUrl + "&type=update" } } if($Module -eq $null) { $connectionString = Invoke-WebRequest -Uri $requestUrl -Method Post -ContentType "application/json" -Body $config Write-Host $connectionString } else { Invoke-WebRequest -Uri $requestUrl -Method Post -ContentType "application/json" -Body $config Write-Host "Update complete" } } function New-DeployFunctions { param([string]$Path, [string]$File, [string]$ConfigAppName, [string]$DeployAppName, [string]$DeployTemplatePath, [string]$Location, [string]$ResourceGroupName, [string]$SubscriptionName) $base64Template = New-FileToBase64 -Path $Path -Filename $DeployTemplatePath $config = Get-Content -Raw -Path $File | ConvertFrom-Json $acctName = Get-AccountName -StorageConnectionString $config.vrtuConnectionString Update-ConfigSecrets -Path $Path -Folder "..\src\VirtualRtu.Configuration.Function" -SymmetricKey $config.symmetricKey -ApiToken $config.apiCode -LifetimeMinutes $config.lifetimeMinutes -TableName $config.tableName -StorageConnectionString $config.vrtuConnectionString -ContainerName $config.containerName -Filename $config.filename New-FunctionApp -AppName $ConfigAppName -StorageAcctName $acctName -Location $Location -AppInsightsName "configfunc" -ResourceGroupName $ResourceGroupName New-ConfigurationFunctionApp -Path $Path -PublishFolder "../build/VirtualRtu.Configuration.Function/publish" -ZipFilename "configfunc.zip" -AppName $ConfigAppName -ResourceGroupName $ResourceGroupName $creds = Get-FunctionCreds -AppName $ConfigAppName -ResourceGroupName $ResourceGroupName -SubscriptionName $SubscriptionName $code = Get-FunctionCode -AppName $ConfigAppName -FunctionName "ConfigurationFunction" -EncodedCreds $creds $serviceUrl = "https://$ConfigAppName.azurewebsites.net/api/ConfigurationFunction?code=$code" Update-DeploySecrets -Path $Path -Folder "..\src\AzureIoT.Deployment.Function" -Hostname $config.piraeusHostname -ServiceUrl $serviceUrl -TableName $config.tableName -StorageConnectionString $config.vrtuConnectionString -IoTHubConnectionString $config.iotHubConnectionString -Template $base64Template New-FunctionApp -AppName $DeployAppName -StorageAcctName $acctName -Location $Location -AppInsightsName "deployfunc" -ResourceGroupName $ResourceGroupName New-DeploymentFunctionApp -Path $Path -PublishFolder "../build/AzureIoT.Deployment.Function/publish" -ZipFilename "deployfunc.zip" -AppName $DeployAppName -ResourceGroupName $ResourceGroupName $creds = Get-FunctionCreds -AppName $DeployAppName -ResourceGroupName $ResourceGroupName -SubscriptionName $SubscriptionName $code2 = Get-FunctionCode -AppName $DeployAppName -FunctionName "DeploymentFunction" -EncodedCreds $creds return "https://$DeployAppName.azurewebsites.net/api/DeploymentFunction?code=$code2" } function Get-AccountName { param([string]$StorageConnectionString) $vals = $acct.Split(";") foreach($item in $vals) { if($item.Contains("AccountName=")) { $acctNameParts = $item.Split("=") return $acctNameParts[1] } } return $null } function Add-VrtuVnetDeploy { param([string]$Path, [string]$File, [string]$SubscriptionName, [string]$ResourceGroupName, [string]$Location, [string]$VirtualRtuId, [string]$Hostname, [string]$SymmetricKey, [string]$BlobContainerName, [string]$TableName, [string]$IoTHubName, [string]$LogLevel, [string]$StorageAcctName, [int]$LifetimeMinutes = 0, [string]$ClusterName, [int]$NodeCount, [string]$VmSize, [string]$VnetName, [string]$SubnetName, [string]$VnetPrefix, [string]$SubnetPrefix, [string]$ServiceCidr, [string]$DnsServiceIP, [string]$PodCidr, [string]$DockerBridgeIP, [string]$AppID, [string]$Password) $env:AZURE_HTTP_USER_AGENT='pid-332e88b9-31d3-5070-af65-de3780ad5c8b' $step = 0 $start = Get-Date if($BlobContainerName.Length -eq 0) { $BlobContainerName = "maps" } if($TableName.Length -eq 0) { $TableName = "gateway" } if($LogLevel.Length -eq 0) { $LogLevel = "Information" } if($LifetimeMinutes -eq 0) { $LifetimeMinutes = 525600 } if($NodeCount -eq 0) { $NodeCount = 1 } if($VmSize.Length -eq 0) { $VmSize = "Standard_D2s_v3" } if($VnetName.Length -eq 0) { $VnetName = "vrtu-vnet" } if($SubnetName.Length -eq 0) { $SubnetName = "vrtu-subnet" } if($VnetPrefix.Length -eq 0) { $VnetPrefix = "192.168.0.0/16" } if($SubnetPrefix.Length -eq 0) { $SubnetPrefix = "192.168.1.0/24" } if($ServiceCidr.Length -eq 0) { $ServiceCidr = "10.0.0.0/16" } if($DnsServiceIP.Length -eq 0) { $DnsServiceIP = "10.0.0.10" } if($PodCidr.Length -eq 0) { $PodCidr = "10.244.0.0/16" } if($DockerBridgeIP.Length -eq 0) { $DockerBridgeIP = "172.17.0.1/16" } #default values $claimTypes = "http://$Hostname/name" $claimValues = $VirtualRtuId $issuer = "http://$Hostname/" $audience = $issuer $filename = "$VirtualRtuId.json" Write-Host "LTM = $LifetimeMinutes" -ForegroundColor Cyan $ltm = '\"'+ $LifetimeMinutes + '\"' #get the service principal Update-Step -Step $step -Message "Set Service Principal" -Start $start $step++ $spn = Get-ServicePrincipal -AppID $AppID -Password $Password $spnAppId = $spn."appId" $spnPwd = $spn."pwd" $iotHubConnection = Get-IoTHubConnectionString -HubName "$IoTHubName" -ResourceGroupName "$ResourceGroupName" if($iotHubConnection.Length -eq 0) { Write-Host "No IoT Hub connection string...stopping script" -ForegroundColor DarkCyan return } #create the storage account $storageAvailable = Get-StorageAccountNameAvailable -SubscriptionName "$SubscriptionName" -StorageAcctName "$StorageAcctName" if($storageAvailable) { New-StorageAccount -StorageAcctName $StorageAcctName -Location $Location -ResourceGroupName $ResourceGroupName } $storageConnectionString = Get-StorageAccountConnectionString -StorageAcctName $StorageAcctName -ResourceGroupName $ResourceGroupName if($LASTEXITCODE -ne 0) { Write-Host "Failed to get VRTU storage account connection string...terminating script." -ForegroundColor Yellow return } Update-Step -Step $step -Message "VRTU storage account connection string obtained" -Start $start $step++ #create app insights and get instrumentation key Update-Step -Step $step -Message "Creating App Insights for VRTU cluster and getting instrumentation key" -Start $start $step++ $instrumentationKey = Get-InstrumentationKey "$VirtualRtuId" -ResourceGroupName $ResourceGroupName -Location $Location Update-Step -Step $step -Message "Creating new VRTU VNET" -Start $start $step++ az network vnet create --resource-group $ResourceGroupName --name $VnetName --address-prefixes 192.168.0.0/16 --subnet-name $SubnetName --subnet-prefix 192.168.1.0/24 $VnetName_ID=$(az network vnet show --resource-group $ResourceGroupName --name $VnetName --query id -o tsv) $SubnetName_ID=$(az network vnet subnet show --resource-group $ResourceGroupName --vnet-name $VnetName --name $SubnetName --query id -o tsv) Update-Step -Step $step -Message "Assigning role to service principal" -Start $start $step++ az role assignment create --assignee $spnAppId --scope $VnetName_ID --role Contributor Update-Step -Step $step -Message "Creating new VRTU AKS cluster" -Start $start $step++ az aks create --resource-group $ResourceGroupName --name $ClusterName --node-count $NodeCount --network-plugin kubenet --service-cidr $ServiceCidr --dns-service-ip $DnsServiceIP --pod-cidr $PodCidr --docker-bridge-address $DockerBridgeIP --vnet-subnet-id $SubnetName_ID --service-principal "$spnAppId" --client-secret "$spnPwd" kubectl config use-context $ClusterName Update-Step -Step $step -Message "Getting AKS credentials" -Start $start $step++ az aks get-credentials --resource-group $ResourceGroupName --name $ClusterName Update-Step -Step $step -Message "Applying Helm RBAC" -Start $start $step++ kubectl apply -f "./helm-rbac.yaml" Update-Step -Step $step -Message "Starting Tiller" -Start $start $step++ helm init --service-account tiller Set-Timer -Message "...waiting 45 seconds for Tiller to start" -Seconds 45 Update-Step -Step $step -Message "Deploying helm chart for VRTU VNET" -Start $start $step++ helm install "$Path/virtualrtu-vnet" --name virtualrtu --namespace kube-system --set claimTypes=$claimTypes --set claimValues=$claimValues --set issuer=$issuer --set audience=$audience --set lifetimeMinutes=$ltm --set symmetricKey=$SymmetricKey --set hostname=$Hostname --set storageConnectionString="$storageConnectionString" --set container=$BlobContainerName --set filename=$filename --set virtualRtuId=$VirtualRtuId --set instrumentationKey=$instrumentationKey --set logLevel=$LogLevel Write-Host "-- Step $step - Geting IP for Subnet communications" -ForegroundColor Green $ip = Get-ExternalIPForService -AppName "vrtu" $step++ Write-Host "-- IP = $ip " -ForegroundColor Magenta Write-Host "VRTU-VNET deployed!" -ForegroundColor Cyan } function New-VrtuVnetDeploy { param([string]$Path, [string]$File, [string]$SubscriptionName, [string]$ResourceGroupName, [string]$Location, [string]$VirtualRtuId, [string]$Hostname, [string]$SymmetricKey, [string]$BlobContainerName, [string]$TableName, [string]$IoTHubName, [string]$LogLevel, [string]$StorageAcctName, [int]$LifetimeMinutes = 0, [string]$ClusterName, [int]$NodeCount, [string]$VmSize, [string]$VnetName, [string]$SubnetName, [string]$VnetPrefix, [string]$SubnetPrefix, [string]$ServiceCidr, [string]$DnsServiceIP, [string]$PodCidr, [string]$DockerBridgeIP, [string]$AppID, [string]$Password, [int]$Step, [DateTime]$StartTime) $env:AZURE_HTTP_USER_AGENT='pid-332e88b9-31d3-5070-af65-de3780ad5c8b' if($Step -eq 0) { $step = 0 } else { $step = $Step } $step++ $endTime = Get-Date $timeSpan = New-TimeSpan -Start $StartTime -End $endTime if($timeSpan.Days -lt 1) { $start = $StartTime } else { $start = $endTime } if($File.Length -eq 0) { $dateTimeString = Get-Date -Format "MM-dd-yyyyTHH-mm-ss" $File = "./vrtu-" + $dateTimeString + ".json" } if($BlobContainerName.Length -eq 0) { $BlobContainerName = "maps" } if($TableName.Length -eq 0) { $TableName = "gateway" } if($LogLevel.Length -eq 0) { $LogLevel = "Information" } if($LifetimeMinutes -eq 0) { $LifetimeMinutes = 525600 } if($NodeCount -eq 0) { $NodeCount = 1 } if($VmSize.Length -eq 0) { $VmSize = "Standard_D2s_v3" } if($VnetName.Length -eq 0) { $VnetName = "vrtu-vnet" } if($SubnetName.Length -eq 0) { $SubnetName = "vrtu-subnet" } if($VnetPrefix.Length -eq 0) { $VnetPrefix = "192.168.0.0/16" } if($SubnetPrefix.Length -eq 0) { $SubnetPrefix = "192.168.1.0/24" } if($ServiceCidr.Length -eq 0) { $ServiceCidr = "10.0.0.0/16" } if($DnsServiceIP.Length -eq 0) { $DnsServiceIP = "10.0.0.10" } if($PodCidr.Length -eq 0) { $PodCidr = "10.244.0.0/16" } if($DockerBridgeIP.Length -eq 0) { $DockerBridgeIP = "172.17.0.1/16" } #default values $claimTypes = "http://$Hostname/name" $claimValues = $VirtualRtuId $issuer = "http://$Hostname/" $audience = $issuer $filename = "$VirtualRtuId.json" Write-Host "LTM = $LifetimeMinutes" -ForegroundColor Cyan $ltm = '\"'+ $LifetimeMinutes + '\"' #get the service principal Update-Step -Step $step -Message "Set Service Principal" -Start $start $step++ $spn = Get-ServicePrincipal -AppID $AppID -Password $Password $spnAppId = $spn."appId" $spnPwd = $spn."pwd" $iotHubConnection = Get-IoTHubConnectionString -HubName "$IoTHubName" -ResourceGroupName "$ResourceGroupName" if($iotHubConnection.Length -eq 0) { Write-Host "No IoT Hub connection string...stopping script" -ForegroundColor DarkCyan return } #create the storage account $storageAvailable = Get-StorageAccountNameAvailable -SubscriptionName "$SubscriptionName" -StorageAcctName "$StorageAcctName" if($storageAvailable) { New-StorageAccount -StorageAcctName $StorageAcctName -Location $Location -ResourceGroupName $ResourceGroupName } $storageConnectionString = Get-StorageAccountConnectionString -StorageAcctName $StorageAcctName -ResourceGroupName $ResourceGroupName if($LASTEXITCODE -ne 0) { Write-Host "Failed to get VRTU storage account connection string...terminating script." -ForegroundColor Yellow return } Update-Step -Step $step -Message "VRTU storage account connection string obtained" -Start $start $step++ #create app insights and get instrumentation key Update-Step -Step $step -Message "Creating App Insights for VRTU cluster and getting instrumentation key" -Start $start $step++ $instrumentationKey = Get-InstrumentationKey "$VirtualRtuId" -ResourceGroupName $ResourceGroupName -Location $Location Update-Step -Step $step -Message "Creating new VRTU VNET" -Start $start $step++ az network vnet create --resource-group $ResourceGroupName --name $VnetName --address-prefixes 192.168.0.0/16 --subnet-name $SubnetName --subnet-prefix 192.168.1.0/24 $VnetName_ID=$(az network vnet show --resource-group $ResourceGroupName --name $VnetName --query id -o tsv) $SubnetName_ID=$(az network vnet subnet show --resource-group $ResourceGroupName --vnet-name $VnetName --name $SubnetName --query id -o tsv) Update-Step -Step $step -Message "Assigning role to service principal" -Start $start $step++ az role assignment create --assignee $spnAppId --scope $VnetName_ID --role Contributor Update-Step -Step $step -Message "Creating new VRTU AKS cluster" -Start $start $step++ az aks create --resource-group $ResourceGroupName --name $ClusterName --node-count $NodeCount --network-plugin kubenet --service-cidr $ServiceCidr --dns-service-ip $DnsServiceIP --pod-cidr $PodCidr --docker-bridge-address $DockerBridgeIP --vnet-subnet-id $SubnetName_ID --service-principal "$spnAppId" --client-secret "$spnPwd" kubectl config use-context $ClusterName Update-Step -Step $step -Message "Getting AKS credentials" -Start $start $step++ az aks get-credentials --resource-group $ResourceGroupName --name $ClusterName Update-Step -Step $step -Message "Applying Helm RBAC" -Start $start $step++ kubectl apply -f "./helm-rbac.yaml" Update-Step -Step $step -Message "Starting Tiller" -Start $start $step++ helm init --service-account tiller Set-Timer -Message "...waiting 45 seconds for Tiller to start" -Seconds 45 Update-Step -Step $step -Message "Deploying helm chart for VRTU VNET" -Start $start $step++ helm install "$Path/virtualrtu-vnet" --name virtualrtu --namespace kube-system --set claimTypes=$claimTypes --set claimValues=$claimValues --set issuer=$issuer --set audience=$audience --set lifetimeMinutes=$ltm --set symmetricKey=$SymmetricKey --set hostname=$Hostname --set storageConnectionString="$storageConnectionString" --set container=$BlobContainerName --set filename=$filename --set virtualRtuId=$VirtualRtuId --set instrumentationKey=$instrumentationKey --set logLevel=$LogLevel Write-Host "-- Step $step - Geting IP for Subnet communications" -ForegroundColor Green $ip = Get-ExternalIPForService -AppName "vrtu" $step++ Write-Host "-- IP = $ip " -ForegroundColor Magenta Update-Step -Step $step -Message "Read file" -Start $start $step++ if(Test-Path $File) { $config = Get-Content -Raw -Path $File | ConvertFrom-Json $config | Add-Member -Name "claimValues" -Value "$VirtualRtuId" -MemberType NoteProperty $config | Add-Member -Name "containerName" -Value "$BlobContainerName" -MemberType NoteProperty $config | Add-Member -Name "filename" -Value "$VirtualRtuId.json" -MemberType NoteProperty $config | Add-Member -Name "tableName" -Value "$TableName" -MemberType NoteProperty $config | Add-Member -Name "lifetimeMinutes" -Value $LifetimeMinutes -MemberType NoteProperty $config | Add-Member -Name "vrtuVmSize" -Value "$VmSize" -MemberType NoteProperty $config | Add-Member -Name "virtualRtuId" -Value "$VirtualRtuId" -MemberType NoteProperty $config | Add-Member -Name "vrtuConnectionString" -Value "$storageConnectionString" -MemberType NoteProperty $config | Add-Member -Name "vrtuInstrumentationKey" -Value "$instrumentationKey" -MemberType NoteProperty $config | Add-Member -Name "iotHubConnectionString" -Value "$iotHubConnection" -MemberType NoteProperty $config | Add-Member -Name "vrtuIP" -Value "$ip" -MemberType NoteProperty #$config.claimValues = "$VirtualRtuId" #$config.containerName = "$BlobContainerName" #$config.filename = "$VirtualRtuId.json" #$config.tableName = "$TableName" #$config.lifetimeMinutes = $LifetimeMinutes #$config.vrtuVmSize = "$VmSize" #$config.virtualRtuId = "$VirtualRtuId" #$config.vrtuConnectionString = "$storageConnectionString" #$config.vrtuInstrumentationKey = "$instrumentationKey" #$config.iotHubConnectionString = "$iotHubConnection" #$config.vrtuIP = "$ip" Update-Step -Step $step -Message "Write file" -Start $start $step++ $config | ConvertTo-Json -depth 100 | Out-File $File } Write-Host "VRTU-VNET deployed!" -ForegroundColor Cyan } function Add-WedMonitorDeploy { param([string]$Path, [string]$File, [string]$SubscriptionName, [string]$ResourceGroupName, [string]$PiraeusHostname, [string]$VirtualRtuId, [string]$StorageAcctName, [string]$SymmetricKey, [string]$Dns, [string]$Location, [string]$Email, [string]$ClusterName, [string]$Domain, [int]$Port, [string]$AppID, [string]$Password, [string]$VmSize, [string]$TableName, [int]$NodeCount, [string]$LogLevel, [int]$Step, [DateTime]$StartTime) $env:AZURE_HTTP_USER_AGENT='pid-332e88b9-31d3-5070-af65-de3780ad5c8b' $step = 0 $start = Get-Date if($LogLevel.Length -eq 0) { $LogLevel = "Information" } if($VmSize.Length -eq 0) { $VmSize = "Standard_D2s_v3" } if($TableName.Length -eq 0) { $TableName = "gateway" } if($NodeCount -eq 0) { $NodeCount = 1 } Update-Step -Step $step -Message "Set Subscription for deployment" -Start $start $step++ Set-Subscription -SubscriptionName $SubscriptionName Update-Step -Step $step -Message "Set Resource Group for deployment" -Start $start $step++ Set-ResourceGroup -ResourceGroupName $ResourceGroupName -Location $Location Update-Step -Step $step -Message "Get Service Principal" -Start $start $step++ $spn = Get-ServicePrincipal -AppID $AppID -Password $Password $spnAppId = $spn."appId" $spnPwd = $spn."pwd" Update-Step -Step $step -Message "Get Tenant ID" -Start $start $step++ $tenantId = Get-TenantId -SubscriptionName "$SubscriptionName" Update-Step -Step $step -Message "Check for App Registration" -Start $start $step++ $appRegJson = az ad app list --display-name "$VirtualRtuId-Monitor" | ConvertFrom-Json if($appRegJson.Length -eq 1) { Update-Step -Step $step -Message "Deleting App Registration" -Start $start $step++ az ad app delete --id $appRegJson.appId } Update-Step -Step $step -Message "Register App in AAD and get Client Id" -Start $start $step++ $appName = "$VirtualRtuId-Monitor" $replyUris = @("https://$Dns.$Location.cloudapp.azure.com/signin-oidc","https://locahost:44386") $clientId = New-RegisterApp -AppName $appName -ReplyUris $replyUris Update-Step -Step $step -Message "Get Storage Connection String" -Start $start $step++ $vrtuConnectionString = Get-StorageAccountConnectionString -StorageAcctName "$StorageAcctName" -ResourceGroupName "$ResourceGroupName" Update-Step -Step $step -Message "See if Monitor AKS cluster exists" -Start $start $step++ $clusterExists = Get-AksClusterExists -SubscriptionName $SubscriptionName -ClusterName $ClusterName if($clusterExists) { Update-Step -Step $step -Message "Setting kubectl context to monitor cluster" -Start $start $step++ kubectl config use-context $ClusterName Update-Step -Step $step -Message "Updating ingress DNS and Location" -Start $start $step++ #Update-MonitorIngressDns -Dns $Dns -Location $Location -Path "$Path/ingress-webmonitor.yaml" -Destination "$Path/ingress-webmonitor-$Dns.yaml" Set-Ingress -Dns $Dns -Location $Location -Path "$Path/ingress-webmonitor.yaml" -Destination "$Path/ingress-webmonitor-copy.yaml" } else { kubectl create namespace "webmon" Update-Step -Step $step -Message "Creating new Monitor AKS cluster" -Start $start $step++ New-AksCluster -ClusterName $ClusterName -ResourceGroupName $ResourceGroupName -AppId "$spnAppId" -Password "$spnPwd" -VmSize $VmSize -NodeCount $NodeCount kubectl config use-context $ClusterName Update-Step -Step $step -Message "Get AKS credentials" -Start $start $step++ Get-AksCredentials -ClusterName $ClusterName -ResourceGroupName $ResourceGroupName Update-Step -Step $step -Message "Apply HELM RBAC" -Start $start $step++ New-KubectlApply -Filename "$Path/helm-rbac.yaml" -Namespace "kube-system" Update-Step -Step $step -Message "Start Tiller" -Start $start $step++ helm init --service-account tiller Set-Timer -Message "...waiting 45 seconds for Tiller to start" -Seconds 45 Update-Step -Step $step -Message "Add cert manager for Let's Encrypt" -Start $start $step++ Add-CertManager2 -Namespace "cert-manager2" Set-Timer -Message "...waiting 45 seconds for cert-manager to initialize" -Seconds 45 Update-Step -Step $step -Message "Add cert issuer for Lets Encrypt" -Start $start $step++ Add-Issuer -Email $Email -IssuerPath "$Path/issuer2.yaml" -IssuerDestination "$Path/issuer2-copy.yaml" -Namespace "webmon" Set-Timer -Message "...waiting 30 seconds for issuer to initialize" -Seconds 30 Update-Step -Step $step -Message "Upate local HELM repo" -Start $start $step++ helm repo add stable https://kubernetes-charts.storage.googleapis.com/ Update-Step -Step $step -Message "Add NGINX" -Start $start $step++ Add-NGINX -Namespace "webmon" Set-Timer "...waiting 45 seconds for nginx to initialize" -Seconds 45 Update-Step -Step $step -Message "Get External IP address" -Start $start $step++ $IP = Get-ExternalIP -Namespace "webmon" Update-Step -Step $step -Message "Create Public IP ID" -Start $start $step++ $PUBLICIPID=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$IP')].[id]" --output tsv) Update-Step -Step $step -Message "Update Public IP ID" -Start $start $step++ Update-PublicIP -PublicIP $PUBLICIPID -Dns $Dns -SubscriptionName $SubscriptionName Update-Step -Step $step -Message "Set certificate for cert-manager and Lets Encrypt" -Start $start $step++ Set-Certificate -Dns $Dns -Location $Location -Path "$Path/certificate2.yaml" -Destination "$Path/certificate2-copy.yaml" -Namespace "webmon" } Update-Step -Step $step -Message "Creating App Insights for Monitor and getting instrumentation key" -Start $start $step++ $aiKey = Get-InstrumentationKey "$Dns-monitors" -ResourceGroupName $ResourceGroupName -Location $Location Update-Step -Step $step -Message "Install Web Monitor from helm chart" -Start $start $step++ $domain = "$Domain.onmicrosoft.com" $hostname = $PiraeusHostname helm install "$Path/virtualrtu-webmonitor" --name virtualrtu-webmonitor --namespace "webmon" --set port=$Port --set symmetricKey=$SymmetricKey --set instrumentationKey=$aiKey --set logLevel=$LogLevel --set tenantId=$tenantId --set clientId=$clientId --set domain=$domain --set hostname=$hostname --set location=$Location --set storageConnectionString=$vrtuConnectionString --set tableName=$TableName if($LASTEXITCODE -ne 0 ) { Update-Step -Step $step -Message "Waiting for Kubernetes API Services to start" -Start $start $step++ Set-WaitForApiServices Update-Step -Step $step -Message "Trying again to install VRTU Monitor from helm chart" -Start $start $step++ helm install "$Path/virtualrtu-webmonitor" --name virtualrtu-webmonitor --namespace "webmon" --set port=$Port --set symmetricKey=$SymmetricKey --set instrumentationKey=$aiKey --set logLevel=$LogLevel --set tenantId=$tenantId --set clientId=$clientId --set domain=$domain --set hostname=$hostname --set location=$Location --set storageConnectionString=$vrtuConnectionString --set tableName=$TableName } Set-Ingress -Dns $Dns -Location $Location -Path "$Path/ingress2.yaml" -Destination "$Path/ingress2-copy.yaml" -Namespace "webmon" } function New-WebMonitorDeploy { param([string]$Path, [string]$File, [string]$SubscriptionName, [string]$ResourceGroupName, [string]$PiraeusHostname, [string]$VirtualRtuId, [string]$StorageAcctName, [string]$SymmetricKey, [string]$Dns, [string]$Location, [string]$Email, [string]$ClusterName, [string]$Domain, [int]$Port, [string]$AppID, [string]$Password, [string]$VmSize, [string]$TableName, [int]$NodeCount, [string]$LogLevel, [int]$Step, [DateTime]$StartTime) $step = $Step $step++ $env:AZURE_HTTP_USER_AGENT='pid-332e88b9-31d3-5070-af65-de3780ad5c8b' $endTime = Get-Date $timeSpan = New-TimeSpan -Start $StartTime -End $endTime if($timeSpan.Days -lt 1) { $start = $StartTime } else { $start = $endTime } if($LogLevel.Length -eq 0) { $LogLevel = "Information" } if($VmSize.Length -eq 0) { $VmSize = "Standard_D2s_v3" } if($TableName.Length -eq 0) { $TableName = "gateway" } if($NodeCount -eq 0) { $NodeCount = 1 } Update-Step -Step $step -Message "Set Subscription for deployment" -Start $start $step++ Set-Subscription -SubscriptionName $SubscriptionName Update-Step -Step $step -Message "Set Resource Group for deployment" -Start $start $step++ Set-ResourceGroup -ResourceGroupName $ResourceGroupName -Location $Location Update-Step -Step $step -Message "Get Service Principal" -Start $start $step++ $spn = Get-ServicePrincipal -AppID $AppID -Password $Password $spnAppId = $spn."appId" $spnPwd = $spn."pwd" Update-Step -Step $step -Message "Get Tenant ID" -Start $start $step++ $tenantId = Get-TenantId -SubscriptionName "$SubscriptionName" Update-Step -Step $step -Message "Check for App Registration" -Start $start $step++ $appRegJson = az ad app list --display-name "$VirtualRtuId-Monitor" | ConvertFrom-Json if($appRegJson.Length -eq 1) { Update-Step -Step $step -Message "Deleting App Registration" -Start $start $step++ az ad app delete --id $appRegJson.appId } Update-Step -Step $step -Message "Register App in AAD and get Client Id" -Start $start $step++ $appName = "$VirtualRtuId-Monitor" $replyUris = @("https://$Dns.$Location.cloudapp.azure.com/signin-oidc","https://locahost:44386") $clientId = New-RegisterApp -AppName $appName -ReplyUris $replyUris Update-Step -Step $step -Message "Get Storage Connection String" -Start $start $step++ $vrtuConnectionString = Get-StorageAccountConnectionString -StorageAcctName "$StorageAcctName" -ResourceGroupName "$ResourceGroupName" Update-Step -Step $step -Message "See if Monitor AKS cluster exists" -Start $start $step++ $clusterExists = Get-AksClusterExists -SubscriptionName $SubscriptionName -ClusterName $ClusterName if($clusterExists) { Update-Step -Step $step -Message "Setting kubectl context to monitor cluster" -Start $start $step++ kubectl config use-context $ClusterName Update-Step -Step $step -Message "Updating ingress DNS and Location" -Start $start $step++ #Update-MonitorIngressDns -Dns $Dns -Location $Location -Path "$Path/ingress-webmonitor.yaml" -Destination "$Path/ingress-webmonitor-$Dns.yaml" Set-Ingress -Dns $Dns -Location $Location -Path "$Path/ingress-webmonitor.yaml" -Destination "$Path/ingress-webmonitor-copy.yaml" } else { kubectl create namespace "webmon" Update-Step -Step $step -Message "Creating new Monitor AKS cluster" -Start $start $step++ New-AksCluster -ClusterName $ClusterName -ResourceGroupName $ResourceGroupName -AppId "$spnAppId" -Password "$spnPwd" -VmSize $VmSize -NodeCount $NodeCount kubectl config use-context $ClusterName Update-Step -Step $step -Message "Get AKS credentials" -Start $start $step++ Get-AksCredentials -ClusterName $ClusterName -ResourceGroupName $ResourceGroupName Update-Step -Step $step -Message "Apply HELM RBAC" -Start $start $step++ New-KubectlApply -Filename "$Path/helm-rbac.yaml" -Namespace "kube-system" Update-Step -Step $step -Message "Start Tiller" -Start $start $step++ helm init --service-account tiller Set-Timer -Message "...waiting 45 seconds for Tiller to start" -Seconds 45 Update-Step -Step $step -Message "Add cert manager for Let's Encrypt" -Start $start $step++ Add-CertManager2 -Namespace "cert-manager2" Set-Timer -Message "...waiting 45 seconds for cert-manager to initialize" -Seconds 45 Update-Step -Step $step -Message "Add cert issuer for Lets Encrypt" -Start $start $step++ Add-Issuer -Email $Email -IssuerPath "$Path/issuer2.yaml" -IssuerDestination "$Path/issuer2-copy.yaml" -Namespace "webmon" Set-Timer -Message "...waiting 30 seconds for issuer to initialize" -Seconds 30 Update-Step -Step $step -Message "Upate local HELM repo" -Start $start $step++ helm repo add stable https://kubernetes-charts.storage.googleapis.com/ Update-Step -Step $step -Message "Add NGINX" -Start $start $step++ Add-NGINX -Namespace "webmon" Set-Timer "...waiting 45 seconds for nginx to initialize" -Seconds 45 Update-Step -Step $step -Message "Get External IP address" -Start $start $step++ $IP = Get-ExternalIP -Namespace "webmon" Update-Step -Step $step -Message "Create Public IP ID" -Start $start $step++ $PUBLICIPID=$(az network public-ip list --query "[?ipAddress!=null]|[?contains(ipAddress, '$IP')].[id]" --output tsv) Update-Step -Step $step -Message "Update Public IP ID" -Start $start $step++ Update-PublicIP -PublicIP $PUBLICIPID -Dns $Dns -SubscriptionName $SubscriptionName Update-Step -Step $step -Message "Set certificate for cert-manager and Lets Encrypt" -Start $start $step++ Set-Certificate -Dns $Dns -Location $Location -Path "$Path/certificate2.yaml" -Destination "$Path/certificate2-copy.yaml" -Namespace "webmon" } Update-Step -Step $step -Message "Creating App Insights for Monitor and getting instrumentation key" -Start $start $step++ $aiKey = Get-InstrumentationKey "$Dns-monitors" -ResourceGroupName $ResourceGroupName -Location $Location Update-Step -Step $step -Message "Install Web Monitor from helm chart" -Start $start $step++ $domain = "$Domain.onmicrosoft.com" $hostname = $PiraeusHostname helm install "$Path/virtualrtu-webmonitor" --name virtualrtu-webmonitor --namespace "webmon" --set port=$Port --set symmetricKey=$SymmetricKey --set instrumentationKey=$aiKey --set logLevel=$LogLevel --set tenantId=$tenantId --set clientId=$clientId --set domain=$domain --set hostname=$hostname --set location=$Location --set storageConnectionString=$vrtuConnectionString --set tableName=$TableName if($LASTEXITCODE -ne 0 ) { Update-Step -Step $step -Message "Waiting for Kubernetes API Services to start" -Start $start $step++ Set-WaitForApiServices Update-Step -Step $step -Message "Trying again to install VRTU Monitor from helm chart" -Start $start $step++ helm install "$Path/virtualrtu-webmonitor" --name virtualrtu-webmonitor --namespace "webmon" --set port=$Port --set symmetricKey=$SymmetricKey --set instrumentationKey=$aiKey --set logLevel=$LogLevel --set tenantId=$tenantId --set clientId=$clientId --set domain=$domain --set hostname=$hostname --set location=$Location --set storageConnectionString=$vrtuConnectionString --set tableName=$TableName } Set-Ingress -Dns $Dns -Location $Location -Path "$Path/ingress2.yaml" -Destination "$Path/ingress2-copy.yaml" -Namespace "webmon" Update-Step -Step $step -Message "Read file" -Start $start $step++ if(Test-Path $File) { $config = Get-Content -Raw -Path $File | ConvertFrom-Json $config.tenantId = "$tenantId" $config.clientId = "$clientId" $config.domain = "$domain" $config.monitorDns = "$Dns" $config.monitorPublicIP = "$IP" $config.monitorInstrumentationKey = "$aiKey" $config.monitorVmSize = "$VmSize" Update-Step -Step $step -Message "Write file" -Start $start $step++ $config | ConvertTo-Json -depth 100 | Out-File $File } } function New-DeviceDeploy { param ([string]$File, [string]$Url = "http://localhost:7071/api/DeploymentFunction", [string]$Key = $null, [bool]$Update = $false) $config = [System.IO.File]::ReadAllBytes($File) $requestUrl = $null if($Key -eq $null) { if($Update -eq $false) { $requestUrl = $Url } else { $requestUrl = $Url + "?type=update" } } else { $requestUrl = $Url + "?code=" + $Key if($Update -ne $false) { $requestUrl = $requestUrl + "&type=update" } } if($Module -eq $null) { $connectionString = Invoke-WebRequest -Uri $requestUrl -Method Post -ContentType "application/json" -Body $config Write-Host $connectionString } else { Invoke-WebRequest -Uri $requestUrl -Method Post -ContentType "application/json" -Body $config Write-Host "Update complete" } } function Get-ExternalIPForService { param([string]$AppName, [string]$Namespace = "kube-system") $looper = $TRUE while($looper) { $externalIP = "" $lineValue = kubectl get service -l app=$AppName --namespace $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 Add-CertManager2 { param([string]$Namespace = "cert-manager") kubectl label namespace $Namespace certmanager.k8s.io/disable-validation="true" kubectl apply -f "https://raw.githubusercontent.com/jetstack/cert-manager/release-0.11/deploy/manifests/00-crds.yaml" -n "$Namespace" --validate=false helm repo add jetstack https://charts.jetstack.io helm repo update helm install --name cert-manager --namespace $Namespace --version v0.11.0 --set ingressShim.extraArgs='{--default-issuer-name=letsencrypt-prod,--default-issuer-kind=ClusterIssuer}' jetstack/cert-manager --set webhook.enabled=true } |