Repository: kubernetes-sigs/cluster-api
Pull request #3376 (2020-07-22 15:17:14)

📖  Update site home page
**What this PR does / why we need it**: 
This PR updates content on the home page of the cluster api docs site. The goal is to add more context around what cluster api is and why it was built to help new users understand the project better. Additionally, this PR includes some minor adjustments to the home page layout.

**Questions**:
* I have some other suggestions for the Community section on this page, which its included from thee README.md:Community file. Should I add those to this PR?


k8s-ci-robot: Hi @a-mccarthy. Thanks for your PR.

I'm waiting for a [kubernetes-sigs](https://github.com/orgs/kubernetes-sigs/people) member to verify that this patch is reasonable to test. If it is, they should reply with `/ok-to-test` on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should [join the org](https://git.k8s.io/community/community-membership.md#member) to skip this step.

Once the patch is verified, the new status will be reflected by the `ok-to-test` label.

I understand the commands that are listed [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fcluster-api).

<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.
</details>

k8s-ci-robot: Welcome @a-mccarthy! <br><br>It looks like this is your first PR to <a href='https://github.com/kubernetes-sigs/cluster-api'>kubernetes-sigs/cluster-api</a> 🎉. Please refer to our [pull request process documentation](https://git.k8s.io/community/contributors/guide/pull-requests.md) to help your PR have a smooth ride to approval. <br><br>You will be prompted by a bot to use commands during the review process. Do not be afraid to follow the prompts! It is okay to experiment. [Here is the bot commands documentation](https://go.k8s.io/bot-commands). <br><br>You can also check if kubernetes-sigs/cluster-api has [its own contribution guidelines](https://github.com/kubernetes-sigs/cluster-api/tree/master/CONTRIBUTING.md). <br><br>You may want to refer to our [testing guide](https://git.k8s.io/community/contributors/devel/sig-testing/testing.md) if you run into trouble with your tests not passing. <br><br>If you are having difficulty getting your pull request seen, please follow the [recommended escalation practices](https://github.com/kubernetes/community/blob/master/contributors/guide/pull-requests.md#why-is-my-pull-request-not-getting-reviewed). Also, for tips and tricks in the contribution process you may want to read the [Kubernetes contributor cheat sheet](https://git.k8s.io/community/contributors/guide/contributor-cheatsheet/README.md). We want to make sure your contribution gets all the attention it needs! <br><br>Thank you, and welcome to Kubernetes. :smiley:
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 **ncdc**
You can assign the PR to them by writing `/assign @ncdc` 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":["ncdc"]} -->

Patch:
diff --git a/Tiltfile b/Tiltfile
index 03ed46360..edcd38108 100644
--- a/Tiltfile
+++ b/Tiltfile
@@ -190,17 +190,15 @@ def enable_provider(name):
         ],
     )
 
+    # Copy all the substitutions from the user's tilt-settings.json into the environment. Otherwise, the substitutions
+    # are not available and their placeholders will be replaced with the empty string when we call kustomize +
+    # envsubst below.
+    substitutions = settings.get("kustomize_substitutions", {})
+    os.environ.update(substitutions)
+
     # Apply the kustomized yaml for this provider
     yaml = str(kustomize_with_envsubst(context + "/config"))
-    substitutions = settings.get("kustomize_substitutions", {})
-    for substitution in substitutions:
-        value = substitutions[substitution]
-        yaml = yaml.replace("${" + substitution + "}", value)
-
-    if yaml.count("${") == 0:
-        k8s_yaml(blob(yaml))
-    else:
-        fail("unsubstituted fields in the input config, make sure your kustomize_substitutions parameters are complete")
+    k8s_yaml(blob(yaml))
 
 # Prepull all the cert-manager images to your local environment and then load them directly into kind. This speeds up
 # setup if you're repeatedly destroying and recreating your kind cluster, as it doesn't have to pull the images over
diff --git a/docs/book/src/introduction.md b/docs/book/src/introduction.md
index 40e45e713..029d746df 100644
--- a/docs/book/src/introduction.md
+++ b/docs/book/src/introduction.md
@@ -1,16 +1,32 @@
-# The Cluster API Book <div style="float: right; position: relative; display: inline;"><img src="images/introduction.png" width="160px" /></div>
+# The Cluster API project<div style="float: right; position: relative; display: inline;"><img src="images/introduction.png" width="160px" /></div>
 
-**Note:** Impatient readers may head straight to [Quick
-Start](./user/quick-start.md).
+Cluster API is a Kubernetes sub-project focused on providing declarative APIs and tooling to simplify provisioning, upgrading, and operating multiple Kubernetes clusters.
 
