Skip to content

Commit

Permalink
Fix webhook debug
Browse files Browse the repository at this point in the history
  • Loading branch information
Gabriel Saratura committed May 27, 2024
1 parent 2c2bef2 commit 30af07f
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 30 deletions.
33 changes: 22 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,27 +39,38 @@ See all targets with `make help`
### QuickStart Demonstration

1. Get an API token exoscale.com
1. `export EXOSCALE_API_KEY=<the-key>`
1. `export EXOSCALE_API_SECRET=<the-secret>`
1. `make local-install`
2. `export EXOSCALE_API_KEY=<the-key>`
3. `export EXOSCALE_API_SECRET=<the-secret>`
4. `make local-install`

### Kubernetes Webhook Troubleshooting

The provider comes with mutating and validation admission webhook server.

To test and troubleshoot the webhooks on the cluster, simply apply your changes with `kubectl`.
1. `make local-debug`

1. To debug the webhook in an IDE, we need to generate certificates:
2. Set the right host ip:
```bash
make webhook-cert
HOSTIP=$(docker inspect kindev-control-plane | jq '.[0].NetworkSettings.Networks.kind.Gateway') # On kind MacOS/Windows
HOSTIP=host.docker.internal # On Docker Desktop distributions
HOSTIP=host.lima.internal # On Lima backed Docker distributions
For Linux users: `ip -4 addr show dev docker0 | grep inet | awk -F' ' '{print $2}' | awk -F'/' '{print $1}'`
```
2. Start the operator in your IDE with `WEBHOOK_TLS_CERT_DIR` environment set to `.kind`.

3. Send an admission request sample of the spec:

3. Get an Exoscale API secret and key and create the following secret:
```bash
EXOSCALE_API_KEY=<your api key>
EXOSCALE_API_SECRET=<your api secret>
kubectl -n crossplane-system create secret generic api-secret-1 --from-literal=EXOSCALE_API_KEY="$EXOSCALE_API_KEY" --from-literal=EXOSCALE_API_SECRET="$EXOSCALE_API_SECRET"
```
4. Run the debug target:
```bash
# send an admission request
curl -k -v -H "Content-Type: application/json" --data @samples/admission.k8s.io_admissionreview.json https://localhost:9443/validate-exoscale-crossplane-io-v1-iamkey
make webhook-debug -e webhook_service_name=$HOSTIP
```
5. Run the operator from IDE in debug mode with env variable:
```bash
WEBHOOK_TLS_CERT_DIR=.kind # or full path if does not work
```

### Crossplane Provider Mechanics

Expand Down
1 change: 0 additions & 1 deletion generate_sample.go
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,6 @@ func newKafkaSample() *exoscalev1.Kafka {
},
IPFilter: exoscalev1.IPFilter{"0.0.0.0/0"},
},
Version: "3.2",
KafkaSettings: runtime.RawExtension{Raw: []byte(`{"connections_max_idle_ms": 60000}`)},
},
},
Expand Down
2 changes: 1 addition & 1 deletion operator/kafkacontroller/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ func (v *Validator) validateCreateWithExoClient(ctx context.Context, obj runtime

err = v.validateVersion(ctx, obj, *availableVersions)
if err != nil {
return err
return fmt.Errorf("invalid version, allowed versions are %v: %w", *availableVersions, err)
}
}

Expand Down
8 changes: 4 additions & 4 deletions package/package.mk
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ $(up_bin):export VERSION=v0.30.0
$(up_bin): | $(go_bin)
curl -sL "https://cli.upbound.io" | sh
@mv up $@
$(up_bin) --version
$(up_bin) version

