Skip to content

Commit 5b8711d

Browse files
committed
docs/tilt: Collection of fixes and improvements for provider implementer's guide and Tilt workflow
1 parent 2c2a1f1 commit 5b8711d

File tree

10 files changed

+126
-87
lines changed

10 files changed

+126
-87
lines changed

Tiltfile

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,20 +192,27 @@ tilt_helper_dockerfile_header = """
192192
FROM golang:1.18.3 as tilt-helper
193193
# Support live reloading with Tilt
194194
RUN go install github.com/go-delve/delve/cmd/dlv@latest
195-
RUN wget --output-document /restart.sh --quiet https://raw.githubusercontent.com/windmilleng/rerun-process-wrapper/master/restart.sh && \
196-
wget --output-document /start.sh --quiet https://raw.githubusercontent.com/windmilleng/rerun-process-wrapper/master/start.sh && \
197-
chmod +x /start.sh && chmod +x /restart.sh && chmod +x /go/bin/dlv
195+
RUN wget --output-document /restart.sh --quiet https://raw.githubusercontent.com/tilt-dev/rerun-process-wrapper/master/restart.sh && \
196+
wget --output-document /start.sh --quiet https://raw.githubusercontent.com/tilt-dev/rerun-process-wrapper/master/start.sh && \
197+
chmod +x /start.sh && chmod +x /restart.sh && chmod +x /go/bin/dlv && \
198+
touch /process.txt && chmod 0777 /process.txt `# pre-create PID file to allow even non-root users to run the image`
198199
"""
199200

200201
tilt_dockerfile_header = """
201202
FROM gcr.io/distroless/base:debug as tilt
202203
WORKDIR /
204+
COPY --from=tilt-helper /process.txt .
203205
COPY --from=tilt-helper /start.sh .
204206
COPY --from=tilt-helper /restart.sh .
205207
COPY --from=tilt-helper /go/bin/dlv .
206208
COPY $binary_name .
207209
"""
208210

211+
tilt_dockerfile_footer = """
212+
# Use same USER instruction as in kubebuilder-generated Dockerfile
213+
USER 65532:65532
214+
"""
215+
209216
def build_go_binary(context, reload_deps, debug, go_main, binary_name, label):
210217
# Set up a local_resource build of a go binary. The target repo is expected to have a main.go in
211218
# the context path or the main.go must be provided via go_main option. The binary is written to .tiltbuild/bin/{$binary_name}.
@@ -268,6 +275,7 @@ def build_docker_image(image, context, binary_name, additional_docker_build_comm
268275
additional_docker_helper_commands,
269276
tilt_dockerfile_header,
270277
additional_docker_build_commands,
278+
tilt_dockerfile_footer,
271279
])
272280

273281
# Set up an image build for the provider. The live update configuration syncs the output from the local_resource

docs/book/src/developer/providers/contracts.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,17 @@ Each value MUST point to an available version in your CRD Spec.
2020
The label allows Cluster API controllers to perform automatic conversions for object references, the controllers will pick the last available version in the list if multiple versions are found.
2121
To apply the label to CRDs it’s possible to use commonLabels in your kustomize.yaml file, usually in config/crd.
2222

23-
In this example we show how to map a particular Cluster API contract version to your own CRD using Kustomize’s commonLabels feature:
23+
In this example we show how to map a particular Cluster API contract version to your own CRD using Kustomize’s `commonLabels` feature, in your `config/crd/kustomization.yaml`:
2424