-**Using Cluster API v1alpha2? Check the [legacy
-documentation](https://release-0-2.cluster-api.sigs.k8s.io)**
+Started by the Kubernetes Special Interest Group (SIG) Cluster Lifecycle, the Cluster API project uses Kubernetes-style APIs and patterns to automate cluster lifecycle management for platform operators. The supporting infrastructure, like virtual machines, networks, load balancers, and VPCs, as well as the Kubernetes cluster configuration are all defined in the same way that application developers operate deploying and managing their workloads. This enables consistent and repeatable cluster deployments across a wide variety of infrastructure environments.
 
-# What is the Cluster API?
-The Cluster API is a Kubernetes project to bring declarative, Kubernetes-style APIs to cluster creation,
-configuration, and management. It provides optional, additive functionality on top of core Kubernetes to
-manage the lifecycle of a Kubernetes cluster.
+### Getting started
+* [Quick start](./user/quick-start.md)
+* [Concepts](./user/concepts.md)
+* [Developer guide](./developer/guide.md)
+* [Contributing](./CONTRIBUTING.md)
 
+**Using Cluster API v1alpha2?** See the [legacy
+documentation](https://release-0-2.cluster-api.sigs.k8s.io).
+
+
+## Why build Cluster API?
+
+Kubernetes is a complex system that relies on several components being configured correctly to have a working cluster. Recognizing this as a potential stumbling block for users, the community focused on simplifying the bootstrapping process. Today, over [100 Kubernetes distributions and installers](https://www.cncf.io/certification/software-conformance/) have been created, each with different default configurations for clusters and supported infrastructure providers. SIG Cluster Lifecycle saw a need for a single tool to address a set of common overlapping installation concerns and started kubeadm.
+
+[Kubeadm](https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/) was designed as a focused tool for bootstrapping a best-practices Kubernetes cluster. The core tenet behind the kubeadm project was to create a tool that other installers can leverage and ultimately alleviate the amount of configuration that an individual installer needed to maintain. Since it began, kubeadm has become the underlying bootstrapping tool for several other applications, including Kubespray, Minikube, kind, etc.
+
+However, while kubeadm and other bootstrap providers reduce installation complexity, they don't address how to manage a cluster day-to-day or a Kubernetes environment long term. You are still faced with several questions when setting up a production environment, including
+
+* How can I consistently provision machines, load balancers, VPC, etc., across multiple infrastructure providers and locations?
+* How can I automate cluster lifecycle management, including things like upgrades and cluster deletion?
+* How can I scale these processes to manage any number of clusters?
+
+SIG Cluster Lifecycle began the Cluster API project as a way to address these gaps by building declarative, Kubernetes-style APIs, that automate cluster creation, configuration, and management. Using this model, Cluster API can also be extended to support any infrastructure provider (AWS, Azure, vSphere, etc.) or bootstrap provider (kubeadm is default) you need. See the growing list of [available providers](./reference/providers.md).
 
 {{#include ../../scope-and-objectives.md:Goals}}
 
diff --git a/go.mod b/go.mod
index 90342e39e..3f8a47830 100644
--- a/go.mod
+++ b/go.mod
@@ -38,7 +38,7 @@ require (
 	k8s.io/component-base v0.17.8
 	k8s.io/klog v1.0.0
 	k8s.io/utils v0.0.0-20200619165400-6e3d28b6ed19
-	sigs.k8s.io/controller-runtime v0.5.8
+	sigs.k8s.io/controller-runtime v0.5.9
 	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 fad368654..01cf45df9 100644
--- a/go.sum
+++ b/go.sum
@@ -646,8 +646,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.8 h1:+pp4plYh2rpjuVo6HBJ1pVgN3cvAfQHfkKK27rLdxxI=
-sigs.k8s.io/controller-runtime v0.5.8/go.mod h1:UI/unU7Q+mo/rWBrND0NAaVNj/Xjh/+aqSv/M3njpmo=
+sigs.k8s.io/controller-runtime v0.5.9 h1:ccbiT+HK8Eyw252Nv8wZi84iWVOQVDha6NU2w2/yML4=
+sigs.k8s.io/controller-runtime v0.5.9/go.mod h1:UI/unU7Q+mo/rWBrND0NAaVNj/Xjh/+aqSv/M3njpmo=
 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/conditions/patch.go b/util/conditions/patch.go
index c1bbdd5a3..9d4d91771 100644
--- a/util/conditions/patch.go
+++ b/util/conditions/patch.go
@@ -19,6 +19,7 @@ package conditions
 import (
 	"reflect"
 
+	"github.com/google/go-cmp/cmp"
 	"github.com/pkg/errors"
 	clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3"
 )
@@ -128,7 +129,7 @@ func (p Patch) Apply(latest Setter, options ...ApplyOption) error {
 			if latestCondition := Get(latest, conditionPatch.After.Type); latestCondition != nil {
 				// If latest and after agree on the change, then it is a conflict.
 				if !hasSameState(latestCondition, conditionPatch.After) {
-					return errors.Errorf("error patching conditions: The condition %q was modified by a different process and this caused a merge/AddCondition conflict", conditionPatch.After.Type)
+					return errors.Errorf("error patching conditions: The condition %q was modified by a different process and this caused a merge/AddCondition conflict: %v", conditionPatch.After.Type, cmp.Diff(conditionPatch.Before, conditionPatch.After))
 				}
 				// otherwise, the latest is already as intended.
 				// NOTE: We are preserving LastTransitionTime from the latest in order to avoid altering the existing value.
@@ -148,14 +149,14 @@ func (p Patch) Apply(latest Setter, options ...ApplyOption) error {
 
 			// If the condition does not exist anymore on the latest, this is a conflict.
 			if latestCondition == nil {
-				return errors.Errorf("error patching conditions: The condition %q was deleted by a different process and this caused a merge/ChangeCondition conflict", conditionPatch.After.Type)
+				return errors.Errorf("error patching conditions: The condition %q was deleted by a different process and this caused a merge/ChangeCondition conflict: %v", conditionPatch.After.Type, cmp.Diff(conditionPatch.Before, conditionPatch.After))
 			}
 
 			// If the condition on the latest is different from the base condition, check if
 			// the after state corresponds to the desired value. If not this is a conflict (unless we should ignore conflicts for this condition type).
 			if !reflect.DeepEqual(latestCondition, conditionPatch.Before) {
 				if !hasSameState(latestCondition, conditionPatch.After) {
-					return errors.Errorf("error patching conditions: The condition %q was modified by a different process and this caused a merge/ChangeCondition conflict", conditionPatch.After.Type)
+					return errors.Errorf("error patching conditions: The condition %q was modified by a different process and this caused a merge/ChangeCondition conflict: %v", conditionPatch.After.Type, cmp.Diff(conditionPatch.Before, conditionPatch.After))
 				}
 				// Otherwise the latest is already as intended.
 				// NOTE: We are preserving LastTransitionTime from the latest in order to avoid altering the existing value.
@@ -175,7 +176,7 @@ func (p Patch) Apply(latest Setter, options ...ApplyOption) error {
 			// if so then this is a conflict.
 			if latestCondition := Get(latest, conditionPatch.Before.Type); latestCondition != nil {
 				if !hasSameState(latestCondition, conditionPatch.Before) {
-					return errors.Errorf("error patching conditions: The condition %q was modified by a different process and this caused a merge/RemoveCondition conflict", conditionPatch.Before.Type)
+					return errors.Errorf("error patching conditions: The condition %q was modified by a different process and this caused a merge/RemoveCondition conflict: %v", conditionPatch.Before.Type, cmp.Diff(conditionPatch.Before, conditionPatch.After))
 				}
 			}
 			// Otherwise the latest and after agreed on the delete operation, so there's nothing to change.


Test patch:
diff --git a/test/infrastructure/docker/go.mod b/test/infrastructure/docker/go.mod
index 6629755a8..da2d30008 100644
--- a/test/infrastructure/docker/go.mod
+++ b/test/infrastructure/docker/go.mod
@@ -11,7 +11,7 @@ require (
 	k8s.io/client-go v0.17.8
 	k8s.io/klog v1.0.0
 	sigs.k8s.io/cluster-api v0.3.3
-	sigs.k8s.io/controller-runtime v0.5.8
+	sigs.k8s.io/controller-runtime v0.5.9
 	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 0302f10b8..f22396227 100644
--- a/test/infrastructure/docker/go.sum
+++ b/test/infrastructure/docker/go.sum
@@ -606,8 +606,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.8 h1:+pp4plYh2rpjuVo6HBJ1pVgN3cvAfQHfkKK27rLdxxI=
-sigs.k8s.io/controller-runtime v0.5.8/go.mod h1:UI/unU7Q+mo/rWBrND0NAaVNj/Xjh/+aqSv/M3njpmo=
+sigs.k8s.io/controller-runtime v0.5.9 h1:ccbiT+HK8Eyw252Nv8wZi84iWVOQVDha6NU2w2/yML4=
+sigs.k8s.io/controller-runtime v0.5.9/go.mod h1:UI/unU7Q+mo/rWBrND0NAaVNj/Xjh/+aqSv/M3njpmo=
 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=