sigs.k8s.io/cluster-api-provider-azure@v1.14.3/docs/book/src/developers/development.md (about)

     1  # Developing Cluster API Provider Azure <!-- omit in toc -->
     2  
     3  ## Contents <!-- omit in toc -->
     4  
     5  <!-- Below is generated using VSCode yzhang.markdown-all-in-one >
     6  
     7  <!-- TOC depthFrom:2 -->
     8  
     9  - [Setting up](#setting-up)
    10    - [Base requirements](#base-requirements)
    11    - [Get the source](#get-the-source)
    12    - [Get familiar with basic concepts](#get-familiar-with-basic-concepts)
    13    - [Dev manifest files](#dev-manifest-files)
    14    - [Dev images](#dev-images)
    15      - [Container registry](#container-registry)
    16  - [Developing](#developing)
    17    - [Modules and dependencies](#modules-and-dependencies)
    18    - [Setting up the environment](#setting-up-the-environment)
    19    - [Tilt Requirements](#tilt-requirements)
    20    - [Using Tilt](#using-tilt)
    21      - [Tilt for dev in CAPZ](#tilt-for-dev-in-capz)
    22      - [Tilt for dev in both CAPZ and CAPI](#tilt-for-dev-in-both-capz-and-capi)
    23      - [Deploying a workload cluster](#deploying-a-workload-cluster)
    24      - [Viewing Telemetry](#viewing-telemetry)
    25      - [Debugging](#debugging)
    26    - [Manual Testing](#manual-testing)
    27      - [Creating a dev cluster](#creating-a-dev-cluster)
    28        - [Building and pushing dev images](#building-and-pushing-dev-images)
    29        - [Customizing the cluster deployment](#customizing-the-cluster-deployment)
    30        - [Creating the cluster](#creating-the-cluster)
    31    - [Instrumenting Telemetry](#instrumenting-telemetry)
    32      - [Distributed Tracing](#distributed-tracing)
    33      - [Metrics](#metrics)
    34    - [Submitting PRs and testing](#submitting-prs-and-testing)
    35      - [Executing unit tests](#executing-unit-tests)
    36    - [Automated Testing](#automated-testing)
    37      - [Mocks](#mocks)
    38      - [E2E Testing](#e2e-testing)
    39      - [Conformance Testing](#conformance-testing)
    40      - [Running custom test suites on CAPZ clusters](#running-custom-test-suites-on-capz-clusters)
    41  
    42  <!-- /TOC -->
    43  
    44  ## Setting up
    45  
    46  ### Base requirements
    47  
    48  1. Install [go][go]
    49     - Get the latest patch version for go v1.20.
    50  2. Install [jq][jq]
    51     - `brew install jq` on macOS.
    52     - `sudo apt install jq` on Windows + WSL2
    53     - `sudo apt install jq` on Ubuntu Linux.
    54  3. Install [gettext][gettext] package
    55     - `brew install gettext && brew link --force gettext` on macOS.
    56     - `sudo apt install gettext` on Windows + WSL2.
    57     - `sudo apt install gettext` on Ubuntu Linux.
    58  4. Install [KIND][kind]
    59     - `GO111MODULE="on" go get sigs.k8s.io/kind@v0.18.0`.
    60  5. Install [Kustomize][kustomize]
    61     - `brew install kustomize` on macOS.
    62     - [install instructions](https://kubectl.docs.kubernetes.io/installation/kustomize/) on Windows + WSL2.
    63     - [install instructions][kustomizelinux] on Linux.
    64  6. Install Python 3.x or 2.7.x, if neither is already installed.
    65  7. Install pip
    66     - [pip installation instruction](https://pip.pypa.io/en/stable/installation/#installation)
    67  8. Install make.
    68     - `brew install make` on MacOS.
    69     - `sudo apt install make` on Windows + WSL2.
    70     - `sudo apt install make` on Linux.
    71  9. Install [timeout][timeout]
    72     - `brew install coreutils` on macOS.
    73  10. Install [pre-commit framework](https://pre-commit.com/#installation)
    74     - `brew install pre-commit` Or `pip install pre-commit`. Installs pre-commit globally.
    75     - run `pre-commit install` at the root of the project to install pre-commit hooks to read `.pre-commit-config.yaml`
    76     - *Note*: use `git commit --no-verify` to skip running pre-commit workflow as and when needed.
    77  
    78  When developing on Windows, it is suggested to set up the project on Windows + WSL2 and the file should be checked out on as wsl file system for better results.
    79  
    80  ### Get the source
    81  
    82  ```shell
    83  git clone https://github.com/kubernetes-sigs/cluster-api-provider-azure
    84  cd cluster-api-provider-azure
    85  ```
    86  
    87  ### Get familiar with basic concepts
    88  
    89  This provider is modeled after the upstream Cluster API project. To get familiar
    90  with Cluster API resources, concepts and conventions ([such as CAPI and CAPZ](https://cluster-api.sigs.k8s.io/reference/glossary.html#c)), refer to the [Cluster API Book](https://cluster-api.sigs.k8s.io/).
    91  
    92  ### Dev manifest files
    93  
    94  Part of running cluster-api-provider-azure is generating manifests to run.
    95  Generating dev manifests allows you to test dev images instead of the default
    96  releases.
    97  
    98  ### Dev images
    99  
   100  #### Container registry
   101  
   102  Any public container registry can be leveraged for storing cluster-api-provider-azure container images.
   103  
   104  ## Developing
   105  
   106  Change some code!
   107  
   108  ### Modules and dependencies
   109  
   110  This repository uses [Go Modules](https://github.com/golang/go/wiki/Modules) to track and vendor dependencies.
   111  
   112  To pin a new dependency:
   113  
   114  - Run `go get <repository>@<version>`.
   115  - (Optional) Add a `replace` statement in `go.mod`.
   116  
   117  Makefile targets and scripts are offered to work with go modules:
   118  
   119  - `make verify-modules` checks whether go module files are out of date.
   120  - `make modules` runs `go mod tidy` to ensure proper vendoring.
   121  - `hack/ensure-go.sh` checks that the Go version and environment variables are properly set.
   122  
   123  ### Setting up the environment
   124  
   125  Your must have the Azure credentials as outlined in the [getting started prerequisites](../topics/getting-started.md#Prerequisites) section.
   126  
   127  ### Tilt Requirements
   128  
   129  Install [Tilt](https://docs.tilt.dev/install.html):
   130   - `brew install tilt-dev/tap/tilt` on macOS or Linux
   131   - `scoop bucket add tilt-dev https://github.com/tilt-dev/scoop-bucket` & `scoop install tilt` on Windows
   132   - for alternatives you can follow the installation instruction for [macOS](https://docs.tilt.dev/install.html#macos),
   133     [Linux](https://docs.tilt.dev/install.html#linux) or [Windows](https://docs.tilt.dev/install.html#windows)
   134  
   135  After the installation is done, verify that you have installed it correctly with: `tilt version`
   136  
   137  Install [Helm](https://helm.sh/docs/intro/install/):
   138   - `brew install helm` on MacOS
   139   - `choco install kubernetes-helm` on Windows
   140   - [Install Instruction](https://helm.sh/docs/intro/install/#from-source-linux-macos) on Linux
   141  
   142  You would require installation of Helm for successfully setting up Tilt.
   143  
   144  ### Using Tilt
   145  
   146  Both of the [Tilt](https://tilt.dev) setups below will get you started developing CAPZ in a local kind cluster.
   147  The main difference is the number of components you will build from source and the scope of the changes you'd like to make.
   148  If you only want to make changes in CAPZ, then follow [CAPZ instructions](#tilt-for-dev-in-capz). This will
   149  save you from having to build all of the images for CAPI, which can take a while. If the scope of your
   150  development will span both CAPZ and CAPI, then follow the [CAPI and CAPZ instructions](#tilt-for-dev-in-both-capz-and-capi).
   151  
   152  #### Tilt for dev in CAPZ
   153  
   154  If you want to develop in CAPZ and get a local development cluster working quickly, this is the path for you.
   155  
   156  Create a file named `tilt-settings.yaml` in the root of the CAPZ repository with the following contents:
   157  
   158  ```yaml
   159  kustomize_substitutions:
   160    AZURE_SUBSCRIPTION_ID: <subscription-id>
   161    AZURE_TENANT_ID: <tenant-id>
   162    AZURE_CLIENT_SECRET: <client-secret>
   163    AZURE_CLIENT_ID: <client-id>
   164  ```
   165  
   166  You should have these values saved from the [getting started prerequisites](../topics/getting-started.md#Prerequisites) section.
   167  
   168  To build a kind cluster and start Tilt, just run:
   169  
   170  ```shell
   171  make tilt-up
   172  ```
   173  By default, the Cluster API components deployed by Tilt have experimental features turned off.
   174  If you would like to enable these features, add `extra_args` as specified in [The Cluster API Book](https://cluster-api.sigs.k8s.io/developer/tilt.html#create-a-tilt-settingsjson-file).
   175  
   176  Once your kind management cluster is up and running, you can [deploy a workload cluster](#deploying-a-workload-cluster).
   177  
   178  To tear down the kind cluster built by the command above, just run:
   179  
   180  ```shell
   181  make kind-reset
   182  ```
   183  
   184  #### Tilt for dev in both CAPZ and CAPI
   185  
   186  If you want to develop in both CAPI and CAPZ at the same time, then this is the path for you.
   187  
   188  To use [Tilt](https://tilt.dev/) for a simplified development workflow, follow the [instructions](https://cluster-api.sigs.k8s.io/developer/tilt.html) in the cluster-api repo.  The instructions will walk you through cloning the Cluster API (CAPI) repository and configuring Tilt to use `kind` to deploy the cluster api management components.
   189  
   190  > you may wish to checkout out the correct version of CAPI to match the [version used in CAPZ][go.mod]
   191  
   192  Note that `tilt up` will be run from the `cluster-api repository` directory and the `tilt-settings.yaml` file will point back to the `cluster-api-provider-azure` repository directory.  Any changes you make to the source code in `cluster-api` or `cluster-api-provider-azure` repositories will automatically redeployed to the `kind` cluster.
   193  
   194  After you have cloned both repositories, your folder structure should look like:
   195  
   196  ```tree
   197  |-- src/cluster-api-provider-azure
   198  |-- src/cluster-api (run `tilt up` here)
   199  ```
   200  
   201  After configuring the environment variables, run the following to generate your `tilt-settings.yaml` file:
   202  
   203  ```shell
   204  cat <<EOF > tilt-settings.yaml
   205  default_registry: "${REGISTRY}"
   206  provider_repos:
   207  - ../cluster-api-provider-azure
   208  enable_providers:
   209  - azure
   210  - docker
   211  - kubeadm-bootstrap
   212  - kubeadm-control-plane
   213  kustomize_substitutions:
   214    AZURE_SUBSCRIPTION_ID: <subscription-id>
   215    AZURE_TENANT_ID: <tenant-id>
   216    AZURE_CLIENT_SECRET: <client-secret>
   217    AZURE_CLIENT_ID: <client-id>
   218  EOF
   219  ```
   220  
   221  Make sure to replace the credentials with the values from the [getting started prerequisites](../topics/getting-started.md#Prerequisites) section.
   222  
   223  > `$REGISTRY` should be in the format `docker.io/<dockerhub-username>`
   224  
   225  The cluster-api management components that are deployed are configured at the `/config` folder of each repository respectively. Making changes to those files will trigger a redeploy of the management cluster components.
   226  
   227  #### Deploying a workload cluster
   228  
   229  ⚠️ Note that when developing with `tilt` as described above, some `clusterctl` commands won't work. Specifically, `clusterctl config` and `clusterctl generate` may fail. These commands expect specific releases of CAPI and CAPZ to be installed, but the `tilt` environment dynamically updates and installs these components from your local code. `clusterctl get kubeconfig` will still work, however.
   230  
   231  After your kind management cluster is up and running with Tilt, you can deploy a workload cluster by opening the `tilt` web UI and clicking the clockwise arrow icon ⟳ on a resource listed, such as "aks-aad," "ipv6," or "windows."
   232  
   233  Deploying a workload cluster from Tilt UI is also termed as flavor cluster deployment. Note that each time a flavor is deployed, it deploys a new workload cluster in addition to the existing ones. All the workload clusters must be manually deleted by the user.
   234  Please refer to [Running flavor clusters as a tilt resource](../../../../templates/flavors/README.md#Running-flavor-clusters-as-a-tilt-resource) to learn more about this.
   235  
   236  Or you can [configure workload cluster settings](#customizing-the-cluster-deployment) and deploy a workload cluster with the following command:
   237  
   238  ```bash
   239  make create-workload-cluster
   240  ```
   241  
   242  To delete the cluster:
   243  
   244  ```bash
   245  make delete-workload-cluster
   246  ```
   247  
   248  > Check out the [troubleshooting guide](../topics/troubleshooting.md) for common errors you might run into.
   249  
   250  #### Viewing Telemetry
   251  
   252  The CAPZ controller emits tracing and metrics data. When run in Tilt, the KinD management cluster is
   253  provisioned with development deployments of OpenTelemetry for collecting distributed traces, Jaeger
   254  for viewing traces, and Prometheus for scraping and visualizing metrics.
   255  
   256  The OpenTelemetry, Jaeger, and Prometheus deployments are for development purposes only. These
   257  illustrate the hooks for tracing and metrics, but lack the robustness of production cluster
   258  deployments. For example, the Jaeger "all-in-one" component only keeps traces in memory, not in a
   259  persistent store.
   260  
   261  To view traces in the Jaeger interface, wait until the Tilt cluster is fully initialized. Then open
   262  the Tilt web interface, select the "traces: jaeger-all-in-one" resource, and click "View traces"
   263  near the top of the screen. Or visit http://localhost:16686/ in your browser. <!-- markdown-link-check-disable-line -->
   264  
   265  To view traces in App Insights, follow the
   266  [tracing documentation](../../../../hack/observability/opentelemetry/readme.md) before running
   267  `make tilt-up`. Then open the Azure Portal in your browser. Find the App Insights resource you
   268  specified in `AZURE_INSTRUMENTATION_KEY`, choose "Transaction search" on the left, and click
   269  "Refresh" to see recent trace data.
   270  
   271  To view metrics in the Prometheus interface, open the Tilt web interface, select the
   272  "metrics: prometheus-operator" resource, and click "View metrics" near the top of the screen. Or
   273  visit http://localhost:9090/ in your browser. <!-- markdown-link-check-disable-line -->
   274  
   275  To view cluster resources using the [Cluster API Visualizer](https://github.com/Jont828/cluster-api-visualizer), select the "visualize-cluster" resource and click "View visualization" or visit "http://localhost:8000/" in your browser. <!-- markdown-link-check-disable-line -->
   276  
   277  #### Debugging
   278  
   279  You can debug CAPZ (or another provider / core CAPI) by running the controllers with delve. When developing using Tilt this is easily done by using the **debug** configuration section in your **tilt-settings.yaml** file. For example:
   280  
   281  ```yaml
   282  default_registry: "${REGISTRY}"
   283  provider_repos:
   284  - ../cluster-api-provider-azure
   285  enable_providers:
   286  - azure
   287  - docker
   288  - kubeadm-bootstrap
   289  - kubeadm-control-plane
   290  kustomize_substitutions:
   291    AZURE_SUBSCRIPTION_ID: <subscription-id>
   292    AZURE_TENANT_ID: <tenant-id>
   293    AZURE_CLIENT_SECRET: <client-secret>
   294    AZURE_CLIENT_ID: <client-id>
   295  debug:
   296    azure:
   297      continue: true
   298      port: 30000
   299  ```
   300  
   301  > Note you can list multiple controllers or **core** CAPI and expose metrics as well in the debug section. Full details of the options can be seen [here](https://cluster-api.sigs.k8s.io/developer/tilt.html).
   302  
   303  If you then start Tilt you can connect to delve via the port defined (i.e. 30000 in the sample). If you are using VSCode then you can use a launch configuration similar to this:
   304  
   305  ```json
   306  {
   307     "name": "Connect to CAPZ",
   308     "type": "go",
   309     "request": "attach",
   310     "mode": "remote",
   311     "remotePath": "",
   312     "port": 30000,
   313     "host": "127.0.0.1",
   314     "showLog": true,
   315     "trace": "log",
   316     "logOutput": "rpc"
   317  }
   318  ```
   319  
   320  ### Manual Testing
   321  
   322  #### Creating a dev cluster
   323  
   324  The steps below are provided in a convenient script in [hack/create-dev-cluster.sh](../../../../hack/create-dev-cluster.sh). Be sure to set `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, and `AZURE_TENANT_ID` before running. Optionally, you can override the different cluster configuration variables. For example, to override the workload cluster name:
   325  
   326  ```bash
   327  CLUSTER_NAME=<my-capz-cluster-name> ./hack/create-dev-cluster.sh
   328  ```
   329  
   330     NOTE: `CLUSTER_NAME` can only include letters, numbers, and hyphens and can't be longer than 44 characters.
   331  
   332  ##### Building and pushing dev images
   333  
   334  1. To build images with custom tags,
   335     run the `make docker-build` as follows:
   336  
   337     ```bash
   338     export REGISTRY="<container-registry>"
   339     export MANAGER_IMAGE_TAG="<image-tag>" # optional - defaults to `dev`.
   340     PULL_POLICY=IfNotPresent make docker-build
   341     ```
   342  
   343  2. (optional) Push your docker images:
   344  
   345     2.1. Login to your container registry using `docker login`.
   346  
   347     e.g., `docker login quay.io`
   348  
   349     2.2. Push to your custom image registry:
   350  
   351     ```bash
   352     REGISTRY=${REGISTRY} MANAGER_IMAGE_TAG=${MANAGER_IMAGE_TAG:="dev"} make docker-push
   353     ```
   354  
   355     NOTE: `make create-cluster` will fetch the manager image locally and load it onto the kind cluster if it is present.
   356  
   357  ##### Customizing the cluster deployment
   358  
   359  Here is a list of required configuration parameters (the full list is available in `templates/cluster-template.yaml`):
   360  
   361  ```bash
   362  # Cluster settings.
   363  export CLUSTER_NAME="capz-cluster"
   364  export AZURE_VNET_NAME=${CLUSTER_NAME}-vnet
   365  
   366  # Azure settings.
   367  export AZURE_LOCATION="southcentralus"
   368  export AZURE_RESOURCE_GROUP=${CLUSTER_NAME}
   369  export AZURE_SUBSCRIPTION_ID_B64="$(echo -n "$AZURE_SUBSCRIPTION_ID" | base64 | tr -d '\n')"
   370  export AZURE_TENANT_ID_B64="$(echo -n "$AZURE_TENANT_ID" | base64 | tr -d '\n')"
   371  export AZURE_CLIENT_ID_B64="$(echo -n "$AZURE_CLIENT_ID" | base64 | tr -d '\n')"
   372  export AZURE_CLIENT_SECRET_B64="$(echo -n "$AZURE_CLIENT_SECRET" | base64 | tr -d '\n')"
   373  
   374  # Machine settings.
   375  export CONTROL_PLANE_MACHINE_COUNT=3
   376  export AZURE_CONTROL_PLANE_MACHINE_TYPE="Standard_B2s"
   377  export AZURE_NODE_MACHINE_TYPE="Standard_B2s"
   378  export WORKER_MACHINE_COUNT=2
   379  export KUBERNETES_VERSION="v1.25.6"
   380  
   381  # Identity secret.
   382  export AZURE_CLUSTER_IDENTITY_SECRET_NAME="cluster-identity-secret"
   383  export CLUSTER_IDENTITY_NAME="cluster-identity"
   384  export AZURE_CLUSTER_IDENTITY_SECRET_NAMESPACE="default"
   385  
   386  # Generate SSH key.
   387  # If you want to provide your own key, skip this step and set AZURE_SSH_PUBLIC_KEY_B64 to your existing file.
   388  SSH_KEY_FILE=.sshkey
   389  rm -f "${SSH_KEY_FILE}" 2>/dev/null
   390  ssh-keygen -t rsa -b 2048 -f "${SSH_KEY_FILE}" -N '' 1>/dev/null
   391  echo "Machine SSH key generated in ${SSH_KEY_FILE}"
   392  # For Linux the ssh key needs to be b64 encoded because we use the azure api to set it
   393  # Windows doesn't support setting ssh keys so we use cloudbase-init to set which doesn't require base64
   394  export AZURE_SSH_PUBLIC_KEY_B64=$(cat "${SSH_KEY_FILE}.pub" | base64 | tr -d '\r\n')
   395  export AZURE_SSH_PUBLIC_KEY=$(cat "${SSH_KEY_FILE}.pub" | tr -d '\r\n')
   396  ```
   397  
   398  ⚠️ Please note the generated templates include default values and therefore require the use of `clusterctl` to create the cluster
   399  or the use of `envsubst` to replace these values
   400  
   401  ##### Creating the cluster
   402  
   403  ⚠️ Make sure you followed the previous two steps to build the dev image and set the required environment variables before proceeding.
   404  
   405  Ensure dev environment has been reset:
   406  
   407  ```bash
   408  make clean kind-reset
   409  ```
   410  
   411  Create the cluster:
   412  
   413  ```bash
   414  make create-cluster
   415  ```
   416  
   417  > Check out the [troubleshooting](../topics/troubleshooting.md) guide for common errors you might run into.
   418  
   419  ### Instrumenting Telemetry
   420  Telemetry is the key to operational transparency. We strive to provide insight into the internal behavior of the
   421  system through observable traces and metrics.
   422  
   423  #### Distributed Tracing
   424  Distributed tracing provides a hierarchical view of how and why an event occurred. CAPZ is instrumented to trace each
   425  controller reconcile loop. When the reconcile loop begins, a trace span begins and is stored in loop `context.Context`.
   426  As the context is passed on to functions below, new spans are created, tied to the parent span by the parent span ID.
   427  The spans form a hierarchical representation of the activities in the controller.
   428  
   429  These spans can also be propagated across service boundaries. The span context can be passed on through metadata such as
   430  HTTP headers. By propagating span context, it creates a distributed, causal relationship between services and functions.
   431  
   432  For tracing, we use [OpenTelemetry](https://github.com/open-telemetry).
   433  
   434  Here is an example of staring a span in the beginning of a controller reconcile.
   435  
   436  ```go
   437  ctx, logger, done := tele.StartSpanWithLogger(ctx, "controllers.AzureMachineReconciler.Reconcile",
   438     tele.KVP("namespace", req.Namespace),
   439     tele.KVP("name", req.Name),
   440     tele.KVP("kind", "AzureMachine"),
   441  )
   442  defer done()
   443  ```
   444  
   445  The code above creates a context with a new span stored in the context.Context value bag. If a span already existed in
   446  the `ctx` argument, then the new span would take on the parentID of the existing span, otherwise the new span
   447  becomes a "root span", one that does not have a parent. The span is also created with labels, or tags, which
   448  provide metadata about the span and can be used to query in many distributed tracing systems.
   449  
   450  It also creates a logger that logs messages both to the span and `STDOUT`. The span is not returned directly, but closure of the span is handled by the final `done` value. This is a simple nil-ary function (`func()`) that should be called  as appropriate. Most likely, this should be done in a defer -- as shown in the above code sample -- to ensure that the span is closed at the end of your function or scope.
   451  
   452  >Consider adding tracing if your func accepts a context.
   453  
   454  #### Metrics
   455  Metrics provide quantitative data about the operations of the controller. This includes cumulative data like
   456  counters, single numerical values like guages, and distributions of counts / samples like histograms & summaries.
   457  
   458  In CAPZ we expose metrics using the Prometheus client. The Kubebuilder project provides
   459  [a guide for metrics and for exposing new ones](https://book.kubebuilder.io/reference/metrics.html#publishing-additional-metrics).
   460  
   461  ### Submitting PRs and testing
   462  
   463  Pull requests and issues are highly encouraged!
   464  If you're interested in submitting PRs to the project, please be sure to run some initial checks prior to submission:
   465  
   466  ```bash
   467  make lint # Runs a suite of quick scripts to check code structure
   468  make lint-fix # Runs a suite of quick scripts to fix lint errors
   469  make verify # Runs a suite of verifying binaries
   470  make test # Runs tests on the Go code
   471  ```
   472  
   473  #### Executing unit tests
   474  
   475  `make test` executes the project's unit tests. These tests do not stand up a
   476  Kubernetes cluster, nor do they have external dependencies.
   477  
   478  ### Automated Testing
   479  
   480  #### Mocks
   481  
   482  Mocks for the services tests are generated using [GoMock][gomock].
   483  
   484  To generate the mocks you can run
   485  
   486  ```bash
   487  make generate-go
   488  ```
   489  
   490  #### E2E Testing
   491  
   492  To run E2E locally, set `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, and run:
   493  
   494  ```bash
   495  ./scripts/ci-e2e.sh
   496  ```
   497  
   498  You can optionally set the following variables:
   499  
   500  | Variable                   | Description                                                                                                                                                                                                                                                                                                                                                                | Default                                                                               |
   501  | -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
   502  | `E2E_CONF_FILE`            | The path of the [E2E configuration file](https://cluster-api.sigs.k8s.io/developer/e2e.html#defining-an-e2e-config-file).                                                                                                                                                                                                                                                  | `${GOPATH}/src/sigs.k8s.io/cluster-api-provider-azure/test/e2e/config/azure-dev.yaml` |
   503  | `SKIP_LOG_COLLECTION`      | Set to `true` if you do not want logs to be collected after running E2E tests. This is highly recommended for developers with Azure subscriptions that block SSH connections.                                                                                                                                                                                              | `false`                                                                               |
   504  | `SKIP_CLEANUP`             | Set to `true` if you do not want the bootstrap and workload clusters to be cleaned up after running E2E tests.                                                                                                                                                                                                                                                             | `false`                                                                               |
   505  | `SKIP_CREATE_MGMT_CLUSTER` | Skip management cluster creation. If skipping management cluster creation you must specify `KUBECONFIG` and `SKIP_CLEANUP`                                                                                                                                                                                                                                                 | `false`                                                                               |
   506  | `USE_LOCAL_KIND_REGISTRY`  | Use Kind local registry and run the subset of tests which don't require a remotely pushed controller image. If set, `REGISTRY` is also set to `localhost:5000/ci-e2e`.                                                                                                                                                                                                     | `true`                                                                                |
   507  | `REGISTRY`                 | Registry to push the controller image.                                                                                                                                                                                                                                                                                                                                     | `capzci.azurecr.io/ci-e2e`                                                            |
   508  | `IMAGE_NAME`               | The name of the CAPZ controller image.                                                                                                                                                                                                                                                                                                                                     | `cluster-api-azure-controller`                                                        |
   509  | `CONTROLLER_IMG`           | The repository/full name of the CAPZ controller image.                                                                                                                                                                                                                                                                                                                     | `${REGISTRY}/${IMAGE_NAME}`                                                           |
   510  | `ARCH`                     | The image architecture argument to pass to Docker, allows for cross-compiling.                                                                                                                                                                                                                                                                                             | `${GOARCH}`                                                                           |
   511  | `TAG`                      | The tag of the CAPZ controller image. If `BUILD_MANAGER_IMAGE` is set, then `TAG` is set to `$(date -u '+%Y%m%d%H%M%S')` instead of `dev`.                                                                                                                                                                                                                                 | `dev`                                                                                 |
   512  | `BUILD_MANAGER_IMAGE`      | Build the CAPZ controller image. If not set, then we will attempt to load an image from `${CONTROLLER_IMG}-${ARCH}:${TAG}`.                                                                                                                                                                                                                                                | `true`                                                                                |
   513  | `CLUSTER_NAME`             | Name of an existing workload cluster.  Must be set to run specs against existing workload cluster. Use in conjunction with `SKIP_CREATE_MGMT_CLUSTER`, `GINKGO_FOCUS`, `CLUSTER_NAMESPACE` and `KUBECONFIG`. Must specify **only one** e2e spec to run against with `GINKGO_FOCUS` such as `export GINKGO_FOCUS=Creating.a.VMSS.cluster.with.a.single.control.plane.node`. |
   514  | `CLUSTER_NAMESPACE`        | Namespace of an existing workload cluster.  Must be set to run specs against existing workload cluster. Use in conjunction with `SKIP_CREATE_MGMT_CLUSTER`, `GINKGO_FOCUS`, `CLUSTER_NAME` and `KUBECONFIG`. Must specify **only one** e2e spec to run against with `GINKGO_FOCUS` such as `export GINKGO_FOCUS=Creating.a.VMSS.cluster.with.a.single.control.plane.node`. |
   515  | `KUBECONFIG`               | Used with `SKIP_CREATE_MGMT_CLUSTER` set to true. Location of kubeconfig for the management cluster you would like to use. Use `kind get kubeconfig --name capz-e2e > kubeconfig.capz-e2e` to get the capz e2e kind cluster config                                                                                                                                         | '~/.kube/config'                                                                      |
   516  
   517  You can also customize the configuration of the CAPZ cluster created by the E2E tests (except for `CLUSTER_NAME`, `AZURE_RESOURCE_GROUP`, `AZURE_VNET_NAME`, `CONTROL_PLANE_MACHINE_COUNT`, and `WORKER_MACHINE_COUNT`, since they are generated by individual test cases). See [Customizing the cluster deployment](#customizing-the-cluster-deployment) for more details.
   518  
   519  #### Conformance Testing
   520  
   521  To run the Kubernetes Conformance test suite locally, you can run
   522  
   523  ```bash
   524  ./scripts/ci-conformance.sh
   525  ```
   526  
   527  Optional settings are:
   528  
   529  | Environment Variable | Default Value | Description                                                                                        |
   530  | -------------------- | ------------- | -------------------------------------------------------------------------------------------------- |
   531  | `WINDOWS`            | `false`       | Run conformance against Windows nodes                                                              |
   532  | `CONFORMANCE_NODES`  | `1`           | Number of parallel ginkgo nodes to run                                                             |
   533  | `CONFORMANCE_FLAVOR` | `""`          | The flavor of the cluster to run conformance against. If not set, the default flavor will be used. |
   534  | `IP_FAMILY`          | `IPv4`        | Set to `IPv6` to run conformance against single-stack IPv6, or `dual` for dual-stack.              |
   535  
   536  With the following environment variables defined, you can build a CAPZ cluster from the HEAD of Kubernetes main branch or release branch, and run the Conformance test suite against it.
   537  
   538  | Environment Variable      | Value                                                                                                                                                                                                    |
   539  | ------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   540  | `E2E_ARGS`                | `-kubetest.use-ci-artifacts`                                                                                                                                                                             |
   541  | `KUBERNETES_VERSION`      | `latest` - extract Kubernetes version from https://dl.k8s.io/ci/latest.txt (main's HEAD)<br>`latest-1.<MINOR>` - extract Kubernetes version from dl.k8s.io/ci/latest-1.<MINOR>.txt (release branch's HEAD) |
   542  | `WINDOWS_SERVER_VERSION`  | Optional, can be `windows-2019` (default) or `windows-2022`                                                                                                                                              |
   543  | `KUBETEST_WINDOWS_CONFIG` | Optional, can be `upstream-windows-serial-slow.yaml`, when not specified `upstream-windows.yaml` is used                                                                                                 |
   544  | `WINDOWS_CONTAINERD_URL`  | Optional, can be any url to a `tar.gz` file containing binaries for containerd in the same format as upstream package                                                                                    |
   545  
   546  With the following environment variables defined, CAPZ runs `./scripts/ci-build-kubernetes.sh` as part of `./scripts/ci-conformance.sh`, which allows developers to build Kubernetes from source and run the Kubernetes Conformance test suite against a CAPZ cluster based on the custom build:
   547  
   548  | Environment Variable      | Value                                                                    |
   549  | ------------------------- | ------------------------------------------------------------------------ |
   550  | `AZURE_STORAGE_ACCOUNT`   | Your Azure storage account name                                          |
   551  | `AZURE_STORAGE_KEY`       | Your Azure storage key                                                   |
   552  | `USE_LOCAL_KIND_REGISTRY` | `false`                                                                  |
   553  | `REGISTRY`                | Your Registry                                                            |
   554  | `TEST_K8S`                | `true`                                                                   |
   555  
   556  #### Running custom test suites on CAPZ clusters
   557  
   558  To run a custom test suite on a CAPZ cluster locally, set `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID` and run:
   559  
   560  ```bash
   561  ./scripts/ci-entrypoint.sh bash -c "cd ${GOPATH}/src/github.com/my-org/my-project && make e2e"
   562  ```
   563  
   564  You can optionally set the following variables:
   565  
   566  | Variable                    | Description                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
   567  | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
   568  | `AZURE_SSH_PUBLIC_KEY_FILE` | Use your own SSH key.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
   569  | `SKIP_CLEANUP`              | Skip deleting the cluster after the tests finish running.                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
   570  | `KUBECONFIG`                | Provide your existing cluster kubeconfig filepath. If no kubeconfig is provided, `./kubeconfig` will be used.                                                                                                                                                                                                                                                                                                                                                                                                                      |
   571  | `KUBERNETES_VERSION`        | Desired Kubernetes version to test. You can pass in a definitive released version, e.g., "v1.24.0". If you want to use pre-released CI bits of a particular release you may use the "latest-" prefix, e.g., "latest-1.24"; you may use the very latest built CI bits from the kubernetes/kubernetes master branch by passing in "latest". If you provide a `KUBERNETES_VERSION` environment variable, you may not also use `CI_VERSION` (below). Use only one configuration variable to declare the version of Kubernetes to test. |
   572  | `CI_VERSION`                | Provide a custom CI version of Kubernetes (e.g., `v1.25.0-alpha.0.597+aa49dffc7f24dc`). If not specified, this will be determined from the KUBERNETES_VERSION above if it is an unreleased version. If you provide a `CI_VERSION` environment variable, you may not also use `KUBERNETES_VERSION` (above).                                                                                                                                                                                                                         |
   573  | `TEST_CCM`                  | Build a cluster that uses custom versions of the Azure cloud-provider cloud-controller-manager and node-controller-manager images                                                                                                                                                                                                                                                                                                                                                                                                  |
   574  | `EXP_MACHINE_POOL`          | Use [Machine Pool](../topics/machinepools.md) for worker machines.                                                                                                                                                                                                                                                                                                                                                                                                                                                                 |
   575  | `TEST_WINDOWS`              | Build a cluster that has Windows worker nodes.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
   576  | `REGISTRY`                  | Registry to push any custom k8s images or cloud provider images built.                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
   577  | `CLUSTER_TEMPLATE`          | Use a custom cluster template. It can be a path to a template under templates/, a path on the host or a link. If the value is not set, the script will choose the appropriate cluster template based on existing environment variables.                                                                                                                                                                                                                                                                                            |
   578  | `CCM_COUNT`                 | Set the number of cloud-controller-manager only when `TEST_CCM` is set. Besides it should not be more than control plane Node number.                                                                                                                                                                                                                                                                                                                                                                                              |
   579  
   580  You can also customize the configuration of the CAPZ cluster (assuming that `SKIP_CREATE_WORKLOAD_CLUSTER` is not set). See [Customizing the cluster deployment](#customizing-the-cluster-deployment) for more details.
   581  
   582  <!-- References -->
   583  
   584  [go]: https://golang.org/doc/install
   585  [jq]: https://stedolan.github.io/jq/download/
   586  [image_pull_secrets]: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod
   587  [gettext]: https://www.gnu.org/software/gettext/
   588  [gettextwindows]: https://mlocati.github.io/articles/gettext-iconv-windows.html
   589  [go.mod]: https://github.com/kubernetes-sigs/cluster-api-provider-azure/blob/main/go.mod
   590  [kind]: https://sigs.k8s.io/kind
   591  [azure_cli]: https://learn.microsoft.com/cli/azure/install-azure-cli?view=azure-cli-latest
   592  [manifests]: /docs/manifests.md
   593  [kustomize]: https://github.com/kubernetes-sigs/kustomize
   594  [kustomizelinux]: https://kubectl.docs.kubernetes.io/installation/kustomize/
   595  [gomock]: https://github.com/golang/mock
   596  [timeout]: http://man7.org/linux/man-pages/man1/timeout.1.html