2525
```yaml
2626
commonLabels:
27-
cluster.x-k8s.io/v1alpha2: v1alpha1
28-
cluster.x-k8s.io/v1alpha3: v1alpha2
29-
cluster.x-k8s.io/v1beta1: v1beta1
27+
cluster.x-k8s.io/v1alpha2: v1alpha1
28+
cluster.x-k8s.io/v1alpha3: v1alpha2
29+
cluster.x-k8s.io/v1beta1: v1beta1
3030
```
3131
3232
An example of this is in the [Kubeadm Bootstrap provider](https://github.com/kubernetes-sigs/cluster-api/blob/release-1.1/controlplane/kubeadm/config/crd/kustomization.yaml).
3333
3434
## Improving and contributing to the contract
3535
36-
The definition of the contract between Cluster API and providers may be changed in future versions of Cluster API. The Cluster API maintainers welcome feedback and contributions to the contract in order to improve how it's defined, its clarity and visibility to provider implementers and its suitability across the different kinds of Cluster API providers. To provide feedback or open a discussion about the provider contract please [open an issue on the Cluster API](https://github.com/kubernetes-sigs/cluster-api/issues/new?assignees=&labels=&template=feature_request.md) repo or add an item to the agenda in the [Cluster API community meeting](http://git.k8s.io/community/sig-cluster-lifecycle/README.md#cluster-api).
36+
The definition of the contract between Cluster API and providers may be changed in future versions of Cluster API. The Cluster API maintainers welcome feedback and contributions to the contract in order to improve how it's defined, its clarity and visibility to provider implementers and its suitability across the different kinds of Cluster API providers. To provide feedback or open a discussion about the provider contract please [open an issue on the Cluster API](https://github.com/kubernetes-sigs/cluster-api/issues/new?assignees=&labels=&template=feature_request.md) repo or add an item to the agenda in the [Cluster API community meeting](http://git.k8s.io/community/sig-cluster-lifecycle/README.md#cluster-api).

docs/book/src/developer/providers/implementers-guide/building_running_and_testing.md

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,17 @@ kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/
2828

2929
### Cluster API
3030

31-
Before you can deploy the infrastructure controller, you'll need to deploy Cluster API itself.
31+
Before you can deploy the infrastructure controller, you'll need to deploy Cluster API itself to the management cluster.
3232

33-
You can use a precompiled manifest from the release page, or clone [`cluster-api`][capi] and apply its manifests using `kustomize`.
33+
You can use a precompiled manifest from the [release page][releases], run `clusterctl init`, or clone [`cluster-api`][capi] and apply its manifests using `kustomize`:
3434

3535
```bash
3636
cd cluster-api
37-
kustomize build config/ | kubectl apply -f-
37+
make envsubst
38+
kustomize build config/default | ./hack/tools/bin/envsubst | kubectl apply -f -
3839
```
3940

40-
Check the status of the manager to make sure it's running properly
41+
Check the status of the manager to make sure it's running properly:
4142

4243
```bash
4344
kubectl describe -n capi-system pod | grep -A 5 Conditions
@@ -52,17 +53,29 @@ Conditions:
5253
```
5354

5455
[capi]: https://github.com/kubernetes-sigs/cluster-api
56+
[releases]: https://github.com/kubernetes-sigs/cluster-api/releases
5557

5658
### Your provider
5759

60+
In this guide, we are building an _infrastructure provider_. We must tell cluster-api and its developer tooling which type of provider it is. Edit `config/default/kustomization.yaml` and add the following common label. The prefix `infrastructure-` [is used][label_prefix] to detect the provider type.
61+
62+
```sh
63+
commonLabels:
64+
cluster.x-k8s.io/provider: infrastructure-mailgun
65+
```
66+
5867
Now you can apply your provider as well:
5968

6069
```bash
6170
cd cluster-api-provider-mailgun
62-
kustomize build config/ | envsubst | kubectl apply -f-
71+
72+
# Install CRD and controller to current kubectl context
73+
make install deploy
74+
6375
kubectl describe -n cluster-api-provider-mailgun-system pod | grep -A 5 Conditions
6476
```
65-
```bash
77+
78+
```text
6679
Conditions:
6780
Type Status
6881
Initialized True
@@ -71,32 +84,61 @@ Conditions:
7184
PodScheduled True
7285
```
7386

87+
[label_prefix]: https://github.com/kubernetes-sigs/cluster-api/search?q=%22infrastructure-%22
88+
7489
### Tiltfile
7590
Cluster API development requires a lot of iteration, and the "build, tag, push, update deployment" workflow can be very tedious.
7691
[Tilt](https://tilt.dev) makes this process much simpler by watching for updates, then automatically building and deploying them.
7792

78-
You can visit [some example repositories][capidev], but you can get started by writing out a yaml manifest and using the following [`Tiltfile`][tiltfile]
79-
`kustomize build config/ | envsubst > capm.yaml`
93+
See [Developing Cluster API with Tilt](../../tilt.md) on all details how to develop both Cluster API and your provider at the same time. In short, you need to perform these steps for a basic Tilt-based development environment:
8094

81-
[capidev]: https://github.com/chuckha/capi-dev
82-
[tiltfile]: https://docs.tilt.dev/tiltfile_concepts.html
95+
- Create file `tilt-provider.yaml` in your provider directory:
8396

84-
```starlark
85-
allow_k8s_contexts('kubernetes-admin@kind)
97+
```yaml
98+
name: mailgun
99+
config:
100+
image: controller:latest # change to remote image name if desired
101+
label: CAPM
102+
live_reload_deps: ["main.go", "go.mod", "go.sum", "api", "controllers", "pkg"]
103+
```
86104
87-
k8s_yaml('capm.yaml')
105+
- Create file `tilt-settings.yaml` in the cluster-api directory:
88106

89-
docker_build('<your docker username or repository url>/cluster-api-controller-mailgun-amd64', '.')
107+
```yaml
108+
default_registry: "" # change if you use a remote image registry
109+
provider_repos:
110+
# This refers to your provider directory and loads settings
111+
# from `tilt-provider.yaml`
112+
- ../cluster-api-provider-mailgun
113+
enable_providers:
114+
- mailgun
90115
```
91116
92-
You can then use Tilt to watch the logs coming off your container.
117+
- Create a kind cluster. By default, Tiltfile assumes the kind cluster is named `capi-test`.
118+
119+
```bash
120+
kind create cluster --name capi-test
121+
122+
# If you want a more sophisticated setup of kind cluster + image registry, try:
123+
# ---
124+
# cd cluster-api
125+
# hack/kind-install-for-capd.sh
126+
```
127+
128+
- Run `tilt up` in the cluster-api folder
129+
130+
You can then use Tilt to watch the container logs.
131+
132+
On any changed file in the listed places (`live_reload_deps` and those watched inside cluster-api repo), Tilt will build and deploy again. In the regular case of a changed file, only your controller's binary gets rebuilt, copied into the running container, and the process restarted. This is much faster than a full re-build and re-deployment of a Docker image and restart of the Kubernetes pod.
133+
134+
You best watch the Kubernetes pods with something like `k9s -A` or `watch kubectl get pod -A`. Particularly in case your provider implementation crashes, Tilt has no chance to deploy any code changes into the container since it might be crash-looping indefinitely. In such a case – which you will notice in the log output – terminate Tilt (hit Ctrl+C) and start it again to deploy the Docker image from scratch.
93135

94136
## Your first Cluster
95137

96138
Let's try our cluster out. We'll make some simple YAML:
97139

98140
```yaml
99-
apiVersion: cluster.x-k8s.io/v1alpha2
141+
apiVersion: cluster.x-k8s.io/v1beta1
100142
kind: Cluster
101143
metadata:
102144
name: hello-mailgun
@@ -105,11 +147,11 @@ spec:
105147
pods:
106148
cidrBlocks: ["192.168.0.0/16"]
107149
infrastructureRef:
108-
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
150+
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1
109151
kind: MailgunCluster
110152
name: hello-mailgun
111153
---
112-
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
154+
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1
113155
kind: MailgunCluster
114156
metadata:
115157
name: hello-mailgun

docs/book/src/developer/providers/implementers-guide/configure.md

Lines changed: 16 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -88,63 +88,35 @@ resources:
8888
You can now (hopefully) generate your yaml!
8989

9090
```bash
91-
kustomize build config/
92-
```
93-
94-
## RBAC Role
95-
96-
The default [RBAC role][role] contains permissions for accessing your cluster infrastructure CRDs, but not for accessing Cluster API resources.
97-
You'll need to add these to `config/rbac/role.yaml`
98-
99-
[role]: https://kubernetes.io/docs/reference/access-authn-authz/rbac/
100-
101-
```diff
102-
diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml
103-
index e9352ce..29008db 100644
104-
--- a/config/rbac/role.yaml
105-
+++ b/config/rbac/role.yaml
106-
@@ -6,6 +6,24 @@ metadata:
107-
creationTimestamp: null
108-
name: manager-role
109-
rules:
110-
+- apiGroups:
111-
+ - cluster.x-k8s.io
112-
+ resources:
113-
+ - clusters
114-
+ - clusters/status
115-
+ verbs:
116-
+ - get
117-
+ - list
118-
+ - watch
119-
+- apiGroups:
120-
+ - cluster.x-k8s.io
121-
+ resources:
122-
+ - machines
123-
+ - machines/status
124-
+ verbs:
125-
+ - get
126-
+ - list
127-
+ - watch
128-
- apiGroups:
129-
- infrastructure.cluster.x-k8s.io
130-
resources:
91+
kustomize build config/default
13192
```
13293

13394
## EnvSubst
13495

13596
_A tool like [direnv](https://direnv.net/) can be used to help manage environment variables._
13697

137-
13898
`kustomize` does not handle replacing those `${VARIABLES}` with actual values.
13999
For that, we use [`envsubst`][envsubst].
140100

141101
You'll need to have those environment variables (`MAILGUN_API_KEY`, `MAILGUN_DOMAIN`, `MAILGUN_RECIPIENT`) in your environment when you generate the final yaml file.
142102

143-
Then we call envsubst in line, like so:
103+
Change `Makefile` to include the call to `envsubst`:
104+
105+
```diff
106+
- $(KUSTOMIZE) build config/default | kubectl apply -f -
107+
+ $(KUSTOMIZE) build config/default | envsubst | kubectl apply -f -
108+
```
109+
110+
To generate the manifests, call envsubst in line, like so:
144111

145112
```bash
146-
kustomize build config/ | envsubst
113+
kustomize build config/default | envsubst
147114
```
148115

149-
[envsubst]: https://linux.die.net/man/1/envsubst
116+
Or to build and deploy the CRDs and manifests directly:
117+
118+
```bash
119+
make install deploy
120+
```
150121

122+
[envsubst]: https://github.com/drone/envsubst

docs/book/src/developer/providers/implementers-guide/controllers_and_reconciliation.md

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,25 +39,34 @@ func (r *MailgunClusterReconciler) Reconcile(ctx context.Context, req ctrl.Reque
3939

4040
## RBAC Roles
4141

42-
Those `// +kubebuilder...` lines tell kubebuilder to generate [RBAC] roles so the manager we're writing can access its own managed resources.
43-
We also need to add roles that will let it retrieve (but not modify) Cluster API objects.
44-
So we'll add another annotation for that:
42+
The `// +kubebuilder...` lines tell kubebuilder to generate [RBAC] roles so the manager we're writing can access its own managed resources. These should already exist in `controllers/mailguncluster_controller.go`:
4543

46-
```
44+
```go
4745
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=mailgunclusters,verbs=get;list;watch;create;update;patch;delete
4846
// +kubebuilder:rbac:groups=infrastructure.cluster.x-k8s.io,resources=mailgunclusters/status,verbs=get;update;patch
47+
```
48+
49+
We also need to add rules that will let it retrieve (but not modify) Cluster API objects.
50+
So we'll add another annotation for that, right below the other lines:
51+
52+
```go
4953
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=clusters;clusters/status,verbs=get;list;watch
5054
```
5155

52-
Make sure to add the annotation to both `MailgunClusterReconciler` and `MailgunMachineReconciler`.
56+
Make sure to add this annotation to `MailgunClusterReconciler`.
5357

54-
Regenerate the RBAC roles after you are done:
58+
For `MailgunMachineReconciler`, access to Cluster API `Machine` object is needed, so you must add this annotation in `controllers/mailgunmachine_controller.go`:
5559

60+
```go
61+
// +kubebuilder:rbac:groups=cluster.x-k8s.io,resources=machines;machines/status,verbs=get;list;watch
5662
```
63+
64+
Regenerate the RBAC roles after you are done:
65+
66+
```bash
5767
make manifests
5868
```
5969

60-
6170
[RBAC]: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#role-and-clusterrole
6271

6372
## State
@@ -90,7 +99,7 @@ func (r *MailgunClusterReconciler) Reconcile(ctx context.Context, req ctrl.Reque
9099
ctx := context.Background()
91100
_ = r.Log.WithValues("mailguncluster", req.NamespacedName)
92101
93-
var cluster infrastructurev1alpha3.MailgunCluster
102+
var cluster infrav1.MailgunCluster
94103
if err := r.Get(ctx, req.NamespacedName, &cluster); err != nil {
95104
return ctrl.Result{}, err
96105
}
@@ -103,7 +112,7 @@ By returning an error, we request that our controller will get `Reconcile()` cal
103112
That may not always be what we want - what if the object's been deleted? So let's check that:
104113

105114
```
106-
var cluster infrastructurev1alpha3.MailgunCluster
115+
var cluster infrav1.MailgunCluster
107116
if err := r.Get(ctx, req.NamespacedName, &cluster); err != nil {
108117
// import apierrors "k8s.io/apimachinery/pkg/api/errors"
109118
if apierrors.IsNotFound(err) {
@@ -198,7 +207,7 @@ if err := helper.Patch(ctx, &mgCluster); err != nil {
198207
return ctrl.Result{}, nil
199208
```
200209

201-
[cluster]: https://godoc.org/sigs.k8s.io/cluster-api/api/v1alpha3#Cluster
210+
[cluster]: https://godoc.org/sigs.k8s.io/cluster-api/api/v1beta1#Cluster
202211
[getowner]: https://godoc.org/sigs.k8s.io/cluster-api/util#GetOwnerMachine
203212
[idempotent]: https://stackoverflow.com/questions/1077412/what-is-an-idempotent-operation
204213

docs/book/src/developer/providers/implementers-guide/generate_crds.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ Here you will be asked if you want to generate resources and controllers.
3737
You'll want both of them:
3838

3939
```bash
40-
kubebuilder create api --group infrastructure --version v1alpha3 --kind MailgunCluster
41-
kubebuilder create api --group infrastructure --version v1alpha3 --kind MailgunMachine
40+
kubebuilder create api --group infrastructure --version v1alpha1 --kind MailgunCluster
41+
kubebuilder create api --group infrastructure --version v1alpha1 --kind MailgunMachine
4242
```
4343

4444
```bash
@@ -48,6 +48,8 @@ Create Controller under pkg/controller [y/n]?
4848
y
4949
```
5050

51+
The latest API version of Cluster API and the version of your provider do not need to be in sync. Instead, prefer choosing a version that matches the stability of the provider API and its backward compatibility guarantees.
52+
5153
### Add Status subresource
5254

5355
The [status subresource][status] lets Spec and Status requests for custom resources be addressed separately so requests don't conflict with each other.
@@ -85,7 +87,7 @@ make manifests
8587
8688
The cluster API CRDs should be further customized:
8789
88-
- [Apply the contract version label to support conversions](../contracts.md#api-version-labels)
90+
- [Apply the contract version label to support conversions](../contracts.md#api-version-labels) (required to deploy _any_ custom resource of your provider)
8991
- [Ensure you are compliant with the clusterctl provider contract](../../../clusterctl/provider-contract.md#components-yaml)
9092
9193
### Commit your changes

docs/book/src/developer/providers/implementers-guide/naming.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ identifies it.
4444

4545
For example, our cluster object will be:
4646
```yaml
47-
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3
47+
apiVersion: infrastructure.cluster.x-k8s.io/v1alpha1
4848
kind: MailgunCluster
4949
```
5050

0 commit comments

Comments
 (0)