diff --git a/docs/book/provider_implementations/building_running_and_testing.md b/docs/book/provider_implementations/building_running_and_testing.md index 47bc0ef5cf8c..011ed944039a 100644 --- a/docs/book/provider_implementations/building_running_and_testing.md +++ b/docs/book/provider_implementations/building_running_and_testing.md @@ -1,60 +1,25 @@ -# Building - -## Fixup Makefile to include common Cluster API CRDs - -Apply the following patch: - -```bash -diff --git a/Makefile b/Makefile -index ac12c7e..cf44312 100644 ---- a/Makefile -+++ b/Makefile -@@ -22,12 +22,15 @@ install: manifests - - # Deploy controller in the configured Kubernetes cluster in ~/.kube/config - deploy: manifests -- kubectl apply -f config/crds -- kustomize build config/default | kubectl apply -f - -+ cat provider-components.yaml | kubectl apply -f - - - # Generate manifests e.g. CRD, RBAC etc. - manifests: - go run vendor/sigs.k8s.io/controller-tools/cmd/controller-gen/main.go all -+ sed -i'' -e 's@^- manager_auth_proxy_patch.yaml.*@#&@' config/default/kustomization.yaml -+ kustomize build config/default/ > provider-components.yaml -+ echo "---" >> provider-components.yaml -+ kustomize build vendor/sigs.k8s.io/cluster-api/config/default/ >> provider-components.yaml - - # Run go fmt against code - fmt: -``` - -## Build and push images - -Determine a location to upload your container and then build and push it: - -```bash -export IMG=/cluster-api-provider-solas -dep ensure -make -make docker-build IMG=${IMG} -make docker-push IMG=${IMG} -``` - -## Start minikube and deploy the provider - -```bash -minikube start -make deploy -``` - -## Verify deployment - -**TODO**: Should deploy a sample `Cluster` and `Machine` resource to verify -controllers are reconciling properly. This is troublesome however since before -the actuator stubs are filled in, all we will see are messages to the effect of -"TODO: Not yet implemented"..." - -```bash -kubectl logs cluster-api-provider-solas-controller-manager-0 -n cluster-api-provider-solas-system -``` +# Building, Running, Testing + +## Docker Image Name + +The patch in `config/default/manager_image_patch.yaml` will be applied to the manager pod. +Right now there is a placeholder `IMAGE_URL`, which you will need to change to your actual image. + +{% hint style="info" %} +Development Images: It's likely that you will want one location and tag for release development, and another during development. + +The approach most Cluster API projects is using [a `Makefile` that uses `sed` to replace the image URL][sed] on demand during development. +[sed]: https://github.com/kubernetes-sigs/cluster-api/blob/e0fb83a839b2755b14fbefbe6f93db9a58c76952/Makefile#L201-L204 +{% endhint %} + +## Deployment + +Before you can deploy the infrastructure controller, you'll need to deploy Cluster API itself. + +You can clone `cluster-api` for the latest version, or just [use a precompiled manifest][install]. + +[install]: https://cluster-api.sigs.k8s.io/tasks/installation.html#install-cluster-api + + + + diff --git a/docs/book/provider_implementations/configure_and_deploy.md b/docs/book/provider_implementations/configure_and_deploy.md new file mode 100644 index 000000000000..d8ebaacc58f5 --- /dev/null +++ b/docs/book/provider_implementations/configure_and_deploy.md @@ -0,0 +1,122 @@ +# Configure and Deploy + +## YAML + +`kubebuilder` generates most of the YAML you'll need to deploy a container. +We just need to modify it to add our new secrets. + +First, let's add our secret as a [patch] to the manager yaml. + +`config/default/manager_config.yaml`: + +```yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + env: + - name: MAILGUN_API_KEY + valueFrom: + secretKeyRef: + name: mailgun-secret + key: api_key + - name: MAILGUN_DOMAIN + valueFrom: + configMapKeyRef: + name: mailgun-config + key: mailgun_domain + - name: MAIL_RECIPIENT + valueFrom: + configMapKeyRef: + name: mailgun-config + key: mail_recipient +``` + +And then, we have to add that patch to [`config/default/kustomization.yaml`][kustomizeyaml]: + +```yaml +patchesStrategicMerge +- manager_image_patch.yaml +# Protect the /metrics endpoint by putting it behind auth. +# Only one of manager_auth_proxy_patch.yaml and +# manager_prometheus_metrics_patch.yaml should be enabled. +- manager_auth_proxy_patch.yaml +# If you want your controller-manager to expose the /metrics +# endpoint w/o any authn/z, uncomment the following line and +# comment manager_auth_proxy_patch.yaml. +# Only one of manager_auth_proxy_patch.yaml and +# manager_prometheus_metrics_patch.yaml should be enabled. +- manager_config.yaml +``` + +[kustomizeyaml]: https://github.com/kubernetes-sigs/kustomize/blob/master/docs/glossary.md#kustomization +[patch]: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/strategic-merge-patch.md + +## Our configuration + +There's many ways to manage configuration in production. +The convention many Cluster-API projects use is enviroment variables. + +`config/manager/configuration.yaml` + +```yaml +--- +apiVersion: v1 +kind: Secret +metadata: + name: mailgun-config + namespace: system +type: Opaque +stringData: + api_key: ${MAILGUN_API_KEY} +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: mailgun-config + namespace: system +data: + mailgun_domain: ${MAILGUN_DOMAIN} + mail_recipient: ${MAILGUN_RECIPIENT} +``` + +And add this to `config/manager/kustomization.yaml` + +```yaml +resources: +- manager.yaml +- credentials.yaml +``` + +You can now (hopefully) generate your yaml! + +``` +kustomize build config/default +``` + +## EnvSubst + +{% hint style="info" %} +A tool like [direnv](https://direnv.net/) can be used to help manage enviroment variables. +{% endhint %} + + +`kustomize` does not handle replacing those `${VARIABLES}` with actual values. +For that, we use [`envsubst`][envsubst]. + +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. + +Then we call envsubst in line, like so: + +``` +kustomize build config/default | envsubst +``` + +[envsubst]: https://linux.die.net/man/1/envsubst + diff --git a/docs/book/provider_implementations/create_api.md b/docs/book/provider_implementations/create_api.md index 8bee4dad6167..b32ea2b4557a 100644 --- a/docs/book/provider_implementations/create_api.md +++ b/docs/book/provider_implementations/create_api.md @@ -64,7 +64,7 @@ type MailgunClusterStatus struct { } ``` -As the deleted comments request, rune `make` to regenerate some of the generated data files afterwards. +As the deleted comments request, run `make manager manifests` to regenerate some of the generated data files afterwards. ```bash git add . diff --git a/docs/book/provider_implementations/populate_controllers.md b/docs/book/provider_implementations/populate_controllers.md index 199f7a89383c..141643257856 100644 --- a/docs/book/provider_implementations/populate_controllers.md +++ b/docs/book/provider_implementations/populate_controllers.md @@ -101,6 +101,21 @@ if err != nil { } ``` +{% hint style="warning" %} +*client-go versions* +At the time this document was written, `kubebuilder` pulls `client-go` version `1.14.1` into `go.mod` (it looks like `k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible`). + +If you encounter an error when compiling like: + +``` +../pkg/mod/k8s.io/client-go@v11.0.1-0.20190409021438-1a26190bd76a+incompatible/rest/request.go:598:31: not enough arguments in call to watch.NewStreamWatcher + have (*versioned.Decoder) + want (watch.Decoder, watch.Reporter)` +``` + +You may need to bump `client-go`. At time of writing, that means `1.15`, which looks like: `k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible`. +{% endhint %} + ## The fun part {% hint style="info" %} @@ -141,7 +156,7 @@ if mgCluster.Status.MessageID != nil { } subject := fmt.Sprintf("[%s] New Cluster %s requested", mgCluster.Spec.Priority, cluster.Name) -body := fmt.Sprint("Hello! One cluster please.\n\n%s\n", mgCluster.Spec.Request) +body := fmt.Sprintf("Hello! One cluster please.\n\n%s\n", mgCluster.Spec.Request) msg := mailgun.NewMessage(mgCluster.Spec.Requester, subject, body, r.Recipient) _, msgID, err := r.Mailgun.Send(msg) @@ -157,3 +172,57 @@ r.Update(ctx, &mgCluster) [cluster]: https://godoc.org/sigs.k8s.io/cluster-api/api/v1alpha3#Cluster [getowner]: https://godoc.org/sigs.k8s.io/cluster-api/util#GetOwnerMachine [idempotent]: https://stackoverflow.com/questions/1077412/what-is-an-idempotent-operation + +## Update `main.go` with your new fields + +If you added fields to your reconciler, you'll need to update `main.go`. + +Right now, it probably looks like this: + +```go +if err = (&controllers.MailgunClusterReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("MailgunCluster"), +}).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "MailgunCluster") + os.Exit(1) +} +``` + +Let's add our configuration. +We're going to use environment variables for this: + +```go +domain := os.Getenv("MAILGUN_DOMAIN") +if domain == "" { + setupLog.Info("missing required env MAILGUN_DOMAIN") + os.Exit(1) +} + +apiKey := os.Getenv("MAILGUN_API_KEY") +if apiKey == "" { + setupLog.Info("missing required env MAILGUN_API_KEY") + os.Exit(1) +} + +recipient := os.Getenv("MAIL_RECIPIENT") +if recipient == "" { + setupLog.Info("missing required env MAIL_RECIPIENT") + os.Exit(1) +} + +mg := mailgun.NewMailgun(domain, apiKey) + +if err = (&controllers.MailgunClusterReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("MailgunCluster"), + Mailgun: mg, + Recipient: recipient, +}).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "MailgunCluster") + os.Exit(1) +} +``` + +If you have some other state, you'll want to initialize it here! +