Skip to content

Commit a20c779

Browse files
azure-pipelines[bot]azure-powershell-botNoriZC
authored
Migrate ConnectedKubernetes from generation to main (Azure#26630)
* Move ConnectedKubernetes to main * Update ChangeLog.md * Update ChangeLog.md * Update ChangeLog.md --------- Co-authored-by: azure-powershell-bot <[email protected]> Co-authored-by: NoriZC <[email protected]>
1 parent 3d75db1 commit a20c779

29 files changed

+1058
-433
lines changed

src/ConnectedKubernetes/ConnectedKubernetes.Autorest/Az.ConnectedKubernetes.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@{
2-
GUID = 'd3467834-8989-4142-8c05-ab93c4bfa6eb'
2+
GUID = 'efbb1325-5081-4947-8508-ab47abbf6e76'
33
RootModule = './Az.ConnectedKubernetes.psm1'
44
ModuleVersion = '0.1.0'
55
CompatiblePSEditions = 'Core', 'Desktop'

src/ConnectedKubernetes/ConnectedKubernetes.Autorest/build-module.ps1

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ if(-not $Isolated -and -not $Debugger) {
6767
$binFolder = Join-Path $PSScriptRoot 'bin'
6868
$objFolder = Join-Path $PSScriptRoot 'obj'
6969

70+
$isAzure = [System.Convert]::ToBoolean('true')
71+
7072
if(-not $Debugger) {
7173
Write-Host -ForegroundColor Green 'Cleaning build folders...'
7274
$null = Remove-Item -Recurse -ErrorAction SilentlyContinue -Path $binFolder, $objFolder
@@ -143,7 +145,7 @@ if($NoDocs) {
143145
$null = Get-ChildItem -Path $docsFolder -Recurse -Exclude 'README.md' | Remove-Item -Recurse -ErrorAction SilentlyContinue
144146
}
145147
$null = New-Item -ItemType Directory -Force -Path $docsFolder
146-
$addComplexInterfaceInfo = ![System.Convert]::ToBoolean('true')
148+
$addComplexInterfaceInfo = !$isAzure
147149
Export-ProxyCmdlet -ModuleName $moduleName -ModulePath $modulePaths -ExportsFolder $exportsFolder -InternalFolder $internalFolder -ModuleDescription $moduleDescription -DocsFolder $docsFolder -ExamplesFolder $examplesFolder -ModuleGuid $guid -AddComplexInterfaceInfo:$addComplexInterfaceInfo
148150
}
149151

@@ -178,5 +180,4 @@ if (-not $DisableAfterBuildTasks){
178180
}
179181
}
180182

181-
182-
Write-Host -ForegroundColor Green '-------------Done-------------'
183+
Write-Host -ForegroundColor Green '-------------Done-------------'
Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,99 @@
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.
1+
# Developing ConnectedKubernetes Powershell Cmdlets
2+
> These notes are intended to complement 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.
33
44
# Overview
55
## 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].
6+
Powershell cmdlets can be created almost totally automatically for many products but ConnectedKubernetes is special. The standard cmdlet interactions 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].
77

88
For this reason, the ConnectedKubernetes cmdlets have two or more steps such as:
99
- Interact with Azure using the REST APIs; this often involves just calling the autogenerated cmdlets
1010
- Now interact with Kubernetes using [helm].
1111

1212
## (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:
13+
The autogeneration process uses [autorest.powershell], an [autorest] extension for creating Powershell cmdlets based on a (Swagger) REST API definition. This tool is run via an [autorest] [Docker] image (you will need something like [Docker Desktop] installed). The typical cmdlet development process is this:
1414

1515
1. Carefully craft your [Swagger] definition of the REST API
1616
1. Read the [Quickstart for Azure PowerShell development using code generator]
1717
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.
18+
1. Create a development branch based on the `generate` branch **and not based on `main`**!
19+
1. Run the [autorest] [Docker] image; see below if you do not already have a local image for [autorest],
20+
1. Inside the [autorest] environment...
21+
1. Run `autorest` to generate configuration and files that will result in the autogenerated cmdlets
22+
1. Run the build process, `pwsh build-module.ps1`, which completes the build process
23+
1. Optionally create a local package `pwsh pack-module.ps1`.
24+
25+
---
26+
Note that many of the intermediate steps rely on output from a previous step. For example `build-module.ps1` is an output from the `autorest` step.
27+
28+
---
2229

2330
### 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!
31+
If you do not already have an [autorest] image, do **NOT** build one using the Dockerfile contained in the `tools/autorest` directory in the [azure-powershell] - repo as this does not produce a working image! Instead, build the image like this:
2532

2633
- Clone the [autorest.powershell] repo
2734
- Navigate to the `tools/docker` directory
28-
- Follow the instructions in the README file in that directory
35+
- Follow the instructions in the README file in that directory.
2936

3037
## Special Aspects for ConnectedKubernetes
3138
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.
3239
> As described earlier, the custom versions often call-through to the autogenerated version to perform the ARM REST API portion of their work.
3340
34-
### Gotchas
35-
#### You Want a New Cmdlet?
41+
The custom cmdlets can be found in the `custom` directory. They are written in Powershell and do some manuipulation of input parameters before interacting with Azure and then Kubernetes via [helm].
42+
43+
## Gotchas
44+
### Desktop Powershell (v5.1) Back-Compatibility
45+
The `Az` packages are all written to work with the preinstalled Windows Desktop version of Powershell, which is obsolete!
46+
47+
We have to maintain this compatibility and the way to prove this is to use `PSScriptAnalyzer` (invoked as `Invoke-ScriptAnalyzer`) to confirm this. The process is below and the following references contain useful information:
48+
- https://devblogs.microsoft.com/powershell/using-psscriptanalyzer-to-check-powershell-version-compatibility/
49+
- https://learn.microsoft.com/en-gb/powershell/utility-modules/psscriptanalyzer/rules/usecompatiblecommands?view=ps-modules
50+
51+
```Powershell
52+
# Run this from within the "custom" directory.
53+
Write-Host -ForegroundColor Green 'Linting and checking Powershell back-compatibility...'
54+
Install-Module PSScriptAnalyzer -Scope CurrentUser -Force
55+
$settings = @{
56+
# Ref: https://devblogs.microsoft.com/powershell/using-psscriptanalyzer-to-check-powershell-version-compatibility/
57+
Rules = @{
58+
PSUseCompatibleSyntax = @{
59+
# This turns the rule on (setting it to false will turn it off)
60+
Enable = $true
61+
62+
# List the targeted versions of PowerShell here
63+
TargetVersions = @(
64+
'5.1',
65+
'7.0'
66+
)
67+
}
68+
PSUseCompatibleCommands = @{
69+
# Turns the rule on
70+
Enable = $true
71+
72+
# Lists the PowerShell platforms we want to check compatibility with
73+
# Ref: https://learn.microsoft.com/en-gb/powershell/utility-modules/psscriptanalyzer/rules/usecompatiblecommands?view=ps-modules
74+
TargetProfiles = @(
75+
'win-8_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework',
76+
'win-8_x64_10.0.14393.0_7.0.0_x64_3.1.2_core'
77+
)
78+
}
79+
}
80+
81+
# Recursively find all *.ps1 files and run Invoke-ScriptAnalyzer against them.
82+
Get-ChildItem -Path . -Recurse -Include '*.ps1' | Invoke-ScriptAnalyzer -Settings $settings
83+
if ($LastExitCode -ne 0) {
84+
Write-Error 'ScriptAnalyzer found (possibly back-compatibility) issues.'
85+
}
86+
```
87+
88+
89+
### Dependencies
90+
We have thus far been unable to make the `Az.ConnectedKubernetes` module install its dependencies (`Az.Resources` and `Az.Accounts`). This is possible for powershell but the issue is that the configuration to do this has to somehow be passed through the [autorest] process and attempts to do this have thus far failed.
91+
92+
### You Want a New Cmdlet?
3693
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.
3794

3895
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
96+
- [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. Note that there are other options possible and the Swagger teams preferred `ConnectedCluster_CreateOrReplace` which works just as well for what we need and introduces no external API differences.
4097
- The `internal` cmdlets are really just Powershell wrappers but these are not created until the `pwsh build-module-ps1` step
4198
- Between the steps above sits the [autorest] configuration found in the XML at the end of [README.md]. This does stuff like:
4299
- Stops the generation of various versions of cmdlets that are not required
@@ -48,4 +105,6 @@ When we tried to add the `Set-` cmdlet, we found it never appeared but eventuall
48105
[Swagger]: https://swagger.io/
49106
[README.md]: ./README.md
50107
[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
108+
[azure-powershell]: https://github.com/azure/azure-powershell
109+
[Docker]: https://www.docker.com
110+
[Docker Desktop]: https://www.docker.com/products/docker-desktop/

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

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1111
# See the License for the specific language governing permissions and
1212
# limitations under the License.
13-
# Code generated by Microsoft (R) AutoRest Code Generator.Changes may cause incorrect behavior and will be lost if the code
14-
# is regenerated.
1513
# ----------------------------------------------------------------------------------
1614

1715
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '',
@@ -374,7 +372,7 @@ function New-AzConnectedKubernetes {
374372
$helmClientLocation = 'helm'
375373

376374
#Region get release namespace
377-
$ReleaseNamespaces = Get-HelmReleaseNamespaces -KubeConfig $KubeConfig -KubeContext $KubeContext
375+
$ReleaseNamespaces = Get-HelmReleaseNamespace -KubeConfig $KubeConfig -KubeContext $KubeContext
378376
$ReleaseNamespace = $ReleaseNamespaces['ReleaseNamespace']
379377
$ReleaseInstallNamespace = $ReleaseNamespaces['ReleaseInstallNamespace']
380378

@@ -417,7 +415,7 @@ function New-AzConnectedKubernetes {
417415
}
418416
}
419417

420-
$RegistryPath = Set-HelmRepositoryAndModules -KubeConfig $KubeConfig -KubeContext $KubeContext -Location $Location -ProxyCert $ProxyCert -DisableAutoUpgrade $DisableAutoUpgrade -ContainerLogPath $ContainerLogPath -CustomLocationsOid $CustomLocationsOid
418+
$RegistryPath = Set-HelmModulesAndRepository -KubeConfig $KubeConfig -KubeContext $KubeContext -Location $Location
421419

422420
# Region create RSA keys
423421
Write-Debug "Generating RSA keys for secure communication."
@@ -641,9 +639,9 @@ function New-AzConnectedKubernetes {
641639
-Debug:($PSCmdlet.MyInvocation.BoundParameters["Debug"].IsPresent -eq $true)
642640

643641
# Convert the $Response object into a nested hashtable.
644-
645642
Write-Debug "PUT response: $Response"
646-
$Response = ConvertFrom-Json "$Response" -AsHashTable -Depth 10
643+
$Response = ConvertFrom-Json "$Response"
644+
$Response = ConvertTo-Hashtable $Response
647645

648646
# What-If processing does not create a full response so we might have
649647
# to create a minimal one.
@@ -660,7 +658,7 @@ function New-AzConnectedKubernetes {
660658
Write-Debug "PUT response: $Response"
661659
$ResponseStr = $Response | ConvertTo-Json -Depth 10
662660
Write-Debug "PUT response: $ResponseStr"
663-
661+
664662
if ($PSCmdlet.ShouldProcess("configDP", "request Helm values")) {
665663
$helmValuesDp = Get-HelmValuesFromConfigDP `
666664
-configDPEndpoint $configDPEndpoint `
@@ -736,8 +734,6 @@ function New-AzConnectedKubernetes {
736734
--set systemDefaultValues.clusterconnect-agent.enabled=true `
737735
--set global.kubernetesDistro=$Distribution `
738736
--set global.kubernetesInfra=$Infrastructure (-split $options)
739-
740-
# $helmDebug
741737
}
742738
catch {
743739
throw "Unable to install helm chart at $ChartPath"
@@ -747,15 +743,15 @@ function New-AzConnectedKubernetes {
747743
if ($PSCmdlet.ShouldProcess($ClusterName, "Check agent state of the connected cluster")) {
748744
if ($PSBoundParameters.ContainsKey('OidcIssuerProfileEnabled') -or $PSBoundParameters.ContainsKey('WorkloadIdentityEnabled') ) {
749745
$ExistConnectedKubernetes = Get-AzConnectedKubernetes -ResourceGroupName $ResourceGroupName -ClusterName $ClusterName @CommonPSBoundParameters
750-
746+
751747
Write-Output "Cluster configuration is in progress..."
752748
$timeout = [datetime]::Now.AddMinutes(60)
753-
749+
754750
while (($ExistConnectedKubernetes.ArcAgentProfileAgentState -ne "Succeeded") -and ($ExistConnectedKubernetes.ArcAgentProfileAgentState -ne "Failed") -and ([datetime]::Now -lt $timeout)) {
755751
Start-Sleep -Seconds 30
756752
$ExistConnectedKubernetes = Get-AzConnectedKubernetes -ResourceGroupName $ResourceGroupName -ClusterName $ClusterName @CommonPSBoundParameters
757753
}
758-
754+
759755
if ($ExistConnectedKubernetes.ArcAgentProfileAgentState -eq "Succeeded") {
760756
Write-Output "Cluster configuration succeeded."
761757
}
@@ -764,7 +760,7 @@ function New-AzConnectedKubernetes {
764760
}
765761
else {
766762
Write-Error "Cluster configuration timed out after 60 minutes."
767-
}
763+
}
768764
}
769765
}
770766
Return $Response

0 commit comments

Comments
 (0)