{"id":18514766,"url":"https://github.com/bentito/clusterextensionhelper","last_synced_at":"2025-04-09T06:34:28.144Z","repository":{"id":260287966,"uuid":"860626385","full_name":"bentito/ClusterExtensionHelper","owner":"bentito","description":null,"archived":false,"fork":false,"pushed_at":"2024-11-22T14:52:55.000Z","size":97,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-24T00:51:34.119Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bentito.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-20T19:50:23.000Z","updated_at":"2025-01-12T18:23:49.000Z","dependencies_parsed_at":"2024-11-22T15:31:12.364Z","dependency_job_id":"6e50c9e0-9d3b-46e3-81f2-a0c25ea087d5","html_url":"https://github.com/bentito/ClusterExtensionHelper","commit_stats":null,"previous_names":["bentito/clusterextensionhelper"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bentito%2FClusterExtensionHelper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bentito%2FClusterExtensionHelper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bentito%2FClusterExtensionHelper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bentito%2FClusterExtensionHelper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bentito","download_url":"https://codeload.github.com/bentito/ClusterExtensionHelper/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247993599,"owners_count":21030043,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-06T15:45:27.211Z","updated_at":"2025-04-09T06:34:23.131Z","avatar_url":"https://github.com/bentito.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Soft ClusterExtension Admission with LLM Integration\n\n## Overview\n\nThis project implements a Kubernetes admission webhook that automatically corrects invalid ClusterExtension Custom Resources (CRs) using a Large Language Model (LLM). When a ClusterExtension CR fails validation against its Custom Resource Definition (CRD), the webhook intercepts the create or update request, leverages an LLM to adjust the CR, and returns a JSON Patch to correct the resource before it's persisted in the cluster.\n\nBy integrating an LLM, this webhook aims to simplify the management of CRs by automatically fixing common errors, reducing the manual effort required to maintain valid configurations.\n\n## Watch the demos\n\nhttps://youtu.be/XLyHyTMrcS4 (OpenAI succeeds at the task)\n\nhttps://youtu.be/EEi7GEAK8v0 (An open source LLM succeeds at the task)\n\n## Prerequisites\n\n- **Podman (or Docker)**: For building and loading container images.\n- **Kind**: To create a local Kubernetes cluster.\n- **kubectl**: For interacting with your Kubernetes cluster.\n- **OpenAI API Key**: Required to interact with the OpenAI API. (for now, this is the LLM)\n\n## Usage\n\nFollow the steps below to build, deploy, and test the admission webhook on a local Kind cluster.\n\n### 1. Set Up Your Environment\n\nEnsure you have the necessary tools installed:\n\n- Install [Podman](https://podman.io/) or [Docker](https://docs.docker.com/get-docker/).\n- Install [Kind](https://kind.sigs.k8s.io/).\n- Install [kubectl](https://kubernetes.io/docs/tasks/tools/).\n\n### 2. Create a Kind Cluster\n\nCreate a local Kubernetes cluster using Kind:\n\n```bash\nkind create cluster\n```\n\n### 3. Export Your OpenAI API Key\n\nSet the `OPENAI_API_KEY` environment variable with your actual OpenAI API key:\n\n```bash\nexport OPENAI_API_KEY=your_actual_openai_api_key\n```\n\n\u003e **Note**: Replace `your_actual_openai_api_key` with your actual OpenAI API key. Keep this key secure and do not share it or commit it to version control.\n\n### 3.1 Alternative: Using Your Own LLM\n\nAlternatively, you can configure the webhook to use your own LLM that supports the completions API by setting the `LOCAL_LLM_URL` environment variable. This setup requires an alternate deployment configuration. Instead of using the default OpenAI deployment configuration (`config/deployment.yaml`), switch to `config/deployment-llm.yaml`.\n\n```bash\nexport LOCAL_LLM_URL=http://your-llm-instance/api\n```\n\nThis will allow you to process LLM prompts with your own hosted LLM.\n\n### 4. Build and Deploy the Webhook\n\nUse the provided Makefile to build the Go application, create Docker images, generate necessary certificates and secrets, and deploy the webhook to your Kind cluster.\n\nRun the following command from the root of the project:\n\n```bash\nmake deploy\n```\n\nThis command performs the following actions:\n\n- Builds the Go application and creates the webhook binary.\n- Builds the Docker image and loads it into the Kind cluster.\n- Generates TLS certificates for secure communication and creates the `webhook-certs.yaml` secret in `config/`.\n- Generates the `openai-api-key.yaml` secret in `config/` using the `OPENAI_API_KEY` environment variable.\n- Applies Kubernetes manifests from the `config/` directory to deploy the webhook and its service.\n- Configures the `MutatingWebhookConfiguration` with the correct CA bundle to register the webhook with the Kubernetes API server.\n\n### 5. Test the Webhook\n\n#### 5.1 Create an Invalid ClusterExtension CR\n\nCreate a YAML file named `invalid-cr.yaml` with the following content:\n\n```yaml\napiVersion: olm.operatorframework.io/v1alpha1\nkind: ClusterExtension\nmetadata:\n  name: test-extension\nspec:\n  install:\n    namespace: test-namespace\n    serviceAccount:\n      name: test-sa\n    source:\n      sourceType: Catalog\n      catalog:\n        # packageName is missing\n```\n\nThis CR is intentionally invalid because it is missing the required `packageName` field under `spec.source.catalog`.\n\n#### 5.2 Apply the Invalid CR\n\nApply the invalid CR to your cluster:\n\n```bash\nkubectl apply -f invalid-cr.yaml --validate=false\n```\n\n#### 5.3 Verify the Mutation\n\nRetrieve the CR to see if it has been mutated by the webhook:\n\n```bash\nkubectl get clusterextension test-extension -o yaml\n```\n\nCheck if the `packageName` field has been added or corrected by the webhook.\n\n#### 5.4 Observe the Webhook Logs\n\nView the logs of the webhook pod to observe its behavior:\n\n```bash\n# Get the webhook pod name\nPOD_NAME=$(kubectl get pods -l app=webhook -o jsonpath='{.items[0].metadata.name}')\n\n# View the logs\nkubectl logs $POD_NAME\n```\n\n### 6. Undeploy the Webhook\n\nWhen you're finished testing, you can remove all deployed resources using:\n\n```bash\nmake undeploy\n```\n\nThis command deletes the Kubernetes resources and cleans up generated files.\n\n### Cleaning Up\n\nTo delete the Kind cluster entirely:\n\n```bash\nkind delete cluster\n```\n\n## Important Notes\n\n- **Security**: Ensure that sensitive files like `openai-api-key.yaml`, `webhook-certs.yaml`, and `mutatingwebhookconfiguration.yaml` are not committed to version control. They are automatically ignored if you have the appropriate entries in your `.gitignore` file.\n  \n  Add the following lines to `.gitignore`:\n\n  ```\n  config/openai-api-key.yaml\n  config/webhook-certs.yaml\n  config/mutatingwebhookconfiguration.yaml\n  ```\n\n- **Executable Permissions**: Ensure that the scripts in the `scripts/` directory have executable permissions:\n\n  ```bash\n  chmod +x scripts/generate-certs.sh\n  chmod +x scripts/generate-openai-secret.sh\n  ```\n\n- **Namespace Consistency**: The default namespace used is `default`. If you wish to deploy to a different namespace, update the `NAMESPACE` variable in the Makefile, scripts, and Kubernetes manifests accordingly.\n\n- **OpenAI API Usage**: Be mindful of the OpenAI API usage limits and associated costs when testing the webhook, as each invalid CR will trigger a request to the OpenAI API.\n\n## Project Details\n\n### How It Works\n\n1. **Admission Webhook Interception**: When a ClusterExtension CR is created or updated, the Kubernetes API server sends the request to the admission webhook for validation and possible mutation.\n   \n2. **Validation**: The webhook validates the CR against its CRD schema using the `ValidateCR` function.\n   \n3. **LLM Adjustment**: If the CR is invalid, the webhook calls the `AdjustCRWithLLM` function, which sends the CR and its validation errors to the OpenAI API. The LLM attempts to correct the CR based on the provided schema and errors.\n   \n4. **Patch Generation**: A JSON Patch is generated based on the differences between the original CR and the adjusted CR returned by the LLM.\n   \n5. **Response to API Server**: The webhook returns an admission response containing the JSON Patch, which the API server applies to the original CR before persisting it.\n\n### Customization\n\n- **CRD Schema**: The webhook relies on the ClusterExtension CRD schema. Ensure that the schema is accurate and up-to-date.\n- **LLM Prompting**: The prompts sent to the OpenAI API can be customized within the webhook code to improve correction accuracy.\n- **Error Handling**: Enhance error handling and logging in the webhook to handle different scenarios gracefully.\n\n## Development\n\n### Running Tests\n\nTo run the unit tests for the webhook:\n\n```bash\nmake test\n```\n\n### Building the Binary\n\nTo build the webhook binary without deploying:\n\n```bash\nmake build\n```\n\nThe binary will be placed in the `bin/` directory.\n\n## Contributing\n\nContributions are welcome! Please open issues or pull requests for enhancements, bug fixes, or other improvements.\n\n## License\n\nThis project is licensed under the MIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbentito%2Fclusterextensionhelper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbentito%2Fclusterextensionhelper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbentito%2Fclusterextensionhelper/lists"}