Repository: kubernetes-sigs/cluster-api
Pull request #3639 (2020-09-15 10:03:57)

🌱 Fix self-hosted flakes in E2E tests
**What this PR does / why we need it**:
This PR aims to fix self-hosted flakes by ensuring that mhc is not run during this test and by adding two delay in order to avoid doing move too aggressively.

In order to make this happen the entire management of cluster templates was re-architected so:
- cluster templates for tests are now generated from a set composable bases
- MHC-remediation has a new dedicated template
- all the other templates are without MHC
- also, in order to simplify things, this PR drops the distinction between CI and DEV test config

On top of that, this PR includes, a set of nits for improving test logs (mostly uppercase)

**Which issue(s) this PR fixes**:
Fixes https://github.com/kubernetes-sigs/cluster-api/issues/3589


k8s-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **fabriziopandini**
You can assign the PR to them by writing `/assign @fabriziopandini` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fcluster-api).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/kubernetes-sigs/cluster-api/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["fabriziopandini"]} -->
fabriziopandini: /milestone v0.3.10
k8s-ci-robot: @fabriziopandini: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-cluster-api-apidiff | 043e765f639d1f0b8af0167a27785a72ddcbe0d6 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-apidiff/1305809623256666115) | `/test pull-cluster-api-apidiff`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=3639). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3fabriziopandini). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @fabriziopandini: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-cluster-api-apidiff | 043e765f639d1f0b8af0167a27785a72ddcbe0d6 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-apidiff/1305809623256666115) | `/test pull-cluster-api-apidiff`
pull-cluster-api-e2e | 043e765f639d1f0b8af0167a27785a72ddcbe0d6 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-e2e/1305809623252471808) | `/test pull-cluster-api-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=3639). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3fabriziopandini). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
fabriziopandini: /retest
k8s-ci-robot: @fabriziopandini: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-cluster-api-e2e | 043e765f639d1f0b8af0167a27785a72ddcbe0d6 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-e2e/1305809623252471808) | `/test pull-cluster-api-e2e`
pull-cluster-api-apidiff | 043e765f639d1f0b8af0167a27785a72ddcbe0d6 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-apidiff/1305815411857559552) | `/test pull-cluster-api-apidiff`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=3639). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3fabriziopandini). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @fabriziopandini: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-cluster-api-apidiff | 043e765f639d1f0b8af0167a27785a72ddcbe0d6 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-apidiff/1305815411857559552) | `/test pull-cluster-api-apidiff`
pull-cluster-api-e2e | 043e765f639d1f0b8af0167a27785a72ddcbe0d6 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-e2e/1305815411857559553) | `/test pull-cluster-api-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=3639). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3fabriziopandini). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @fabriziopandini: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-cluster-api-e2e | 043e765f639d1f0b8af0167a27785a72ddcbe0d6 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-e2e/1305815411857559553) | `/test pull-cluster-api-e2e`
pull-cluster-api-apidiff | 46ad5309104f52eea71e9bbd5fcbc115fff205e9 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-apidiff/1305833404473806850) | `/test pull-cluster-api-apidiff`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=3639). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3fabriziopandini). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @fabriziopandini: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-cluster-api-apidiff | 46ad5309104f52eea71e9bbd5fcbc115fff205e9 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-apidiff/1305833404473806850) | `/test pull-cluster-api-apidiff`
pull-cluster-api-e2e | 46ad5309104f52eea71e9bbd5fcbc115fff205e9 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-e2e/1305833404473806849) | `/test pull-cluster-api-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=3639). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3fabriziopandini). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @fabriziopandini: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-cluster-api-apidiff | 46ad5309104f52eea71e9bbd5fcbc115fff205e9 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-apidiff/1305833404473806850) | `/test pull-cluster-api-apidiff`
pull-cluster-api-e2e | 46ad5309104f52eea71e9bbd5fcbc115fff205e9 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-e2e/1305833404473806849) | `/test pull-cluster-api-e2e`
pull-cluster-api-test | 46ad5309104f52eea71e9bbd5fcbc115fff205e9 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-test/1305833404473806851) | `/test pull-cluster-api-test`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=3639). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3fabriziopandini). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @fabriziopandini: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-cluster-api-e2e | 46ad5309104f52eea71e9bbd5fcbc115fff205e9 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-e2e/1305833404473806849) | `/test pull-cluster-api-e2e`
pull-cluster-api-test | 46ad5309104f52eea71e9bbd5fcbc115fff205e9 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-test/1305833404473806851) | `/test pull-cluster-api-test`
pull-cluster-api-apidiff | 343f90fc06a462b02bbbf31c41395a87177e839e | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-apidiff/1305836299386621952) | `/test pull-cluster-api-apidiff`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=3639). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3fabriziopandini). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @fabriziopandini: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-cluster-api-apidiff | 343f90fc06a462b02bbbf31c41395a87177e839e | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-apidiff/1305836299386621952) | `/test pull-cluster-api-apidiff`
pull-cluster-api-e2e | 343f90fc06a462b02bbbf31c41395a87177e839e | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-e2e/1305836299390816258) | `/test pull-cluster-api-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=3639). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3fabriziopandini). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @fabriziopandini: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-cluster-api-e2e | 9121d593d745c535661939db864afd5cc3476dfb | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-e2e/1305841457562652674) | `/test pull-cluster-api-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=3639). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3fabriziopandini). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
k8s-ci-robot: @fabriziopandini: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-cluster-api-e2e | c5f15b14db5771b3eed592f1ba73025e18c761c0 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-e2e/1305856305352675330) | `/test pull-cluster-api-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=3639). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3fabriziopandini). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
fabriziopandini: /hold 
investigating an error on ci-e2e.sh that shows up un CI only, while locally everything works just fine 🤔 
vincepri: From the PR's description, seems we're now splitting manifests in order to separate MHC components? Would this be something that we would expect users to do as well? 

During move, we should be able to pause controllers and look at the state of the cluster if it's safe to move, is there anything stopping us to do so?

Can we split this PR in multiple ones? In particular:
> also, in order to simplify things, this PR drops the distinction between CI and DEV test config
> On top of that, this PR includes, a set of nits for improving test logs (mostly uppercase)

These changes seems outside of the PR's scope
sedefsavas: @fabriziopandini Locally, works for me as well.


/test pull-cluster-api-e2e

