Skip to content

Commit 91ace9e

Browse files
azure-pipelines[bot]azure-powershell-botNickcandy
authored
Migrate ConnectedKubernetes from generation to main (Azure#26287)
* Move ConnectedKubernetes to main * Update ChangeLog.md --------- Co-authored-by: azure-powershell-bot <[email protected]> Co-authored-by: NanxiangLiu <[email protected]>
1 parent 693a9e9 commit 91ace9e

17 files changed

+343
-80
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Develpoing ConnectedKubernetes Powershell Cmdlets
2+
> These notes are intended to compliment and extend the common instructions for this process. If you spot a sensible common location where part of this document could live, please do move the information out of here.
3+
4+
# Overview
5+
## Why Custom Cmdlets?
6+
Powerhsll cmdlets can be created almost totally automatically for many products but ConnectedKubernetes is special. The standard cmdlet interations are one or more ([Swagger]) REST API exchanges with Azure but ConnectedKubernetes also has to install Azure Arc support into a Kubernetes cluster and this requires work to be performed using [helm].
7+
8+
For this reason, the ConnectedKubernetes cmdlets have two or more steps such as:
9+
- Interact with Azure using the REST APIs; this often involves just calling the autogenerated cmdlets
10+
- Now interact with Kubernetes using [helm].
11+
12+
## (Part) Autogeneration Process
13+
The autogeneration process uses [autorest.powershell], an [autorest] extension for creating Powershell cmdlets based on a (Swagger) REST API definition. this is typically as follows:
14+
15+
1. Carefully craft your [Swagger] definition of the REST API
16+
1. Read the [Quickstart for Azure PowerShell development using code generator]
17+
1. Clone the [azure-powershell] repo
18+
1. Create a develpoment branch based on the `generate` branch **and not based on `main`**!
19+
1. Run the [autorest] Docker image; if you have no local image for [autorest], refer to
20+
1. Run [autorest] to generate configuration and files that will result in the autogenerated cmdlets
21+
1. Run the build process (`pwsh build-module.ps1`) which completes the build process.
22+
23+
### Building the [autorest] Docker image
24+
> Do **NOT** build an [autorest] image based on the Dockerfile contained in the `tools/autorest` directory below the [azure-powershell] repo as this does not produce a working image!
25+
26+
- Clone the [autorest.powershell] repo
27+
- Navigate to the `tools/docker` directory
28+
- Follow the instructions in the README file in that directory
29+
30+
## Special Aspects for ConnectedKubernetes
31+
The autogenerated cmdlets are created in C# with Powershell wrappers that are placed into the `internal` folder. This is because we are **NOT** exposing the autogenerated functions to the user, rather er export our custom versions.
32+
> As described earlier, the custom versions often call-through to the autogenerated version to perform the ARM REST API portion of their work.
33+
34+
### Gotchas
35+
#### You Want a New Cmdlet?
36+
If you are creating a whole new command, then you need to get the [autorest] process and the build process to work together to create the underlying `internal` command for you and this is not trivial.
37+
38+
When we tried to add the `Set-` cmdlet, we found it never appeared but eventually we discovered these nuggets of knowledge.
39+
- [autorest] will look at the `operationId` field in the [Swagger] for each REST API method and determine what commands to create. So in our case `ConnectedCluster_Create` only causes `New-` cmdlets to be created and we had to update the [Swagger] to say `ConnectedCluster_CreateOrUpdate` before any `Set-` cmdlets were created
40+
- The `internal` cmdlets are really just Powershell wrappers but these are not created until the `pwsh build-module-ps1` step
41+
- Between the steps above sits the [autorest] configuration found in the XML at the end of [README.md]. This does stuff like:
42+
- Stops the generation of various versions of cmdlets that are not required
43+
- **hides** the autogenerated cmdlets, which is what causes them to be created in `internal`; we had to add `set` to the list of cmdlets so hidden before the `internal` `Set-` cmdlet appeared.
44+
45+
[autorest.powershell]: https://github.com/Azure/autorest.powershell
46+
[autorest]: https://github.com/Azure/autorest
47+
[helm]: https://helm.sh/
48+
[Swagger]: https://swagger.io/
49+
[README.md]: ./README.md
50+
[Quickstart for Azure PowerShell development using code generator]: https://eng.ms/docs/cloud-ai-platform/azure-core/azure-management-and-platforms/control-plane-bburns/azure-cli-tools-azure-cli-powershell-and-terraform/azure-cli-tools/onboarding/azurepowershell/quickstart_codegen
51+
[azure-powershell]: https://github.com/azure/azure-powershell

src/ConnectedKubernetes/ConnectedKubernetes.Autorest/custom/New-AzConnectedKubernetes.ps1

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ function New-AzConnectedKubernetes {
319319
$Null = $PSBoundParameters.Remove('KubeConfig')
320320
}
321321
elseif (Test-Path Env:KUBECONFIG) {
322-
$KubeConfig = Get-ChildItem -Path Env:KUBECONFIG
322+
$KubeConfig = Get-ChildItem -Path $Env:KUBECONFIG
323323
}
324324
elseif (Test-Path Env:Home) {
325325
$KubeConfig = Join-Path -Path $Env:Home -ChildPath '.kube' | Join-Path -ChildPath 'config'
@@ -364,7 +364,11 @@ function New-AzConnectedKubernetes {
364364
$PSBoundParameters.Add('IdentityType', $IdentityType)
365365

366366
#Region check helm install
367-
Confirm-HelmVersion -KubeConfig $KubeConfig
367+
Confirm-HelmVersion `
368+
-KubeConfig $KubeConfig `
369+
-Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) `
370+
-Debug:($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent -eq $true)
371+
368372

369373
#EndRegion
370374
$helmClientLocation = 'helm'
@@ -421,8 +425,13 @@ function New-AzConnectedKubernetes {
421425
if ($PSVersionTable.PSVersion.Major -eq 5) {
422426
try {
423427
. "$PSScriptRoot/helpers/RSAHelper.ps1"
424-
$AgentPublicKey = ExportRSAPublicKeyBase64($RSA)
425-
$AgentPrivateKey = ExportRSAPrivateKeyBase64($RSA)
428+
$AgentPublicKey = ExportRSAPublicKeyBase64($RSA) `
429+
-Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) `
430+
-Debug:($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent -eq $true)
431+
$AgentPrivateKey = ExportRSAPrivateKeyBase64($RSA) `
432+
-Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) `
433+
-Debug:($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent -eq $true)
434+
426435
$AgentPrivateKey = "-----BEGIN RSA PRIVATE KEY-----`n" + $AgentPrivateKey + "`n-----END RSA PRIVATE KEY-----"
427436
}
428437
catch {
@@ -541,15 +550,25 @@ function New-AzConnectedKubernetes {
541550

542551
# A lot of what follows relies on knowing the cloud we are using and the
543552
# various endpoints so get that information now.
544-
$cloudMetadata = Get-AzCloudMetadata
553+
$cloudMetadata = Get-AzCloudMetadata `
554+
-Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) `
555+
-Debug:($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent -eq $true)
545556

546557
# Perform DP health check
547-
$configDpinfo = Get-ConfigDPEndpoint -location $Location -Cloud $cloudMetadata
558+
$configDpinfo = Get-ConfigDPEndpoint `
559+
-location $Location `
560+
-Cloud $cloudMetadata `
561+
-Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) `
562+
-Debug:($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent -eq $true)
563+
548564
$configDPEndpoint = $configDpInfo.configDPEndpoint
549565

550566
# If the health check fails (not 200 response), an exception is thrown
551567
# so we can ignore the output.
552-
$null = Invoke-ConfigDPHealthCheck -configDPEndpoint $configDPEndpoint
568+
$null = Invoke-ConfigDPHealthCheck `
569+
-configDPEndpoint $configDPEndpoint `
570+
-Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) `
571+
-Debug:($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent -eq $true)
553572