.PHONY: package
package: ## All-in-one packaging and releasing
Expand All @@ -28,7 +28,7 @@ package-provider-local: export CONTROLLER_IMG = $(CONTAINER_IMG)
package-provider-local: $(crossplane_bin) generate-go ## Build Crossplane package for local installation in kind-cluster
@rm -rf package/*.xpkg
@yq e '.spec.controller.image=strenv(CONTROLLER_IMG)' $(package_dir)/crossplane.yaml.template > $(package_dir)/crossplane.yaml
@$(crossplane_bin) build provider -f $(package_dir)
@$(crossplane_bin) xpkg build -f $(package_dir)
@echo Package file: $$(ls $(package_dir)/*.xpkg)

.PHONY: package-provider
Expand All @@ -41,12 +41,12 @@ package-provider: $(up_bin) generate-go build-docker ## Build Crossplane package
.PHONY: .local-package-push
.local-package-push: pkg_file = $(shell ls $(package_dir)/*.xpkg)
.local-package-push: $(crossplane_bin) package-provider-local
$(crossplane_bin) push provider -f $(pkg_file) $(LOCAL_PACKAGE_IMG)
$(crossplane_bin) xpkg push -f $(pkg_file) $(LOCAL_PACKAGE_IMG)

.PHONY: .ghcr-package-push
.ghcr-package-push: pkg_file = $(package_dir)/provider-exoscale.xpkg
.ghcr-package-push: $(crossplane_bin) package-provider
$(crossplane_bin) push provider -f $(pkg_file) $(GHCR_PACKAGE_IMG)
$(crossplane_bin) xpkg push -f $(pkg_file) $(GHCR_PACKAGE_IMG)

.PHONY: .upbound-package-push
.upbound-package-push: pkg_file = $(package_dir)/provider-exoscale.xpkg
Expand Down
56 changes: 43 additions & 13 deletions test/local.mk
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@ registry_sentinel = $(kind_dir)/registry_sentinel
local-install: export KUBECONFIG = $(KIND_KUBECONFIG)
# for ControllerConfig:
local-install: export INTERNAL_PACKAGE_IMG = registry.registry-system.svc.cluster.local:5000/$(PROJECT_OWNER)/$(PROJECT_NAME)/package:$(IMG_TAG)
local-install: kind-load-image crossplane-setup registry-setup .local-package-push ## Install Operator in local cluster
local-install: local-debug ## Install Operator in local cluster
yq e '.spec.metadata.annotations."local.dev/installed"="$(shell date)"' test/controllerconfig-exoscale.yaml | kubectl apply -f -
yq e '.spec.package=strenv(INTERNAL_PACKAGE_IMG)' test/provider-exoscale.yaml | kubectl apply -f -
kubectl wait --for condition=Healthy provider.pkg.crossplane.io/provider-exoscale --timeout 60s
kubectl -n crossplane-system wait --for condition=Ready $$(kubectl -n crossplane-system get pods -o name -l pkg.crossplane.io/provider=provider-exoscale) --timeout 60s

.PHONY: local-debug
local-debug: export KUBECONFIG = $(KIND_KUBECONFIG)
local-debug: kind-load-image crossplane-setup registry-setup .local-package-push ## Install Operator in local cluster

.PHONY: crossplane-setup
crossplane-setup: $(crossplane_sentinel) ## Installs Crossplane in kind cluster.

Expand Down Expand Up @@ -95,18 +99,6 @@ webhook_key = $(kind_dir)/tls.key
webhook_cert = $(kind_dir)/tls.crt
webhook_service_name = provider-exocale.crossplane-system.svc

# Generate webhook certificates.
# This is only relevant when running in IDE with debugger.
# When installed as a provider, Crossplane handles the certificate generation.
.PHONY: webhook-cert
webhook-cert: $(webhook_cert) ## Generate webhook certificates for out-of-cluster debugging in an IDE

$(webhook_key):
openssl req -x509 -newkey rsa:4096 -nodes -keyout $@ --noout -days 3650 -subj "/CN=$(webhook_service_name)" -addext "subjectAltName = DNS:$(webhook_service_name)"

$(webhook_cert): $(webhook_key)
openssl req -x509 -key $(webhook_key) -nodes -out $@ -days 3650 -subj "/CN=$(webhook_service_name)" -addext "subjectAltName = DNS:$(webhook_service_name)"

###
### E2E Tests
### with KUTTL (https://kuttl.dev)
Expand Down Expand Up @@ -148,3 +140,41 @@ run-single-e2e: $(kuttl_bin) $(mc_bin) local-install provider-config ## Run spec
echo "no kubeconfig found"; \
fi
rm -f $(kuttl_bin) $(mc_bin)

.PHONY: webhook-debug
webhook_service_name = host.docker.internal

webhook-debug: export KUBECONFIG = $(KIND_KUBECONFIG)
webhook-debug: $(webhook_cert) ## Creates certificates, patches the webhook registrations and applies everything to the given kube cluster
webhook-debug:
kubectl apply -f package/crds/
kubectl apply -f package/webhook/manifests.yaml
kubectl apply -f samples/exoscale.crossplane.io_providerconfig.yaml
kubectl apply -f samples/lab-provider-keys-exo.yaml
cabundle=$$(cat $(kind_dir)/tls.crt | base64) && \
kubectl annotate validatingwebhookconfigurations.admissionregistration.k8s.io validating-webhook-configuration kubectl.kubernetes.io/last-applied-configuration- && \
kubectl annotate validatingwebhookconfigurations.admissionregistration.k8s.io validating-webhook-configuration cert-manager.io/inject-ca-from- && \
kubectl get validatingwebhookconfigurations.admissionregistration.k8s.io validating-webhook-configuration -oyaml | \
yq e "with(.webhooks[]; .clientConfig.caBundle = \"$$cabundle\") | with(.webhooks[]; .clientConfig.url = \"https://$(webhook_service_name):9443\" + .clientConfig.service.path) | with(.webhooks[]; del(.clientConfig.service))" | \
kubectl replace -f - && \
kubectl annotate validatingwebhookconfigurations.admissionregistration.k8s.io validating-webhook-configuration kubectl.kubernetes.io/last-applied-configuration-

# Generate webhook certificates.
# This is only relevant when debugging.
# Component-appcat installs a proper certificate for this.
.PHONY: webhook-cert
webhook-cert: $(webhook_cert) ## Generate webhook certificates for out-of-cluster debugging in an IDE

$(webhook_key):
ipsan="" && \
if [[ $(webhook_service_name) =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$$ ]]; then \
ipsan=", IP:$(webhook_service_name)"; \
fi; \
openssl req -x509 -newkey rsa:4096 -nodes -keyout $@ --noout -days 3650 -subj "/CN=$(webhook_service_name)" -addext "subjectAltName = DNS:$(webhook_service_name)$$ipsan"

$(webhook_cert): $(webhook_key)
ipsan="" && \
if [[ $(webhook_service_name) =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$$ ]]; then \
ipsan=", IP:$(webhook_service_name)"; \
fi; \
openssl req -x509 -key $(webhook_key) -nodes -out $@ -days 3650 -subj "/CN=$(webhook_service_name)" -addext "subjectAltName = DNS:$(webhook_service_name)$$ipsan"

0 comments on commit 30af07f

Please sign in to comment.