k8s-ci-robot: @fabriziopandini: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-cluster-api-e2e | c5f15b14db5771b3eed592f1ba73025e18c761c0 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_cluster-api/3639/pull-cluster-api-e2e/1306100576672550912) | `/test pull-cluster-api-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=cluster-api&pr=3639). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3fabriziopandini). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/cluster-api/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
sedefsavas: In `test/e2e/Makefile`

    cd $(TOOLS_DIR); go build -tags=tools -o $(BIN_DIR)/kustomize sigs.k8s.io/kustomize/kustomize/v3

should be 

	cd $(TOOLS_DIR) && go build -tags=tools -o $(BIN_DIR)/kustomize sigs.k8s.io/kustomize/kustomize/v3


Patch:
diff --git a/cmd/clusterctl/client/config/providers_client.go b/cmd/clusterctl/client/config/providers_client.go
index 286abb707..0d40010cc 100644
--- a/cmd/clusterctl/client/config/providers_client.go
+++ b/cmd/clusterctl/client/config/providers_client.go
@@ -44,7 +44,6 @@ const (
 	// Bootstrap providers
 	KubeadmBootstrapProviderName = "kubeadm"
 	TalosBootstrapProviderName   = "talos"
-	EKSBootstrapProviderName     = "eks"
 
 	// ControlPlane providers
 	KubeadmControlPlaneProviderName = "kubeadm"
@@ -153,11 +152,7 @@ func (p *providersClient) defaults() []Provider {
 			url:          "https://github.com/talos-systems/cluster-api-bootstrap-provider-talos/releases/latest/bootstrap-components.yaml",
 			providerType: clusterctlv1.BootstrapProviderType,
 		},
-		&provider{
-			name:         EKSBootstrapProviderName,
-			url:          "https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases/latest/eks-bootstrap-components.yaml",
-			providerType: clusterctlv1.BootstrapProviderType,
-		},
+
 		// ControlPlane providers
 		&provider{
 			name:         KubeadmControlPlaneProviderName,
diff --git a/cmd/clusterctl/client/repository/metadata_client.go b/cmd/clusterctl/client/repository/metadata_client.go
index 1b4876d7a..8fe1c3aee 100644
--- a/cmd/clusterctl/client/repository/metadata_client.go
+++ b/cmd/clusterctl/client/repository/metadata_client.go
@@ -156,17 +156,6 @@ func (f *metadataClient) getEmbeddedMetadata() *clusterctlv1.Metadata {
 					// older version are not supported by clusterctl
 				},
 			}
-		case config.EKSBootstrapProviderName:
-			return &clusterctlv1.Metadata{
-				TypeMeta: metav1.TypeMeta{
-					APIVersion: clusterctlv1.GroupVersion.String(),
-					Kind:       "Metadata",
-				},
-				ReleaseSeries: []clusterctlv1.ReleaseSeries{
-					// v1alpha3 release series
-					{Major: 0, Minor: 6, Contract: "v1alpha3"},
-				},
-			}
 		default:
 			return nil
 		}
diff --git a/controllers/machine_controller.go b/controllers/machine_controller.go
index 56fed8fc0..4fd7196eb 100644
--- a/controllers/machine_controller.go
+++ b/controllers/machine_controller.go
@@ -227,7 +227,6 @@ func patchMachine(ctx context.Context, patchHelper *patch.Helper, machine *clust
 			clusterv1.ReadyCondition,
 			clusterv1.BootstrapReadyCondition,
 			clusterv1.InfrastructureReadyCondition,
-			clusterv1.DrainingSucceededCondition,
 		}},
 	)
 
diff --git a/docs/book/src/reference/providers.md b/docs/book/src/reference/providers.md
index 5cf588522..1e7c23b8a 100644
--- a/docs/book/src/reference/providers.md
+++ b/docs/book/src/reference/providers.md
@@ -8,7 +8,6 @@ updated info about which API version they are supporting.
 ## Bootstrap
 - [Kubeadm](https://github.com/kubernetes-sigs/cluster-api/tree/master/bootstrap/kubeadm)
 - [Talos](https://github.com/talos-systems/cluster-api-bootstrap-provider-talos)
-- [EKS](https://github.com/kubernetes-sigs/cluster-api-provider-aws/tree/master/bootstrap/eks)
 
 
 ## Infrastructure
diff --git a/docs/proposals/20191017-kubeadm-based-control-plane.md b/docs/proposals/20191017-kubeadm-based-control-plane.md
index 27a7cfb81..1dff19f80 100644
--- a/docs/proposals/20191017-kubeadm-based-control-plane.md
+++ b/docs/proposals/20191017-kubeadm-based-control-plane.md
@@ -18,7 +18,7 @@ reviewers:
   - "@hardikdr"
   - "@sbueringer"
 creation-date: 2019-10-17
-last-updated: 2020-09-07
+last-updated: 2019-12-04
 status: implementable
 ---
 
@@ -91,15 +91,14 @@ for the default implementation would not preclude the use of alternative control
 
 - To establish new resource types for control plane management
 - To support single node and multiple node control plane instances, with the requirement that the infrastructure provider supports some type of a stable endpoint for the API Server (Load Balancer, VIP, etc).
-- To enable scaling of the number of control plane nodes
 - To enable declarative orchestrated control plane upgrades
 - To provide a default machine-based implementation using kubeadm
 - To provide a kubeadm-based implementation that is infrastructure provider agnostic
 - To enable declarative orchestrated replacement of control plane machines, such as to roll out an OS-level CVE fix.
 - To manage a kubeadm-based, "stacked etcd" control plane
-- To manage a kubeadm-based, "external etcd" control plane (using a pre-existing, user-managed, etcd clusters).
-- To manage control plane deployments across failure domains.
-- To support user-initiated remediation:
+- To enable scaling of the number of control plane nodes
+- To support pre-existing, user-managed, external etcd clusters
+- To support only user-initiated remediation:
   E.g. user deletes a Machine. Control Plane Provider reconciles by removing the corresponding etcd member and updating related metadata
 
 ### Non-Goals / Future Work
@@ -109,6 +108,7 @@ Non-Goals listed in this document are intended to scope bound the current v1alph
 - To manage non-machine based topologies, e.g.
   - Pod based control planes.
   - Non-node control planes (i.e. EKS, GKE, AKS).
+- To manage control plane deployments across failure domains, follow up work for this will be tracked on [this issue](https://github.com/kubernetes-sigs/cluster-api/issues/1647).
 - To define a mechanism for providing a stable API endpoint for providers that do not currently have one, follow up work for this will be tracked on [this issue](https://github.com/kubernetes-sigs/cluster-api/issues/1687)
 - To predefine the exact contract/interoperability mechanism for alternative control plane providers, follow up work for this will be tracked on [this issue](https://github.com/kubernetes-sigs/cluster-api/issues/1727)
 - To manage CA certificates outside of what is provided by Kubeadm bootstrapping
@@ -151,7 +151,156 @@ Non-Goals listed in this document are intended to scope bound the current v1alph
 
 #### New API Types
 
-See [kubeadm_control_plane_types.go](https://github.com/kubernetes-sigs/cluster-api/blob/master/controlplane/kubeadm/api/v1alpha3/kubeadm_control_plane_types.go)
+KubeadmControlPlane:
+
+```go
+package v1alpha3
+
+import (
+    corev1  "k8s.io/api/core/v1"
+    metav1  "k8s.io/apimachinery/pkg/apis/meta/v1"
+    cabpkv1 "sigs.k8s.io/cluster-api-bootstrap-provider-kubeadm/api/v1alpha2"
+)
+
+// KubeadmControlPlaneSpec defines the desired state of KubeadmControlPlane.
+type KubeadmControlPlaneSpec struct {
+    // Number of desired machines. Defaults to 1. When stacked etcd is used only
+    // odd numbers are permitted, as per [etcd best practice](https://etcd.io/docs/v3.3.12/faq/#why-an-odd-number-of-cluster-members).
+    // This is a pointer to distinguish between explicit zero and not specified.
+    // +optional
+    Replicas *int32 `json:"replicas,omitempty"`
+
+    // Version defines the desired Kubernetes version.
+    Version string `json:"version"`
+
+    // InfrastructureTemplate is a required reference to a custom resource
+    // offered by an infrastructure provider.
+    InfrastructureTemplate corev1.ObjectReference `json:"infrastructureTemplate"`
+
+    // KubeadmConfigSpec is a KubeadmConfigSpec
+    // to use for initializing and joining machines to the control plane.
+    KubeadmConfigSpec cabpkv1.KubeadmConfigSpec `json:"kubeadmConfigSpec"`
+}
+
+// KubeadmControlPlaneStatus defines the observed state of KubeadmControlPlane.
+type KubeadmControlPlaneStatus struct {
+    // Selector is the label selector in string format to avoid introspection
+    // by clients, and is used to provide the CRD-based integration for the
+    // scale subresource and additional integrations for things like kubectl
+    // describe.. The string will be in the same format as the query-param syntax.
+    // More info about label selectors: http://kubernetes.io/docs/user-guide/labels#label-selectors
+    // +optional
+    Selector string `json:"selector,omitempty"`
+
+    // Total number of non-terminated machines targeted by this control plane
+    // (their labels match the selector).
+    // +optional
+    Replicas int32 `json:"replicas,omitempty"`
+
+    // Total number of non-terminated machines targeted by this control plane
+    // that have the desired template spec.
+    // +optional
+    UpdatedReplicas int32 `json:"updatedReplicas,omitempty"`
+
+    // Total number of fully running and ready control plane machines.
+    // +optional
+    ReadyReplicas int32 `json:"readyReplicas,omitempty"`
+
+    // Total number of unavailable machines targeted by this control plane.
+    // This is the total number of machines that are still required for
+    // the deployment to have 100% available capacity. They may either
+    // be machines that are running but not yet ready or machines
+    // that still have not been created.
+    // +optional
+    UnavailableReplicas int32 `json:"unavailableReplicas,omitempty"`
+
+    // Initialized denotes whether or not the control plane has the
+    // uploaded kubeadm-config configmap.
+    // +optional
+    Initialized bool `json:"initialized,omitempty”`
+
+    // Ready denotes that the KubeadmControlPlane API Server is ready to
+    // receive requests.
+    // +optional
+    Ready bool `json:"ready,omitempty"`
+
+    // FailureReason indicates that there is a problem reconciling the
+    // state, and will be set to a token value suitable for
+    // programmatic interpretation.
+    // +optional
+    FailureReason KubeadmControlPlaneStatusError `json:"errorReason,omitempty"`
+
+    // FailureMessage indicates that there is a problem reconciling the
+    // state, and will be set to a descriptive error message.
+    // +optional
+    FailureMessage *string `json:"errorMessage,omitempty"`
+
+// +kubebuilder:object:root=true
+// +kubebuilder:resource:path=controlplanes,shortName=cp,scope=Namespaced,categories=cluster-api
+// +kubebuilder:storageversion
+// +kubebuilder:subresource:status
+// +kubebuilder:subresource:scale:specpath=.spec.replicas,statuspath=.status.replicas,selectorpath=.status.selector
+
+// KubeadmControlPlane is the Schema for the KubeadmControlPlane API.
+type KubeadmControlPlane struct {
+    metav1.TypeMeta   `json:",inline"`
+    metav1.ObjectMeta `json:"metadata,omitempty"`
+
+    Spec   KubeadmControlPlaneSpec   `json:"spec,omitempty"`
+    Status KubeadmControlPlaneStatus `json:"status,omitempty"`
+}
+
+// +kubebuilder:object:root=true
+
+// KubeadmControlPlaneList contains a list of KubeadmControlPlane.
+type KubeadmControlPlaneList struct {
+    metav1.TypeMeta `json:",inline"`
+    metav1.ListMeta `json:"metadata,omitempty"`
+    Items           []KubeadmControlPlane `json:"items"`
+}
+
+func init() {
+    SchemeBuilder.Register(&KubeadmControlPlane{}, &KubeadmControlPlaneList{})
+}
+
+type KubeadmControlPlaneStatusError string
+
+// A more descriptive kind of error that represents an error condition that
+// should be set in the KubeadmControlPlane.Status. The "Reason" field is meant for short,
+// enum-style constants meant to be interpreted by control planes. The "Message"
+// field is meant to be read by humans.
+type KubeadmControlPlaneError struct {
+    Reason  KubeadmControlPlaneStatusError
+    Message string
+}
+
+func (e *KubeadmControlPlaneError) Error() string {
+    return e.Message
+}
+
+const (
+    // InvalidConfigurationKubeadmControlPlaneError indicates that the kubeadm control plane
+    // configuration is invalid.
+    InvalidConfigurationKubeadmControlPlaneError KubeadmControlPlaneStatusError = "InvalidConfiguration"
+
+    // UnsupportedChangeKubeadmControlPlaneError indicates that the kubeadm control plane
+    // spec has been updated in an unsupported way. That cannot be
+    // reconciled.
+    UnsupportedChangeKubeadmControlPlaneError KubeadmControlPlaneStatusError = "UnsupportedChange"
+
+    // CreateKubeadmControlPlaneError indicates that an error was encountered
+    // when trying to create the kubeadm control plane.
+    CreateKubeadmControlPlaneError KubeadmControlPlaneStatusError = "CreateError"
+
+    // UpdateKubeadmControlPlaneError indicates that an error was encountered
+    // when trying to update the kubeadm control plane.
+    UpdateKubeadmControlPlaneError KubeadmControlPlaneStatusError = "UpdateError"
+
+    // DeleteKubeadmControlPlaneError indicates that an error was encountered
+    // when trying to delete the kubeadm control plane.
+    DeleteKubeadmControlPlaneError KubeadmControlPlaneStatusError = "DeleteError"
+)
+```
 
 With the following validations:
 
@@ -159,16 +308,12 @@ With the following validations:
   - `KubeadmControlPlane.Spec.Replicas` is an odd number.
   - Configuration of external etcd is determined by introspecting the provided `KubeadmConfigSpec`.
 - `KubeadmControlPlane.Spec.Replicas` is >= 0 or is nil
-- `KubeadmControlPlane.Spec.Version` should be a valid semantic version
-- `KubeadmControlPlane.Spec.KubeadmConfigSpec` allows mutations required for supporting following use cases:
-    - Change of imagesRepository/imageTags (with validation of CoreDNS supported upgrade)
-    - Change of node registration options
-    - Change of pre/post kubeadm commands 
-    - Change of cloud init files
+- `KubeadmControlPlane.Spec.Version != ""` (openapi)
+- `KubeadmControlPlane.Spec.KubeadmConfigSpec` must be treated as immutable (via webhook)
 
 And the following defaulting:
 
-- `KubeadmControlPlane.Spec.Replicas: 1` 
+- `KubeadmControlPlane.Spec.Replicas: 1` (openapi or webhook)
 
 #### Modifications required to existing API Types
 
@@ -203,6 +348,7 @@ And the following defaulting:
 ##### Create
 
 - After a KubeadmControlPlane object is created, it must bootstrap a control plane with a given number of replicas.
+- If an error occurs, `KubeadmControlPlane.Status.FailureReason` and `KubeadmControlPlane.Status.FailureMessage` are populated.
 - `KubeadmControlPlane.Spec.Replicas` must be an odd number.
 - Can create an arbitrary number of control planes if etcd is external to the control plane, which will be determined by introspecting `KubeadmControlPlane.Spec.KubeadmConfigSpec`.
 - Creating a KubeadmControlPlane with > 1 replicas is equivalent to creating a KubeadmControlPlane with 1 replica followed by scaling the KubeadmControlPlane to the desired number of replicas
@@ -307,62 +453,70 @@ spec:
 - Allow scale up a control plane with stacked etcd to only odd numbers, as per
   [etcd best practice](https://etcd.io/docs/v3.3.12/faq/#why-an-odd-number-of-cluster-members).
 - However, allow a control plane using an external etcd cluster to scale up to other numbers such as 2 or 4.
-- Scale up operations must not be done in conjunction with:
-  - Adopting machines
-  - Upgrading machines
+- Scale up operations must not be done in conjunction with an upgrade operation, this should be enforced using a validation webhook.
 - Scale up operations are blocked based on Etcd and control plane health checks.
   - See [Health checks](#Health checks) below.
-- Scale up operations creates the next machine in the failure domain with the fewest number of machines. 
 
 ![controlplane-init-6](images/controlplane/controlplane-init-6.png)
 
 ##### Scale Down
 
-- Allow scale down a control plane with stacked etcd to only odd numbers, as per
-  [etcd best practice](https://etcd.io/docs/v3.3.12/faq/#why-an-odd-number-of-cluster-members).
-- However, allow a control plane using an external etcd cluster to scale down to other numbers such as 2 or 4.
-- Scale up operations must not be done in conjunction with:
-  - Adopting machines
-  - Upgrading machines
-- Scale up operations are blocked based on Etcd and control plane health checks.
+The annotation steps are required to make scale down re-entrant.
+
+- Scale down a stacked control plane
+  - Wait for deletes to finish before scaling down
+  - Find the oldest machine, or machine marked for removal and target that as the replica to remove
+  - Apply an annotation to the machine marked for removal
+  - Require Etcd to be healthy
+  - Remove the replica’s etcd member from the etcd cluster
+  - Apply an annotation to the machine that has had the etcd member removed from the etcd cluster
+  - Require Control plane to be healthy
+  - Update the kubeadm generated config map
+  - Apply an annotation to the machine that the kubeadm config map has been updated
+  - Require the annotations that the etcd member has been removed and the kubeadm config map updated
+  - Remove the Machine
+- Scale down a control plane with an external etcd
+  - Same as above minus etcd management
+- Scale down operations must not be done in conjunction with an upgrade operation, this should not impact manual operations for recovery. This should also be enforced using a validation webhook.
+- Scale down operations are blocked based on Etcd and control plane health checks
+  - Etcd health is not required if a machine has already been selected for scale down
   - See [Health checks](#Health checks) below.
-- Scale down operations removes the oldest machine in the failure domain that has the most control-plane machines on it 
+- Scale to 0 must be rejected for the initial support, see below for deletion workflows.
 
 ![controlplane-init-7](images/controlplane/controlplane-init-7.png)
 
 ##### Delete of the entire KubeadmControlPlane (kubectl delete controlplane my-controlplane)
 
-- KubeadmControlPlane deletion should be blocked until all the worker nodes are deleted.
 - Completely removing the control plane and issuing a delete on the underlying machines.
+  - Deletion is equivalent to a scale to 1 followed by a deletion of a single replica control plane.
 - User documentation should focus on deletion of the Cluster resource rather than the KubeadmControlPlane resource.
+- Cluster deletion will need to be modified to ensure KubeadmControlPlane deletion is done in the proper order.
 
-##### KubeadmControlPlane rollout (using create-swap-and-delete)
+##### Cluster upgrade (using create-swap-and-delete)
 
-- Triggered by: 
-    - Changes to Version
-    - Changes to the kubeadmConfigSpec
-    - Changes to the infrastructureRef
-    - The `upgradeAfter` field, which can be set to a specific time in the future
+- Triggered on any changes to Version or the InfrastructureTemplate
+  - The KubeadmConfiguration, for the first iteration, is treated and validated as immutable and changes to it do not trigger an upgrade
+  - Must be able to trigger an upgrade for the underlying machine image (e.g. nothing in the above list has changed but an upgrade is required)
+      - By adding a timestamp field, `upgradeAfter`, which can be set to a specific time in the future
         - Set to `nil` or the zero value of `time.Time` if no upgrades are desired
         - An upgrade will run when that timestamp is passed
         - Good for scheduling upgrades/SLOs
         - Set `upgradeAfter` to now (in RFC3339 form) if an upgrade is required immediately
 
-- Rollout operations rely on scale up and scale down which are be blocked based on Etcd and control plane health checks
+- Upgrade operations rely on scale up and scale down which are be blocked based on Etcd and control plane health checks
   - See [Health checks](#Health checks) below.
 
-- The rollout algorithm is the following:
-  - Find Machines that have an outdated spec
-  - If there is a machine requiring rollout
-    - Scale up control plane creating a machine with the new spec
-    - Scale down control plane by removing one of the machine that needs rollout (the oldest out-of date machine in the failure domain that has the most control-plane machines on it)
-    
-- In order to determine if a Machine need rollouts includes:
-    - The infrastructureRef link used by each machine at creation time is stored in annotations at machine level.
-    - The kubeadmConfigSpec used by each machine at creation time is stored in annotations at machine level.
-        - If the annotation is not present (machine is either old or adopted), we won't roll out on any possible changes made in KCP's ClusterConfiguration given that we don't have enough information to make a decision.
-           Users should use KCP.Spec.UpgradeAfter field to force a rollout in this case.
-    
+- The upgrade algorithm is as follows:
+  - Find Machines that need upgrading
+    - Configuration hash doesn't match
+    - `upgradeAfter` field is before now
+  - Mark machine as selected for upgrade
+  - Scale up control plane
+  - Mark machine as having a replacement
+  - Scale down control plane by removing a machine that has been marked for removal and has a replacement already created
+
+- Determining if a Machine is "up to date" will be done through the use of a label (controlplane.cluster.x-k8s.io/hash) that is placed on the Machine at creation time. The value of this label is generated by computing the Hash of the KubeadmControlPlaneSpec (minus the replicas field). This would allow triggering an Upgrade based on any changes to Version, InfrastructureTemplate, or the KubeadmConfiguration used (when a new configuration is referenced in a new InfrastructureTemplate).
+  - For example, a CVE is patched in containerd and updated images are available. Note that the Kubernetes version is not changed. To trigger an upgrade, the user updates the image in the InfrastructureTemplate (as in the Acme cluster example above, the image is stored in InfrastructureTemplate.Spec.OSImage.ID).
 - The controller should tolerate the manual removal of a replica during the upgrade process. A replica that fails during the upgrade may block the completion of the upgrade. Removal or other remedial action may be necessary to allow the upgrade to complete.
 
 ###### Constraints and Assumptions
@@ -452,5 +606,4 @@ For the purposes of designing upgrades, two existing lifecycle managers were exa
 - [x] 10/17/2019: Initial Creation
 - [x] 11/19/2019: Initial KubeadmControlPlane types added [#1765](https://github.com/kubernetes-sigs/cluster-api/pull/1765)
 - [x] 12/04/2019: Updated References to ErrorMessage/ErrorReason to FailureMessage/FailureReason
-- [x] 12/04/2019: Initial stubbed KubeadmControlPlane controller added [#1826](https://github.com/kubernetes-sigs/cluster-api/pull/1826)
-- [x] 07/09/2020: Document updated to reflect latest changes
\ No newline at end of file
+- [] 12/04/2019: Initial stubbed KubeadmControlPlane controller added [#1826](https://github.com/kubernetes-sigs/cluster-api/pull/1826)
diff --git a/go.mod b/go.mod
index 0dedc704c..19d7790b1 100644
--- a/go.mod
+++ b/go.mod
@@ -37,11 +37,11 @@ require (
 	k8s.io/apimachinery v0.17.9
 	k8s.io/apiserver v0.17.9
 	k8s.io/client-go v0.17.9
-	k8s.io/cluster-bootstrap v0.17.9
+	k8s.io/cluster-bootstrap v0.17.8
 	k8s.io/component-base v0.17.9
 	k8s.io/klog v1.0.0
 	k8s.io/utils v0.0.0-20200619165400-6e3d28b6ed19
-	sigs.k8s.io/controller-runtime v0.5.11
+	sigs.k8s.io/controller-runtime v0.5.10
 	sigs.k8s.io/kind v0.7.1-0.20200303021537-981bd80d3802
 	sigs.k8s.io/yaml v1.2.0
 )
diff --git a/go.sum b/go.sum
index 0d7503b57..fc42d1638 100644
--- a/go.sum
+++ b/go.sum
@@ -624,19 +624,23 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+k8s.io/api v0.17.8 h1:8JHlbqJ3A6sGhoacXfu/sASSD+HWWqVq67qt9lyB0kU=
+k8s.io/api v0.17.8/go.mod h1:N++Llhs8kCixMUoCaXXAyMMPbo8dDVnh+IQ36xZV2/0=
 k8s.io/api v0.17.9 h1:BA/U8qtSNzx7BbmQy3lODbCxVMKGNUpBJ2fjsKt6OOY=
 k8s.io/api v0.17.9/go.mod h1:avJJAA1fSV6tnbCGW2K+S+ilDFW7WpNr5BScoiZ1M1U=
 k8s.io/apiextensions-apiserver v0.17.9 h1:GWtUr9LErCZBV7QEUIF7wiICPG6wzPukFRrwDv/AIdM=
 k8s.io/apiextensions-apiserver v0.17.9/go.mod h1:p2C9cDflVAUPMl5/QOMHxnSzQWF/cDqu7AP2KUXHHMA=
 k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
+k8s.io/apimachinery v0.17.8 h1:zXvd8rYMAjRJXpILP9tdAiUnFIENM9EmHuE81apIoms=
+k8s.io/apimachinery v0.17.8/go.mod h1:Lg8zZ5iC/O8UjCqW6DNhcQG2m4TdjF9kwG3891OWbbA=
 k8s.io/apimachinery v0.17.9 h1:knQxNgMu57Oxlm12J6DS375kmGMeuWV0VNzRRUBB2Yk=
 k8s.io/apimachinery v0.17.9/go.mod h1:Lg8zZ5iC/O8UjCqW6DNhcQG2m4TdjF9kwG3891OWbbA=
 k8s.io/apiserver v0.17.9 h1:q50QEJ51xdHy2Gl1lo9yJexiyixxof/yDUFdWNnZxh0=
 k8s.io/apiserver v0.17.9/go.mod h1:Qaxd3EbeoPRBHVMtFyuKNAObqP6VAkzIMyWYz8KuE2k=
 k8s.io/client-go v0.17.9 h1:qUPhohX4bUBx0L7pfye02aPnu3PQ0t+B8dqHfGvt++k=
 k8s.io/client-go v0.17.9/go.mod h1:3cM92qAd1XknA5IRkRfpJhl9OQjkYy97ZEUio70wVnI=
-k8s.io/cluster-bootstrap v0.17.9 h1:IH/MwGor5/7bwHClz0PO/8pKq+SU1eSB1rs645pGu8Y=
-k8s.io/cluster-bootstrap v0.17.9/go.mod h1:Q6nXn/sqVfMvT1VIJVPxFboYAoqH06PCjZnaYzbpZC0=
+k8s.io/cluster-bootstrap v0.17.8 h1:qee9dmkOVwngBf98zbwrij1s898EZ2aHg+ymXw1UBLU=
+k8s.io/cluster-bootstrap v0.17.8/go.mod h1:SC9J2Lt/MBOkxcCB04+5mYULLfDQL5kdM0BjtKaVCVU=
 k8s.io/code-generator v0.17.9/go.mod h1:iiHz51+oTx+Z9D0vB3CH3O4HDDPWrvZyUgUYaIE9h9M=
 k8s.io/component-base v0.17.9 h1:1CmgQ367Eo6UWkfO1sl7Z99KJpbwkrs9aMY5LZTQR9s=
 k8s.io/component-base v0.17.9/go.mod h1:Wg22ePDK0mfTa+bEFgZHGwr0h40lXnYy6D7D+f7itFk=
@@ -659,8 +663,8 @@ modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
 modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
 modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
 modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
-sigs.k8s.io/controller-runtime v0.5.11 h1:U/FjGJ61aR2T2mCrdlBCxEcWgLEwLmK6YZKf0NC0a24=
-sigs.k8s.io/controller-runtime v0.5.11/go.mod h1:OTqxLuz7gVcrq+BHGUgedRu6b2VIKCEc7Pu4Jbwui0A=
+sigs.k8s.io/controller-runtime v0.5.10 h1:IJ2zO+BeNvTJEo2W1Kho1+X756QroQjYCKIzEYYqsI8=
+sigs.k8s.io/controller-runtime v0.5.10/go.mod h1:OTqxLuz7gVcrq+BHGUgedRu6b2VIKCEc7Pu4Jbwui0A=
 sigs.k8s.io/kind v0.7.1-0.20200303021537-981bd80d3802 h1:L6/8hETA7jvdx3xBcbDifrIN2xaYHE7tA58n+Kdp2Zw=
 sigs.k8s.io/kind v0.7.1-0.20200303021537-981bd80d3802/go.mod h1:HIZ3PWUezpklcjkqpFbnYOqaqsAE1JeCTEwkgvPLXjk=
 sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
diff --git a/util/util.go b/util/util.go
index 805c9998a..91d0def06 100644
--- a/util/util.go
+++ b/util/util.go
@@ -493,25 +493,15 @@ func UnstructuredUnmarshalField(obj *unstructured.Unstructured, v interface{}, f
 	return nil
 }
 
-// HasOwner checks if any of the references in the passed list match the given group from apiVersion and one of the given kinds.
+// HasOwner checks if any of the references in the passed list match the given apiVersion and one of the given kinds
 func HasOwner(refList []metav1.OwnerReference, apiVersion string, kinds []string) bool {
-	gv, err := schema.ParseGroupVersion(apiVersion)
-	if err != nil {
-		return false
-	}
-
 	kMap := make(map[string]bool)
 	for _, kind := range kinds {
 		kMap[kind] = true
 	}
 
 	for _, mr := range refList {
-		mrGroupVersion, err := schema.ParseGroupVersion(mr.APIVersion)
-		if err != nil {
-			return false
-		}
-
-		if mrGroupVersion.Group == gv.Group && kMap[mr.Kind] {
+		if mr.APIVersion == apiVersion && kMap[mr.Kind] {
 			return true
 		}
 	}


Test patch:
diff --git a/cmd/clusterctl/client/config_test.go b/cmd/clusterctl/client/config_test.go
index a3d2a7b67..5f254ce39 100644
--- a/cmd/clusterctl/client/config_test.go
+++ b/cmd/clusterctl/client/config_test.go
@@ -55,7 +55,6 @@ func Test_clusterctlClient_GetProvidersConfig(t *testing.T) {
 			// note: these will be sorted by name by the Providers() call, so be sure they are in alphabetical order here too
 			wantProviders: []string{
 				config.ClusterAPIProviderName,
-				config.EKSBootstrapProviderName,
 				config.KubeadmBootstrapProviderName,
 				config.TalosBootstrapProviderName,
 				config.KubeadmControlPlaneProviderName,
@@ -81,7 +80,6 @@ func Test_clusterctlClient_GetProvidersConfig(t *testing.T) {
 			wantProviders: []string{
 				config.ClusterAPIProviderName,
 				customProviderConfig.Name(),
-				config.EKSBootstrapProviderName,
 				config.KubeadmBootstrapProviderName,
 				config.TalosBootstrapProviderName,
 				config.KubeadmControlPlaneProviderName,
diff --git a/cmd/clusterctl/cmd/config_repositories_test.go b/cmd/clusterctl/cmd/config_repositories_test.go
index 38db4d691..5ae5dee76 100644
--- a/cmd/clusterctl/cmd/config_repositories_test.go
+++ b/cmd/clusterctl/cmd/config_repositories_test.go
@@ -44,7 +44,6 @@ func Test_runGetRepositories(t *testing.T) {
 			g.Expect(runGetRepositories(path, buf)).To(Succeed())
 			out, err := ioutil.ReadAll(buf)
 			g.Expect(err).ToNot(HaveOccurred())
-
 			if val == RepositoriesOutputText {
 				g.Expect(string(out)).To(Equal(expectedOutputText))
 			} else if val == RepositoriesOutputYaml {
@@ -102,7 +101,6 @@ providers:
 var expectedOutputText = `NAME                TYPE                     URL                                                                                          FILE
 cluster-api         CoreProvider             https://github.com/myorg/myforkofclusterapi/releases/latest/                                 core_components.yaml
 another-provider    BootstrapProvider        ./                                                                                           bootstrap-components.yaml
-eks                 BootstrapProvider        https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases/latest/                 eks-bootstrap-components.yaml
 kubeadm             BootstrapProvider        https://github.com/kubernetes-sigs/cluster-api/releases/latest/                              bootstrap-components.yaml
 talos               BootstrapProvider        https://github.com/talos-systems/cluster-api-bootstrap-provider-talos/releases/latest/       bootstrap-components.yaml
 kubeadm             ControlPlaneProvider     https://github.com/kubernetes-sigs/cluster-api/releases/latest/                              control-plane-components.yaml
@@ -127,10 +125,6 @@ var expectedOutputYaml = `- File: core_components.yaml
   Name: another-provider
   ProviderType: BootstrapProvider
   URL: ./
-- File: eks-bootstrap-components.yaml
-  Name: eks
-  ProviderType: BootstrapProvider
-  URL: https://github.com/kubernetes-sigs/cluster-api-provider-aws/releases/latest/
 - File: bootstrap-components.yaml
   Name: kubeadm
   ProviderType: BootstrapProvider
diff --git a/test/e2e/self_hosted.go b/test/e2e/self_hosted.go
index 06bfc173f..0ecb4e0d1 100644
--- a/test/e2e/self_hosted.go
+++ b/test/e2e/self_hosted.go
@@ -24,6 +24,7 @@ import (
 
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"sigs.k8s.io/controller-runtime/pkg/client"
 
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/utils/pointer"
@@ -96,7 +97,6 @@ func SelfHostedSpec(ctx context.Context, inputGetter func() SelfHostedSpecInput)
 		})
 
 		By("Turning the workload cluster into a management cluster")
-		//TODO: refactor into an helper func e.g. "UpgradeToManagementCluster"
 
 		// In case of the cluster id a DockerCluster, we should load controller images into the nodes.
 		// Nb. this can be achieved also by changing the DockerMachine spec, but for the time being we are using
@@ -127,7 +127,19 @@ func SelfHostedSpec(ctx context.Context, inputGetter func() SelfHostedSpecInput)
 			LogFolder:               filepath.Join(input.ArtifactFolder, "clusters", cluster.Name),
 		}, input.E2EConfig.GetIntervals(specName, "wait-controllers")...)
 
-		//TODO: refactor in to an helper func e.g. "MoveToSelfHostedAndWait"
+		By("Ensure API servers are stable before doing move")
+		// Nb. This check was introduced to prevent doing move to self-hosted in an aggressive way and thus avoid flakes.
+		// More specifically, we were observing the test failing to get objects from the API server during move, so we
+		// are now testing the API servers are stable before starting move.
+		Consistently(func() error {
+			kubeSystem := &corev1.Namespace{}
+			return input.BootstrapClusterProxy.GetClient().Get(ctx, client.ObjectKey{Name: "kube-system"}, kubeSystem)
+		}, "5s", "100ms").Should(BeNil(), "Failed to assert bootstrap API server stability")
+		Consistently(func() error {
+			kubeSystem := &corev1.Namespace{}
+			return selfHostedClusterProxy.GetClient().Get(ctx, client.ObjectKey{Name: "kube-system"}, kubeSystem)
+		}, "5s", "100ms").Should(BeNil(), "Failed to assert self-hosted API server stability")
+
 		By("Moving the cluster to self hosted")
 		clusterctl.Move(context.TODO(), clusterctl.MoveInput{
 			LogFolder:            filepath.Join(input.ArtifactFolder, "clusters", "bootstrap"),
@@ -155,7 +167,6 @@ func SelfHostedSpec(ctx context.Context, inputGetter func() SelfHostedSpecInput)
 	})
 
 	AfterEach(func() {
-		//TODO: refactor in to an helper func e.g. "MoveToBootstrapAndWait"
 		if selfHostedNamespace != nil {
 			// Dump all Cluster API related resources to artifacts before pivoting back.
 			framework.DumpAllResources(ctx, framework.DumpAllResourcesInput{
@@ -165,6 +176,19 @@ func SelfHostedSpec(ctx context.Context, inputGetter func() SelfHostedSpecInput)
 			})
 		}
 		if selfHostedCluster != nil {
+			By("Ensure API servers are stable before doing move")
+			// Nb. This check was introduced to prevent doing move back to bootstrap in an aggressive way and thus avoid flakes.
+			// More specifically, we were observing the test failing to get objects from the API server during move, so we
+			// are now testing the API servers are stable before starting move.
+			Consistently(func() error {
+				kubeSystem := &corev1.Namespace{}
+				return input.BootstrapClusterProxy.GetClient().Get(ctx, client.ObjectKey{Name: "kube-system"}, kubeSystem)
+			}, "5s", "100ms").Should(BeNil(), "Failed to assert bootstrap API server stability")
+			Consistently(func() error {
+				kubeSystem := &corev1.Namespace{}
+				return selfHostedClusterProxy.GetClient().Get(ctx, client.ObjectKey{Name: "kube-system"}, kubeSystem)
+			}, "5s", "100ms").Should(BeNil(), "Failed to assert self-hosted API server stability")
+
 			By("Moving the cluster back to bootstrap")
 			clusterctl.Move(ctx, clusterctl.MoveInput{
 				LogFolder:            filepath.Join(input.ArtifactFolder, "clusters", cluster.Name),
diff --git a/test/infrastructure/docker/go.mod b/test/infrastructure/docker/go.mod
index a66fbe6a0..11a373b0d 100644
--- a/test/infrastructure/docker/go.mod
+++ b/test/infrastructure/docker/go.mod
@@ -11,7 +11,7 @@ require (
 	k8s.io/client-go v0.17.9
 	k8s.io/klog v1.0.0
 	sigs.k8s.io/cluster-api v0.3.3
-	sigs.k8s.io/controller-runtime v0.5.11
+	sigs.k8s.io/controller-runtime v0.5.10
 	sigs.k8s.io/kind v0.7.1-0.20200303021537-981bd80d3802
 	sigs.k8s.io/yaml v1.2.0
 )
diff --git a/test/infrastructure/docker/go.sum b/test/infrastructure/docker/go.sum
index b7f71f5d6..f9f0da050 100644
--- a/test/infrastructure/docker/go.sum
+++ b/test/infrastructure/docker/go.sum
@@ -582,19 +582,23 @@ gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81
 honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
+k8s.io/api v0.17.8 h1:8JHlbqJ3A6sGhoacXfu/sASSD+HWWqVq67qt9lyB0kU=
+k8s.io/api v0.17.8/go.mod h1:N++Llhs8kCixMUoCaXXAyMMPbo8dDVnh+IQ36xZV2/0=
 k8s.io/api v0.17.9 h1:BA/U8qtSNzx7BbmQy3lODbCxVMKGNUpBJ2fjsKt6OOY=
 k8s.io/api v0.17.9/go.mod h1:avJJAA1fSV6tnbCGW2K+S+ilDFW7WpNr5BScoiZ1M1U=
 k8s.io/apiextensions-apiserver v0.17.9 h1:GWtUr9LErCZBV7QEUIF7wiICPG6wzPukFRrwDv/AIdM=
 k8s.io/apiextensions-apiserver v0.17.9/go.mod h1:p2C9cDflVAUPMl5/QOMHxnSzQWF/cDqu7AP2KUXHHMA=
 k8s.io/apimachinery v0.17.0/go.mod h1:b9qmWdKlLuU9EBh+06BtLcSf/Mu89rWL33naRxs1uZg=
+k8s.io/apimachinery v0.17.8 h1:zXvd8rYMAjRJXpILP9tdAiUnFIENM9EmHuE81apIoms=
+k8s.io/apimachinery v0.17.8/go.mod h1:Lg8zZ5iC/O8UjCqW6DNhcQG2m4TdjF9kwG3891OWbbA=
 k8s.io/apimachinery v0.17.9 h1:knQxNgMu57Oxlm12J6DS375kmGMeuWV0VNzRRUBB2Yk=
 k8s.io/apimachinery v0.17.9/go.mod h1:Lg8zZ5iC/O8UjCqW6DNhcQG2m4TdjF9kwG3891OWbbA=
 k8s.io/apiserver v0.17.9 h1:q50QEJ51xdHy2Gl1lo9yJexiyixxof/yDUFdWNnZxh0=
 k8s.io/apiserver v0.17.9/go.mod h1:Qaxd3EbeoPRBHVMtFyuKNAObqP6VAkzIMyWYz8KuE2k=
 k8s.io/client-go v0.17.9 h1:qUPhohX4bUBx0L7pfye02aPnu3PQ0t+B8dqHfGvt++k=
 k8s.io/client-go v0.17.9/go.mod h1:3cM92qAd1XknA5IRkRfpJhl9OQjkYy97ZEUio70wVnI=
-k8s.io/cluster-bootstrap v0.17.9 h1:IH/MwGor5/7bwHClz0PO/8pKq+SU1eSB1rs645pGu8Y=
-k8s.io/cluster-bootstrap v0.17.9/go.mod h1:Q6nXn/sqVfMvT1VIJVPxFboYAoqH06PCjZnaYzbpZC0=
+k8s.io/cluster-bootstrap v0.17.8 h1:qee9dmkOVwngBf98zbwrij1s898EZ2aHg+ymXw1UBLU=
+k8s.io/cluster-bootstrap v0.17.8/go.mod h1:SC9J2Lt/MBOkxcCB04+5mYULLfDQL5kdM0BjtKaVCVU=
 k8s.io/code-generator v0.17.9/go.mod h1:iiHz51+oTx+Z9D0vB3CH3O4HDDPWrvZyUgUYaIE9h9M=
 k8s.io/component-base v0.17.9/go.mod h1:Wg22ePDK0mfTa+bEFgZHGwr0h40lXnYy6D7D+f7itFk=
 k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
@@ -617,8 +621,8 @@ modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
 modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
 modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
 modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
-sigs.k8s.io/controller-runtime v0.5.11 h1:U/FjGJ61aR2T2mCrdlBCxEcWgLEwLmK6YZKf0NC0a24=
-sigs.k8s.io/controller-runtime v0.5.11/go.mod h1:OTqxLuz7gVcrq+BHGUgedRu6b2VIKCEc7Pu4Jbwui0A=
+sigs.k8s.io/controller-runtime v0.5.10 h1:IJ2zO+BeNvTJEo2W1Kho1+X756QroQjYCKIzEYYqsI8=
+sigs.k8s.io/controller-runtime v0.5.10/go.mod h1:OTqxLuz7gVcrq+BHGUgedRu6b2VIKCEc7Pu4Jbwui0A=
 sigs.k8s.io/kind v0.7.1-0.20200303021537-981bd80d3802 h1:L6/8hETA7jvdx3xBcbDifrIN2xaYHE7tA58n+Kdp2Zw=
 sigs.k8s.io/kind v0.7.1-0.20200303021537-981bd80d3802/go.mod h1:HIZ3PWUezpklcjkqpFbnYOqaqsAE1JeCTEwkgvPLXjk=
 sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
diff --git a/util/util_test.go b/util/util_test.go
index b84c6679b..b75618d8a 100644
--- a/util/util_test.go
+++ b/util/util_test.go
@@ -255,26 +255,6 @@ func TestHasOwner(t *testing.T) {
 			},
 			expected: true,
 		},
-		{
-			name: "owned by cluster from older version",
-			refList: []metav1.OwnerReference{
-				{
-					Kind:       "Cluster",
-					APIVersion: "cluster.x-k8s.io/v1alpha2",
-				},
-			},
-			expected: true,
-		},
-		{
-			name: "owned by a MachineDeployment from older version",
-			refList: []metav1.OwnerReference{
-				{
-					Kind:       "MachineDeployment",
-					APIVersion: "cluster.x-k8s.io/v1alpha2",
-				},
-			},
-			expected: true,
-		},
 		{
 			name: "owned by something else",
 			refList: []metav1.OwnerReference{