554573
# This call does the "pure ARM" update of the ARM objects.
555574
Write-Debug "Writing Connected Kubernetes ARM objects."
@@ -586,7 +605,12 @@ function New-AzConnectedKubernetes {
586605
# needs to change and not the Powershell script (or az CLI).
587606
#
588607
# Do not send protected settings to CCRP
589-
$arcAgentryConfigs = ConvertTo-ArcAgentryConfiguration -ConfigurationSetting $ConfigurationSetting -RedactedProtectedConfiguration @{} -CCRP $true
608+
$arcAgentryConfigs = ConvertTo-ArcAgentryConfiguration `
609+
-ConfigurationSetting $ConfigurationSetting `
610+
-RedactedProtectedConfiguration @{} `
611+
-CCRP $true `
612+
-Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) `
613+
-Debug:($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent -eq $true)
590614

591615
# It is possible to set an empty value for these parameters and then
592616
# the code above gets skipped but we still need to remove the empty
@@ -601,14 +625,20 @@ function New-AzConnectedKubernetes {
601625
$PSBoundParameters.Add('ArcAgentryConfiguration', $arcAgentryConfigs)
602626

603627
Write-Output "Creating 'Kubernetes - Azure Arc' object in Azure"
628+
Write-Debug "PSBoundParameters: $PSBoundParameters"
604629
$Response = Az.ConnectedKubernetes.internal\New-AzConnectedKubernetes @PSBoundParameters
605630

606631
if ((-not $WhatIfPreference) -and (-not $Response)) {
607632
Write-Error "Failed to create the 'Kubernetes - Azure Arc' resource."
608633
return
609634
}
610635

611-
$arcAgentryConfigs = ConvertTo-ArcAgentryConfiguration -ConfigurationSetting $ConfigurationSetting -RedactedProtectedConfiguration $RedactedProtectedConfiguration -CCRP $false
636+
$arcAgentryConfigs = ConvertTo-ArcAgentryConfiguration `
637+
-ConfigurationSetting $ConfigurationSetting `
638+
-RedactedProtectedConfiguration $RedactedProtectedConfiguration `
639+
-CCRP $false `
640+
-Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) `
641+
-Debug:($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent -eq $true)
612642

613643
# Convert the $Response object into a nested hashtable.
614644

@@ -643,7 +673,7 @@ function New-AzConnectedKubernetes {
643673
Write-Debug "OCI Artifact location: ${helmValuesDp.repositoryPath}."
644674

645675
$registryPath = if ($env:HELMREGISTRY) { $env:HELMREGISTRY } else { $helmValuesDp.repositoryPath }
646-
Write-Debug "RegistryPath: ${registryPath}."
676+
Write-Debug "RegistryPath: ${registryPath}"
647677

648678
$helmValuesContent = $helmValuesDp.helmValuesContent
649679
Write-Debug "Helm values: ${helmValuesContent}."
@@ -654,7 +684,7 @@ function New-AzConnectedKubernetes {
654684
# hashtable.
655685
$optionsFromDp = ""
656686
foreach ($field in $helmValuesContent.PSObject.Properties) {
657-
if($field.Value.StartsWith($ProtectedSettingsPlaceholderValue)){
687+
if ($field.Value.StartsWith($ProtectedSettingsPlaceholderValue)) {
658688
$parsedValue = $field.Value.Split(":")
659689
# "${ProtectedSettingsPlaceholderValue}:${feature}:${setting}"
660690
$field.Value = $ConfigurationProtectedSetting[$parsedValue[1]][$parsedValue[2]]
@@ -670,9 +700,15 @@ function New-AzConnectedKubernetes {
670700

671701
# Get helm chart path (within the OCI registry).
672702
if ($PSCmdlet.ShouldProcess("configDP", "request Helm chart")) {
673-
$chartPath = Get-HelmChartPath -registryPath $registryPath -kubeConfig $KubeConfig -kubeContext $KubeContext -helmClientLocation $HelmClientLocation
703+
$chartPath = Get-HelmChartPath `
704+
-registryPath $registryPath `
705+
-kubeConfig $KubeConfig `
706+
-kubeContext $KubeContext `
707+
-helmClientLocation $HelmClientLocation `
708+
-Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) `
709+
-Debug:($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent -eq $true)
674710
if (Test-Path Env:HELMCHART) {
675-
$ChartPath = Get-ChildItem -Path Env:HELMCHART
711+
$ChartPath = Get-ChildItem -Path $Env:HELMCHART
676712
}
677713
}
678714

@@ -722,9 +758,11 @@ function New-AzConnectedKubernetes {
722758

723759
if ($ExistConnectedKubernetes.ArcAgentProfileAgentState -eq "Succeeded") {
724760
Write-Output "Cluster configuration succeeded."
725-
} elseif ($ExistConnectedKubernetes.ArcAgentProfileAgentState -eq "Failed") {
761+
}
762+
elseif ($ExistConnectedKubernetes.ArcAgentProfileAgentState -eq "Failed") {
726763
Write-Error "Cluster configuration failed."
727-
} else {
764+
}
765+
else {
728766
Write-Error "Cluster configuration timed out after 60 minutes."
729767
}
730768
}

src/ConnectedKubernetes/ConnectedKubernetes.Autorest/custom/Remove-AzConnectedKubernetes.ps1

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ param(
156156
if ($PSBoundParameters.ContainsKey('KubeConfig')) {
157157
$Null = $PSBoundParameters.Remove('KubeConfig')
158158
} elseif (Test-Path Env:KUBECONFIG) {
159-
$KubeConfig = Get-ChildItem -Path Env:KUBECONFIG
159+
$KubeConfig = Get-ChildItem -Path $Env:KUBECONFIG
160160
} elseif (Test-Path Env:Home) {
161161
$KubeConfig = Join-Path -Path $Env:Home -ChildPath '.kube' | Join-Path -ChildPath 'config'
162162
} else {
@@ -175,7 +175,10 @@ param(
175175

176176
#Region check helm install
177177
try {
178-
Set-HelmClientLocation
178+
Set-HelmClientLocation `
179+
-Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) `
180+
-Debug:($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent -eq $true)
181+
179182
$HelmVersion = helm version --short --kubeconfig $KubeConfig
180183
if ($HelmVersion.Contains("v2")) {
181184
Write-Error "Helm version 3+ is required. Ensure that you have installed the latest version of Helm. Learn more at https://aka.ms/arc/k8s/onboarding-helm-install"
@@ -187,7 +190,10 @@ param(
187190
#Endregion
188191

189192
#Region get release namespace
190-
$ReleaseInstallNamespace = Get-ReleaseInstallNamespace
193+
$ReleaseInstallNamespace = Get-ReleaseInstallNamespace `
194+
-Verbose:($PSCmdlet.MyInvocation.BoundParameters["Verbose"].IsPresent -eq $true) `
195+
-Debug:($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent -eq $true)
196+
191197
$ReleaseNamespace = $null
192198
try {
193199
$ReleaseNamespace = (helm status azure-arc -o json --kubeconfig $KubeConfig --kube-context $KubeContext -n $ReleaseInstallNamespace | ConvertFrom-Json).namespace

0 commit comments

Comments
 (0)